Home | History | Annotate | Line # | Download | only in aarch64
aarch64-sve.md revision 1.1.1.2
      1 ;; Machine description for AArch64 SVE.
      2 ;; Copyright (C) 2009-2019 Free Software Foundation, Inc.
      3 ;; Contributed by ARM Ltd.
      4 ;;
      5 ;; This file is part of GCC.
      6 ;;
      7 ;; GCC is free software; you can redistribute it and/or modify it
      8 ;; under the terms of the GNU General Public License as published by
      9 ;; the Free Software Foundation; either version 3, or (at your option)
     10 ;; any later version.
     11 ;;
     12 ;; GCC is distributed in the hope that it will be useful, but
     13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
     14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 ;; General Public License for more details.
     16 ;;
     17 ;; You should have received a copy of the GNU General Public License
     18 ;; along with GCC; see the file COPYING3.  If not see
     19 ;; <http://www.gnu.org/licenses/>.
     20 
     21 ;; Note on the handling of big-endian SVE
     22 ;; --------------------------------------
     23 ;;
     24 ;; On big-endian systems, Advanced SIMD mov<mode> patterns act in the
     25 ;; same way as movdi or movti would: the first byte of memory goes
     26 ;; into the most significant byte of the register and the last byte
     27 ;; of memory goes into the least significant byte of the register.
     28 ;; This is the most natural ordering for Advanced SIMD and matches
     29 ;; the ABI layout for 64-bit and 128-bit vector types.
     30 ;;
     31 ;; As a result, the order of bytes within the register is what GCC
     32 ;; expects for a big-endian target, and subreg offsets therefore work
     33 ;; as expected, with the first element in memory having subreg offset 0
     34 ;; and the last element in memory having the subreg offset associated
     35 ;; with a big-endian lowpart.  However, this ordering also means that
     36 ;; GCC's lane numbering does not match the architecture's numbering:
     37 ;; GCC always treats the element at the lowest address in memory
     38 ;; (subreg offset 0) as element 0, while the architecture treats
     39 ;; the least significant end of the register as element 0.
     40 ;;
     41 ;; The situation for SVE is different.  We want the layout of the
     42 ;; SVE register to be same for mov<mode> as it is for maskload<mode>:
     43 ;; logically, a mov<mode> load must be indistinguishable from a
     44 ;; maskload<mode> whose mask is all true.  We therefore need the
     45 ;; register layout to match LD1 rather than LDR.  The ABI layout of
     46 ;; SVE types also matches LD1 byte ordering rather than LDR byte ordering.
     47 ;;
     48 ;; As a result, the architecture lane numbering matches GCC's lane
     49 ;; numbering, with element 0 always being the first in memory.
     50 ;; However:
     51 ;;
     52 ;; - Applying a subreg offset to a register does not give the element
     53 ;;   that GCC expects: the first element in memory has the subreg offset
     54 ;;   associated with a big-endian lowpart while the last element in memory
     55 ;;   has subreg offset 0.  We handle this via TARGET_CAN_CHANGE_MODE_CLASS.
     56 ;;
     57 ;; - We cannot use LDR and STR for spill slots that might be accessed
     58 ;;   via subregs, since although the elements have the order GCC expects,
     59 ;;   the order of the bytes within the elements is different.  We instead
     60 ;;   access spill slots via LD1 and ST1, using secondary reloads to
     61 ;;   reserve a predicate register.
     62 
     63 
     64 ;; SVE data moves.
     65 (define_expand "mov<mode>"
     66   [(set (match_operand:SVE_ALL 0 "nonimmediate_operand")
     67 	(match_operand:SVE_ALL 1 "general_operand"))]
     68   "TARGET_SVE"
     69   {
     70     /* Use the predicated load and store patterns where possible.
     71        This is required for big-endian targets (see the comment at the
     72        head of the file) and increases the addressing choices for
     73        little-endian.  */
     74     if ((MEM_P (operands[0]) || MEM_P (operands[1]))
     75         && can_create_pseudo_p ())
     76       {
     77 	aarch64_expand_sve_mem_move (operands[0], operands[1], <VPRED>mode);
     78 	DONE;
     79       }
     80 
     81     if (CONSTANT_P (operands[1]))
     82       {
     83 	aarch64_expand_mov_immediate (operands[0], operands[1],
     84 				      gen_vec_duplicate<mode>);
     85 	DONE;
     86       }
     87 
     88     /* Optimize subregs on big-endian targets: we can use REV[BHW]
     89        instead of going through memory.  */
     90     if (BYTES_BIG_ENDIAN
     91         && aarch64_maybe_expand_sve_subreg_move (operands[0], operands[1]))
     92       DONE;
     93   }
     94 )
     95 
     96 ;; A pattern for optimizing SUBREGs that have a reinterpreting effect
     97 ;; on big-endian targets; see aarch64_maybe_expand_sve_subreg_move
     98 ;; for details.  We use a special predicate for operand 2 to reduce
     99 ;; the number of patterns.
    100 (define_insn_and_split "*aarch64_sve_mov<mode>_subreg_be"
    101   [(set (match_operand:SVE_ALL 0 "aarch64_sve_nonimmediate_operand" "=w")
    102 	(unspec:SVE_ALL
    103           [(match_operand:VNx16BI 1 "register_operand" "Upl")
    104 	   (match_operand 2 "aarch64_any_register_operand" "w")]
    105 	  UNSPEC_REV_SUBREG))]
    106   "TARGET_SVE && BYTES_BIG_ENDIAN"
    107   "#"
    108   "&& reload_completed"
    109   [(const_int 0)]
    110   {
    111     aarch64_split_sve_subreg_move (operands[0], operands[1], operands[2]);
    112     DONE;
    113   }
    114 )
    115 
    116 ;; Unpredicated moves (little-endian).  Only allow memory operations
    117 ;; during and after RA; before RA we want the predicated load and
    118 ;; store patterns to be used instead.
    119 (define_insn "*aarch64_sve_mov<mode>_le"
    120   [(set (match_operand:SVE_ALL 0 "aarch64_sve_nonimmediate_operand" "=w, Utr, w, w")
    121 	(match_operand:SVE_ALL 1 "aarch64_sve_general_operand" "Utr, w, w, Dn"))]
    122   "TARGET_SVE
    123    && !BYTES_BIG_ENDIAN
    124    && ((lra_in_progress || reload_completed)
    125        || (register_operand (operands[0], <MODE>mode)
    126 	   && nonmemory_operand (operands[1], <MODE>mode)))"
    127   "@
    128    ldr\t%0, %1
    129    str\t%1, %0
    130    mov\t%0.d, %1.d
    131    * return aarch64_output_sve_mov_immediate (operands[1]);"
    132 )
    133 
    134 ;; Unpredicated moves (big-endian).  Memory accesses require secondary
    135 ;; reloads.
    136 (define_insn "*aarch64_sve_mov<mode>_be"
    137   [(set (match_operand:SVE_ALL 0 "register_operand" "=w, w")
    138 	(match_operand:SVE_ALL 1 "aarch64_nonmemory_operand" "w, Dn"))]
    139   "TARGET_SVE && BYTES_BIG_ENDIAN"
    140   "@
    141    mov\t%0.d, %1.d
    142    * return aarch64_output_sve_mov_immediate (operands[1]);"
    143 )
    144 
    145 ;; Handle big-endian memory reloads.  We use byte PTRUE for all modes
    146 ;; to try to encourage reuse.
    147 (define_expand "aarch64_sve_reload_be"
    148   [(parallel
    149      [(set (match_operand 0)
    150            (match_operand 1))
    151       (clobber (match_operand:VNx16BI 2 "register_operand" "=Upl"))])]
    152   "TARGET_SVE && BYTES_BIG_ENDIAN"
    153   {
    154     /* Create a PTRUE.  */
    155     emit_move_insn (operands[2], CONSTM1_RTX (VNx16BImode));
    156 
    157     /* Refer to the PTRUE in the appropriate mode for this move.  */
    158     machine_mode mode = GET_MODE (operands[0]);
    159     machine_mode pred_mode
    160       = aarch64_sve_pred_mode (GET_MODE_UNIT_SIZE (mode)).require ();
    161     rtx pred = gen_lowpart (pred_mode, operands[2]);
    162 
    163     /* Emit a predicated load or store.  */
    164     aarch64_emit_sve_pred_move (operands[0], pred, operands[1]);
    165     DONE;
    166   }
    167 )
    168 
    169 ;; A predicated load or store for which the predicate is known to be
    170 ;; all-true.  Note that this pattern is generated directly by
    171 ;; aarch64_emit_sve_pred_move, so changes to this pattern will
    172 ;; need changes there as well.
    173 (define_insn_and_split "@aarch64_pred_mov<mode>"
    174   [(set (match_operand:SVE_ALL 0 "nonimmediate_operand" "=w, w, m")
    175 	(unspec:SVE_ALL
    176 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
    177 	   (match_operand:SVE_ALL 2 "nonimmediate_operand" "w, m, w")]
    178 	  UNSPEC_MERGE_PTRUE))]
    179   "TARGET_SVE
    180    && (register_operand (operands[0], <MODE>mode)
    181        || register_operand (operands[2], <MODE>mode))"
    182   "@
    183    #
    184    ld1<Vesize>\t%0.<Vetype>, %1/z, %2
    185    st1<Vesize>\t%2.<Vetype>, %1, %0"
    186   "&& register_operand (operands[0], <MODE>mode)
    187    && register_operand (operands[2], <MODE>mode)"
    188   [(set (match_dup 0) (match_dup 2))]
    189 )
    190 
    191 (define_expand "movmisalign<mode>"
    192   [(set (match_operand:SVE_ALL 0 "nonimmediate_operand")
    193 	(match_operand:SVE_ALL 1 "general_operand"))]
    194   "TARGET_SVE"
    195   {
    196     /* Equivalent to a normal move for our purpooses.  */
    197     emit_move_insn (operands[0], operands[1]);
    198     DONE;
    199   }
    200 )
    201 
    202 (define_insn "maskload<mode><vpred>"
    203   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
    204 	(unspec:SVE_ALL
    205 	  [(match_operand:<VPRED> 2 "register_operand" "Upl")
    206 	   (match_operand:SVE_ALL 1 "memory_operand" "m")]
    207 	  UNSPEC_LD1_SVE))]
    208   "TARGET_SVE"
    209   "ld1<Vesize>\t%0.<Vetype>, %2/z, %1"
    210 )
    211 
    212 (define_insn "maskstore<mode><vpred>"
    213   [(set (match_operand:SVE_ALL 0 "memory_operand" "+m")
    214 	(unspec:SVE_ALL [(match_operand:<VPRED> 2 "register_operand" "Upl")
    215 			 (match_operand:SVE_ALL 1 "register_operand" "w")
    216 			 (match_dup 0)]
    217 			UNSPEC_ST1_SVE))]
    218   "TARGET_SVE"
    219   "st1<Vesize>\t%1.<Vetype>, %2, %0"
    220 )
    221 
    222 ;; Unpredicated gather loads.
    223 (define_expand "gather_load<mode>"
    224   [(set (match_operand:SVE_SD 0 "register_operand")
    225 	(unspec:SVE_SD
    226 	  [(match_dup 5)
    227 	   (match_operand:DI 1 "aarch64_reg_or_zero")
    228 	   (match_operand:<V_INT_EQUIV> 2 "register_operand")
    229 	   (match_operand:DI 3 "const_int_operand")
    230 	   (match_operand:DI 4 "aarch64_gather_scale_operand_<Vesize>")
    231 	   (mem:BLK (scratch))]
    232 	  UNSPEC_LD1_GATHER))]
    233   "TARGET_SVE"
    234   {
    235     operands[5] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
    236   }
    237 )
    238 
    239 ;; Predicated gather loads for 32-bit elements.  Operand 3 is true for
    240 ;; unsigned extension and false for signed extension.
    241 (define_insn "mask_gather_load<mode>"
    242   [(set (match_operand:SVE_S 0 "register_operand" "=w, w, w, w, w")
    243 	(unspec:SVE_S
    244 	  [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl, Upl, Upl")
    245 	   (match_operand:DI 1 "aarch64_reg_or_zero" "Z, rk, rk, rk, rk")
    246 	   (match_operand:<V_INT_EQUIV> 2 "register_operand" "w, w, w, w, w")
    247 	   (match_operand:DI 3 "const_int_operand" "i, Z, Ui1, Z, Ui1")
    248 	   (match_operand:DI 4 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, i, i")
    249 	   (mem:BLK (scratch))]
    250 	  UNSPEC_LD1_GATHER))]
    251   "TARGET_SVE"
    252   "@
    253    ld1w\t%0.s, %5/z, [%2.s]
    254    ld1w\t%0.s, %5/z, [%1, %2.s, sxtw]
    255    ld1w\t%0.s, %5/z, [%1, %2.s, uxtw]
    256    ld1w\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
    257    ld1w\t%0.s, %5/z, [%1, %2.s, uxtw %p4]"
    258 )
    259 
    260 ;; Predicated gather loads for 64-bit elements.  The value of operand 3
    261 ;; doesn't matter in this case.
    262 (define_insn "mask_gather_load<mode>"
    263   [(set (match_operand:SVE_D 0 "register_operand" "=w, w, w")
    264 	(unspec:SVE_D
    265 	  [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl")
    266 	   (match_operand:DI 1 "aarch64_reg_or_zero" "Z, rk, rk")
    267 	   (match_operand:<V_INT_EQUIV> 2 "register_operand" "w, w, w")
    268 	   (match_operand:DI 3 "const_int_operand")
    269 	   (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, Ui1, i")
    270 	   (mem:BLK (scratch))]
    271 	  UNSPEC_LD1_GATHER))]
    272   "TARGET_SVE"
    273   "@
    274    ld1d\t%0.d, %5/z, [%2.d]
    275    ld1d\t%0.d, %5/z, [%1, %2.d]
    276    ld1d\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
    277 )
    278 
    279 ;; Unpredicated scatter store.
    280 (define_expand "scatter_store<mode>"
    281   [(set (mem:BLK (scratch))
    282 	(unspec:BLK
    283 	  [(match_dup 5)
    284 	   (match_operand:DI 0 "aarch64_reg_or_zero")
    285 	   (match_operand:<V_INT_EQUIV> 1 "register_operand")
    286 	   (match_operand:DI 2 "const_int_operand")
    287 	   (match_operand:DI 3 "aarch64_gather_scale_operand_<Vesize>")
    288 	   (match_operand:SVE_SD 4 "register_operand")]
    289 	  UNSPEC_ST1_SCATTER))]
    290   "TARGET_SVE"
    291   {
    292     operands[5] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
    293   }
    294 )
    295 
    296 ;; Predicated scatter stores for 32-bit elements.  Operand 2 is true for
    297 ;; unsigned extension and false for signed extension.
    298 (define_insn "mask_scatter_store<mode>"
    299   [(set (mem:BLK (scratch))
    300 	(unspec:BLK
    301 	  [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl, Upl, Upl")
    302 	   (match_operand:DI 0 "aarch64_reg_or_zero" "Z, rk, rk, rk, rk")
    303 	   (match_operand:<V_INT_EQUIV> 1 "register_operand" "w, w, w, w, w")
    304 	   (match_operand:DI 2 "const_int_operand" "i, Z, Ui1, Z, Ui1")
    305 	   (match_operand:DI 3 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, i, i")
    306 	   (match_operand:SVE_S 4 "register_operand" "w, w, w, w, w")]
    307 	  UNSPEC_ST1_SCATTER))]
    308   "TARGET_SVE"
    309   "@
    310    st1w\t%4.s, %5, [%1.s]
    311    st1w\t%4.s, %5, [%0, %1.s, sxtw]
    312    st1w\t%4.s, %5, [%0, %1.s, uxtw]
    313    st1w\t%4.s, %5, [%0, %1.s, sxtw %p3]
    314    st1w\t%4.s, %5, [%0, %1.s, uxtw %p3]"
    315 )
    316 
    317 ;; Predicated scatter stores for 64-bit elements.  The value of operand 2
    318 ;; doesn't matter in this case.
    319 (define_insn "mask_scatter_store<mode>"
    320   [(set (mem:BLK (scratch))
    321 	(unspec:BLK
    322 	  [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl")
    323 	   (match_operand:DI 0 "aarch64_reg_or_zero" "Z, rk, rk")
    324 	   (match_operand:<V_INT_EQUIV> 1 "register_operand" "w, w, w")
    325 	   (match_operand:DI 2 "const_int_operand")
    326 	   (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, Ui1, i")
    327 	   (match_operand:SVE_D 4 "register_operand" "w, w, w")]
    328 	  UNSPEC_ST1_SCATTER))]
    329   "TARGET_SVE"
    330   "@
    331    st1d\t%4.d, %5, [%1.d]
    332    st1d\t%4.d, %5, [%0, %1.d]
    333    st1d\t%4.d, %5, [%0, %1.d, lsl %p3]"
    334 )
    335 
    336 ;; SVE structure moves.
    337 (define_expand "mov<mode>"
    338   [(set (match_operand:SVE_STRUCT 0 "nonimmediate_operand")
    339 	(match_operand:SVE_STRUCT 1 "general_operand"))]
    340   "TARGET_SVE"
    341   {
    342     /* Big-endian loads and stores need to be done via LD1 and ST1;
    343        see the comment at the head of the file for details.  */
    344     if ((MEM_P (operands[0]) || MEM_P (operands[1]))
    345 	&& BYTES_BIG_ENDIAN)
    346       {
    347 	gcc_assert (can_create_pseudo_p ());
    348 	aarch64_expand_sve_mem_move (operands[0], operands[1], <VPRED>mode);
    349 	DONE;
    350       }
    351 
    352     if (CONSTANT_P (operands[1]))
    353       {
    354 	aarch64_expand_mov_immediate (operands[0], operands[1]);
    355 	DONE;
    356       }
    357   }
    358 )
    359 
    360 ;; Unpredicated structure moves (little-endian).
    361 (define_insn "*aarch64_sve_mov<mode>_le"
    362   [(set (match_operand:SVE_STRUCT 0 "aarch64_sve_nonimmediate_operand" "=w, Utr, w, w")
    363 	(match_operand:SVE_STRUCT 1 "aarch64_sve_general_operand" "Utr, w, w, Dn"))]
    364   "TARGET_SVE && !BYTES_BIG_ENDIAN"
    365   "#"
    366   [(set_attr "length" "<insn_length>")]
    367 )
    368 
    369 ;; Unpredicated structure moves (big-endian).  Memory accesses require
    370 ;; secondary reloads.
    371 (define_insn "*aarch64_sve_mov<mode>_le"
    372   [(set (match_operand:SVE_STRUCT 0 "register_operand" "=w, w")
    373 	(match_operand:SVE_STRUCT 1 "aarch64_nonmemory_operand" "w, Dn"))]
    374   "TARGET_SVE && BYTES_BIG_ENDIAN"
    375   "#"
    376   [(set_attr "length" "<insn_length>")]
    377 )
    378 
    379 ;; Split unpredicated structure moves into pieces.  This is the same
    380 ;; for both big-endian and little-endian code, although it only needs
    381 ;; to handle memory operands for little-endian code.
    382 (define_split
    383   [(set (match_operand:SVE_STRUCT 0 "aarch64_sve_nonimmediate_operand")
    384 	(match_operand:SVE_STRUCT 1 "aarch64_sve_general_operand"))]
    385   "TARGET_SVE && reload_completed"
    386   [(const_int 0)]
    387   {
    388     rtx dest = operands[0];
    389     rtx src = operands[1];
    390     if (REG_P (dest) && REG_P (src))
    391       aarch64_simd_emit_reg_reg_move (operands, <VSINGLE>mode, <vector_count>);
    392     else
    393       for (unsigned int i = 0; i < <vector_count>; ++i)
    394 	{
    395 	  rtx subdest = simplify_gen_subreg (<VSINGLE>mode, dest, <MODE>mode,
    396 					     i * BYTES_PER_SVE_VECTOR);
    397 	  rtx subsrc = simplify_gen_subreg (<VSINGLE>mode, src, <MODE>mode,
    398 					    i * BYTES_PER_SVE_VECTOR);
    399 	  emit_insn (gen_rtx_SET (subdest, subsrc));
    400 	}
    401     DONE;
    402   }
    403 )
    404 
    405 ;; Predicated structure moves.  This works for both endiannesses but in
    406 ;; practice is only useful for big-endian.
    407 (define_insn_and_split "@aarch64_pred_mov<mode>"
    408   [(set (match_operand:SVE_STRUCT 0 "aarch64_sve_struct_nonimmediate_operand" "=w, w, Utx")
    409 	(unspec:SVE_STRUCT
    410 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
    411 	   (match_operand:SVE_STRUCT 2 "aarch64_sve_struct_nonimmediate_operand" "w, Utx, w")]
    412 	  UNSPEC_MERGE_PTRUE))]
    413   "TARGET_SVE
    414    && (register_operand (operands[0], <MODE>mode)
    415        || register_operand (operands[2], <MODE>mode))"
    416   "#"
    417   "&& reload_completed"
    418   [(const_int 0)]
    419   {
    420     for (unsigned int i = 0; i < <vector_count>; ++i)
    421       {
    422 	rtx subdest = simplify_gen_subreg (<VSINGLE>mode, operands[0],
    423 					   <MODE>mode,
    424 					   i * BYTES_PER_SVE_VECTOR);
    425 	rtx subsrc = simplify_gen_subreg (<VSINGLE>mode, operands[2],
    426 					  <MODE>mode,
    427 					  i * BYTES_PER_SVE_VECTOR);
    428 	aarch64_emit_sve_pred_move (subdest, operands[1], subsrc);
    429       }
    430     DONE;
    431   }
    432   [(set_attr "length" "<insn_length>")]
    433 )
    434 
    435 (define_expand "mov<mode>"
    436   [(set (match_operand:PRED_ALL 0 "nonimmediate_operand")
    437 	(match_operand:PRED_ALL 1 "general_operand"))]
    438   "TARGET_SVE"
    439   {
    440     if (GET_CODE (operands[0]) == MEM)
    441       operands[1] = force_reg (<MODE>mode, operands[1]);
    442   }
    443 )
    444 
    445 (define_insn "*aarch64_sve_mov<mode>"
    446   [(set (match_operand:PRED_ALL 0 "nonimmediate_operand" "=Upa, m, Upa, Upa, Upa")
    447 	(match_operand:PRED_ALL 1 "general_operand" "Upa, Upa, m, Dz, Dm"))]
    448   "TARGET_SVE
    449    && (register_operand (operands[0], <MODE>mode)
    450        || register_operand (operands[1], <MODE>mode))"
    451   "@
    452    mov\t%0.b, %1.b
    453    str\t%1, %0
    454    ldr\t%0, %1
    455    pfalse\t%0.b
    456    * return aarch64_output_ptrue (<MODE>mode, '<Vetype>');"
    457 )
    458 
    459 ;; Handle extractions from a predicate by converting to an integer vector
    460 ;; and extracting from there.
    461 (define_expand "vec_extract<vpred><Vel>"
    462   [(match_operand:<VEL> 0 "register_operand")
    463    (match_operand:<VPRED> 1 "register_operand")
    464    (match_operand:SI 2 "nonmemory_operand")
    465    ;; Dummy operand to which we can attach the iterator.
    466    (reg:SVE_I V0_REGNUM)]
    467   "TARGET_SVE"
    468   {
    469     rtx tmp = gen_reg_rtx (<MODE>mode);
    470     emit_insn (gen_aarch64_sve_dup<mode>_const (tmp, operands[1],
    471 						CONST1_RTX (<MODE>mode),
    472 						CONST0_RTX (<MODE>mode)));
    473     emit_insn (gen_vec_extract<mode><Vel> (operands[0], tmp, operands[2]));
    474     DONE;
    475   }
    476 )
    477 
    478 (define_expand "vec_extract<mode><Vel>"
    479   [(set (match_operand:<VEL> 0 "register_operand")
    480 	(vec_select:<VEL>
    481 	  (match_operand:SVE_ALL 1 "register_operand")
    482 	  (parallel [(match_operand:SI 2 "nonmemory_operand")])))]
    483   "TARGET_SVE"
    484   {
    485     poly_int64 val;
    486     if (poly_int_rtx_p (operands[2], &val)
    487 	&& known_eq (val, GET_MODE_NUNITS (<MODE>mode) - 1))
    488       {
    489 	/* The last element can be extracted with a LASTB and a false
    490 	   predicate.  */
    491 	rtx sel = force_reg (<VPRED>mode, CONST0_RTX (<VPRED>mode));
    492 	emit_insn (gen_extract_last_<mode> (operands[0], sel, operands[1]));
    493 	DONE;
    494       }
    495     if (!CONST_INT_P (operands[2]))
    496       {
    497 	/* Create an index with operand[2] as the base and -1 as the step.
    498 	   It will then be zero for the element we care about.  */
    499 	rtx index = gen_lowpart (<VEL_INT>mode, operands[2]);
    500 	index = force_reg (<VEL_INT>mode, index);
    501 	rtx series = gen_reg_rtx (<V_INT_EQUIV>mode);
    502 	emit_insn (gen_vec_series<v_int_equiv> (series, index, constm1_rtx));
    503 
    504 	/* Get a predicate that is true for only that element.  */
    505 	rtx zero = CONST0_RTX (<V_INT_EQUIV>mode);
    506 	rtx cmp = gen_rtx_EQ (<V_INT_EQUIV>mode, series, zero);
    507 	rtx sel = gen_reg_rtx (<VPRED>mode);
    508 	emit_insn (gen_vec_cmp<v_int_equiv><vpred> (sel, cmp, series, zero));
    509 
    510 	/* Select the element using LASTB.  */
    511 	emit_insn (gen_extract_last_<mode> (operands[0], sel, operands[1]));
    512 	DONE;
    513       }
    514   }
    515 )
    516 
    517 ;; Extract element zero.  This is a special case because we want to force
    518 ;; the registers to be the same for the second alternative, and then
    519 ;; split the instruction into nothing after RA.
    520 (define_insn_and_split "*vec_extract<mode><Vel>_0"
    521   [(set (match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand" "=r, w, Utv")
    522 	(vec_select:<VEL>
    523 	  (match_operand:SVE_ALL 1 "register_operand" "w, 0, w")
    524 	  (parallel [(const_int 0)])))]
    525   "TARGET_SVE"
    526   {
    527     operands[1] = gen_rtx_REG (<V128>mode, REGNO (operands[1]));
    528     switch (which_alternative)
    529       {
    530 	case 0:
    531 	  return "umov\\t%<vwcore>0, %1.<Vetype>[0]";
    532 	case 1:
    533 	  return "#";
    534 	case 2:
    535 	  return "st1\\t{%1.<Vetype>}[0], %0";
    536 	default:
    537 	  gcc_unreachable ();
    538       }
    539   }
    540   "&& reload_completed
    541    && REG_P (operands[0])
    542    && REGNO (operands[0]) == REGNO (operands[1])"
    543   [(const_int 0)]
    544   {
    545     emit_note (NOTE_INSN_DELETED);
    546     DONE;
    547   }
    548   [(set_attr "type" "neon_to_gp_q, untyped, neon_store1_one_lane_q")]
    549 )
    550 
    551 ;; Extract an element from the Advanced SIMD portion of the register.
    552 ;; We don't just reuse the aarch64-simd.md pattern because we don't
    553 ;; want any change in lane number on big-endian targets.
    554 (define_insn "*vec_extract<mode><Vel>_v128"
    555   [(set (match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand" "=r, w, Utv")
    556 	(vec_select:<VEL>
    557 	  (match_operand:SVE_ALL 1 "register_operand" "w, w, w")
    558 	  (parallel [(match_operand:SI 2 "const_int_operand")])))]
    559   "TARGET_SVE
    560    && IN_RANGE (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode), 1, 15)"
    561   {
    562     operands[1] = gen_rtx_REG (<V128>mode, REGNO (operands[1]));
    563     switch (which_alternative)
    564       {
    565 	case 0:
    566 	  return "umov\\t%<vwcore>0, %1.<Vetype>[%2]";
    567 	case 1:
    568 	  return "dup\\t%<Vetype>0, %1.<Vetype>[%2]";
    569 	case 2:
    570 	  return "st1\\t{%1.<Vetype>}[%2], %0";
    571 	default:
    572 	  gcc_unreachable ();
    573       }
    574   }
    575   [(set_attr "type" "neon_to_gp_q, neon_dup_q, neon_store1_one_lane_q")]
    576 )
    577 
    578 ;; Extract an element in the range of DUP.  This pattern allows the
    579 ;; source and destination to be different.
    580 (define_insn "*vec_extract<mode><Vel>_dup"
    581   [(set (match_operand:<VEL> 0 "register_operand" "=w")
    582 	(vec_select:<VEL>
    583 	  (match_operand:SVE_ALL 1 "register_operand" "w")
    584 	  (parallel [(match_operand:SI 2 "const_int_operand")])))]
    585   "TARGET_SVE
    586    && IN_RANGE (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode), 16, 63)"
    587   {
    588     operands[0] = gen_rtx_REG (<MODE>mode, REGNO (operands[0]));
    589     return "dup\t%0.<Vetype>, %1.<Vetype>[%2]";
    590   }
    591 )
    592 
    593 ;; Extract an element outside the range of DUP.  This pattern requires the
    594 ;; source and destination to be the same.
    595 (define_insn "*vec_extract<mode><Vel>_ext"
    596   [(set (match_operand:<VEL> 0 "register_operand" "=w")
    597 	(vec_select:<VEL>
    598 	  (match_operand:SVE_ALL 1 "register_operand" "0")
    599 	  (parallel [(match_operand:SI 2 "const_int_operand")])))]
    600   "TARGET_SVE && INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode) >= 64"
    601   {
    602     operands[0] = gen_rtx_REG (<MODE>mode, REGNO (operands[0]));
    603     operands[2] = GEN_INT (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode));
    604     return "ext\t%0.b, %0.b, %0.b, #%2";
    605   }
    606 )
    607 
    608 ;; Extract the last active element of operand 1 into operand 0.
    609 ;; If no elements are active, extract the last inactive element instead.
    610 (define_insn "extract_last_<mode>"
    611   [(set (match_operand:<VEL> 0 "register_operand" "=r, w")
    612 	(unspec:<VEL>
    613 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
    614 	   (match_operand:SVE_ALL 2 "register_operand" "w, w")]
    615 	  UNSPEC_LASTB))]
    616   "TARGET_SVE"
    617   "@
    618    lastb\t%<vwcore>0, %1, %2.<Vetype>
    619    lastb\t%<Vetype>0, %1, %2.<Vetype>"
    620 )
    621 
    622 (define_expand "vec_duplicate<mode>"
    623   [(parallel
    624     [(set (match_operand:SVE_ALL 0 "register_operand")
    625 	  (vec_duplicate:SVE_ALL
    626 	    (match_operand:<VEL> 1 "aarch64_sve_dup_operand")))
    627      (clobber (scratch:<VPRED>))])]
    628   "TARGET_SVE"
    629   {
    630     if (MEM_P (operands[1]))
    631       {
    632 	rtx ptrue = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
    633 	emit_insn (gen_sve_ld1r<mode> (operands[0], ptrue, operands[1],
    634 				       CONST0_RTX (<MODE>mode)));
    635 	DONE;
    636       }
    637   }
    638 )
    639 
    640 ;; Accept memory operands for the benefit of combine, and also in case
    641 ;; the scalar input gets spilled to memory during RA.  We want to split
    642 ;; the load at the first opportunity in order to allow the PTRUE to be
    643 ;; optimized with surrounding code.
    644 (define_insn_and_split "*vec_duplicate<mode>_reg"
    645   [(set (match_operand:SVE_ALL 0 "register_operand" "=w, w, w")
    646 	(vec_duplicate:SVE_ALL
    647 	  (match_operand:<VEL> 1 "aarch64_sve_dup_operand" "r, w, Uty")))
    648    (clobber (match_scratch:<VPRED> 2 "=X, X, Upl"))]
    649   "TARGET_SVE"
    650   "@
    651    mov\t%0.<Vetype>, %<vwcore>1
    652    mov\t%0.<Vetype>, %<Vetype>1
    653    #"
    654   "&& MEM_P (operands[1])"
    655   [(const_int 0)]
    656   {
    657     if (GET_CODE (operands[2]) == SCRATCH)
    658       operands[2] = gen_reg_rtx (<VPRED>mode);
    659     emit_move_insn (operands[2], CONSTM1_RTX (<VPRED>mode));
    660     emit_insn (gen_sve_ld1r<mode> (operands[0], operands[2], operands[1],
    661 				   CONST0_RTX (<MODE>mode)));
    662     DONE;
    663   }
    664   [(set_attr "length" "4,4,8")]
    665 )
    666 
    667 ;; This is used for vec_duplicate<mode>s from memory, but can also
    668 ;; be used by combine to optimize selects of a a vec_duplicate<mode>
    669 ;; with zero.
    670 (define_insn "sve_ld1r<mode>"
    671   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
    672 	(unspec:SVE_ALL
    673 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
    674 	   (vec_duplicate:SVE_ALL
    675 	     (match_operand:<VEL> 2 "aarch64_sve_ld1r_operand" "Uty"))
    676 	   (match_operand:SVE_ALL 3 "aarch64_simd_imm_zero")]
    677 	  UNSPEC_SEL))]
    678   "TARGET_SVE"
    679   "ld1r<Vesize>\t%0.<Vetype>, %1/z, %2"
    680 )
    681 
    682 ;; Load 128 bits from memory and duplicate to fill a vector.  Since there
    683 ;; are so few operations on 128-bit "elements", we don't define a VNx1TI
    684 ;; and simply use vectors of bytes instead.
    685 (define_insn "*sve_ld1rq<Vesize>"
    686   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
    687 	(unspec:SVE_ALL
    688 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
    689 	   (match_operand:TI 2 "aarch64_sve_ld1r_operand" "Uty")]
    690 	  UNSPEC_LD1RQ))]
    691   "TARGET_SVE"
    692   "ld1rq<Vesize>\t%0.<Vetype>, %1/z, %2"
    693 )
    694 
    695 ;; Implement a predicate broadcast by shifting the low bit of the scalar
    696 ;; input into the top bit and using a WHILELO.  An alternative would be to
    697 ;; duplicate the input and do a compare with zero.
    698 (define_expand "vec_duplicate<mode>"
    699   [(set (match_operand:PRED_ALL 0 "register_operand")
    700 	(vec_duplicate:PRED_ALL (match_operand 1 "register_operand")))]
    701   "TARGET_SVE"
    702   {
    703     rtx tmp = gen_reg_rtx (DImode);
    704     rtx op1 = gen_lowpart (DImode, operands[1]);
    705     emit_insn (gen_ashldi3 (tmp, op1, gen_int_mode (63, DImode)));
    706     emit_insn (gen_while_ultdi<mode> (operands[0], const0_rtx, tmp));
    707     DONE;
    708   }
    709 )
    710 
    711 (define_insn "vec_series<mode>"
    712   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, w")
    713 	(vec_series:SVE_I
    714 	  (match_operand:<VEL> 1 "aarch64_sve_index_operand" "Usi, r, r")
    715 	  (match_operand:<VEL> 2 "aarch64_sve_index_operand" "r, Usi, r")))]
    716   "TARGET_SVE"
    717   "@
    718    index\t%0.<Vetype>, #%1, %<vw>2
    719    index\t%0.<Vetype>, %<vw>1, #%2
    720    index\t%0.<Vetype>, %<vw>1, %<vw>2"
    721 )
    722 
    723 ;; Optimize {x, x, x, x, ...} + {0, n, 2*n, 3*n, ...} if n is in range
    724 ;; of an INDEX instruction.
    725 (define_insn "*vec_series<mode>_plus"
    726   [(set (match_operand:SVE_I 0 "register_operand" "=w")
    727 	(plus:SVE_I
    728 	  (vec_duplicate:SVE_I
    729 	    (match_operand:<VEL> 1 "register_operand" "r"))
    730 	  (match_operand:SVE_I 2 "immediate_operand")))]
    731   "TARGET_SVE && aarch64_check_zero_based_sve_index_immediate (operands[2])"
    732   {
    733     operands[2] = aarch64_check_zero_based_sve_index_immediate (operands[2]);
    734     return "index\t%0.<Vetype>, %<vw>1, #%2";
    735   }
    736 )
    737 
    738 ;; Unpredicated LD[234].
    739 (define_expand "vec_load_lanes<mode><vsingle>"
    740   [(set (match_operand:SVE_STRUCT 0 "register_operand")
    741 	(unspec:SVE_STRUCT
    742 	  [(match_dup 2)
    743 	   (match_operand:SVE_STRUCT 1 "memory_operand")]
    744 	  UNSPEC_LDN))]
    745   "TARGET_SVE"
    746   {
    747     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
    748   }
    749 )
    750 
    751 ;; Predicated LD[234].
    752 (define_insn "vec_mask_load_lanes<mode><vsingle>"
    753   [(set (match_operand:SVE_STRUCT 0 "register_operand" "=w")
    754 	(unspec:SVE_STRUCT
    755 	  [(match_operand:<VPRED> 2 "register_operand" "Upl")
    756 	   (match_operand:SVE_STRUCT 1 "memory_operand" "m")]
    757 	  UNSPEC_LDN))]
    758   "TARGET_SVE"
    759   "ld<vector_count><Vesize>\t%0, %2/z, %1"
    760 )
    761 
    762 ;; Unpredicated ST[234].  This is always a full update, so the dependence
    763 ;; on the old value of the memory location (via (match_dup 0)) is redundant.
    764 ;; There doesn't seem to be any obvious benefit to treating the all-true
    765 ;; case differently though.  In particular, it's very unlikely that we'll
    766 ;; only find out during RTL that a store_lanes is dead.
    767 (define_expand "vec_store_lanes<mode><vsingle>"
    768   [(set (match_operand:SVE_STRUCT 0 "memory_operand")
    769 	(unspec:SVE_STRUCT
    770 	  [(match_dup 2)
    771 	   (match_operand:SVE_STRUCT 1 "register_operand")
    772 	   (match_dup 0)]
    773 	  UNSPEC_STN))]
    774   "TARGET_SVE"
    775   {
    776     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
    777   }
    778 )
    779 
    780 ;; Predicated ST[234].
    781 (define_insn "vec_mask_store_lanes<mode><vsingle>"
    782   [(set (match_operand:SVE_STRUCT 0 "memory_operand" "+m")
    783 	(unspec:SVE_STRUCT
    784 	  [(match_operand:<VPRED> 2 "register_operand" "Upl")
    785 	   (match_operand:SVE_STRUCT 1 "register_operand" "w")
    786 	   (match_dup 0)]
    787 	  UNSPEC_STN))]
    788   "TARGET_SVE"
    789   "st<vector_count><Vesize>\t%1, %2, %0"
    790 )
    791 
    792 (define_expand "vec_perm<mode>"
    793   [(match_operand:SVE_ALL 0 "register_operand")
    794    (match_operand:SVE_ALL 1 "register_operand")
    795    (match_operand:SVE_ALL 2 "register_operand")
    796    (match_operand:<V_INT_EQUIV> 3 "aarch64_sve_vec_perm_operand")]
    797   "TARGET_SVE && GET_MODE_NUNITS (<MODE>mode).is_constant ()"
    798   {
    799     aarch64_expand_sve_vec_perm (operands[0], operands[1],
    800 				 operands[2], operands[3]);
    801     DONE;
    802   }
    803 )
    804 
    805 (define_insn "*aarch64_sve_tbl<mode>"
    806   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
    807 	(unspec:SVE_ALL
    808 	  [(match_operand:SVE_ALL 1 "register_operand" "w")
    809 	   (match_operand:<V_INT_EQUIV> 2 "register_operand" "w")]
    810 	  UNSPEC_TBL))]
    811   "TARGET_SVE"
    812   "tbl\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
    813 )
    814 
    815 (define_insn "*aarch64_sve_<perm_insn><perm_hilo><mode>"
    816   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
    817 	(unspec:PRED_ALL [(match_operand:PRED_ALL 1 "register_operand" "Upa")
    818 			  (match_operand:PRED_ALL 2 "register_operand" "Upa")]
    819 			 PERMUTE))]
    820   "TARGET_SVE"
    821   "<perm_insn><perm_hilo>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
    822 )
    823 
    824 (define_insn "aarch64_sve_<perm_insn><perm_hilo><mode>"
    825   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
    826 	(unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "w")
    827 			 (match_operand:SVE_ALL 2 "register_operand" "w")]
    828 			PERMUTE))]
    829   "TARGET_SVE"
    830   "<perm_insn><perm_hilo>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
    831 )
    832 
    833 (define_insn "*aarch64_sve_rev64<mode>"
    834   [(set (match_operand:SVE_BHS 0 "register_operand" "=w")
    835 	(unspec:SVE_BHS
    836 	  [(match_operand:VNx2BI 1 "register_operand" "Upl")
    837 	   (unspec:SVE_BHS [(match_operand:SVE_BHS 2 "register_operand" "w")]
    838 			   UNSPEC_REV64)]
    839 	  UNSPEC_MERGE_PTRUE))]
    840   "TARGET_SVE"
    841   "rev<Vesize>\t%0.d, %1/m, %2.d"
    842 )
    843 
    844 (define_insn "*aarch64_sve_rev32<mode>"
    845   [(set (match_operand:SVE_BH 0 "register_operand" "=w")
    846 	(unspec:SVE_BH
    847 	  [(match_operand:VNx4BI 1 "register_operand" "Upl")
    848 	   (unspec:SVE_BH [(match_operand:SVE_BH 2 "register_operand" "w")]
    849 			  UNSPEC_REV32)]
    850 	  UNSPEC_MERGE_PTRUE))]
    851   "TARGET_SVE"
    852   "rev<Vesize>\t%0.s, %1/m, %2.s"
    853 )
    854 
    855 (define_insn "*aarch64_sve_rev16vnx16qi"
    856   [(set (match_operand:VNx16QI 0 "register_operand" "=w")
    857 	(unspec:VNx16QI
    858 	  [(match_operand:VNx8BI 1 "register_operand" "Upl")
    859 	   (unspec:VNx16QI [(match_operand:VNx16QI 2 "register_operand" "w")]
    860 			   UNSPEC_REV16)]
    861 	  UNSPEC_MERGE_PTRUE))]
    862   "TARGET_SVE"
    863   "revb\t%0.h, %1/m, %2.h"
    864 )
    865 
    866 (define_insn "*aarch64_sve_rev<mode>"
    867   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
    868 	(unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "w")]
    869 			UNSPEC_REV))]
    870   "TARGET_SVE"
    871   "rev\t%0.<Vetype>, %1.<Vetype>")
    872 
    873 (define_insn "*aarch64_sve_dup_lane<mode>"
    874   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
    875 	(vec_duplicate:SVE_ALL
    876 	  (vec_select:<VEL>
    877 	    (match_operand:SVE_ALL 1 "register_operand" "w")
    878 	    (parallel [(match_operand:SI 2 "const_int_operand")]))))]
    879   "TARGET_SVE
    880    && IN_RANGE (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode), 0, 63)"
    881   "dup\t%0.<Vetype>, %1.<Vetype>[%2]"
    882 )
    883 
    884 ;; Note that the immediate (third) operand is the lane index not
    885 ;; the byte index.
    886 (define_insn "*aarch64_sve_ext<mode>"
    887   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
    888 	(unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "0")
    889 			 (match_operand:SVE_ALL 2 "register_operand" "w")
    890 			 (match_operand:SI 3 "const_int_operand")]
    891 			UNSPEC_EXT))]
    892   "TARGET_SVE
    893    && IN_RANGE (INTVAL (operands[3]) * GET_MODE_SIZE (<VEL>mode), 0, 255)"
    894   {
    895     operands[3] = GEN_INT (INTVAL (operands[3]) * GET_MODE_SIZE (<VEL>mode));
    896     return "ext\\t%0.b, %0.b, %2.b, #%3";
    897   }
    898 )
    899 
    900 (define_insn "add<mode>3"
    901   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, w, w")
    902 	(plus:SVE_I
    903 	  (match_operand:SVE_I 1 "register_operand" "%0, 0, 0, w")
    904 	  (match_operand:SVE_I 2 "aarch64_sve_add_operand" "vsa, vsn, vsi, w")))]
    905   "TARGET_SVE"
    906   "@
    907    add\t%0.<Vetype>, %0.<Vetype>, #%D2
    908    sub\t%0.<Vetype>, %0.<Vetype>, #%N2
    909    * return aarch64_output_sve_inc_dec_immediate (\"%0.<Vetype>\", operands[2]);
    910    add\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
    911 )
    912 
    913 (define_insn "sub<mode>3"
    914   [(set (match_operand:SVE_I 0 "register_operand" "=w, w")
    915 	(minus:SVE_I
    916 	  (match_operand:SVE_I 1 "aarch64_sve_arith_operand" "w, vsa")
    917 	  (match_operand:SVE_I 2 "register_operand" "w, 0")))]
    918   "TARGET_SVE"
    919   "@
    920    sub\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>
    921    subr\t%0.<Vetype>, %0.<Vetype>, #%D1"
    922 )
    923 
    924 ;; Unpredicated multiplication.
    925 (define_expand "mul<mode>3"
    926   [(set (match_operand:SVE_I 0 "register_operand")
    927 	(unspec:SVE_I
    928 	  [(match_dup 3)
    929 	   (mult:SVE_I
    930 	     (match_operand:SVE_I 1 "register_operand")
    931 	     (match_operand:SVE_I 2 "aarch64_sve_mul_operand"))]
    932 	  UNSPEC_MERGE_PTRUE))]
    933   "TARGET_SVE"
    934   {
    935     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
    936   }
    937 )
    938 
    939 ;; Multiplication predicated with a PTRUE.  We don't actually need the
    940 ;; predicate for the first alternative, but using Upa or X isn't likely
    941 ;; to gain much and would make the instruction seem less uniform to the
    942 ;; register allocator.
    943 (define_insn_and_split "*mul<mode>3"
    944   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w")
    945 	(unspec:SVE_I
    946 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
    947 	   (mult:SVE_I
    948 	     (match_operand:SVE_I 2 "register_operand" "%0, 0, w")
    949 	     (match_operand:SVE_I 3 "aarch64_sve_mul_operand" "vsm, w, w"))]
    950 	  UNSPEC_MERGE_PTRUE))]
    951   "TARGET_SVE"
    952   "@
    953    #
    954    mul\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
    955    movprfx\t%0, %2\;mul\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
    956   ; Split the unpredicated form after reload, so that we don't have
    957   ; the unnecessary PTRUE.
    958   "&& reload_completed
    959    && !register_operand (operands[3], <MODE>mode)"
    960   [(set (match_dup 0) (mult:SVE_I (match_dup 2) (match_dup 3)))]
    961   ""
    962   [(set_attr "movprfx" "*,*,yes")]
    963 )
    964 
    965 ;; Unpredicated multiplications by a constant (post-RA only).
    966 ;; These are generated by splitting a predicated instruction whose
    967 ;; predicate is unused.
    968 (define_insn "*post_ra_mul<mode>3"
    969   [(set (match_operand:SVE_I 0 "register_operand" "=w")
    970 	(mult:SVE_I
    971 	  (match_operand:SVE_I 1 "register_operand" "0")
    972 	  (match_operand:SVE_I 2 "aarch64_sve_mul_immediate")))]
    973   "TARGET_SVE && reload_completed"
    974   "mul\t%0.<Vetype>, %0.<Vetype>, #%2"
    975 )
    976 
    977 (define_insn "*madd<mode>"
    978   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w")
    979 	(plus:SVE_I
    980 	  (unspec:SVE_I
    981 	    [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
    982 	     (mult:SVE_I (match_operand:SVE_I 2 "register_operand" "%0, w, w")
    983 			 (match_operand:SVE_I 3 "register_operand" "w, w, w"))]
    984 	    UNSPEC_MERGE_PTRUE)
    985 	  (match_operand:SVE_I 4 "register_operand" "w, 0, w")))]
    986   "TARGET_SVE"
    987   "@
    988    mad\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
    989    mla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
    990    movprfx\t%0, %4\;mla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>"
    991   [(set_attr "movprfx" "*,*,yes")]
    992 )
    993 
    994 (define_insn "*msub<mode>3"
    995   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w")
    996 	(minus:SVE_I
    997 	  (match_operand:SVE_I 4 "register_operand" "w, 0, w")
    998 	  (unspec:SVE_I
    999 	    [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   1000 	     (mult:SVE_I (match_operand:SVE_I 2 "register_operand" "%0, w, w")
   1001 			 (match_operand:SVE_I 3 "register_operand" "w, w, w"))]
   1002 	    UNSPEC_MERGE_PTRUE)))]
   1003   "TARGET_SVE"
   1004   "@
   1005    msb\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   1006    mls\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   1007    movprfx\t%0, %4\;mls\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>"
   1008   [(set_attr "movprfx" "*,*,yes")]
   1009 )
   1010 
   1011 ;; Unpredicated highpart multiplication.
   1012 (define_expand "<su>mul<mode>3_highpart"
   1013   [(set (match_operand:SVE_I 0 "register_operand")
   1014 	(unspec:SVE_I
   1015 	  [(match_dup 3)
   1016 	   (unspec:SVE_I [(match_operand:SVE_I 1 "register_operand")
   1017 			  (match_operand:SVE_I 2 "register_operand")]
   1018 			 MUL_HIGHPART)]
   1019 	  UNSPEC_MERGE_PTRUE))]
   1020   "TARGET_SVE"
   1021   {
   1022     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   1023   }
   1024 )
   1025 
   1026 ;; Predicated highpart multiplication.
   1027 (define_insn "*<su>mul<mode>3_highpart"
   1028   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
   1029 	(unspec:SVE_I
   1030 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1031 	   (unspec:SVE_I [(match_operand:SVE_I 2 "register_operand" "%0, w")
   1032 			  (match_operand:SVE_I 3 "register_operand" "w, w")]
   1033 			 MUL_HIGHPART)]
   1034 	  UNSPEC_MERGE_PTRUE))]
   1035   "TARGET_SVE"
   1036   "@
   1037    <su>mulh\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1038    movprfx\t%0, %2\;<su>mulh\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1039   [(set_attr "movprfx" "*,yes")]
   1040 )
   1041 
   1042 ;; Unpredicated division.
   1043 (define_expand "<optab><mode>3"
   1044   [(set (match_operand:SVE_SDI 0 "register_operand")
   1045 	(unspec:SVE_SDI
   1046 	  [(match_dup 3)
   1047 	   (SVE_INT_BINARY_SD:SVE_SDI
   1048 	     (match_operand:SVE_SDI 1 "register_operand")
   1049 	     (match_operand:SVE_SDI 2 "register_operand"))]
   1050 	  UNSPEC_MERGE_PTRUE))]
   1051   "TARGET_SVE"
   1052   {
   1053     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   1054   }
   1055 )
   1056 
   1057 ;; Division predicated with a PTRUE.
   1058 (define_insn "*<optab><mode>3"
   1059   [(set (match_operand:SVE_SDI 0 "register_operand" "=w, w, ?&w")
   1060 	(unspec:SVE_SDI
   1061 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   1062 	   (SVE_INT_BINARY_SD:SVE_SDI
   1063 	     (match_operand:SVE_SDI 2 "register_operand" "0, w, w")
   1064 	     (match_operand:SVE_SDI 3 "aarch64_sve_mul_operand" "w, 0, w"))]
   1065 	  UNSPEC_MERGE_PTRUE))]
   1066   "TARGET_SVE"
   1067   "@
   1068    <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1069    <sve_int_op>r\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   1070    movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1071   [(set_attr "movprfx" "*,*,yes")]
   1072 )
   1073 
   1074 ;; Unpredicated NEG, NOT and POPCOUNT.
   1075 (define_expand "<optab><mode>2"
   1076   [(set (match_operand:SVE_I 0 "register_operand")
   1077 	(unspec:SVE_I
   1078 	  [(match_dup 2)
   1079 	   (SVE_INT_UNARY:SVE_I (match_operand:SVE_I 1 "register_operand"))]
   1080 	  UNSPEC_MERGE_PTRUE))]
   1081   "TARGET_SVE"
   1082   {
   1083     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   1084   }
   1085 )
   1086 
   1087 ;; NEG, NOT and POPCOUNT predicated with a PTRUE.
   1088 (define_insn "*<optab><mode>2"
   1089   [(set (match_operand:SVE_I 0 "register_operand" "=w")
   1090 	(unspec:SVE_I
   1091 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   1092 	   (SVE_INT_UNARY:SVE_I
   1093 	     (match_operand:SVE_I 2 "register_operand" "w"))]
   1094 	  UNSPEC_MERGE_PTRUE))]
   1095   "TARGET_SVE"
   1096   "<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
   1097 )
   1098 
   1099 ;; Vector AND, ORR and XOR.
   1100 (define_insn "<optab><mode>3"
   1101   [(set (match_operand:SVE_I 0 "register_operand" "=w, w")
   1102 	(LOGICAL:SVE_I
   1103 	  (match_operand:SVE_I 1 "register_operand" "%0, w")
   1104 	  (match_operand:SVE_I 2 "aarch64_sve_logical_operand" "vsl, w")))]
   1105   "TARGET_SVE"
   1106   "@
   1107    <logical>\t%0.<Vetype>, %0.<Vetype>, #%C2
   1108    <logical>\t%0.d, %1.d, %2.d"
   1109 )
   1110 
   1111 ;; Vector AND, ORR and XOR on floating-point modes.  We avoid subregs
   1112 ;; by providing this, but we need to use UNSPECs since rtx logical ops
   1113 ;; aren't defined for floating-point modes.
   1114 (define_insn "*<optab><mode>3"
   1115   [(set (match_operand:SVE_F 0 "register_operand" "=w")
   1116 	(unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "w")
   1117 		       (match_operand:SVE_F 2 "register_operand" "w")]
   1118 		      LOGICALF))]
   1119   "TARGET_SVE"
   1120   "<logicalf_op>\t%0.d, %1.d, %2.d"
   1121 )
   1122 
   1123 ;; REG_EQUAL notes on "not<mode>3" should ensure that we can generate
   1124 ;; this pattern even though the NOT instruction itself is predicated.
   1125 (define_insn "bic<mode>3"
   1126   [(set (match_operand:SVE_I 0 "register_operand" "=w")
   1127 	(and:SVE_I
   1128 	  (not:SVE_I (match_operand:SVE_I 1 "register_operand" "w"))
   1129 	  (match_operand:SVE_I 2 "register_operand" "w")))]
   1130   "TARGET_SVE"
   1131   "bic\t%0.d, %2.d, %1.d"
   1132 )
   1133 
   1134 ;; Predicate AND.  We can reuse one of the inputs as the GP.
   1135 (define_insn "and<mode>3"
   1136   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
   1137 	(and:PRED_ALL (match_operand:PRED_ALL 1 "register_operand" "Upa")
   1138 		      (match_operand:PRED_ALL 2 "register_operand" "Upa")))]
   1139   "TARGET_SVE"
   1140   "and\t%0.b, %1/z, %1.b, %2.b"
   1141 )
   1142 
   1143 ;; Unpredicated predicate ORR and XOR.
   1144 (define_expand "<optab><mode>3"
   1145   [(set (match_operand:PRED_ALL 0 "register_operand")
   1146 	(and:PRED_ALL
   1147 	  (LOGICAL_OR:PRED_ALL
   1148 	    (match_operand:PRED_ALL 1 "register_operand")
   1149 	    (match_operand:PRED_ALL 2 "register_operand"))
   1150 	  (match_dup 3)))]
   1151   "TARGET_SVE"
   1152   {
   1153     operands[3] = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
   1154   }
   1155 )
   1156 
   1157 ;; Predicated predicate ORR and XOR.
   1158 (define_insn "pred_<optab><mode>3"
   1159   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
   1160 	(and:PRED_ALL
   1161 	  (LOGICAL:PRED_ALL
   1162 	    (match_operand:PRED_ALL 2 "register_operand" "Upa")
   1163 	    (match_operand:PRED_ALL 3 "register_operand" "Upa"))
   1164 	  (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
   1165   "TARGET_SVE"
   1166   "<logical>\t%0.b, %1/z, %2.b, %3.b"
   1167 )
   1168 
   1169 ;; Perform a logical operation on operands 2 and 3, using operand 1 as
   1170 ;; the GP (which is known to be a PTRUE).  Store the result in operand 0
   1171 ;; and set the flags in the same way as for PTEST.  The (and ...) in the
   1172 ;; UNSPEC_PTEST_PTRUE is logically redundant, but means that the tested
   1173 ;; value is structurally equivalent to rhs of the second set.
   1174 (define_insn "*<optab><mode>3_cc"
   1175   [(set (reg:CC CC_REGNUM)
   1176 	(compare:CC
   1177 	  (unspec:SI [(match_operand:PRED_ALL 1 "register_operand" "Upa")
   1178 		      (and:PRED_ALL
   1179 			(LOGICAL:PRED_ALL
   1180 			  (match_operand:PRED_ALL 2 "register_operand" "Upa")
   1181 			  (match_operand:PRED_ALL 3 "register_operand" "Upa"))
   1182 			(match_dup 1))]
   1183 		     UNSPEC_PTEST_PTRUE)
   1184 	  (const_int 0)))
   1185    (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
   1186 	(and:PRED_ALL (LOGICAL:PRED_ALL (match_dup 2) (match_dup 3))
   1187 		      (match_dup 1)))]
   1188   "TARGET_SVE"
   1189   "<logical>s\t%0.b, %1/z, %2.b, %3.b"
   1190 )
   1191 
   1192 ;; Unpredicated predicate inverse.
   1193 (define_expand "one_cmpl<mode>2"
   1194   [(set (match_operand:PRED_ALL 0 "register_operand")
   1195 	(and:PRED_ALL
   1196 	  (not:PRED_ALL (match_operand:PRED_ALL 1 "register_operand"))
   1197 	  (match_dup 2)))]
   1198   "TARGET_SVE"
   1199   {
   1200     operands[2] = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
   1201   }
   1202 )
   1203 
   1204 ;; Predicated predicate inverse.
   1205 (define_insn "*one_cmpl<mode>3"
   1206   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
   1207 	(and:PRED_ALL
   1208 	  (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand" "Upa"))
   1209 	  (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
   1210   "TARGET_SVE"
   1211   "not\t%0.b, %1/z, %2.b"
   1212 )
   1213 
   1214 ;; Predicated predicate BIC and ORN.
   1215 (define_insn "*<nlogical><mode>3"
   1216   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
   1217 	(and:PRED_ALL
   1218 	  (NLOGICAL:PRED_ALL
   1219 	    (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand" "Upa"))
   1220 	    (match_operand:PRED_ALL 3 "register_operand" "Upa"))
   1221 	  (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
   1222   "TARGET_SVE"
   1223   "<nlogical>\t%0.b, %1/z, %3.b, %2.b"
   1224 )
   1225 
   1226 ;; Predicated predicate NAND and NOR.
   1227 (define_insn "*<logical_nn><mode>3"
   1228   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
   1229 	(and:PRED_ALL
   1230 	  (NLOGICAL:PRED_ALL
   1231 	    (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand" "Upa"))
   1232 	    (not:PRED_ALL (match_operand:PRED_ALL 3 "register_operand" "Upa")))
   1233 	  (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
   1234   "TARGET_SVE"
   1235   "<logical_nn>\t%0.b, %1/z, %2.b, %3.b"
   1236 )
   1237 
   1238 ;; Unpredicated LSL, LSR and ASR by a vector.
   1239 (define_expand "v<optab><mode>3"
   1240   [(set (match_operand:SVE_I 0 "register_operand")
   1241 	(unspec:SVE_I
   1242 	  [(match_dup 3)
   1243 	   (ASHIFT:SVE_I
   1244 	     (match_operand:SVE_I 1 "register_operand")
   1245 	     (match_operand:SVE_I 2 "aarch64_sve_<lr>shift_operand"))]
   1246 	  UNSPEC_MERGE_PTRUE))]
   1247   "TARGET_SVE"
   1248   {
   1249     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   1250   }
   1251 )
   1252 
   1253 ;; LSL, LSR and ASR by a vector, predicated with a PTRUE.  We don't
   1254 ;; actually need the predicate for the first alternative, but using Upa
   1255 ;; or X isn't likely to gain much and would make the instruction seem
   1256 ;; less uniform to the register allocator.
   1257 (define_insn_and_split "*v<optab><mode>3"
   1258   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w")
   1259 	(unspec:SVE_I
   1260 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   1261 	   (ASHIFT:SVE_I
   1262 	     (match_operand:SVE_I 2 "register_operand" "w, 0, w")
   1263 	     (match_operand:SVE_I 3 "aarch64_sve_<lr>shift_operand" "D<lr>, w, w"))]
   1264 	  UNSPEC_MERGE_PTRUE))]
   1265   "TARGET_SVE"
   1266   "@
   1267    #
   1268    <shift>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1269    movprfx\t%0, %2\;<shift>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1270   "&& reload_completed
   1271    && !register_operand (operands[3], <MODE>mode)"
   1272   [(set (match_dup 0) (ASHIFT:SVE_I (match_dup 2) (match_dup 3)))]
   1273   ""
   1274   [(set_attr "movprfx" "*,*,yes")]
   1275 )
   1276 
   1277 ;; Unpredicated shift operations by a constant (post-RA only).
   1278 ;; These are generated by splitting a predicated instruction whose
   1279 ;; predicate is unused.
   1280 (define_insn "*post_ra_v<optab><mode>3"
   1281   [(set (match_operand:SVE_I 0 "register_operand" "=w")
   1282 	(ASHIFT:SVE_I
   1283 	  (match_operand:SVE_I 1 "register_operand" "w")
   1284 	  (match_operand:SVE_I 2 "aarch64_simd_<lr>shift_imm")))]
   1285   "TARGET_SVE && reload_completed"
   1286   "<shift>\t%0.<Vetype>, %1.<Vetype>, #%2"
   1287 )
   1288 
   1289 ;; LSL, LSR and ASR by a scalar, which expands into one of the vector
   1290 ;; shifts above.
   1291 (define_expand "<ASHIFT:optab><mode>3"
   1292   [(set (match_operand:SVE_I 0 "register_operand")
   1293 	(ASHIFT:SVE_I (match_operand:SVE_I 1 "register_operand")
   1294 		      (match_operand:<VEL> 2 "general_operand")))]
   1295   "TARGET_SVE"
   1296   {
   1297     rtx amount;
   1298     if (CONST_INT_P (operands[2]))
   1299       {
   1300 	amount = gen_const_vec_duplicate (<MODE>mode, operands[2]);
   1301 	if (!aarch64_sve_<lr>shift_operand (operands[2], <MODE>mode))
   1302 	  amount = force_reg (<MODE>mode, amount);
   1303       }
   1304     else
   1305       {
   1306 	amount = gen_reg_rtx (<MODE>mode);
   1307 	emit_insn (gen_vec_duplicate<mode> (amount,
   1308 					    convert_to_mode (<VEL>mode,
   1309 							     operands[2], 0)));
   1310       }
   1311     emit_insn (gen_v<optab><mode>3 (operands[0], operands[1], amount));
   1312     DONE;
   1313   }
   1314 )
   1315 
   1316 ;; Test all bits of operand 1.  Operand 0 is a GP that is known to hold PTRUE.
   1317 ;;
   1318 ;; Using UNSPEC_PTEST_PTRUE allows combine patterns to assume that the GP
   1319 ;; is a PTRUE even if the optimizers haven't yet been able to propagate
   1320 ;; the constant.  We would use a separate unspec code for PTESTs involving
   1321 ;; GPs that might not be PTRUEs.
   1322 (define_insn "ptest_ptrue<mode>"
   1323   [(set (reg:CC CC_REGNUM)
   1324 	(compare:CC
   1325 	  (unspec:SI [(match_operand:PRED_ALL 0 "register_operand" "Upa")
   1326 		      (match_operand:PRED_ALL 1 "register_operand" "Upa")]
   1327 		     UNSPEC_PTEST_PTRUE)
   1328 	  (const_int 0)))]
   1329   "TARGET_SVE"
   1330   "ptest\t%0, %1.b"
   1331 )
   1332 
   1333 ;; Set element I of the result if operand1 + J < operand2 for all J in [0, I].
   1334 ;; with the comparison being unsigned.
   1335 (define_insn "while_ult<GPI:mode><PRED_ALL:mode>"
   1336   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
   1337 	(unspec:PRED_ALL [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
   1338 			  (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
   1339 			 UNSPEC_WHILE_LO))
   1340    (clobber (reg:CC CC_REGNUM))]
   1341   "TARGET_SVE"
   1342   "whilelo\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
   1343 )
   1344 
   1345 ;; WHILELO sets the flags in the same way as a PTEST with a PTRUE GP.
   1346 ;; Handle the case in which both results are useful.  The GP operand
   1347 ;; to the PTEST isn't needed, so we allow it to be anything.
   1348 (define_insn_and_split "while_ult<GPI:mode><PRED_ALL:mode>_cc"
   1349   [(set (reg:CC CC_REGNUM)
   1350 	(compare:CC
   1351 	  (unspec:SI [(match_operand:PRED_ALL 1)
   1352 		      (unspec:PRED_ALL
   1353 			[(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")
   1354 			 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")]
   1355 			UNSPEC_WHILE_LO)]
   1356 		     UNSPEC_PTEST_PTRUE)
   1357 	  (const_int 0)))
   1358    (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
   1359 	(unspec:PRED_ALL [(match_dup 2)
   1360 			  (match_dup 3)]
   1361 			 UNSPEC_WHILE_LO))]
   1362   "TARGET_SVE"
   1363   "whilelo\t%0.<PRED_ALL:Vetype>, %<w>2, %<w>3"
   1364   ;; Force the compiler to drop the unused predicate operand, so that we
   1365   ;; don't have an unnecessary PTRUE.
   1366   "&& !CONSTANT_P (operands[1])"
   1367   [(const_int 0)]
   1368   {
   1369     emit_insn (gen_while_ult<GPI:mode><PRED_ALL:mode>_cc
   1370 	       (operands[0], CONSTM1_RTX (<MODE>mode),
   1371 		operands[2], operands[3]));
   1372     DONE;
   1373   }
   1374 )
   1375 
   1376 ;; Integer comparisons predicated with a PTRUE.
   1377 (define_insn "*cmp<cmp_op><mode>"
   1378   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
   1379 	(unspec:<VPRED>
   1380 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1381 	   (SVE_INT_CMP:<VPRED>
   1382 	     (match_operand:SVE_I 2 "register_operand" "w, w")
   1383 	     (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
   1384 	  UNSPEC_MERGE_PTRUE))
   1385    (clobber (reg:CC CC_REGNUM))]
   1386   "TARGET_SVE"
   1387   "@
   1388    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
   1389    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1390 )
   1391 
   1392 ;; Integer comparisons predicated with a PTRUE in which only the flags result
   1393 ;; is interesting.
   1394 (define_insn "*cmp<cmp_op><mode>_ptest"
   1395   [(set (reg:CC CC_REGNUM)
   1396 	(compare:CC
   1397 	  (unspec:SI
   1398 	    [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1399 	     (unspec:<VPRED>
   1400 	       [(match_dup 1)
   1401 		(SVE_INT_CMP:<VPRED>
   1402 		  (match_operand:SVE_I 2 "register_operand" "w, w")
   1403 		  (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
   1404 	       UNSPEC_MERGE_PTRUE)]
   1405 	    UNSPEC_PTEST_PTRUE)
   1406 	  (const_int 0)))
   1407    (clobber (match_scratch:<VPRED> 0 "=Upa, Upa"))]
   1408   "TARGET_SVE"
   1409   "@
   1410    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
   1411    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1412 )
   1413 
   1414 ;; Integer comparisons predicated with a PTRUE in which both the flag and
   1415 ;; predicate results are interesting.
   1416 (define_insn "*cmp<cmp_op><mode>_cc"
   1417   [(set (reg:CC CC_REGNUM)
   1418 	(compare:CC
   1419 	  (unspec:SI
   1420 	    [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1421 	     (unspec:<VPRED>
   1422 	       [(match_dup 1)
   1423 		(SVE_INT_CMP:<VPRED>
   1424 		  (match_operand:SVE_I 2 "register_operand" "w, w")
   1425 		  (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
   1426 	       UNSPEC_MERGE_PTRUE)]
   1427 	    UNSPEC_PTEST_PTRUE)
   1428 	  (const_int 0)))
   1429    (set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
   1430 	(unspec:<VPRED>
   1431 	  [(match_dup 1)
   1432 	   (SVE_INT_CMP:<VPRED>
   1433 	     (match_dup 2)
   1434 	     (match_dup 3))]
   1435 	  UNSPEC_MERGE_PTRUE))]
   1436   "TARGET_SVE"
   1437   "@
   1438    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
   1439    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1440 )
   1441 
   1442 ;; Predicated integer comparisons, formed by combining a PTRUE-predicated
   1443 ;; comparison with an AND.  Split the instruction into its preferred form
   1444 ;; (below) at the earliest opportunity, in order to get rid of the
   1445 ;; redundant operand 1.
   1446 (define_insn_and_split "*pred_cmp<cmp_op><mode>_combine"
   1447   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
   1448        (and:<VPRED>
   1449          (unspec:<VPRED>
   1450            [(match_operand:<VPRED> 1)
   1451             (SVE_INT_CMP:<VPRED>
   1452               (match_operand:SVE_I 2 "register_operand" "w, w")
   1453               (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
   1454            UNSPEC_MERGE_PTRUE)
   1455          (match_operand:<VPRED> 4 "register_operand" "Upl, Upl")))
   1456    (clobber (reg:CC CC_REGNUM))]
   1457   "TARGET_SVE"
   1458   "#"
   1459   "&& 1"
   1460   [(parallel
   1461      [(set (match_dup 0)
   1462           (and:<VPRED>
   1463             (SVE_INT_CMP:<VPRED>
   1464               (match_dup 2)
   1465               (match_dup 3))
   1466             (match_dup 4)))
   1467       (clobber (reg:CC CC_REGNUM))])]
   1468 )
   1469 
   1470 ;; Predicated integer comparisons.
   1471 (define_insn "*pred_cmp<cmp_op><mode>"
   1472   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
   1473 	(and:<VPRED>
   1474 	  (SVE_INT_CMP:<VPRED>
   1475 	    (match_operand:SVE_I 2 "register_operand" "w, w")
   1476 	    (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))
   1477 	  (match_operand:<VPRED> 1 "register_operand" "Upl, Upl")))
   1478    (clobber (reg:CC CC_REGNUM))]
   1479   "TARGET_SVE"
   1480   "@
   1481    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
   1482    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1483 )
   1484 
   1485 ;; Floating-point comparisons predicated with a PTRUE.
   1486 (define_insn "*fcm<cmp_op><mode>"
   1487   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
   1488 	(unspec:<VPRED>
   1489 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1490 	   (SVE_FP_CMP:<VPRED>
   1491 	     (match_operand:SVE_F 2 "register_operand" "w, w")
   1492 	     (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w"))]
   1493 	  UNSPEC_MERGE_PTRUE))]
   1494   "TARGET_SVE"
   1495   "@
   1496    fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #0.0
   1497    fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1498 )
   1499 
   1500 (define_insn "*fcmuo<mode>"
   1501   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
   1502 	(unspec:<VPRED>
   1503 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   1504 	   (unordered:<VPRED>
   1505 	     (match_operand:SVE_F 2 "register_operand" "w")
   1506 	     (match_operand:SVE_F 3 "register_operand" "w"))]
   1507 	  UNSPEC_MERGE_PTRUE))]
   1508   "TARGET_SVE"
   1509   "fcmuo\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1510 )
   1511 
   1512 ;; Floating-point comparisons predicated on a PTRUE, with the results ANDed
   1513 ;; with another predicate P.  This does not have the same trapping behavior
   1514 ;; as predicating the comparison itself on P, but it's a legitimate fold,
   1515 ;; since we can drop any potentially-trapping operations whose results
   1516 ;; are not needed.
   1517 ;;
   1518 ;; Split the instruction into its preferred form (below) at the earliest
   1519 ;; opportunity, in order to get rid of the redundant operand 1.
   1520 (define_insn_and_split "*fcm<cmp_op><mode>_and_combine"
   1521   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
   1522 	(and:<VPRED>
   1523 	  (unspec:<VPRED>
   1524 	    [(match_operand:<VPRED> 1)
   1525 	     (SVE_FP_CMP
   1526 	       (match_operand:SVE_F 2 "register_operand" "w, w")
   1527 	       (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w"))]
   1528 	    UNSPEC_MERGE_PTRUE)
   1529 	  (match_operand:<VPRED> 4 "register_operand" "Upl, Upl")))]
   1530   "TARGET_SVE"
   1531   "#"
   1532   "&& 1"
   1533   [(set (match_dup 0)
   1534 	(and:<VPRED>
   1535 	  (SVE_FP_CMP:<VPRED>
   1536 	    (match_dup 2)
   1537 	    (match_dup 3))
   1538 	  (match_dup 4)))]
   1539 )
   1540 
   1541 (define_insn_and_split "*fcmuo<mode>_and_combine"
   1542   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
   1543 	(and:<VPRED>
   1544 	  (unspec:<VPRED>
   1545 	    [(match_operand:<VPRED> 1)
   1546 	     (unordered
   1547 	       (match_operand:SVE_F 2 "register_operand" "w")
   1548 	       (match_operand:SVE_F 3 "register_operand" "w"))]
   1549 	    UNSPEC_MERGE_PTRUE)
   1550 	  (match_operand:<VPRED> 4 "register_operand" "Upl")))]
   1551   "TARGET_SVE"
   1552   "#"
   1553   "&& 1"
   1554   [(set (match_dup 0)
   1555 	(and:<VPRED>
   1556 	  (unordered:<VPRED>
   1557 	    (match_dup 2)
   1558 	    (match_dup 3))
   1559 	  (match_dup 4)))]
   1560 )
   1561 
   1562 ;; Unpredicated floating-point comparisons, with the results ANDed
   1563 ;; with another predicate.  This is a valid fold for the same reasons
   1564 ;; as above.
   1565 (define_insn "*fcm<cmp_op><mode>_and"
   1566   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
   1567 	(and:<VPRED>
   1568 	  (SVE_FP_CMP:<VPRED>
   1569 	    (match_operand:SVE_F 2 "register_operand" "w, w")
   1570 	    (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w"))
   1571 	  (match_operand:<VPRED> 1 "register_operand" "Upl, Upl")))]
   1572   "TARGET_SVE"
   1573   "@
   1574    fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #0.0
   1575    fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1576 )
   1577 
   1578 (define_insn "*fcmuo<mode>_and"
   1579   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
   1580 	(and:<VPRED>
   1581 	  (unordered:<VPRED>
   1582 	    (match_operand:SVE_F 2 "register_operand" "w")
   1583 	    (match_operand:SVE_F 3 "register_operand" "w"))
   1584 	  (match_operand:<VPRED> 1 "register_operand" "Upl")))]
   1585   "TARGET_SVE"
   1586   "fcmuo\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1587 )
   1588 
   1589 ;; Predicated floating-point comparisons.  We don't need a version
   1590 ;; of this for unordered comparisons.
   1591 (define_insn "*pred_fcm<cmp_op><mode>"
   1592   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
   1593 	(unspec:<VPRED>
   1594 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1595 	   (match_operand:SVE_F 2 "register_operand" "w, w")
   1596 	   (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w")]
   1597 	  SVE_COND_FP_CMP))]
   1598   "TARGET_SVE"
   1599   "@
   1600    fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #0.0
   1601    fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
   1602 )
   1603 
   1604 ;; vcond_mask operand order: true, false, mask
   1605 ;; UNSPEC_SEL operand order: mask, true, false (as for VEC_COND_EXPR)
   1606 ;; SEL operand order:        mask, true, false
   1607 (define_insn "vcond_mask_<mode><vpred>"
   1608   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
   1609 	(unspec:SVE_ALL
   1610 	  [(match_operand:<VPRED> 3 "register_operand" "Upa")
   1611 	   (match_operand:SVE_ALL 1 "register_operand" "w")
   1612 	   (match_operand:SVE_ALL 2 "register_operand" "w")]
   1613 	  UNSPEC_SEL))]
   1614   "TARGET_SVE"
   1615   "sel\t%0.<Vetype>, %3, %1.<Vetype>, %2.<Vetype>"
   1616 )
   1617 
   1618 ;; Selects between a duplicated immediate and zero.
   1619 (define_insn "aarch64_sve_dup<mode>_const"
   1620   [(set (match_operand:SVE_I 0 "register_operand" "=w")
   1621 	(unspec:SVE_I
   1622 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   1623 	   (match_operand:SVE_I 2 "aarch64_sve_dup_immediate")
   1624 	   (match_operand:SVE_I 3 "aarch64_simd_imm_zero")]
   1625 	  UNSPEC_SEL))]
   1626   "TARGET_SVE"
   1627   "mov\t%0.<Vetype>, %1/z, #%2"
   1628 )
   1629 
   1630 ;; Integer (signed) vcond.  Don't enforce an immediate range here, since it
   1631 ;; depends on the comparison; leave it to aarch64_expand_sve_vcond instead.
   1632 (define_expand "vcond<mode><v_int_equiv>"
   1633   [(set (match_operand:SVE_ALL 0 "register_operand")
   1634 	(if_then_else:SVE_ALL
   1635 	  (match_operator 3 "comparison_operator"
   1636 	    [(match_operand:<V_INT_EQUIV> 4 "register_operand")
   1637 	     (match_operand:<V_INT_EQUIV> 5 "nonmemory_operand")])
   1638 	  (match_operand:SVE_ALL 1 "register_operand")
   1639 	  (match_operand:SVE_ALL 2 "register_operand")))]
   1640   "TARGET_SVE"
   1641   {
   1642     aarch64_expand_sve_vcond (<MODE>mode, <V_INT_EQUIV>mode, operands);
   1643     DONE;
   1644   }
   1645 )
   1646 
   1647 ;; Integer vcondu.  Don't enforce an immediate range here, since it
   1648 ;; depends on the comparison; leave it to aarch64_expand_sve_vcond instead.
   1649 (define_expand "vcondu<mode><v_int_equiv>"
   1650   [(set (match_operand:SVE_ALL 0 "register_operand")
   1651 	(if_then_else:SVE_ALL
   1652 	  (match_operator 3 "comparison_operator"
   1653 	    [(match_operand:<V_INT_EQUIV> 4 "register_operand")
   1654 	     (match_operand:<V_INT_EQUIV> 5 "nonmemory_operand")])
   1655 	  (match_operand:SVE_ALL 1 "register_operand")
   1656 	  (match_operand:SVE_ALL 2 "register_operand")))]
   1657   "TARGET_SVE"
   1658   {
   1659     aarch64_expand_sve_vcond (<MODE>mode, <V_INT_EQUIV>mode, operands);
   1660     DONE;
   1661   }
   1662 )
   1663 
   1664 ;; Floating-point vcond.  All comparisons except FCMUO allow a zero
   1665 ;; operand; aarch64_expand_sve_vcond handles the case of an FCMUO
   1666 ;; with zero.
   1667 (define_expand "vcond<mode><v_fp_equiv>"
   1668   [(set (match_operand:SVE_SD 0 "register_operand")
   1669 	(if_then_else:SVE_SD
   1670 	  (match_operator 3 "comparison_operator"
   1671 	    [(match_operand:<V_FP_EQUIV> 4 "register_operand")
   1672 	     (match_operand:<V_FP_EQUIV> 5 "aarch64_simd_reg_or_zero")])
   1673 	  (match_operand:SVE_SD 1 "register_operand")
   1674 	  (match_operand:SVE_SD 2 "register_operand")))]
   1675   "TARGET_SVE"
   1676   {
   1677     aarch64_expand_sve_vcond (<MODE>mode, <V_FP_EQUIV>mode, operands);
   1678     DONE;
   1679   }
   1680 )
   1681 
   1682 ;; Signed integer comparisons.  Don't enforce an immediate range here, since
   1683 ;; it depends on the comparison; leave it to aarch64_expand_sve_vec_cmp_int
   1684 ;; instead.
   1685 (define_expand "vec_cmp<mode><vpred>"
   1686   [(parallel
   1687     [(set (match_operand:<VPRED> 0 "register_operand")
   1688 	  (match_operator:<VPRED> 1 "comparison_operator"
   1689 	    [(match_operand:SVE_I 2 "register_operand")
   1690 	     (match_operand:SVE_I 3 "nonmemory_operand")]))
   1691      (clobber (reg:CC CC_REGNUM))])]
   1692   "TARGET_SVE"
   1693   {
   1694     aarch64_expand_sve_vec_cmp_int (operands[0], GET_CODE (operands[1]),
   1695 				    operands[2], operands[3]);
   1696     DONE;
   1697   }
   1698 )
   1699 
   1700 ;; Unsigned integer comparisons.  Don't enforce an immediate range here, since
   1701 ;; it depends on the comparison; leave it to aarch64_expand_sve_vec_cmp_int
   1702 ;; instead.
   1703 (define_expand "vec_cmpu<mode><vpred>"
   1704   [(parallel
   1705     [(set (match_operand:<VPRED> 0 "register_operand")
   1706 	  (match_operator:<VPRED> 1 "comparison_operator"
   1707 	    [(match_operand:SVE_I 2 "register_operand")
   1708 	     (match_operand:SVE_I 3 "nonmemory_operand")]))
   1709      (clobber (reg:CC CC_REGNUM))])]
   1710   "TARGET_SVE"
   1711   {
   1712     aarch64_expand_sve_vec_cmp_int (operands[0], GET_CODE (operands[1]),
   1713 				    operands[2], operands[3]);
   1714     DONE;
   1715   }
   1716 )
   1717 
   1718 ;; Floating-point comparisons.  All comparisons except FCMUO allow a zero
   1719 ;; operand; aarch64_expand_sve_vec_cmp_float handles the case of an FCMUO
   1720 ;; with zero.
   1721 (define_expand "vec_cmp<mode><vpred>"
   1722   [(set (match_operand:<VPRED> 0 "register_operand")
   1723 	(match_operator:<VPRED> 1 "comparison_operator"
   1724 	  [(match_operand:SVE_F 2 "register_operand")
   1725 	   (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero")]))]
   1726   "TARGET_SVE"
   1727   {
   1728     aarch64_expand_sve_vec_cmp_float (operands[0], GET_CODE (operands[1]),
   1729 				      operands[2], operands[3], false);
   1730     DONE;
   1731   }
   1732 )
   1733 
   1734 ;; Branch based on predicate equality or inequality.
   1735 (define_expand "cbranch<mode>4"
   1736   [(set (pc)
   1737 	(if_then_else
   1738 	  (match_operator 0 "aarch64_equality_operator"
   1739 	    [(match_operand:PRED_ALL 1 "register_operand")
   1740 	     (match_operand:PRED_ALL 2 "aarch64_simd_reg_or_zero")])
   1741 	  (label_ref (match_operand 3 ""))
   1742 	  (pc)))]
   1743   ""
   1744   {
   1745     rtx ptrue = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
   1746     rtx pred;
   1747     if (operands[2] == CONST0_RTX (<MODE>mode))
   1748       pred = operands[1];
   1749     else
   1750       {
   1751 	pred = gen_reg_rtx (<MODE>mode);
   1752 	emit_insn (gen_pred_xor<mode>3 (pred, ptrue, operands[1],
   1753 					operands[2]));
   1754       }
   1755     emit_insn (gen_ptest_ptrue<mode> (ptrue, pred));
   1756     operands[1] = gen_rtx_REG (CCmode, CC_REGNUM);
   1757     operands[2] = const0_rtx;
   1758   }
   1759 )
   1760 
   1761 ;; Unpredicated integer MIN/MAX.
   1762 (define_expand "<su><maxmin><mode>3"
   1763   [(set (match_operand:SVE_I 0 "register_operand")
   1764 	(unspec:SVE_I
   1765 	  [(match_dup 3)
   1766 	   (MAXMIN:SVE_I (match_operand:SVE_I 1 "register_operand")
   1767 			 (match_operand:SVE_I 2 "register_operand"))]
   1768 	  UNSPEC_MERGE_PTRUE))]
   1769   "TARGET_SVE"
   1770   {
   1771     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   1772   }
   1773 )
   1774 
   1775 ;; Integer MIN/MAX predicated with a PTRUE.
   1776 (define_insn "*<su><maxmin><mode>3"
   1777   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
   1778 	(unspec:SVE_I
   1779 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1780 	   (MAXMIN:SVE_I (match_operand:SVE_I 2 "register_operand" "%0, w")
   1781 			 (match_operand:SVE_I 3 "register_operand" "w, w"))]
   1782 	  UNSPEC_MERGE_PTRUE))]
   1783   "TARGET_SVE"
   1784   "@
   1785    <su><maxmin>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1786    movprfx\t%0, %2\;<su><maxmin>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1787   [(set_attr "movprfx" "*,yes")]
   1788 )
   1789 
   1790 ;; Unpredicated floating-point MIN/MAX.
   1791 (define_expand "<su><maxmin><mode>3"
   1792   [(set (match_operand:SVE_F 0 "register_operand")
   1793 	(unspec:SVE_F
   1794 	  [(match_dup 3)
   1795 	   (FMAXMIN:SVE_F (match_operand:SVE_F 1 "register_operand")
   1796 			  (match_operand:SVE_F 2 "register_operand"))]
   1797 	  UNSPEC_MERGE_PTRUE))]
   1798   "TARGET_SVE"
   1799   {
   1800     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   1801   }
   1802 )
   1803 
   1804 ;; Floating-point MIN/MAX predicated with a PTRUE.
   1805 (define_insn "*<su><maxmin><mode>3"
   1806   [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
   1807 	(unspec:SVE_F
   1808 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1809 	   (FMAXMIN:SVE_F (match_operand:SVE_F 2 "register_operand" "%0, w")
   1810 			  (match_operand:SVE_F 3 "register_operand" "w, w"))]
   1811 	  UNSPEC_MERGE_PTRUE))]
   1812   "TARGET_SVE"
   1813   "@
   1814    f<maxmin>nm\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1815    movprfx\t%0, %2\;f<maxmin>nm\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1816   [(set_attr "movprfx" "*,yes")]
   1817 )
   1818 
   1819 ;; Unpredicated fmin/fmax.
   1820 (define_expand "<maxmin_uns><mode>3"
   1821   [(set (match_operand:SVE_F 0 "register_operand")
   1822 	(unspec:SVE_F
   1823 	  [(match_dup 3)
   1824 	   (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand")
   1825 			  (match_operand:SVE_F 2 "register_operand")]
   1826 			 FMAXMIN_UNS)]
   1827 	  UNSPEC_MERGE_PTRUE))]
   1828   "TARGET_SVE"
   1829   {
   1830     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   1831   }
   1832 )
   1833 
   1834 ;; fmin/fmax predicated with a PTRUE.
   1835 (define_insn "*<maxmin_uns><mode>3"
   1836   [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
   1837 	(unspec:SVE_F
   1838 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1839 	   (unspec:SVE_F [(match_operand:SVE_F 2 "register_operand" "%0, w")
   1840 			  (match_operand:SVE_F 3 "register_operand" "w, w")]
   1841 			 FMAXMIN_UNS)]
   1842 	  UNSPEC_MERGE_PTRUE))]
   1843   "TARGET_SVE"
   1844   "@
   1845    <maxmin_uns_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1846    movprfx\t%0, %2\;<maxmin_uns_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1847   [(set_attr "movprfx" "*,yes")]
   1848 )
   1849 
   1850 ;; Predicated integer operations with select.
   1851 (define_expand "cond_<optab><mode>"
   1852   [(set (match_operand:SVE_I 0 "register_operand")
   1853 	(unspec:SVE_I
   1854 	  [(match_operand:<VPRED> 1 "register_operand")
   1855 	   (SVE_INT_BINARY:SVE_I
   1856 	     (match_operand:SVE_I 2 "register_operand")
   1857 	     (match_operand:SVE_I 3 "register_operand"))
   1858 	   (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
   1859 	  UNSPEC_SEL))]
   1860   "TARGET_SVE"
   1861 )
   1862 
   1863 (define_expand "cond_<optab><mode>"
   1864   [(set (match_operand:SVE_SDI 0 "register_operand")
   1865 	(unspec:SVE_SDI
   1866 	  [(match_operand:<VPRED> 1 "register_operand")
   1867 	   (SVE_INT_BINARY_SD:SVE_SDI
   1868 	     (match_operand:SVE_SDI 2 "register_operand")
   1869 	     (match_operand:SVE_SDI 3 "register_operand"))
   1870 	   (match_operand:SVE_SDI 4 "aarch64_simd_reg_or_zero")]
   1871 	  UNSPEC_SEL))]
   1872   "TARGET_SVE"
   1873 )
   1874 
   1875 ;; Predicated integer operations with select matching the output operand.
   1876 (define_insn "*cond_<optab><mode>_0"
   1877   [(set (match_operand:SVE_I 0 "register_operand" "+w, w, ?&w")
   1878 	(unspec:SVE_I
   1879 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   1880 	   (SVE_INT_BINARY:SVE_I
   1881 	     (match_operand:SVE_I 2 "register_operand" "0, w, w")
   1882 	     (match_operand:SVE_I 3 "register_operand" "w, 0, w"))
   1883 	   (match_dup 0)]
   1884 	  UNSPEC_SEL))]
   1885   "TARGET_SVE"
   1886   "@
   1887    <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1888    <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   1889    movprfx\t%0, %1/m, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1890   [(set_attr "movprfx" "*,*,yes")]
   1891 )
   1892 
   1893 (define_insn "*cond_<optab><mode>_0"
   1894   [(set (match_operand:SVE_SDI 0 "register_operand" "+w, w, ?&w")
   1895 	(unspec:SVE_SDI
   1896 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   1897 	   (SVE_INT_BINARY_SD:SVE_SDI
   1898 	     (match_operand:SVE_SDI 2 "register_operand" "0, w, w")
   1899 	     (match_operand:SVE_SDI 3 "register_operand" "w, 0, w"))
   1900 	   (match_dup 0)]
   1901 	  UNSPEC_SEL))]
   1902   "TARGET_SVE"
   1903   "@
   1904    <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1905    <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   1906    movprfx\t%0, %1/m, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1907   [(set_attr "movprfx" "*,*,yes")]
   1908 )
   1909 
   1910 ;; Predicated integer operations with select matching the first operand.
   1911 (define_insn "*cond_<optab><mode>_2"
   1912   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
   1913 	(unspec:SVE_I
   1914 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1915 	   (SVE_INT_BINARY:SVE_I
   1916 	     (match_operand:SVE_I 2 "register_operand" "0, w")
   1917 	     (match_operand:SVE_I 3 "register_operand" "w, w"))
   1918 	   (match_dup 2)]
   1919 	  UNSPEC_SEL))]
   1920   "TARGET_SVE"
   1921   "@
   1922    <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1923    movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1924   [(set_attr "movprfx" "*,yes")]
   1925 )
   1926 
   1927 (define_insn "*cond_<optab><mode>_2"
   1928   [(set (match_operand:SVE_SDI 0 "register_operand" "=w, ?&w")
   1929 	(unspec:SVE_SDI
   1930 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1931 	   (SVE_INT_BINARY_SD:SVE_SDI
   1932 	     (match_operand:SVE_SDI 2 "register_operand" "0, w")
   1933 	     (match_operand:SVE_SDI 3 "register_operand" "w, w"))
   1934 	   (match_dup 2)]
   1935 	  UNSPEC_SEL))]
   1936   "TARGET_SVE"
   1937   "@
   1938    <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   1939    movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1940   [(set_attr "movprfx" "*,yes")]
   1941 )
   1942 
   1943 ;; Predicated integer operations with select matching the second operand.
   1944 (define_insn "*cond_<optab><mode>_3"
   1945   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
   1946 	(unspec:SVE_I
   1947 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1948 	   (SVE_INT_BINARY:SVE_I
   1949 	     (match_operand:SVE_I 2 "register_operand" "w, w")
   1950 	     (match_operand:SVE_I 3 "register_operand" "0, w"))
   1951 	   (match_dup 3)]
   1952 	  UNSPEC_SEL))]
   1953   "TARGET_SVE"
   1954   "@
   1955    <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   1956    movprfx\t%0, %3\;<sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
   1957   [(set_attr "movprfx" "*,yes")]
   1958 )
   1959 
   1960 (define_insn "*cond_<optab><mode>_3"
   1961   [(set (match_operand:SVE_SDI 0 "register_operand" "=w, ?&w")
   1962 	(unspec:SVE_SDI
   1963 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   1964 	   (SVE_INT_BINARY_SD:SVE_SDI
   1965 	     (match_operand:SVE_SDI 2 "register_operand" "w, w")
   1966 	     (match_operand:SVE_SDI 3 "register_operand" "0, w"))
   1967 	   (match_dup 3)]
   1968 	  UNSPEC_SEL))]
   1969   "TARGET_SVE"
   1970   "@
   1971    <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   1972    movprfx\t%0, %3\;<sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
   1973   [(set_attr "movprfx" "*,yes")]
   1974 )
   1975 
   1976 ;; Predicated integer operations with select matching zero.
   1977 (define_insn "*cond_<optab><mode>_z"
   1978   [(set (match_operand:SVE_I 0 "register_operand" "=&w")
   1979 	(unspec:SVE_I
   1980 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   1981 	   (SVE_INT_BINARY:SVE_I
   1982 	     (match_operand:SVE_I 2 "register_operand" "w")
   1983 	     (match_operand:SVE_I 3 "register_operand" "w"))
   1984 	   (match_operand:SVE_I 4 "aarch64_simd_imm_zero")]
   1985 	  UNSPEC_SEL))]
   1986   "TARGET_SVE"
   1987   "movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   1988   [(set_attr "movprfx" "yes")]
   1989 )
   1990 
   1991 (define_insn "*cond_<optab><mode>_z"
   1992   [(set (match_operand:SVE_SDI 0 "register_operand" "=&w")
   1993 	(unspec:SVE_SDI
   1994 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   1995 	   (SVE_INT_BINARY_SD:SVE_SDI
   1996 	     (match_operand:SVE_SDI 2 "register_operand" "w")
   1997 	     (match_operand:SVE_SDI 3 "register_operand" "w"))
   1998 	   (match_operand:SVE_SDI 4 "aarch64_simd_imm_zero")]
   1999 	  UNSPEC_SEL))]
   2000   "TARGET_SVE"
   2001   "movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   2002   [(set_attr "movprfx" "yes")]
   2003 )
   2004 
   2005 ;; Synthetic predications with select unmatched.
   2006 (define_insn "*cond_<optab><mode>_any"
   2007   [(set (match_operand:SVE_I 0 "register_operand" "=&w")
   2008 	(unspec:SVE_I
   2009 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2010 	   (SVE_INT_BINARY:SVE_I
   2011 	     (match_operand:SVE_I 2 "register_operand" "w")
   2012 	     (match_operand:SVE_I 3 "register_operand" "w"))
   2013 	   (match_operand:SVE_I 4 "register_operand"   "w")]
   2014 	  UNSPEC_SEL))]
   2015   "TARGET_SVE"
   2016   "#"
   2017 )
   2018 
   2019 (define_insn "*cond_<optab><mode>_any"
   2020   [(set (match_operand:SVE_SDI 0 "register_operand" "=&w")
   2021 	(unspec:SVE_SDI
   2022 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2023 	   (SVE_INT_BINARY_SD:SVE_I
   2024 	     (match_operand:SVE_SDI 2 "register_operand" "w")
   2025 	     (match_operand:SVE_SDI 3 "register_operand" "w"))
   2026 	   (match_operand:SVE_SDI 4 "register_operand"   "w")]
   2027 	  UNSPEC_SEL))]
   2028   "TARGET_SVE"
   2029   "#"
   2030 )
   2031 
   2032 (define_split
   2033   [(set (match_operand:SVE_I 0 "register_operand")
   2034 	(unspec:SVE_I
   2035 	  [(match_operand:<VPRED> 1 "register_operand")
   2036 	   (match_operator:SVE_I 5 "aarch64_sve_any_binary_operator"
   2037 	     [(match_operand:SVE_I 2 "register_operand")
   2038 	      (match_operand:SVE_I 3 "register_operand")])
   2039 	   (match_operand:SVE_I 4 "register_operand")]
   2040 	  UNSPEC_SEL))]
   2041   "TARGET_SVE && reload_completed
   2042    && !(rtx_equal_p (operands[0], operands[4])
   2043         || rtx_equal_p (operands[2], operands[4])
   2044         || rtx_equal_p (operands[3], operands[4]))"
   2045   ; Not matchable by any one insn or movprfx insn.  We need a separate select.
   2046   [(set (match_dup 0)
   2047 	(unspec:SVE_I [(match_dup 1) (match_dup 2) (match_dup 4)]
   2048                       UNSPEC_SEL))
   2049    (set (match_dup 0)
   2050 	(unspec:SVE_I
   2051 	  [(match_dup 1)
   2052 	   (match_op_dup 5 [(match_dup 0) (match_dup 3)])
   2053            (match_dup 0)]
   2054 	  UNSPEC_SEL))]
   2055 )
   2056 
   2057 ;; Set operand 0 to the last active element in operand 3, or to tied
   2058 ;; operand 1 if no elements are active.
   2059 (define_insn "fold_extract_last_<mode>"
   2060   [(set (match_operand:<VEL> 0 "register_operand" "=r, w")
   2061 	(unspec:<VEL>
   2062 	  [(match_operand:<VEL> 1 "register_operand" "0, 0")
   2063 	   (match_operand:<VPRED> 2 "register_operand" "Upl, Upl")
   2064 	   (match_operand:SVE_ALL 3 "register_operand" "w, w")]
   2065 	  UNSPEC_CLASTB))]
   2066   "TARGET_SVE"
   2067   "@
   2068    clastb\t%<vwcore>0, %2, %<vwcore>0, %3.<Vetype>
   2069    clastb\t%<vw>0, %2, %<vw>0, %3.<Vetype>"
   2070 )
   2071 
   2072 ;; Unpredicated integer add reduction.
   2073 (define_expand "reduc_plus_scal_<mode>"
   2074   [(set (match_operand:<VEL> 0 "register_operand")
   2075 	(unspec:<VEL> [(match_dup 2)
   2076 		       (match_operand:SVE_I 1 "register_operand")]
   2077 		      UNSPEC_ADDV))]
   2078   "TARGET_SVE"
   2079   {
   2080     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2081   }
   2082 )
   2083 
   2084 ;; Predicated integer add reduction.  The result is always 64-bits.
   2085 (define_insn "*reduc_plus_scal_<mode>"
   2086   [(set (match_operand:<VEL> 0 "register_operand" "=w")
   2087 	(unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2088 		       (match_operand:SVE_I 2 "register_operand" "w")]
   2089 		      UNSPEC_ADDV))]
   2090   "TARGET_SVE"
   2091   "uaddv\t%d0, %1, %2.<Vetype>"
   2092 )
   2093 
   2094 ;; Unpredicated floating-point add reduction.
   2095 (define_expand "reduc_plus_scal_<mode>"
   2096   [(set (match_operand:<VEL> 0 "register_operand")
   2097 	(unspec:<VEL> [(match_dup 2)
   2098 		       (match_operand:SVE_F 1 "register_operand")]
   2099 		      UNSPEC_FADDV))]
   2100   "TARGET_SVE"
   2101   {
   2102     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2103   }
   2104 )
   2105 
   2106 ;; Predicated floating-point add reduction.
   2107 (define_insn "*reduc_plus_scal_<mode>"
   2108   [(set (match_operand:<VEL> 0 "register_operand" "=w")
   2109 	(unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2110 		       (match_operand:SVE_F 2 "register_operand" "w")]
   2111 		      UNSPEC_FADDV))]
   2112   "TARGET_SVE"
   2113   "faddv\t%<Vetype>0, %1, %2.<Vetype>"
   2114 )
   2115 
   2116 ;; Unpredicated integer MIN/MAX reduction.
   2117 (define_expand "reduc_<maxmin_uns>_scal_<mode>"
   2118   [(set (match_operand:<VEL> 0 "register_operand")
   2119 	(unspec:<VEL> [(match_dup 2)
   2120 		       (match_operand:SVE_I 1 "register_operand")]
   2121 		      MAXMINV))]
   2122   "TARGET_SVE"
   2123   {
   2124     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2125   }
   2126 )
   2127 
   2128 ;; Predicated integer MIN/MAX reduction.
   2129 (define_insn "*reduc_<maxmin_uns>_scal_<mode>"
   2130   [(set (match_operand:<VEL> 0 "register_operand" "=w")
   2131 	(unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2132 		       (match_operand:SVE_I 2 "register_operand" "w")]
   2133 		      MAXMINV))]
   2134   "TARGET_SVE"
   2135   "<maxmin_uns_op>v\t%<Vetype>0, %1, %2.<Vetype>"
   2136 )
   2137 
   2138 ;; Unpredicated floating-point MIN/MAX reduction.
   2139 (define_expand "reduc_<maxmin_uns>_scal_<mode>"
   2140   [(set (match_operand:<VEL> 0 "register_operand")
   2141 	(unspec:<VEL> [(match_dup 2)
   2142 		       (match_operand:SVE_F 1 "register_operand")]
   2143 		      FMAXMINV))]
   2144   "TARGET_SVE"
   2145   {
   2146     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2147   }
   2148 )
   2149 
   2150 ;; Predicated floating-point MIN/MAX reduction.
   2151 (define_insn "*reduc_<maxmin_uns>_scal_<mode>"
   2152   [(set (match_operand:<VEL> 0 "register_operand" "=w")
   2153 	(unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2154 		       (match_operand:SVE_F 2 "register_operand" "w")]
   2155 		      FMAXMINV))]
   2156   "TARGET_SVE"
   2157   "<maxmin_uns_op>v\t%<Vetype>0, %1, %2.<Vetype>"
   2158 )
   2159 
   2160 (define_expand "reduc_<optab>_scal_<mode>"
   2161   [(set (match_operand:<VEL> 0 "register_operand")
   2162 	(unspec:<VEL> [(match_dup 2)
   2163 		       (match_operand:SVE_I 1 "register_operand")]
   2164 		      BITWISEV))]
   2165   "TARGET_SVE"
   2166   {
   2167     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2168   }
   2169 )
   2170 
   2171 (define_insn "*reduc_<optab>_scal_<mode>"
   2172   [(set (match_operand:<VEL> 0 "register_operand" "=w")
   2173 	(unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2174 		       (match_operand:SVE_I 2 "register_operand" "w")]
   2175 		      BITWISEV))]
   2176   "TARGET_SVE"
   2177   "<bit_reduc_op>\t%<Vetype>0, %1, %2.<Vetype>"
   2178 )
   2179 
   2180 ;; Unpredicated in-order FP reductions.
   2181 (define_expand "fold_left_plus_<mode>"
   2182   [(set (match_operand:<VEL> 0 "register_operand")
   2183 	(unspec:<VEL> [(match_dup 3)
   2184 		       (match_operand:<VEL> 1 "register_operand")
   2185 		       (match_operand:SVE_F 2 "register_operand")]
   2186 		      UNSPEC_FADDA))]
   2187   "TARGET_SVE"
   2188   {
   2189     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2190   }
   2191 )
   2192 
   2193 ;; In-order FP reductions predicated with PTRUE.
   2194 (define_insn "*fold_left_plus_<mode>"
   2195   [(set (match_operand:<VEL> 0 "register_operand" "=w")
   2196 	(unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2197 		       (match_operand:<VEL> 2 "register_operand" "0")
   2198 		       (match_operand:SVE_F 3 "register_operand" "w")]
   2199 		      UNSPEC_FADDA))]
   2200   "TARGET_SVE"
   2201   "fadda\t%<Vetype>0, %1, %<Vetype>0, %3.<Vetype>"
   2202 )
   2203 
   2204 ;; Predicated form of the above in-order reduction.
   2205 (define_insn "*pred_fold_left_plus_<mode>"
   2206   [(set (match_operand:<VEL> 0 "register_operand" "=w")
   2207 	(unspec:<VEL>
   2208 	  [(match_operand:<VEL> 1 "register_operand" "0")
   2209 	   (unspec:SVE_F
   2210 	     [(match_operand:<VPRED> 2 "register_operand" "Upl")
   2211 	      (match_operand:SVE_F 3 "register_operand" "w")
   2212 	      (match_operand:SVE_F 4 "aarch64_simd_imm_zero")]
   2213 	     UNSPEC_SEL)]
   2214 	  UNSPEC_FADDA))]
   2215   "TARGET_SVE"
   2216   "fadda\t%<Vetype>0, %2, %<Vetype>0, %3.<Vetype>"
   2217 )
   2218 
   2219 ;; Unpredicated floating-point addition.
   2220 (define_expand "add<mode>3"
   2221   [(set (match_operand:SVE_F 0 "register_operand")
   2222 	(unspec:SVE_F
   2223 	  [(match_dup 3)
   2224 	   (plus:SVE_F
   2225 	     (match_operand:SVE_F 1 "register_operand")
   2226 	     (match_operand:SVE_F 2 "aarch64_sve_float_arith_with_sub_operand"))]
   2227 	  UNSPEC_MERGE_PTRUE))]
   2228   "TARGET_SVE"
   2229   {
   2230     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2231   }
   2232 )
   2233 
   2234 ;; Floating-point addition predicated with a PTRUE.
   2235 (define_insn_and_split "*add<mode>3"
   2236   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w")
   2237 	(unspec:SVE_F
   2238 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   2239 	   (plus:SVE_F
   2240 	      (match_operand:SVE_F 2 "register_operand" "%0, 0, w")
   2241 	      (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand" "vsA, vsN, w"))]
   2242 	  UNSPEC_MERGE_PTRUE))]
   2243   "TARGET_SVE"
   2244   "@
   2245    fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
   2246    fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
   2247    #"
   2248   ; Split the unpredicated form after reload, so that we don't have
   2249   ; the unnecessary PTRUE.
   2250   "&& reload_completed
   2251    && register_operand (operands[3], <MODE>mode)"
   2252   [(set (match_dup 0) (plus:SVE_F (match_dup 2) (match_dup 3)))]
   2253 )
   2254 
   2255 ;; Unpredicated floating-point subtraction.
   2256 (define_expand "sub<mode>3"
   2257   [(set (match_operand:SVE_F 0 "register_operand")
   2258 	(unspec:SVE_F
   2259 	  [(match_dup 3)
   2260 	   (minus:SVE_F
   2261 	     (match_operand:SVE_F 1 "aarch64_sve_float_arith_operand")
   2262 	     (match_operand:SVE_F 2 "register_operand"))]
   2263 	  UNSPEC_MERGE_PTRUE))]
   2264   "TARGET_SVE"
   2265   {
   2266     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2267   }
   2268 )
   2269 
   2270 ;; Floating-point subtraction predicated with a PTRUE.
   2271 (define_insn_and_split "*sub<mode>3"
   2272   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, w")
   2273 	(unspec:SVE_F
   2274 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
   2275 	   (minus:SVE_F
   2276 	     (match_operand:SVE_F 2 "aarch64_sve_float_arith_operand" "0, 0, vsA, w")
   2277 	     (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand" "vsA, vsN, 0, w"))]
   2278 	  UNSPEC_MERGE_PTRUE))]
   2279   "TARGET_SVE
   2280    && (register_operand (operands[2], <MODE>mode)
   2281        || register_operand (operands[3], <MODE>mode))"
   2282   "@
   2283    fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
   2284    fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
   2285    fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
   2286    #"
   2287   ; Split the unpredicated form after reload, so that we don't have
   2288   ; the unnecessary PTRUE.
   2289   "&& reload_completed
   2290    && register_operand (operands[2], <MODE>mode)
   2291    && register_operand (operands[3], <MODE>mode)"
   2292   [(set (match_dup 0) (minus:SVE_F (match_dup 2) (match_dup 3)))]
   2293 )
   2294 
   2295 ;; Unpredicated floating-point multiplication.
   2296 (define_expand "mul<mode>3"
   2297   [(set (match_operand:SVE_F 0 "register_operand")
   2298 	(unspec:SVE_F
   2299 	  [(match_dup 3)
   2300 	   (mult:SVE_F
   2301 	     (match_operand:SVE_F 1 "register_operand")
   2302 	     (match_operand:SVE_F 2 "aarch64_sve_float_mul_operand"))]
   2303 	  UNSPEC_MERGE_PTRUE))]
   2304   "TARGET_SVE"
   2305   {
   2306     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2307   }
   2308 )
   2309 
   2310 ;; Floating-point multiplication predicated with a PTRUE.
   2311 (define_insn_and_split "*mul<mode>3"
   2312   [(set (match_operand:SVE_F 0 "register_operand" "=w, w")
   2313 	(unspec:SVE_F
   2314 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   2315 	   (mult:SVE_F
   2316 	     (match_operand:SVE_F 2 "register_operand" "%0, w")
   2317 	     (match_operand:SVE_F 3 "aarch64_sve_float_mul_operand" "vsM, w"))]
   2318 	  UNSPEC_MERGE_PTRUE))]
   2319   "TARGET_SVE"
   2320   "@
   2321    fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
   2322    #"
   2323   ; Split the unpredicated form after reload, so that we don't have
   2324   ; the unnecessary PTRUE.
   2325   "&& reload_completed
   2326    && register_operand (operands[3], <MODE>mode)"
   2327   [(set (match_dup 0) (mult:SVE_F (match_dup 2) (match_dup 3)))]
   2328 )
   2329 
   2330 ;; Unpredicated floating-point binary operations (post-RA only).
   2331 ;; These are generated by splitting a predicated instruction whose
   2332 ;; predicate is unused.
   2333 (define_insn "*post_ra_<sve_fp_op><mode>3"
   2334   [(set (match_operand:SVE_F 0 "register_operand" "=w")
   2335 	(SVE_UNPRED_FP_BINARY:SVE_F
   2336 	  (match_operand:SVE_F 1 "register_operand" "w")
   2337 	  (match_operand:SVE_F 2 "register_operand" "w")))]
   2338   "TARGET_SVE && reload_completed"
   2339   "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>")
   2340 
   2341 ;; Unpredicated fma (%0 = (%1 * %2) + %3).
   2342 (define_expand "fma<mode>4"
   2343   [(set (match_operand:SVE_F 0 "register_operand")
   2344 	(unspec:SVE_F
   2345 	  [(match_dup 4)
   2346 	   (fma:SVE_F (match_operand:SVE_F 1 "register_operand")
   2347 		      (match_operand:SVE_F 2 "register_operand")
   2348 		      (match_operand:SVE_F 3 "register_operand"))]
   2349 	  UNSPEC_MERGE_PTRUE))]
   2350   "TARGET_SVE"
   2351   {
   2352     operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2353   }
   2354 )
   2355 
   2356 ;; fma predicated with a PTRUE.
   2357 (define_insn "*fma<mode>4"
   2358   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
   2359 	(unspec:SVE_F
   2360 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   2361 	   (fma:SVE_F (match_operand:SVE_F 3 "register_operand" "%0, w, w")
   2362 		      (match_operand:SVE_F 4 "register_operand" "w, w, w")
   2363 		      (match_operand:SVE_F 2 "register_operand" "w, 0, w"))]
   2364 	  UNSPEC_MERGE_PTRUE))]
   2365   "TARGET_SVE"
   2366   "@
   2367    fmad\t%0.<Vetype>, %1/m, %4.<Vetype>, %2.<Vetype>
   2368    fmla\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   2369    movprfx\t%0, %2\;fmla\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
   2370   [(set_attr "movprfx" "*,*,yes")]
   2371 )
   2372 
   2373 ;; Unpredicated fnma (%0 = (-%1 * %2) + %3).
   2374 (define_expand "fnma<mode>4"
   2375   [(set (match_operand:SVE_F 0 "register_operand")
   2376 	(unspec:SVE_F
   2377 	  [(match_dup 4)
   2378 	   (fma:SVE_F (neg:SVE_F
   2379 			(match_operand:SVE_F 1 "register_operand"))
   2380 		      (match_operand:SVE_F 2 "register_operand")
   2381 		      (match_operand:SVE_F 3 "register_operand"))]
   2382 	  UNSPEC_MERGE_PTRUE))]
   2383   "TARGET_SVE"
   2384   {
   2385     operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2386   }
   2387 )
   2388 
   2389 ;; fnma predicated with a PTRUE.
   2390 (define_insn "*fnma<mode>4"
   2391   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
   2392 	(unspec:SVE_F
   2393 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   2394 	   (fma:SVE_F (neg:SVE_F
   2395 			(match_operand:SVE_F 3 "register_operand" "%0, w, w"))
   2396 		      (match_operand:SVE_F 4 "register_operand" "w, w, w")
   2397 		      (match_operand:SVE_F 2 "register_operand" "w, 0, w"))]
   2398 	  UNSPEC_MERGE_PTRUE))]
   2399   "TARGET_SVE"
   2400   "@
   2401    fmsb\t%0.<Vetype>, %1/m, %4.<Vetype>, %2.<Vetype>
   2402    fmls\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   2403    movprfx\t%0, %2\;fmls\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
   2404   [(set_attr "movprfx" "*,*,yes")]
   2405 )
   2406 
   2407 ;; Unpredicated fms (%0 = (%1 * %2) - %3).
   2408 (define_expand "fms<mode>4"
   2409   [(set (match_operand:SVE_F 0 "register_operand")
   2410 	(unspec:SVE_F
   2411 	  [(match_dup 4)
   2412 	   (fma:SVE_F (match_operand:SVE_F 1 "register_operand")
   2413 		      (match_operand:SVE_F 2 "register_operand")
   2414 		      (neg:SVE_F
   2415 			(match_operand:SVE_F 3 "register_operand")))]
   2416 	  UNSPEC_MERGE_PTRUE))]
   2417   "TARGET_SVE"
   2418   {
   2419     operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2420   }
   2421 )
   2422 
   2423 ;; fms predicated with a PTRUE.
   2424 (define_insn "*fms<mode>4"
   2425   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
   2426 	(unspec:SVE_F
   2427 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   2428 	   (fma:SVE_F (match_operand:SVE_F 3 "register_operand" "%0, w, w")
   2429 		      (match_operand:SVE_F 4 "register_operand" "w, w, w")
   2430 		      (neg:SVE_F
   2431 			(match_operand:SVE_F 2 "register_operand" "w, 0, w")))]
   2432 	  UNSPEC_MERGE_PTRUE))]
   2433   "TARGET_SVE"
   2434   "@
   2435    fnmsb\t%0.<Vetype>, %1/m, %4.<Vetype>, %2.<Vetype>
   2436    fnmls\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   2437    movprfx\t%0, %2\;fnmls\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
   2438   [(set_attr "movprfx" "*,*,yes")]
   2439 )
   2440 
   2441 ;; Unpredicated fnms (%0 = (-%1 * %2) - %3).
   2442 (define_expand "fnms<mode>4"
   2443   [(set (match_operand:SVE_F 0 "register_operand")
   2444 	(unspec:SVE_F
   2445 	  [(match_dup 4)
   2446 	   (fma:SVE_F (neg:SVE_F
   2447 			(match_operand:SVE_F 1 "register_operand"))
   2448 		      (match_operand:SVE_F 2 "register_operand")
   2449 		      (neg:SVE_F
   2450 			(match_operand:SVE_F 3 "register_operand")))]
   2451 	  UNSPEC_MERGE_PTRUE))]
   2452   "TARGET_SVE"
   2453   {
   2454     operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2455   }
   2456 )
   2457 
   2458 ;; fnms predicated with a PTRUE.
   2459 (define_insn "*fnms<mode>4"
   2460   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
   2461 	(unspec:SVE_F
   2462 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   2463 	   (fma:SVE_F (neg:SVE_F
   2464 			(match_operand:SVE_F 3 "register_operand" "%0, w, w"))
   2465 		      (match_operand:SVE_F 4 "register_operand" "w, w, w")
   2466 		      (neg:SVE_F
   2467 			(match_operand:SVE_F 2 "register_operand" "w, 0, w")))]
   2468 	  UNSPEC_MERGE_PTRUE))]
   2469   "TARGET_SVE"
   2470   "@
   2471    fnmad\t%0.<Vetype>, %1/m, %4.<Vetype>, %2.<Vetype>
   2472    fnmla\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   2473    movprfx\t%0, %2\;fnmla\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
   2474   [(set_attr "movprfx" "*,*,yes")]
   2475 )
   2476 
   2477 ;; Unpredicated floating-point division.
   2478 (define_expand "div<mode>3"
   2479   [(set (match_operand:SVE_F 0 "register_operand")
   2480 	(unspec:SVE_F
   2481 	  [(match_dup 3)
   2482 	   (div:SVE_F (match_operand:SVE_F 1 "register_operand")
   2483 		      (match_operand:SVE_F 2 "register_operand"))]
   2484 	  UNSPEC_MERGE_PTRUE))]
   2485   "TARGET_SVE"
   2486   {
   2487     operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2488   }
   2489 )
   2490 
   2491 ;; Floating-point division predicated with a PTRUE.
   2492 (define_insn "*div<mode>3"
   2493   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
   2494 	(unspec:SVE_F
   2495 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   2496 	   (div:SVE_F (match_operand:SVE_F 2 "register_operand" "0, w, w")
   2497 		      (match_operand:SVE_F 3 "register_operand" "w, 0, w"))]
   2498 	  UNSPEC_MERGE_PTRUE))]
   2499   "TARGET_SVE"
   2500   "@
   2501    fdiv\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   2502    fdivr\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   2503    movprfx\t%0, %2\;fdiv\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   2504   [(set_attr "movprfx" "*,*,yes")]
   2505 )
   2506 
   2507 ;; Unpredicated FNEG, FABS and FSQRT.
   2508 (define_expand "<optab><mode>2"
   2509   [(set (match_operand:SVE_F 0 "register_operand")
   2510 	(unspec:SVE_F
   2511 	  [(match_dup 2)
   2512 	   (SVE_FP_UNARY:SVE_F (match_operand:SVE_F 1 "register_operand"))]
   2513 	  UNSPEC_MERGE_PTRUE))]
   2514   "TARGET_SVE"
   2515   {
   2516     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2517   }
   2518 )
   2519 
   2520 ;; FNEG, FABS and FSQRT predicated with a PTRUE.
   2521 (define_insn "*<optab><mode>2"
   2522   [(set (match_operand:SVE_F 0 "register_operand" "=w")
   2523 	(unspec:SVE_F
   2524 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2525 	   (SVE_FP_UNARY:SVE_F (match_operand:SVE_F 2 "register_operand" "w"))]
   2526 	  UNSPEC_MERGE_PTRUE))]
   2527   "TARGET_SVE"
   2528   "<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
   2529 )
   2530 
   2531 ;; Unpredicated FRINTy.
   2532 (define_expand "<frint_pattern><mode>2"
   2533   [(set (match_operand:SVE_F 0 "register_operand")
   2534 	(unspec:SVE_F
   2535 	  [(match_dup 2)
   2536 	   (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand")]
   2537 			 FRINT)]
   2538 	  UNSPEC_MERGE_PTRUE))]
   2539   "TARGET_SVE"
   2540   {
   2541     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2542   }
   2543 )
   2544 
   2545 ;; FRINTy predicated with a PTRUE.
   2546 (define_insn "*<frint_pattern><mode>2"
   2547   [(set (match_operand:SVE_F 0 "register_operand" "=w")
   2548 	(unspec:SVE_F
   2549 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2550 	   (unspec:SVE_F [(match_operand:SVE_F 2 "register_operand" "w")]
   2551 			 FRINT)]
   2552 	  UNSPEC_MERGE_PTRUE))]
   2553   "TARGET_SVE"
   2554   "frint<frint_suffix>\t%0.<Vetype>, %1/m, %2.<Vetype>"
   2555 )
   2556 
   2557 ;; Unpredicated conversion of floats to integers of the same size (HF to HI,
   2558 ;; SF to SI or DF to DI).
   2559 (define_expand "<fix_trunc_optab><mode><v_int_equiv>2"
   2560   [(set (match_operand:<V_INT_EQUIV> 0 "register_operand")
   2561 	(unspec:<V_INT_EQUIV>
   2562 	  [(match_dup 2)
   2563 	   (FIXUORS:<V_INT_EQUIV>
   2564 	     (match_operand:SVE_F 1 "register_operand"))]
   2565 	  UNSPEC_MERGE_PTRUE))]
   2566   "TARGET_SVE"
   2567   {
   2568     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2569   }
   2570 )
   2571 
   2572 ;; Conversion of SF to DI, SI or HI, predicated with a PTRUE.
   2573 (define_insn "*<fix_trunc_optab>v16hsf<mode>2"
   2574   [(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
   2575 	(unspec:SVE_HSDI
   2576 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2577 	   (FIXUORS:SVE_HSDI
   2578 	     (match_operand:VNx8HF 2 "register_operand" "w"))]
   2579 	  UNSPEC_MERGE_PTRUE))]
   2580   "TARGET_SVE"
   2581   "fcvtz<su>\t%0.<Vetype>, %1/m, %2.h"
   2582 )
   2583 
   2584 ;; Conversion of SF to DI or SI, predicated with a PTRUE.
   2585 (define_insn "*<fix_trunc_optab>vnx4sf<mode>2"
   2586   [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
   2587 	(unspec:SVE_SDI
   2588 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2589 	   (FIXUORS:SVE_SDI
   2590 	     (match_operand:VNx4SF 2 "register_operand" "w"))]
   2591 	  UNSPEC_MERGE_PTRUE))]
   2592   "TARGET_SVE"
   2593   "fcvtz<su>\t%0.<Vetype>, %1/m, %2.s"
   2594 )
   2595 
   2596 ;; Conversion of DF to DI or SI, predicated with a PTRUE.
   2597 (define_insn "*<fix_trunc_optab>vnx2df<mode>2"
   2598   [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
   2599 	(unspec:SVE_SDI
   2600 	  [(match_operand:VNx2BI 1 "register_operand" "Upl")
   2601 	   (FIXUORS:SVE_SDI
   2602 	     (match_operand:VNx2DF 2 "register_operand" "w"))]
   2603 	  UNSPEC_MERGE_PTRUE))]
   2604   "TARGET_SVE"
   2605   "fcvtz<su>\t%0.<Vetype>, %1/m, %2.d"
   2606 )
   2607 
   2608 ;; Unpredicated conversion of integers to floats of the same size
   2609 ;; (HI to HF, SI to SF or DI to DF).
   2610 (define_expand "<optab><v_int_equiv><mode>2"
   2611   [(set (match_operand:SVE_F 0 "register_operand")
   2612 	(unspec:SVE_F
   2613 	  [(match_dup 2)
   2614 	   (FLOATUORS:SVE_F
   2615 	     (match_operand:<V_INT_EQUIV> 1 "register_operand"))]
   2616 	  UNSPEC_MERGE_PTRUE))]
   2617   "TARGET_SVE"
   2618   {
   2619     operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
   2620   }
   2621 )
   2622 
   2623 ;; Conversion of DI, SI or HI to the same number of HFs, predicated
   2624 ;; with a PTRUE.
   2625 (define_insn "*<optab><mode>vnx8hf2"
   2626   [(set (match_operand:VNx8HF 0 "register_operand" "=w")
   2627 	(unspec:VNx8HF
   2628 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2629 	   (FLOATUORS:VNx8HF
   2630 	     (match_operand:SVE_HSDI 2 "register_operand" "w"))]
   2631 	  UNSPEC_MERGE_PTRUE))]
   2632   "TARGET_SVE"
   2633   "<su_optab>cvtf\t%0.h, %1/m, %2.<Vetype>"
   2634 )
   2635 
   2636 ;; Conversion of DI or SI to the same number of SFs, predicated with a PTRUE.
   2637 (define_insn "*<optab><mode>vnx4sf2"
   2638   [(set (match_operand:VNx4SF 0 "register_operand" "=w")
   2639 	(unspec:VNx4SF
   2640 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2641 	   (FLOATUORS:VNx4SF
   2642 	     (match_operand:SVE_SDI 2 "register_operand" "w"))]
   2643 	  UNSPEC_MERGE_PTRUE))]
   2644   "TARGET_SVE"
   2645   "<su_optab>cvtf\t%0.s, %1/m, %2.<Vetype>"
   2646 )
   2647 
   2648 ;; Conversion of DI or SI to DF, predicated with a PTRUE.
   2649 (define_insn "aarch64_sve_<optab><mode>vnx2df2"
   2650   [(set (match_operand:VNx2DF 0 "register_operand" "=w")
   2651 	(unspec:VNx2DF
   2652 	  [(match_operand:VNx2BI 1 "register_operand" "Upl")
   2653 	   (FLOATUORS:VNx2DF
   2654 	     (match_operand:SVE_SDI 2 "register_operand" "w"))]
   2655 	  UNSPEC_MERGE_PTRUE))]
   2656   "TARGET_SVE"
   2657   "<su_optab>cvtf\t%0.d, %1/m, %2.<Vetype>"
   2658 )
   2659 
   2660 ;; Conversion of DFs to the same number of SFs, or SFs to the same number
   2661 ;; of HFs.
   2662 (define_insn "*trunc<Vwide><mode>2"
   2663   [(set (match_operand:SVE_HSF 0 "register_operand" "=w")
   2664 	(unspec:SVE_HSF
   2665 	  [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
   2666 	   (unspec:SVE_HSF
   2667 	     [(match_operand:<VWIDE> 2 "register_operand" "w")]
   2668 	     UNSPEC_FLOAT_CONVERT)]
   2669 	  UNSPEC_MERGE_PTRUE))]
   2670   "TARGET_SVE"
   2671   "fcvt\t%0.<Vetype>, %1/m, %2.<Vewtype>"
   2672 )
   2673 
   2674 ;; Conversion of SFs to the same number of DFs, or HFs to the same number
   2675 ;; of SFs.
   2676 (define_insn "aarch64_sve_extend<mode><Vwide>2"
   2677   [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
   2678 	(unspec:<VWIDE>
   2679 	  [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
   2680 	   (unspec:<VWIDE>
   2681 	     [(match_operand:SVE_HSF 2 "register_operand" "w")]
   2682 	     UNSPEC_FLOAT_CONVERT)]
   2683 	  UNSPEC_MERGE_PTRUE))]
   2684   "TARGET_SVE"
   2685   "fcvt\t%0.<Vewtype>, %1/m, %2.<Vetype>"
   2686 )
   2687 
   2688 ;; Unpack the low or high half of a predicate, where "high" refers to
   2689 ;; the low-numbered lanes for big-endian and the high-numbered lanes
   2690 ;; for little-endian.
   2691 (define_expand "vec_unpack<su>_<perm_hilo>_<mode>"
   2692   [(match_operand:<VWIDE> 0 "register_operand")
   2693    (unspec:<VWIDE> [(match_operand:PRED_BHS 1 "register_operand")]
   2694 		   UNPACK)]
   2695   "TARGET_SVE"
   2696   {
   2697     emit_insn ((<hi_lanes_optab>
   2698 		? gen_aarch64_sve_punpkhi_<PRED_BHS:mode>
   2699 		: gen_aarch64_sve_punpklo_<PRED_BHS:mode>)
   2700 	       (operands[0], operands[1]));
   2701     DONE;
   2702   }
   2703 )
   2704 
   2705 ;; PUNPKHI and PUNPKLO.
   2706 (define_insn "aarch64_sve_punpk<perm_hilo>_<mode>"
   2707   [(set (match_operand:<VWIDE> 0 "register_operand" "=Upa")
   2708 	(unspec:<VWIDE> [(match_operand:PRED_BHS 1 "register_operand" "Upa")]
   2709 			UNPACK_UNSIGNED))]
   2710   "TARGET_SVE"
   2711   "punpk<perm_hilo>\t%0.h, %1.b"
   2712 )
   2713 
   2714 ;; Unpack the low or high half of a vector, where "high" refers to
   2715 ;; the low-numbered lanes for big-endian and the high-numbered lanes
   2716 ;; for little-endian.
   2717 (define_expand "vec_unpack<su>_<perm_hilo>_<SVE_BHSI:mode>"
   2718   [(match_operand:<VWIDE> 0 "register_operand")
   2719    (unspec:<VWIDE> [(match_operand:SVE_BHSI 1 "register_operand")] UNPACK)]
   2720   "TARGET_SVE"
   2721   {
   2722     emit_insn ((<hi_lanes_optab>
   2723 		? gen_aarch64_sve_<su>unpkhi_<SVE_BHSI:mode>
   2724 		: gen_aarch64_sve_<su>unpklo_<SVE_BHSI:mode>)
   2725 	       (operands[0], operands[1]));
   2726     DONE;
   2727   }
   2728 )
   2729 
   2730 ;; SUNPKHI, UUNPKHI, SUNPKLO and UUNPKLO.
   2731 (define_insn "aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>"
   2732   [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
   2733 	(unspec:<VWIDE> [(match_operand:SVE_BHSI 1 "register_operand" "w")]
   2734 			UNPACK))]
   2735   "TARGET_SVE"
   2736   "<su>unpk<perm_hilo>\t%0.<Vewtype>, %1.<Vetype>"
   2737 )
   2738 
   2739 ;; Unpack one half of a VNx4SF to VNx2DF, or one half of a VNx8HF to VNx4SF.
   2740 ;; First unpack the source without conversion, then float-convert the
   2741 ;; unpacked source.
   2742 (define_expand "vec_unpacks_<perm_hilo>_<mode>"
   2743   [(match_operand:<VWIDE> 0 "register_operand")
   2744    (unspec:SVE_HSF [(match_operand:SVE_HSF 1 "register_operand")]
   2745 		   UNPACK_UNSIGNED)]
   2746   "TARGET_SVE"
   2747   {
   2748     /* Use ZIP to do the unpack, since we don't care about the upper halves
   2749        and since it has the nice property of not needing any subregs.
   2750        If using UUNPK* turns out to be preferable, we could model it as
   2751        a ZIP whose first operand is zero.  */
   2752     rtx temp = gen_reg_rtx (<MODE>mode);
   2753     emit_insn ((<hi_lanes_optab>
   2754 		? gen_aarch64_sve_zip2<mode>
   2755 		: gen_aarch64_sve_zip1<mode>)
   2756 		(temp, operands[1], operands[1]));
   2757     rtx ptrue = force_reg (<VWIDE_PRED>mode, CONSTM1_RTX (<VWIDE_PRED>mode));
   2758     emit_insn (gen_aarch64_sve_extend<mode><Vwide>2 (operands[0],
   2759 						     ptrue, temp));
   2760     DONE;
   2761   }
   2762 )
   2763 
   2764 ;; Unpack one half of a VNx4SI to VNx2DF.  First unpack from VNx4SI
   2765 ;; to VNx2DI, reinterpret the VNx2DI as a VNx4SI, then convert the
   2766 ;; unpacked VNx4SI to VNx2DF.
   2767 (define_expand "vec_unpack<su_optab>_float_<perm_hilo>_vnx4si"
   2768   [(match_operand:VNx2DF 0 "register_operand")
   2769    (FLOATUORS:VNx2DF
   2770      (unspec:VNx2DI [(match_operand:VNx4SI 1 "register_operand")]
   2771 		    UNPACK_UNSIGNED))]
   2772   "TARGET_SVE"
   2773   {
   2774     /* Use ZIP to do the unpack, since we don't care about the upper halves
   2775        and since it has the nice property of not needing any subregs.
   2776        If using UUNPK* turns out to be preferable, we could model it as
   2777        a ZIP whose first operand is zero.  */
   2778     rtx temp = gen_reg_rtx (VNx4SImode);
   2779     emit_insn ((<hi_lanes_optab>
   2780 	        ? gen_aarch64_sve_zip2vnx4si
   2781 	        : gen_aarch64_sve_zip1vnx4si)
   2782 	       (temp, operands[1], operands[1]));
   2783     rtx ptrue = force_reg (VNx2BImode, CONSTM1_RTX (VNx2BImode));
   2784     emit_insn (gen_aarch64_sve_<FLOATUORS:optab>vnx4sivnx2df2 (operands[0],
   2785 							       ptrue, temp));
   2786     DONE;
   2787   }
   2788 )
   2789 
   2790 ;; Predicate pack.  Use UZP1 on the narrower type, which discards
   2791 ;; the high part of each wide element.
   2792 (define_insn "vec_pack_trunc_<Vwide>"
   2793   [(set (match_operand:PRED_BHS 0 "register_operand" "=Upa")
   2794 	(unspec:PRED_BHS
   2795 	  [(match_operand:<VWIDE> 1 "register_operand" "Upa")
   2796 	   (match_operand:<VWIDE> 2 "register_operand" "Upa")]
   2797 	  UNSPEC_PACK))]
   2798   "TARGET_SVE"
   2799   "uzp1\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
   2800 )
   2801 
   2802 ;; Integer pack.  Use UZP1 on the narrower type, which discards
   2803 ;; the high part of each wide element.
   2804 (define_insn "vec_pack_trunc_<Vwide>"
   2805   [(set (match_operand:SVE_BHSI 0 "register_operand" "=w")
   2806 	(unspec:SVE_BHSI
   2807 	  [(match_operand:<VWIDE> 1 "register_operand" "w")
   2808 	   (match_operand:<VWIDE> 2 "register_operand" "w")]
   2809 	  UNSPEC_PACK))]
   2810   "TARGET_SVE"
   2811   "uzp1\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
   2812 )
   2813 
   2814 ;; Convert two vectors of DF to SF, or two vectors of SF to HF, and pack
   2815 ;; the results into a single vector.
   2816 (define_expand "vec_pack_trunc_<Vwide>"
   2817   [(set (match_dup 4)
   2818 	(unspec:SVE_HSF
   2819 	  [(match_dup 3)
   2820 	   (unspec:SVE_HSF [(match_operand:<VWIDE> 1 "register_operand")]
   2821 			   UNSPEC_FLOAT_CONVERT)]
   2822 	  UNSPEC_MERGE_PTRUE))
   2823    (set (match_dup 5)
   2824 	(unspec:SVE_HSF
   2825 	  [(match_dup 3)
   2826 	   (unspec:SVE_HSF [(match_operand:<VWIDE> 2 "register_operand")]
   2827 			   UNSPEC_FLOAT_CONVERT)]
   2828 	  UNSPEC_MERGE_PTRUE))
   2829    (set (match_operand:SVE_HSF 0 "register_operand")
   2830 	(unspec:SVE_HSF [(match_dup 4) (match_dup 5)] UNSPEC_UZP1))]
   2831   "TARGET_SVE"
   2832   {
   2833     operands[3] = force_reg (<VWIDE_PRED>mode, CONSTM1_RTX (<VWIDE_PRED>mode));
   2834     operands[4] = gen_reg_rtx (<MODE>mode);
   2835     operands[5] = gen_reg_rtx (<MODE>mode);
   2836   }
   2837 )
   2838 
   2839 ;; Convert two vectors of DF to SI and pack the results into a single vector.
   2840 (define_expand "vec_pack_<su>fix_trunc_vnx2df"
   2841   [(set (match_dup 4)
   2842 	(unspec:VNx4SI
   2843 	  [(match_dup 3)
   2844 	   (FIXUORS:VNx4SI (match_operand:VNx2DF 1 "register_operand"))]
   2845 	  UNSPEC_MERGE_PTRUE))
   2846    (set (match_dup 5)
   2847 	(unspec:VNx4SI
   2848 	  [(match_dup 3)
   2849 	   (FIXUORS:VNx4SI (match_operand:VNx2DF 2 "register_operand"))]
   2850 	  UNSPEC_MERGE_PTRUE))
   2851    (set (match_operand:VNx4SI 0 "register_operand")
   2852 	(unspec:VNx4SI [(match_dup 4) (match_dup 5)] UNSPEC_UZP1))]
   2853   "TARGET_SVE"
   2854   {
   2855     operands[3] = force_reg (VNx2BImode, CONSTM1_RTX (VNx2BImode));
   2856     operands[4] = gen_reg_rtx (VNx4SImode);
   2857     operands[5] = gen_reg_rtx (VNx4SImode);
   2858   }
   2859 )
   2860 
   2861 ;; Predicated floating-point operations with select.
   2862 (define_expand "cond_<optab><mode>"
   2863   [(set (match_operand:SVE_F 0 "register_operand")
   2864 	(unspec:SVE_F
   2865 	  [(match_operand:<VPRED> 1 "register_operand")
   2866 	   (unspec:SVE_F
   2867 	     [(match_operand:SVE_F 2 "register_operand")
   2868 	      (match_operand:SVE_F 3 "register_operand")]
   2869 	     SVE_COND_FP_BINARY)
   2870 	   (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
   2871 	  UNSPEC_SEL))]
   2872   "TARGET_SVE"
   2873 )
   2874 
   2875 ;; Predicated floating-point operations with select matching output.
   2876 (define_insn "*cond_<optab><mode>_0"
   2877   [(set (match_operand:SVE_F 0 "register_operand" "+w, w, ?&w")
   2878 	(unspec:SVE_F
   2879 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   2880 	   (unspec:SVE_F
   2881 	     [(match_operand:SVE_F 2 "register_operand" "0, w, w")
   2882 	      (match_operand:SVE_F 3 "register_operand" "w, 0, w")]
   2883 	     SVE_COND_FP_BINARY)
   2884 	   (match_dup 0)]
   2885 	  UNSPEC_SEL))]
   2886   "TARGET_SVE"
   2887   "@
   2888    <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   2889    <sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   2890    movprfx\t%0, %1/m, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   2891   [(set_attr "movprfx" "*,*,yes")]
   2892 )
   2893 
   2894 ;; Predicated floating-point operations with select matching first operand.
   2895 (define_insn "*cond_<optab><mode>_2"
   2896   [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
   2897 	(unspec:SVE_F
   2898 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   2899 	   (unspec:SVE_F
   2900 	     [(match_operand:SVE_F 2 "register_operand" "0, w")
   2901 	      (match_operand:SVE_F 3 "register_operand" "w, w")]
   2902 	     SVE_COND_FP_BINARY)
   2903 	   (match_dup 2)]
   2904 	  UNSPEC_SEL))]
   2905   "TARGET_SVE"
   2906   "@
   2907    <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   2908    movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   2909   [(set_attr "movprfx" "*,yes")]
   2910 )
   2911 
   2912 ;; Predicated floating-point operations with select matching second operand.
   2913 (define_insn "*cond_<optab><mode>_3"
   2914   [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
   2915 	(unspec:SVE_F
   2916 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   2917 	   (unspec:SVE_F
   2918 	     [(match_operand:SVE_F 2 "register_operand" "w, w")
   2919 	      (match_operand:SVE_F 3 "register_operand" "0, w")]
   2920 	     SVE_COND_FP_BINARY)
   2921 	   (match_dup 3)]
   2922 	  UNSPEC_SEL))]
   2923   "TARGET_SVE"
   2924   "@
   2925    <sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   2926    movprfx\t%0, %3\;<sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
   2927   [(set_attr "movprfx" "*,yes")]
   2928 )
   2929 
   2930 ;; Predicated floating-point operations with select matching zero.
   2931 (define_insn "*cond_<optab><mode>_z"
   2932   [(set (match_operand:SVE_F 0 "register_operand" "=&w")
   2933 	(unspec:SVE_F
   2934 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2935 	   (unspec:SVE_F
   2936 	     [(match_operand:SVE_F 2 "register_operand" "w")
   2937 	      (match_operand:SVE_F 3 "register_operand" "w")]
   2938 	     SVE_COND_FP_BINARY)
   2939 	   (match_operand:SVE_F 4 "aarch64_simd_imm_zero")]
   2940 	  UNSPEC_SEL))]
   2941   "TARGET_SVE"
   2942   "movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   2943   [(set_attr "movprfx" "yes")]
   2944 )
   2945 
   2946 ;; Synthetic predication of floating-point operations with select unmatched.
   2947 (define_insn_and_split "*cond_<optab><mode>_any"
   2948   [(set (match_operand:SVE_F 0 "register_operand" "=&w")
   2949 	(unspec:SVE_F
   2950 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
   2951 	   (unspec:SVE_F
   2952 	     [(match_operand:SVE_F 2 "register_operand" "w")
   2953 	      (match_operand:SVE_F 3 "register_operand" "w")]
   2954 	     SVE_COND_FP_BINARY)
   2955 	   (match_operand:SVE_F 4 "register_operand" "w")]
   2956 	  UNSPEC_SEL))]
   2957   "TARGET_SVE"
   2958   "#"
   2959   "&& reload_completed
   2960    && !(rtx_equal_p (operands[0], operands[4])
   2961         || rtx_equal_p (operands[2], operands[4])
   2962         || rtx_equal_p (operands[3], operands[4]))"
   2963   ; Not matchable by any one insn or movprfx insn.  We need a separate select.
   2964   [(set (match_dup 0)
   2965 	(unspec:SVE_F [(match_dup 1) (match_dup 2) (match_dup 4)] UNSPEC_SEL))
   2966    (set (match_dup 0)
   2967 	(unspec:SVE_F
   2968 	  [(match_dup 1)
   2969 	   (unspec:SVE_F [(match_dup 0) (match_dup 3)] SVE_COND_FP_BINARY)
   2970            (match_dup 0)]
   2971 	  UNSPEC_SEL))]
   2972 )
   2973 
   2974 ;; Predicated floating-point ternary operations with select.
   2975 (define_expand "cond_<optab><mode>"
   2976   [(set (match_operand:SVE_F 0 "register_operand")
   2977 	(unspec:SVE_F
   2978 	  [(match_operand:<VPRED> 1 "register_operand")
   2979 	   (unspec:SVE_F
   2980 	     [(match_operand:SVE_F 2 "register_operand")
   2981 	      (match_operand:SVE_F 3 "register_operand")
   2982 	      (match_operand:SVE_F 4 "register_operand")]
   2983 	     SVE_COND_FP_TERNARY)
   2984 	   (match_operand:SVE_F 5 "aarch64_simd_reg_or_zero")]
   2985 	  UNSPEC_SEL))]
   2986   "TARGET_SVE"
   2987 {
   2988   /* Swap the multiplication operands if the fallback value is the
   2989      second of the two.  */
   2990   if (rtx_equal_p (operands[3], operands[5]))
   2991     std::swap (operands[2], operands[3]);
   2992 })
   2993 
   2994 ;; Predicated floating-point ternary operations using the FMAD-like form.
   2995 (define_insn "*cond_<optab><mode>_2"
   2996   [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
   2997 	(unspec:SVE_F
   2998 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   2999 	   (unspec:SVE_F
   3000 	     [(match_operand:SVE_F 2 "register_operand" "0, w")
   3001 	      (match_operand:SVE_F 3 "register_operand" "w, w")
   3002 	      (match_operand:SVE_F 4 "register_operand" "w, w")]
   3003 	     SVE_COND_FP_TERNARY)
   3004 	   (match_dup 2)]
   3005 	  UNSPEC_SEL))]
   3006   "TARGET_SVE"
   3007   "@
   3008    <sve_fmad_op>\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   3009    movprfx\t%0, %2\;<sve_fmad_op>\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
   3010   [(set_attr "movprfx" "*,yes")]
   3011 )
   3012 
   3013 ;; Predicated floating-point ternary operations using the FMLA-like form.
   3014 (define_insn "*cond_<optab><mode>_4"
   3015   [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
   3016 	(unspec:SVE_F
   3017 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   3018 	   (unspec:SVE_F
   3019 	     [(match_operand:SVE_F 2 "register_operand" "w, w")
   3020 	      (match_operand:SVE_F 3 "register_operand" "w, w")
   3021 	      (match_operand:SVE_F 4 "register_operand" "0, w")]
   3022 	     SVE_COND_FP_TERNARY)
   3023 	   (match_dup 4)]
   3024 	  UNSPEC_SEL))]
   3025   "TARGET_SVE"
   3026   "@
   3027    <sve_fmla_op>\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   3028    movprfx\t%0, %4\;<sve_fmla_op>\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>"
   3029   [(set_attr "movprfx" "*,yes")]
   3030 )
   3031 
   3032 ;; Predicated floating-point ternary operations in which the value for
   3033 ;; inactive lanes is distinct from the other inputs.
   3034 (define_insn_and_split "*cond_<optab><mode>_any"
   3035   [(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, ?&w")
   3036 	(unspec:SVE_F
   3037 	  [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
   3038 	   (unspec:SVE_F
   3039 	     [(match_operand:SVE_F 2 "register_operand" "w, w, w")
   3040 	      (match_operand:SVE_F 3 "register_operand" "w, w, w")
   3041 	      (match_operand:SVE_F 4 "register_operand" "w, w, w")]
   3042 	     SVE_COND_FP_TERNARY)
   3043 	   (match_operand:SVE_F 5 "aarch64_simd_reg_or_zero" "Dz, 0, w")]
   3044 	  UNSPEC_SEL))]
   3045   "TARGET_SVE
   3046    && !rtx_equal_p (operands[2], operands[5])
   3047    && !rtx_equal_p (operands[3], operands[5])
   3048    && !rtx_equal_p (operands[4], operands[5])"
   3049   "@
   3050    movprfx\t%0.<Vetype>, %1/z, %4.<Vetype>\;<sve_fmla_op>\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   3051    movprfx\t%0.<Vetype>, %1/m, %4.<Vetype>\;<sve_fmla_op>\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   3052    #"
   3053   "&& reload_completed
   3054    && !CONSTANT_P (operands[5])
   3055    && !rtx_equal_p (operands[0], operands[5])"
   3056   [(set (match_dup 0)
   3057 	(unspec:SVE_F [(match_dup 1) (match_dup 4) (match_dup 5)] UNSPEC_SEL))
   3058    (set (match_dup 0)
   3059 	(unspec:SVE_F
   3060 	  [(match_dup 1)
   3061 	   (unspec:SVE_F [(match_dup 2) (match_dup 3) (match_dup 0)]
   3062 			 SVE_COND_FP_TERNARY)
   3063            (match_dup 0)]
   3064 	  UNSPEC_SEL))]
   3065   ""
   3066   [(set_attr "movprfx" "yes")]
   3067 )
   3068 
   3069 ;; Shift an SVE vector left and insert a scalar into element 0.
   3070 (define_insn "vec_shl_insert_<mode>"
   3071   [(set (match_operand:SVE_ALL 0 "register_operand" "=w, w")
   3072 	(unspec:SVE_ALL
   3073 	  [(match_operand:SVE_ALL 1 "register_operand" "0, 0")
   3074 	   (match_operand:<VEL> 2 "register_operand" "rZ, w")]
   3075 	  UNSPEC_INSR))]
   3076   "TARGET_SVE"
   3077   "@
   3078    insr\t%0.<Vetype>, %<vwcore>2
   3079    insr\t%0.<Vetype>, %<Vetype>2"
   3080 )
   3081 
   3082 (define_expand "copysign<mode>3"
   3083   [(match_operand:SVE_F 0 "register_operand")
   3084    (match_operand:SVE_F 1 "register_operand")
   3085    (match_operand:SVE_F 2 "register_operand")]
   3086   "TARGET_SVE"
   3087   {
   3088     rtx sign = gen_reg_rtx (<V_INT_EQUIV>mode);
   3089     rtx mant = gen_reg_rtx (<V_INT_EQUIV>mode);
   3090     rtx int_res = gen_reg_rtx (<V_INT_EQUIV>mode);
   3091     int bits = GET_MODE_UNIT_BITSIZE (<MODE>mode) - 1;
   3092 
   3093     rtx arg1 = lowpart_subreg (<V_INT_EQUIV>mode, operands[1], <MODE>mode);
   3094     rtx arg2 = lowpart_subreg (<V_INT_EQUIV>mode, operands[2], <MODE>mode);
   3095 
   3096     emit_insn (gen_and<v_int_equiv>3
   3097 	       (sign, arg2,
   3098 		aarch64_simd_gen_const_vector_dup (<V_INT_EQUIV>mode,
   3099 						   HOST_WIDE_INT_M1U
   3100 						   << bits)));
   3101     emit_insn (gen_and<v_int_equiv>3
   3102 	       (mant, arg1,
   3103 		aarch64_simd_gen_const_vector_dup (<V_INT_EQUIV>mode,
   3104 						   ~(HOST_WIDE_INT_M1U
   3105 						     << bits))));
   3106     emit_insn (gen_ior<v_int_equiv>3 (int_res, sign, mant));
   3107     emit_move_insn (operands[0], gen_lowpart (<MODE>mode, int_res));
   3108     DONE;
   3109   }
   3110 )
   3111 
   3112 (define_expand "xorsign<mode>3"
   3113   [(match_operand:SVE_F 0 "register_operand")
   3114    (match_operand:SVE_F 1 "register_operand")
   3115    (match_operand:SVE_F 2 "register_operand")]
   3116   "TARGET_SVE"
   3117   {
   3118     rtx sign = gen_reg_rtx (<V_INT_EQUIV>mode);
   3119     rtx int_res = gen_reg_rtx (<V_INT_EQUIV>mode);
   3120     int bits = GET_MODE_UNIT_BITSIZE (<MODE>mode) - 1;
   3121 
   3122     rtx arg1 = lowpart_subreg (<V_INT_EQUIV>mode, operands[1], <MODE>mode);
   3123     rtx arg2 = lowpart_subreg (<V_INT_EQUIV>mode, operands[2], <MODE>mode);
   3124 
   3125     emit_insn (gen_and<v_int_equiv>3
   3126 	       (sign, arg2,
   3127 		aarch64_simd_gen_const_vector_dup (<V_INT_EQUIV>mode,
   3128 						   HOST_WIDE_INT_M1U
   3129 						   << bits)));
   3130     emit_insn (gen_xor<v_int_equiv>3 (int_res, arg1, sign));
   3131     emit_move_insn (operands[0], gen_lowpart (<MODE>mode, int_res));
   3132     DONE;
   3133   }
   3134 )
   3135