1 ;; Machine description for AArch64 AdvSIMD architecture.
2 ;; Copyright (C) 2011-2013 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
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)
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.
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/>.
22 ; Main data types used by the insntructions
24 (define_attr "simd_mode" "unknown,none,V8QI,V16QI,V4HI,V8HI,V2SI,V4SI,V2DI,V2SF,V4SF,V2DF,OI,CI,XI,DI,DF,SI,SF,HI,QI"
25 (const_string "unknown"))
28 ; Classification of AdvSIMD instructions for scheduling purposes.
29 ; Do not set this attribute and the "v8type" attribute together in
30 ; any instruction pattern.
32 ; simd_abd integer absolute difference and accumulate.
33 ; simd_abdl integer absolute difference and accumulate (long).
34 ; simd_adal integer add and accumulate (long).
35 ; simd_add integer addition/subtraction.
36 ; simd_addl integer addition/subtraction (long).
37 ; simd_addlv across lanes integer sum (long).
38 ; simd_addn integer addition/subtraction (narrow).
39 ; simd_addn2 integer addition/subtraction (narrow, high).
40 ; simd_addv across lanes integer sum.
41 ; simd_cls count leading sign/zero bits.
42 ; simd_cmp compare / create mask.
43 ; simd_cnt population count.
44 ; simd_dup duplicate element.
45 ; simd_dupgp duplicate general purpose register.
46 ; simd_ext bitwise extract from pair.
47 ; simd_fabd floating absolute difference and accumulate.
48 ; simd_fadd floating point add/sub.
49 ; simd_fcmp floating point compare.
50 ; simd_fcvti floating point convert to integer.
51 ; simd_fcvtl floating-point convert upsize.
52 ; simd_fcvtn floating-point convert downsize (narrow).
53 ; simd_fcvtn2 floating-point convert downsize (narrow, high).
54 ; simd_fdiv floating point division.
55 ; simd_fminmax floating point min/max.
56 ; simd_fminmaxv across lanes floating point min/max.
57 ; simd_fmla floating point multiply-add.
58 ; simd_fmla_elt floating point multiply-add (by element).
59 ; simd_fmul floating point multiply.
60 ; simd_fmul_elt floating point multiply (by element).
61 ; simd_fnegabs floating point neg/abs.
62 ; simd_frecpe floating point reciprocal estimate.
63 ; simd_frecps floating point reciprocal step.
64 ; simd_frecpx floating point reciprocal exponent.
65 ; simd_frint floating point round to integer.
66 ; simd_fsqrt floating point square root.
67 ; simd_icvtf integer convert to floating point.
68 ; simd_ins insert element.
69 ; simd_insgp insert general purpose register.
70 ; simd_load1 load multiple structures to one register (LD1).
71 ; simd_load1r load single structure to all lanes of one register (LD1R).
72 ; simd_load1s load single structure to one lane of one register (LD1 [index]).
73 ; simd_load2 load multiple structures to two registers (LD1, LD2).
74 ; simd_load2r load single structure to all lanes of two registers (LD1R, LD2R).
75 ; simd_load2s load single structure to one lane of two registers (LD2 [index]).
76 ; simd_load3 load multiple structures to three registers (LD1, LD3).
77 ; simd_load3r load single structure to all lanes of three registers (LD3R).
78 ; simd_load3s load single structure to one lane of three registers (LD3 [index]).
79 ; simd_load4 load multiple structures to four registers (LD1, LD2, LD4).
80 ; simd_load4r load single structure to all lanes of four registers (LD4R).
81 ; simd_load4s load single structure to one lane of four registers (LD4 [index]).
82 ; simd_logic logical operation.
83 ; simd_logic_imm logcial operation (immediate).
84 ; simd_minmax integer min/max.
85 ; simd_minmaxv across lanes integer min/max,
86 ; simd_mla integer multiply-accumulate.
87 ; simd_mla_elt integer multiply-accumulate (by element).
88 ; simd_mlal integer multiply-accumulate (long).
89 ; simd_mlal_elt integer multiply-accumulate (by element, long).
90 ; simd_move move register.
91 ; simd_move_imm move immediate.
92 ; simd_movgp move element to general purpose register.
93 ; simd_mul integer multiply.
94 ; simd_mul_elt integer multiply (by element).
95 ; simd_mull integer multiply (long).
96 ; simd_mull_elt integer multiply (by element, long).
97 ; simd_negabs integer negate/absolute.
98 ; simd_rbit bitwise reverse.
99 ; simd_rcpe integer reciprocal estimate.
100 ; simd_rcps integer reciprocal square root.
101 ; simd_rev element reverse.
102 ; simd_sat_add integer saturating addition/subtraction.
103 ; simd_sat_mlal integer saturating multiply-accumulate (long).
104 ; simd_sat_mlal_elt integer saturating multiply-accumulate (by element, long).
105 ; simd_sat_mul integer saturating multiply.
106 ; simd_sat_mul_elt integer saturating multiply (by element).
107 ; simd_sat_mull integer saturating multiply (long).
108 ; simd_sat_mull_elt integer saturating multiply (by element, long).
109 ; simd_sat_negabs integer saturating negate/absolute.
110 ; simd_sat_shift integer saturating shift.
111 ; simd_sat_shift_imm integer saturating shift (immediate).
112 ; simd_sat_shiftn_imm integer saturating shift (narrow, immediate).
113 ; simd_sat_shiftn2_imm integer saturating shift (narrow, high, immediate).
114 ; simd_shift shift register/vector.
115 ; simd_shift_acc shift accumulate.
116 ; simd_shift_imm shift immediate.
117 ; simd_shift_imm_acc shift immediate and accumualte.
118 ; simd_shiftl shift register/vector (long).
119 ; simd_shiftl_imm shift register/vector (long, immediate).
120 ; simd_shiftn_imm shift register/vector (narrow, immediate).
121 ; simd_shiftn2_imm shift register/vector (narrow, high, immediate).
122 ; simd_store1 store multiple structures from one register (ST1).
123 ; simd_store1s store single structure from one lane of one register (ST1 [index]).
124 ; simd_store2 store multiple structures from two registers (ST1, ST2).
125 ; simd_store2s store single structure from one lane of two registers (ST2 [index]).
126 ; simd_store3 store multiple structures from three registers (ST1, ST3).
127 ; simd_store3s store single structure from one lane of three register (ST3 [index]).
128 ; simd_store4 store multiple structures from four registers (ST1, ST2, ST4).
129 ; simd_store4s store single structure from one lane for four registers (ST4 [index]).
130 ; simd_tbl table lookup.
131 ; simd_trn transpose.
135 (define_attr "simd_type"
216 simd_sat_shiftn_imm,\
217 simd_sat_shiftn2_imm,\
239 (const_string "none"))
242 ; The "neon_type" attribute is used by the AArch32 backend. Below is a mapping
243 ; from "simd_type" to "neon_type".
245 (define_attr "neon_type"
246 "neon_int_1,neon_int_2,neon_int_3,neon_int_4,neon_int_5,neon_vqneg_vqabs,
247 neon_vmov,neon_vaba,neon_vsma,neon_vaba_qqq,
248 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,neon_mul_qqq_8_16_32_ddd_32,
249 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,
250 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,neon_mla_qqq_8_16,
251 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,
252 neon_mla_qqq_32_qqd_32_scalar,neon_mul_ddd_16_scalar_32_16_long_scalar,
253 neon_mul_qqd_32_scalar,neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,
254 neon_shift_1,neon_shift_2,neon_shift_3,neon_vshl_ddd,
255 neon_vqshl_vrshl_vqrshl_qqq,neon_vsra_vrsra,neon_fp_vadd_ddd_vabs_dd,
256 neon_fp_vadd_qqq_vabs_qq,neon_fp_vsum,neon_fp_vmul_ddd,neon_fp_vmul_qqd,
257 neon_fp_vmla_ddd,neon_fp_vmla_qqq,neon_fp_vmla_ddd_scalar,
258 neon_fp_vmla_qqq_scalar,neon_fp_vrecps_vrsqrts_ddd,
259 neon_fp_vrecps_vrsqrts_qqq,neon_bp_simple,neon_bp_2cycle,neon_bp_3cycle,
260 neon_ldr,neon_str,neon_vld1_1_2_regs,neon_vld1_3_4_regs,
261 neon_vld2_2_regs_vld1_vld2_all_lanes,neon_vld2_4_regs,neon_vld3_vld4,
262 neon_vst1_1_2_regs_vst2_2_regs,neon_vst1_3_4_regs,
263 neon_vst2_4_regs_vst3_vst4,neon_vst3_vst4,neon_vld1_vld2_lane,
264 neon_vld3_vld4_lane,neon_vst1_vst2_lane,neon_vst3_vst4_lane,
265 neon_vld3_vld4_all_lanes,neon_mcr,neon_mcr_2_mcrr,neon_mrc,neon_mrrc,
266 neon_ldm_2,neon_stm_2,none,unknown"
268 (eq_attr "simd_type" "simd_dup") (const_string "neon_bp_simple")
269 (eq_attr "simd_type" "simd_movgp") (const_string "neon_bp_simple")
270 (eq_attr "simd_type" "simd_add,simd_logic,simd_logic_imm") (const_string "neon_int_1")
271 (eq_attr "simd_type" "simd_negabs,simd_addlv") (const_string "neon_int_3")
272 (eq_attr "simd_type" "simd_addn,simd_addn2,simd_addl,simd_sat_add,simd_sat_negabs") (const_string "neon_int_4")
273 (eq_attr "simd_type" "simd_move") (const_string "neon_vmov")
274 (eq_attr "simd_type" "simd_ins") (const_string "neon_mcr")
275 (and (eq_attr "simd_type" "simd_mul,simd_sat_mul") (eq_attr "simd_mode" "V8QI,V4HI")) (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
276 (and (eq_attr "simd_type" "simd_mul,simd_sat_mul") (eq_attr "simd_mode" "V2SI,V8QI,V16QI,V2SI")) (const_string "neon_mul_qqq_8_16_32_ddd_32")
277 (and (eq_attr "simd_type" "simd_mull,simd_sat_mull") (eq_attr "simd_mode" "V8QI,V16QI,V4HI,V8HI")) (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
278 (and (eq_attr "simd_type" "simd_mull,simd_sat_mull") (eq_attr "simd_mode" "V2SI,V4SI,V2DI")) (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
279 (and (eq_attr "simd_type" "simd_mla,simd_sat_mlal") (eq_attr "simd_mode" "V8QI,V4HI")) (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
280 (and (eq_attr "simd_type" "simd_mla,simd_sat_mlal") (eq_attr "simd_mode" "V2SI")) (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
281 (and (eq_attr "simd_type" "simd_mla,simd_sat_mlal") (eq_attr "simd_mode" "V16QI,V8HI")) (const_string "neon_mla_qqq_8_16")
282 (and (eq_attr "simd_type" "simd_mla,simd_sat_mlal") (eq_attr "simd_mode" "V4SI")) (const_string "neon_mla_qqq_32_qqd_32_scalar")
283 (and (eq_attr "simd_type" "simd_mlal") (eq_attr "simd_mode" "V8QI,V16QI,V4HI,V8HI")) (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
284 (and (eq_attr "simd_type" "simd_mlal") (eq_attr "simd_mode" "V2SI,V4SI,V2DI")) (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
285 (and (eq_attr "simd_type" "simd_fmla") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vmla_ddd")
286 (and (eq_attr "simd_type" "simd_fmla") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vmla_qqq")
287 (and (eq_attr "simd_type" "simd_fmla_elt") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vmla_ddd_scalar")
288 (and (eq_attr "simd_type" "simd_fmla_elt") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vmla_qqq_scalar")
289 (and (eq_attr "simd_type" "simd_fmul,simd_fmul_elt,simd_fdiv,simd_fsqrt") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vmul_ddd")
290 (and (eq_attr "simd_type" "simd_fmul,simd_fmul_elt,simd_fdiv,simd_fsqrt") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vmul_qqd")
291 (and (eq_attr "simd_type" "simd_fadd") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vadd_ddd_vabs_dd")
292 (and (eq_attr "simd_type" "simd_fadd") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vadd_qqq_vabs_qq")
293 (and (eq_attr "simd_type" "simd_fnegabs,simd_fminmax,simd_fminmaxv") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vadd_ddd_vabs_dd")
294 (and (eq_attr "simd_type" "simd_fnegabs,simd_fminmax,simd_fminmaxv") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vadd_qqq_vabs_qq")
295 (and (eq_attr "simd_type" "simd_shift,simd_shift_acc") (eq_attr "simd_mode" "V8QI,V4HI,V2SI")) (const_string "neon_vshl_ddd")
296 (and (eq_attr "simd_type" "simd_shift,simd_shift_acc") (eq_attr "simd_mode" "V16QI,V8HI,V4SI,V2DI")) (const_string "neon_shift_3")
297 (eq_attr "simd_type" "simd_minmax,simd_minmaxv") (const_string "neon_int_5")
298 (eq_attr "simd_type" "simd_shiftn_imm,simd_shiftn2_imm,simd_shiftl_imm,") (const_string "neon_shift_1")
299 (eq_attr "simd_type" "simd_load1,simd_load2") (const_string "neon_vld1_1_2_regs")
300 (eq_attr "simd_type" "simd_load3,simd_load3") (const_string "neon_vld1_3_4_regs")
301 (eq_attr "simd_type" "simd_load1r,simd_load2r,simd_load3r,simd_load4r") (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
302 (eq_attr "simd_type" "simd_load1s,simd_load2s") (const_string "neon_vld1_vld2_lane")
303 (eq_attr "simd_type" "simd_load3s,simd_load4s") (const_string "neon_vld3_vld4_lane")
304 (eq_attr "simd_type" "simd_store1,simd_store2") (const_string "neon_vst1_1_2_regs_vst2_2_regs")
305 (eq_attr "simd_type" "simd_store3,simd_store4") (const_string "neon_vst1_3_4_regs")
306 (eq_attr "simd_type" "simd_store1s,simd_store2s") (const_string "neon_vst1_vst2_lane")
307 (eq_attr "simd_type" "simd_store3s,simd_store4s") (const_string "neon_vst3_vst4_lane")
308 (and (eq_attr "simd_type" "simd_frecpe,simd_frecps") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vrecps_vrsqrts_ddd")
309 (and (eq_attr "simd_type" "simd_frecpe,simd_frecps") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vrecps_vrsqrts_qqq")
310 (eq_attr "simd_type" "none") (const_string "none")
312 (const_string "unknown")))
315 (define_expand "mov<mode>"
316 [(set (match_operand:VALL 0 "aarch64_simd_nonimmediate_operand" "")
317 (match_operand:VALL 1 "aarch64_simd_general_operand" ""))]
320 if (GET_CODE (operands[0]) == MEM)
321 operands[1] = force_reg (<MODE>mode, operands[1]);
325 (define_expand "movmisalign<mode>"
326 [(set (match_operand:VALL 0 "aarch64_simd_nonimmediate_operand" "")
327 (match_operand:VALL 1 "aarch64_simd_general_operand" ""))]
330 /* This pattern is not permitted to fail during expansion: if both arguments
331 are non-registers (e.g. memory := constant, which can be created by the
332 auto-vectorizer), force operand 1 into a register. */
333 if (!register_operand (operands[0], <MODE>mode)
334 && !register_operand (operands[1], <MODE>mode))
335 operands[1] = force_reg (<MODE>mode, operands[1]);
338 (define_insn "aarch64_simd_dup<mode>"
339 [(set (match_operand:VDQ 0 "register_operand" "=w")
340 (vec_duplicate:VDQ (match_operand:<VEL> 1 "register_operand" "r")))]
342 "dup\\t%0.<Vtype>, %<vw>1"
343 [(set_attr "simd_type" "simd_dupgp")
344 (set_attr "simd_mode" "<MODE>")]
347 (define_insn "aarch64_dup_lane<mode>"
348 [(set (match_operand:VDQ_I 0 "register_operand" "=w")
351 (match_operand:<VCON> 1 "register_operand" "w")
352 (parallel [(match_operand:SI 2 "immediate_operand" "i")])
355 "dup\\t%<v>0<Vmtype>, %1.<Vetype>[%2]"
356 [(set_attr "simd_type" "simd_dup")
357 (set_attr "simd_mode" "<MODE>")]
360 (define_insn "aarch64_dup_lane<mode>"
361 [(set (match_operand:SDQ_I 0 "register_operand" "=w")
363 (match_operand:<VCON> 1 "register_operand" "w")
364 (parallel [(match_operand:SI 2 "immediate_operand" "i")])
367 "dup\\t%<v>0<Vmtype>, %1.<Vetype>[%2]"
368 [(set_attr "simd_type" "simd_dup")
369 (set_attr "simd_mode" "<MODE>")]
372 (define_insn "aarch64_simd_dup<mode>"
373 [(set (match_operand:VDQF 0 "register_operand" "=w")
374 (vec_duplicate:VDQF (match_operand:<VEL> 1 "register_operand" "w")))]
376 "dup\\t%0.<Vtype>, %1.<Vetype>[0]"
377 [(set_attr "simd_type" "simd_dup")
378 (set_attr "simd_mode" "<MODE>")]
381 (define_insn "*aarch64_simd_mov<mode>"
382 [(set (match_operand:VD 0 "aarch64_simd_nonimmediate_operand"
383 "=w, Utv, w, ?r, ?w, ?r, w")
384 (match_operand:VD 1 "aarch64_simd_general_operand"
385 "Utv, w, w, w, r, r, Dn"))]
387 && (register_operand (operands[0], <MODE>mode)
388 || register_operand (operands[1], <MODE>mode))"
390 switch (which_alternative)
392 case 0: return "ld1\t{%0.<Vtype>}, %1";
393 case 1: return "st1\t{%1.<Vtype>}, %0";
394 case 2: return "orr\t%0.<Vbtype>, %1.<Vbtype>, %1.<Vbtype>";
395 case 3: return "umov\t%0, %1.d[0]";
396 case 4: return "ins\t%0.d[0], %1";
397 case 5: return "mov\t%0, %1";
399 return aarch64_output_simd_mov_immediate (&operands[1],
401 default: gcc_unreachable ();
404 [(set_attr "simd_type" "simd_load1,simd_store1,simd_move,simd_movgp,simd_insgp,simd_move,simd_move_imm")
405 (set_attr "simd_mode" "<MODE>")]
408 (define_insn "*aarch64_simd_mov<mode>"
409 [(set (match_operand:VQ 0 "aarch64_simd_nonimmediate_operand"
410 "=w, Utv, w, ?r, ?w, ?r, w")
411 (match_operand:VQ 1 "aarch64_simd_general_operand"
412 "Utv, w, w, w, r, r, Dn"))]
414 && (register_operand (operands[0], <MODE>mode)
415 || register_operand (operands[1], <MODE>mode))"
417 switch (which_alternative)
419 case 0: return "ld1\t{%0.<Vtype>}, %1";
420 case 1: return "st1\t{%1.<Vtype>}, %0";
421 case 2: return "orr\t%0.<Vbtype>, %1.<Vbtype>, %1.<Vbtype>";
422 case 3: return "umov\t%0, %1.d[0]\;umov\t%H0, %1.d[1]";
423 case 4: return "ins\t%0.d[0], %1\;ins\t%0.d[1], %H1";
426 return aarch64_output_simd_mov_immediate (&operands[1],
428 default: gcc_unreachable ();
431 [(set_attr "simd_type" "simd_load1,simd_store1,simd_move,simd_movgp,simd_insgp,simd_move,simd_move_imm")
432 (set_attr "simd_mode" "<MODE>")
433 (set_attr "length" "4,4,4,8,8,8,4")]
437 [(set (match_operand:VQ 0 "register_operand" "")
438 (match_operand:VQ 1 "register_operand" ""))]
439 "TARGET_SIMD && reload_completed
440 && GP_REGNUM_P (REGNO (operands[0]))
441 && GP_REGNUM_P (REGNO (operands[1]))"
442 [(set (match_dup 0) (match_dup 1))
443 (set (match_dup 2) (match_dup 3))]
445 int rdest = REGNO (operands[0]);
446 int rsrc = REGNO (operands[1]);
449 dest[0] = gen_rtx_REG (DImode, rdest);
450 src[0] = gen_rtx_REG (DImode, rsrc);
451 dest[1] = gen_rtx_REG (DImode, rdest + 1);
452 src[1] = gen_rtx_REG (DImode, rsrc + 1);
454 aarch64_simd_disambiguate_copy (operands, dest, src, 2);
457 (define_insn "orn<mode>3"
458 [(set (match_operand:VDQ 0 "register_operand" "=w")
459 (ior:VDQ (not:VDQ (match_operand:VDQ 1 "register_operand" "w"))
460 (match_operand:VDQ 2 "register_operand" "w")))]
462 "orn\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
463 [(set_attr "simd_type" "simd_logic")
464 (set_attr "simd_mode" "<MODE>")]
467 (define_insn "bic<mode>3"
468 [(set (match_operand:VDQ 0 "register_operand" "=w")
469 (and:VDQ (not:VDQ (match_operand:VDQ 1 "register_operand" "w"))
470 (match_operand:VDQ 2 "register_operand" "w")))]
472 "bic\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
473 [(set_attr "simd_type" "simd_logic")
474 (set_attr "simd_mode" "<MODE>")]
477 (define_insn "add<mode>3"
478 [(set (match_operand:VDQ 0 "register_operand" "=w")
479 (plus:VDQ (match_operand:VDQ 1 "register_operand" "w")
480 (match_operand:VDQ 2 "register_operand" "w")))]
482 "add\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
483 [(set_attr "simd_type" "simd_add")
484 (set_attr "simd_mode" "<MODE>")]
487 (define_insn "sub<mode>3"
488 [(set (match_operand:VDQ 0 "register_operand" "=w")
489 (minus:VDQ (match_operand:VDQ 1 "register_operand" "w")
490 (match_operand:VDQ 2 "register_operand" "w")))]
492 "sub\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
493 [(set_attr "simd_type" "simd_add")
494 (set_attr "simd_mode" "<MODE>")]
497 (define_insn "mul<mode>3"
498 [(set (match_operand:VDQM 0 "register_operand" "=w")
499 (mult:VDQM (match_operand:VDQM 1 "register_operand" "w")
500 (match_operand:VDQM 2 "register_operand" "w")))]
502 "mul\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
503 [(set_attr "simd_type" "simd_mul")
504 (set_attr "simd_mode" "<MODE>")]
507 (define_insn "neg<mode>2"
508 [(set (match_operand:VDQ 0 "register_operand" "=w")
509 (neg:VDQ (match_operand:VDQ 1 "register_operand" "w")))]
511 "neg\t%0.<Vtype>, %1.<Vtype>"
512 [(set_attr "simd_type" "simd_negabs")
513 (set_attr "simd_mode" "<MODE>")]
516 (define_insn "abs<mode>2"
517 [(set (match_operand:VDQ 0 "register_operand" "=w")
518 (abs:VDQ (match_operand:VDQ 1 "register_operand" "w")))]
520 "abs\t%0.<Vtype>, %1.<Vtype>"
521 [(set_attr "simd_type" "simd_negabs")
522 (set_attr "simd_mode" "<MODE>")]
525 (define_insn "abd<mode>_3"
526 [(set (match_operand:VDQ_BHSI 0 "register_operand" "=w")
527 (abs:VDQ_BHSI (minus:VDQ_BHSI
528 (match_operand:VDQ_BHSI 1 "register_operand" "w")
529 (match_operand:VDQ_BHSI 2 "register_operand" "w"))))]
531 "sabd\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
532 [(set_attr "simd_type" "simd_abd")
533 (set_attr "simd_mode" "<MODE>")]
536 (define_insn "aba<mode>_3"
537 [(set (match_operand:VDQ_BHSI 0 "register_operand" "=w")
538 (plus:VDQ_BHSI (abs:VDQ_BHSI (minus:VDQ_BHSI
539 (match_operand:VDQ_BHSI 1 "register_operand" "w")
540 (match_operand:VDQ_BHSI 2 "register_operand" "w")))
541 (match_operand:VDQ_BHSI 3 "register_operand" "0")))]
543 "saba\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
544 [(set_attr "simd_type" "simd_abd")
545 (set_attr "simd_mode" "<MODE>")]
548 (define_insn "fabd<mode>_3"
549 [(set (match_operand:VDQF 0 "register_operand" "=w")
550 (abs:VDQF (minus:VDQF
551 (match_operand:VDQF 1 "register_operand" "w")
552 (match_operand:VDQF 2 "register_operand" "w"))))]
554 "fabd\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
555 [(set_attr "simd_type" "simd_fabd")
556 (set_attr "simd_mode" "<MODE>")]
559 (define_insn "and<mode>3"
560 [(set (match_operand:VDQ 0 "register_operand" "=w")
561 (and:VDQ (match_operand:VDQ 1 "register_operand" "w")
562 (match_operand:VDQ 2 "register_operand" "w")))]
564 "and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
565 [(set_attr "simd_type" "simd_logic")
566 (set_attr "simd_mode" "<MODE>")]
569 (define_insn "ior<mode>3"
570 [(set (match_operand:VDQ 0 "register_operand" "=w")
571 (ior:VDQ (match_operand:VDQ 1 "register_operand" "w")
572 (match_operand:VDQ 2 "register_operand" "w")))]
574 "orr\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
575 [(set_attr "simd_type" "simd_logic")
576 (set_attr "simd_mode" "<MODE>")]
579 (define_insn "xor<mode>3"
580 [(set (match_operand:VDQ 0 "register_operand" "=w")
581 (xor:VDQ (match_operand:VDQ 1 "register_operand" "w")
582 (match_operand:VDQ 2 "register_operand" "w")))]
584 "eor\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
585 [(set_attr "simd_type" "simd_logic")
586 (set_attr "simd_mode" "<MODE>")]
589 (define_insn "one_cmpl<mode>2"
590 [(set (match_operand:VDQ 0 "register_operand" "=w")
591 (not:VDQ (match_operand:VDQ 1 "register_operand" "w")))]
593 "not\t%0.<Vbtype>, %1.<Vbtype>"
594 [(set_attr "simd_type" "simd_logic")
595 (set_attr "simd_mode" "<MODE>")]
598 (define_insn "aarch64_simd_vec_set<mode>"
599 [(set (match_operand:VQ_S 0 "register_operand" "=w")
602 (match_operand:<VEL> 1 "register_operand" "r"))
603 (match_operand:VQ_S 3 "register_operand" "0")
604 (match_operand:SI 2 "immediate_operand" "i")))]
606 "ins\t%0.<Vetype>[%p2], %w1";
607 [(set_attr "simd_type" "simd_insgp")
608 (set_attr "simd_mode" "<MODE>")]
611 (define_insn "aarch64_simd_lshr<mode>"
612 [(set (match_operand:VDQ 0 "register_operand" "=w")
613 (lshiftrt:VDQ (match_operand:VDQ 1 "register_operand" "w")
614 (match_operand:VDQ 2 "aarch64_simd_rshift_imm" "Dr")))]
616 "ushr\t%0.<Vtype>, %1.<Vtype>, %2"
617 [(set_attr "simd_type" "simd_shift_imm")
618 (set_attr "simd_mode" "<MODE>")]
621 (define_insn "aarch64_simd_ashr<mode>"
622 [(set (match_operand:VDQ 0 "register_operand" "=w")
623 (ashiftrt:VDQ (match_operand:VDQ 1 "register_operand" "w")
624 (match_operand:VDQ 2 "aarch64_simd_rshift_imm" "Dr")))]
626 "sshr\t%0.<Vtype>, %1.<Vtype>, %2"
627 [(set_attr "simd_type" "simd_shift_imm")
628 (set_attr "simd_mode" "<MODE>")]
631 (define_insn "aarch64_simd_imm_shl<mode>"
632 [(set (match_operand:VDQ 0 "register_operand" "=w")
633 (ashift:VDQ (match_operand:VDQ 1 "register_operand" "w")
634 (match_operand:VDQ 2 "aarch64_simd_lshift_imm" "Dl")))]
636 "shl\t%0.<Vtype>, %1.<Vtype>, %2"
637 [(set_attr "simd_type" "simd_shift_imm")
638 (set_attr "simd_mode" "<MODE>")]
641 (define_insn "aarch64_simd_reg_sshl<mode>"
642 [(set (match_operand:VDQ 0 "register_operand" "=w")
643 (ashift:VDQ (match_operand:VDQ 1 "register_operand" "w")
644 (match_operand:VDQ 2 "register_operand" "w")))]
646 "sshl\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
647 [(set_attr "simd_type" "simd_shift")
648 (set_attr "simd_mode" "<MODE>")]
651 (define_insn "aarch64_simd_reg_shl<mode>_unsigned"
652 [(set (match_operand:VDQ 0 "register_operand" "=w")
653 (unspec:VDQ [(match_operand:VDQ 1 "register_operand" "w")
654 (match_operand:VDQ 2 "register_operand" "w")]
655 UNSPEC_ASHIFT_UNSIGNED))]
657 "ushl\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
658 [(set_attr "simd_type" "simd_shift")
659 (set_attr "simd_mode" "<MODE>")]
662 (define_insn "aarch64_simd_reg_shl<mode>_signed"
663 [(set (match_operand:VDQ 0 "register_operand" "=w")
664 (unspec:VDQ [(match_operand:VDQ 1 "register_operand" "w")
665 (match_operand:VDQ 2 "register_operand" "w")]
666 UNSPEC_ASHIFT_SIGNED))]
668 "sshl\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
669 [(set_attr "simd_type" "simd_shift")
670 (set_attr "simd_mode" "<MODE>")]
673 (define_expand "ashl<mode>3"
674 [(match_operand:VDQ 0 "register_operand" "")
675 (match_operand:VDQ 1 "register_operand" "")
676 (match_operand:SI 2 "general_operand" "")]
679 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
682 if (CONST_INT_P (operands[2]))
684 shift_amount = INTVAL (operands[2]);
685 if (shift_amount >= 0 && shift_amount < bit_width)
687 rtx tmp = aarch64_simd_gen_const_vector_dup (<MODE>mode,
689 emit_insn (gen_aarch64_simd_imm_shl<mode> (operands[0],
696 operands[2] = force_reg (SImode, operands[2]);
699 else if (MEM_P (operands[2]))
701 operands[2] = force_reg (SImode, operands[2]);
704 if (REG_P (operands[2]))
706 rtx tmp = gen_reg_rtx (<MODE>mode);
707 emit_insn (gen_aarch64_simd_dup<mode> (tmp,
708 convert_to_mode (<VEL>mode,
711 emit_insn (gen_aarch64_simd_reg_sshl<mode> (operands[0], operands[1],
720 (define_expand "lshr<mode>3"
721 [(match_operand:VDQ 0 "register_operand" "")
722 (match_operand:VDQ 1 "register_operand" "")
723 (match_operand:SI 2 "general_operand" "")]
726 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
729 if (CONST_INT_P (operands[2]))
731 shift_amount = INTVAL (operands[2]);
732 if (shift_amount > 0 && shift_amount <= bit_width)
734 rtx tmp = aarch64_simd_gen_const_vector_dup (<MODE>mode,
736 emit_insn (gen_aarch64_simd_lshr<mode> (operands[0],
742 operands[2] = force_reg (SImode, operands[2]);
744 else if (MEM_P (operands[2]))
746 operands[2] = force_reg (SImode, operands[2]);
749 if (REG_P (operands[2]))
751 rtx tmp = gen_reg_rtx (SImode);
752 rtx tmp1 = gen_reg_rtx (<MODE>mode);
753 emit_insn (gen_negsi2 (tmp, operands[2]));
754 emit_insn (gen_aarch64_simd_dup<mode> (tmp1,
755 convert_to_mode (<VEL>mode,
757 emit_insn (gen_aarch64_simd_reg_shl<mode>_unsigned (operands[0],
767 (define_expand "ashr<mode>3"
768 [(match_operand:VDQ 0 "register_operand" "")
769 (match_operand:VDQ 1 "register_operand" "")
770 (match_operand:SI 2 "general_operand" "")]
773 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
776 if (CONST_INT_P (operands[2]))
778 shift_amount = INTVAL (operands[2]);
779 if (shift_amount > 0 && shift_amount <= bit_width)
781 rtx tmp = aarch64_simd_gen_const_vector_dup (<MODE>mode,
783 emit_insn (gen_aarch64_simd_ashr<mode> (operands[0],
789 operands[2] = force_reg (SImode, operands[2]);
791 else if (MEM_P (operands[2]))
793 operands[2] = force_reg (SImode, operands[2]);
796 if (REG_P (operands[2]))
798 rtx tmp = gen_reg_rtx (SImode);
799 rtx tmp1 = gen_reg_rtx (<MODE>mode);
800 emit_insn (gen_negsi2 (tmp, operands[2]));
801 emit_insn (gen_aarch64_simd_dup<mode> (tmp1,
802 convert_to_mode (<VEL>mode,
804 emit_insn (gen_aarch64_simd_reg_shl<mode>_signed (operands[0],
814 (define_expand "vashl<mode>3"
815 [(match_operand:VDQ 0 "register_operand" "")
816 (match_operand:VDQ 1 "register_operand" "")
817 (match_operand:VDQ 2 "register_operand" "")]
820 emit_insn (gen_aarch64_simd_reg_sshl<mode> (operands[0], operands[1],
825 ;; Using mode VQ_S as there is no V2DImode neg!
826 ;; Negating individual lanes most certainly offsets the
827 ;; gain from vectorization.
828 (define_expand "vashr<mode>3"
829 [(match_operand:VQ_S 0 "register_operand" "")
830 (match_operand:VQ_S 1 "register_operand" "")
831 (match_operand:VQ_S 2 "register_operand" "")]
834 rtx neg = gen_reg_rtx (<MODE>mode);
835 emit (gen_neg<mode>2 (neg, operands[2]));
836 emit_insn (gen_aarch64_simd_reg_shl<mode>_signed (operands[0], operands[1],
841 (define_expand "vlshr<mode>3"
842 [(match_operand:VQ_S 0 "register_operand" "")
843 (match_operand:VQ_S 1 "register_operand" "")
844 (match_operand:VQ_S 2 "register_operand" "")]
847 rtx neg = gen_reg_rtx (<MODE>mode);
848 emit (gen_neg<mode>2 (neg, operands[2]));
849 emit_insn (gen_aarch64_simd_reg_shl<mode>_unsigned (operands[0], operands[1],
854 (define_expand "vec_set<mode>"
855 [(match_operand:VQ_S 0 "register_operand" "+w")
856 (match_operand:<VEL> 1 "register_operand" "r")
857 (match_operand:SI 2 "immediate_operand" "")]
860 HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
861 emit_insn (gen_aarch64_simd_vec_set<mode> (operands[0], operands[1],
862 GEN_INT (elem), operands[0]));
867 (define_insn "aarch64_simd_vec_setv2di"
868 [(set (match_operand:V2DI 0 "register_operand" "=w")
871 (match_operand:DI 1 "register_operand" "r"))
872 (match_operand:V2DI 3 "register_operand" "0")
873 (match_operand:SI 2 "immediate_operand" "i")))]
875 "ins\t%0.d[%p2], %1";
876 [(set_attr "simd_type" "simd_insgp")
877 (set_attr "simd_mode" "V2DI")]
880 (define_expand "vec_setv2di"
881 [(match_operand:V2DI 0 "register_operand" "+w")
882 (match_operand:DI 1 "register_operand" "r")
883 (match_operand:SI 2 "immediate_operand" "")]
886 HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
887 emit_insn (gen_aarch64_simd_vec_setv2di (operands[0], operands[1],
888 GEN_INT (elem), operands[0]));
893 (define_insn "aarch64_simd_vec_set<mode>"
894 [(set (match_operand:VDQF 0 "register_operand" "=w")
897 (match_operand:<VEL> 1 "register_operand" "w"))
898 (match_operand:VDQF 3 "register_operand" "0")
899 (match_operand:SI 2 "immediate_operand" "i")))]
901 "ins\t%0.<Vetype>[%p2], %1.<Vetype>[0]";
902 [(set_attr "simd_type" "simd_ins")
903 (set_attr "simd_mode" "<MODE>")]
906 (define_expand "vec_set<mode>"
907 [(match_operand:VDQF 0 "register_operand" "+w")
908 (match_operand:<VEL> 1 "register_operand" "w")
909 (match_operand:SI 2 "immediate_operand" "")]
912 HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
913 emit_insn (gen_aarch64_simd_vec_set<mode> (operands[0], operands[1],
914 GEN_INT (elem), operands[0]));
920 (define_insn "aarch64_mla<mode>"
921 [(set (match_operand:VQ_S 0 "register_operand" "=w")
922 (plus:VQ_S (mult:VQ_S (match_operand:VQ_S 2 "register_operand" "w")
923 (match_operand:VQ_S 3 "register_operand" "w"))
924 (match_operand:VQ_S 1 "register_operand" "0")))]
926 "mla\t%0.<Vtype>, %2.<Vtype>, %3.<Vtype>"
927 [(set_attr "simd_type" "simd_mla")
928 (set_attr "simd_mode" "<MODE>")]
931 (define_insn "aarch64_mls<mode>"
932 [(set (match_operand:VQ_S 0 "register_operand" "=w")
933 (minus:VQ_S (match_operand:VQ_S 1 "register_operand" "0")
934 (mult:VQ_S (match_operand:VQ_S 2 "register_operand" "w")
935 (match_operand:VQ_S 3 "register_operand" "w"))))]
937 "mls\t%0.<Vtype>, %2.<Vtype>, %3.<Vtype>"
938 [(set_attr "simd_type" "simd_mla")
939 (set_attr "simd_mode" "<MODE>")]
942 ;; Max/Min operations.
943 (define_insn "<maxmin><mode>3"
944 [(set (match_operand:VQ_S 0 "register_operand" "=w")
945 (MAXMIN:VQ_S (match_operand:VQ_S 1 "register_operand" "w")
946 (match_operand:VQ_S 2 "register_operand" "w")))]
948 "<maxmin>\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
949 [(set_attr "simd_type" "simd_minmax")
950 (set_attr "simd_mode" "<MODE>")]
953 ;; Move into low-half clearing high half to 0.
955 (define_insn "move_lo_quad_<mode>"
956 [(set (match_operand:VQ 0 "register_operand" "=w")
958 (match_operand:<VHALF> 1 "register_operand" "w")
959 (vec_duplicate:<VHALF> (const_int 0))))]
962 [(set_attr "simd_type" "simd_dup")
963 (set_attr "simd_mode" "<MODE>")]
966 ;; Move into high-half.
968 (define_insn "aarch64_simd_move_hi_quad_<mode>"
969 [(set (match_operand:VQ 0 "register_operand" "+w")
973 (match_operand:VQ 2 "vect_par_cnst_lo_half" ""))
974 (match_operand:<VHALF> 1 "register_operand" "w")))]
976 "ins\\t%0.d[1], %1.d[0]";
977 [(set_attr "simd_type" "simd_ins")
978 (set_attr "simd_mode" "<MODE>")]
981 (define_expand "move_hi_quad_<mode>"
982 [(match_operand:VQ 0 "register_operand" "")
983 (match_operand:<VHALF> 1 "register_operand" "")]
986 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, false);
987 emit_insn (gen_aarch64_simd_move_hi_quad_<mode> (operands[0],
992 ;; Narrowing operations.
995 (define_insn "aarch64_simd_vec_pack_trunc_<mode>"
996 [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
997 (truncate:<VNARROWQ> (match_operand:VQN 1 "register_operand" "w")))]
999 "xtn\\t%0.<Vntype>, %1.<Vtype>"
1000 [(set_attr "simd_type" "simd_shiftn_imm")
1001 (set_attr "simd_mode" "<MODE>")]
1004 (define_expand "vec_pack_trunc_<mode>"
1005 [(match_operand:<VNARROWD> 0 "register_operand" "")
1006 (match_operand:VDN 1 "register_operand" "")
1007 (match_operand:VDN 2 "register_operand" "")]
1010 rtx tempreg = gen_reg_rtx (<VDBL>mode);
1012 emit_insn (gen_move_lo_quad_<Vdbl> (tempreg, operands[1]));
1013 emit_insn (gen_move_hi_quad_<Vdbl> (tempreg, operands[2]));
1014 emit_insn (gen_aarch64_simd_vec_pack_trunc_<Vdbl> (operands[0], tempreg));
1020 (define_insn "vec_pack_trunc_<mode>"
1021 [(set (match_operand:<VNARROWQ2> 0 "register_operand" "+&w")
1022 (vec_concat:<VNARROWQ2>
1023 (truncate:<VNARROWQ> (match_operand:VQN 1 "register_operand" "w"))
1024 (truncate:<VNARROWQ> (match_operand:VQN 2 "register_operand" "w"))))]
1026 "xtn\\t%0.<Vntype>, %1.<Vtype>\;xtn2\\t%0.<V2ntype>, %2.<Vtype>"
1027 [(set_attr "simd_type" "simd_shiftn2_imm")
1028 (set_attr "simd_mode" "<MODE>")
1029 (set_attr "length" "8")]
1032 ;; Widening operations.
1034 (define_insn "aarch64_simd_vec_unpack<su>_lo_<mode>"
1035 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
1036 (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
1037 (match_operand:VQW 1 "register_operand" "w")
1038 (match_operand:VQW 2 "vect_par_cnst_lo_half" "")
1041 "<su>shll %0.<Vwtype>, %1.<Vhalftype>, 0"
1042 [(set_attr "simd_type" "simd_shiftl_imm")
1043 (set_attr "simd_mode" "<MODE>")]
1046 (define_insn "aarch64_simd_vec_unpack<su>_hi_<mode>"
1047 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
1048 (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
1049 (match_operand:VQW 1 "register_operand" "w")
1050 (match_operand:VQW 2 "vect_par_cnst_hi_half" "")
1053 "<su>shll2 %0.<Vwtype>, %1.<Vtype>, 0"
1054 [(set_attr "simd_type" "simd_shiftl_imm")
1055 (set_attr "simd_mode" "<MODE>")]
1058 (define_expand "vec_unpack<su>_hi_<mode>"
1059 [(match_operand:<VWIDE> 0 "register_operand" "")
1060 (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))]
1063 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
1064 emit_insn (gen_aarch64_simd_vec_unpack<su>_hi_<mode> (operands[0],
1070 (define_expand "vec_unpack<su>_lo_<mode>"
1071 [(match_operand:<VWIDE> 0 "register_operand" "")
1072 (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand" ""))]
1075 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, false);
1076 emit_insn (gen_aarch64_simd_vec_unpack<su>_lo_<mode> (operands[0],
1082 ;; Widening arithmetic.
1084 (define_insn "aarch64_simd_vec_<su>mult_lo_<mode>"
1085 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
1086 (mult:<VWIDE> (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
1087 (match_operand:VQW 1 "register_operand" "w")
1088 (match_operand:VQW 3 "vect_par_cnst_lo_half" "")))
1089 (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
1090 (match_operand:VQW 2 "register_operand" "w")
1093 "<su>mull\\t%0.<Vwtype>, %1.<Vhalftype>, %2.<Vhalftype>"
1094 [(set_attr "simd_type" "simd_mull")
1095 (set_attr "simd_mode" "<MODE>")]
1098 (define_expand "vec_widen_<su>mult_lo_<mode>"
1099 [(match_operand:<VWIDE> 0 "register_operand" "")
1100 (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand" ""))
1101 (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand" ""))]
1104 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, false);
1105 emit_insn (gen_aarch64_simd_vec_<su>mult_lo_<mode> (operands[0],
1112 (define_insn "aarch64_simd_vec_<su>mult_hi_<mode>"
1113 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
1114 (mult:<VWIDE> (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
1115 (match_operand:VQW 1 "register_operand" "w")
1116 (match_operand:VQW 3 "vect_par_cnst_hi_half" "")))
1117 (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
1118 (match_operand:VQW 2 "register_operand" "w")
1121 "<su>mull2\\t%0.<Vwtype>, %1.<Vtype>, %2.<Vtype>"
1122 [(set_attr "simd_type" "simd_mull")
1123 (set_attr "simd_mode" "<MODE>")]
1126 (define_expand "vec_widen_<su>mult_hi_<mode>"
1127 [(match_operand:<VWIDE> 0 "register_operand" "")
1128 (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand" ""))
1129 (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand" ""))]
1132 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
1133 emit_insn (gen_aarch64_simd_vec_<su>mult_hi_<mode> (operands[0],
1141 ;; FP vector operations.
1142 ;; AArch64 AdvSIMD supports single-precision (32-bit) and
1143 ;; double-precision (64-bit) floating-point data types and arithmetic as
1144 ;; defined by the IEEE 754-2008 standard. This makes them vectorizable
1145 ;; without the need for -ffast-math or -funsafe-math-optimizations.
1147 ;; Floating-point operations can raise an exception. Vectorizing such
1148 ;; operations are safe because of reasons explained below.
1150 ;; ARMv8 permits an extension to enable trapped floating-point
1151 ;; exception handling, however this is an optional feature. In the
1152 ;; event of a floating-point exception being raised by vectorised
1154 ;; 1. If trapped floating-point exceptions are available, then a trap
1155 ;; will be taken when any lane raises an enabled exception. A trap
1156 ;; handler may determine which lane raised the exception.
1157 ;; 2. Alternatively a sticky exception flag is set in the
1158 ;; floating-point status register (FPSR). Software may explicitly
1159 ;; test the exception flags, in which case the tests will either
1160 ;; prevent vectorisation, allowing precise identification of the
1161 ;; failing operation, or if tested outside of vectorisable regions
1162 ;; then the specific operation and lane are not of interest.
1164 ;; FP arithmetic operations.
1166 (define_insn "add<mode>3"
1167 [(set (match_operand:VDQF 0 "register_operand" "=w")
1168 (plus:VDQF (match_operand:VDQF 1 "register_operand" "w")
1169 (match_operand:VDQF 2 "register_operand" "w")))]
1171 "fadd\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
1172 [(set_attr "simd_type" "simd_fadd")
1173 (set_attr "simd_mode" "<MODE>")]
1176 (define_insn "sub<mode>3"
1177 [(set (match_operand:VDQF 0 "register_operand" "=w")
1178 (minus:VDQF (match_operand:VDQF 1 "register_operand" "w")
1179 (match_operand:VDQF 2 "register_operand" "w")))]
1181 "fsub\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
1182 [(set_attr "simd_type" "simd_fadd")
1183 (set_attr "simd_mode" "<MODE>")]
1186 (define_insn "mul<mode>3"
1187 [(set (match_operand:VDQF 0 "register_operand" "=w")
1188 (mult:VDQF (match_operand:VDQF 1 "register_operand" "w")
1189 (match_operand:VDQF 2 "register_operand" "w")))]
1191 "fmul\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
1192 [(set_attr "simd_type" "simd_fmul")
1193 (set_attr "simd_mode" "<MODE>")]
1196 (define_insn "div<mode>3"
1197 [(set (match_operand:VDQF 0 "register_operand" "=w")
1198 (div:VDQF (match_operand:VDQF 1 "register_operand" "w")
1199 (match_operand:VDQF 2 "register_operand" "w")))]
1201 "fdiv\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
1202 [(set_attr "simd_type" "simd_fdiv")
1203 (set_attr "simd_mode" "<MODE>")]
1206 (define_insn "neg<mode>2"
1207 [(set (match_operand:VDQF 0 "register_operand" "=w")
1208 (neg:VDQF (match_operand:VDQF 1 "register_operand" "w")))]
1210 "fneg\\t%0.<Vtype>, %1.<Vtype>"
1211 [(set_attr "simd_type" "simd_fnegabs")
1212 (set_attr "simd_mode" "<MODE>")]
1215 (define_insn "abs<mode>2"
1216 [(set (match_operand:VDQF 0 "register_operand" "=w")
1217 (abs:VDQF (match_operand:VDQF 1 "register_operand" "w")))]
1219 "fabs\\t%0.<Vtype>, %1.<Vtype>"
1220 [(set_attr "simd_type" "simd_fnegabs")
1221 (set_attr "simd_mode" "<MODE>")]
1224 (define_insn "fma<mode>4"
1225 [(set (match_operand:VDQF 0 "register_operand" "=w")
1226 (fma:VDQF (match_operand:VDQF 1 "register_operand" "w")
1227 (match_operand:VDQF 2 "register_operand" "w")
1228 (match_operand:VDQF 3 "register_operand" "0")))]
1230 "fmla\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
1231 [(set_attr "simd_type" "simd_fmla")
1232 (set_attr "simd_mode" "<MODE>")]
1235 ;; Vector versions of the floating-point frint patterns.
1236 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round.
1237 (define_insn "<frint_pattern><mode>2"
1238 [(set (match_operand:VDQF 0 "register_operand" "=w")
1239 (unspec:VDQF [(match_operand:VDQF 1 "register_operand" "w")]
1242 "frint<frint_suffix>\\t%0.<Vtype>, %1.<Vtype>"
1243 [(set_attr "simd_type" "simd_frint")
1244 (set_attr "simd_mode" "<MODE>")]
1247 ;; Vector versions of the fcvt standard patterns.
1248 ;; Expands to lbtrunc, lround, lceil, lfloor
1249 (define_insn "l<fcvt_pattern><su_optab><VDQF:mode><fcvt_target>2"
1250 [(set (match_operand:<FCVT_TARGET> 0 "register_operand" "=w")
1251 (FIXUORS:<FCVT_TARGET> (unspec:<FCVT_TARGET>
1252 [(match_operand:VDQF 1 "register_operand" "w")]
1255 "fcvt<frint_suffix><su>\\t%0.<Vtype>, %1.<Vtype>"
1256 [(set_attr "simd_type" "simd_fcvti")
1257 (set_attr "simd_mode" "<MODE>")]
1260 (define_expand "<optab><VDQF:mode><fcvt_target>2"
1261 [(set (match_operand:<FCVT_TARGET> 0 "register_operand")
1262 (FIXUORS:<FCVT_TARGET> (unspec:<FCVT_TARGET>
1263 [(match_operand:VDQF 1 "register_operand")]
1268 (define_expand "<fix_trunc_optab><VDQF:mode><fcvt_target>2"
1269 [(set (match_operand:<FCVT_TARGET> 0 "register_operand")
1270 (FIXUORS:<FCVT_TARGET> (unspec:<FCVT_TARGET>
1271 [(match_operand:VDQF 1 "register_operand")]
1276 (define_expand "ftrunc<VDQF:mode>2"
1277 [(set (match_operand:VDQF 0 "register_operand")
1278 (unspec:VDQF [(match_operand:VDQF 1 "register_operand")]
1283 (define_insn "<optab><fcvt_target><VDQF:mode>2"
1284 [(set (match_operand:VDQF 0 "register_operand" "=w")
1286 (match_operand:<FCVT_TARGET> 1 "register_operand" "w")))]
1288 "<su_optab>cvtf\\t%0.<Vtype>, %1.<Vtype>"
1289 [(set_attr "simd_type" "simd_icvtf")
1290 (set_attr "simd_mode" "<MODE>")]
1293 ;; Conversions between vectors of floats and doubles.
1294 ;; Contains a mix of patterns to match standard pattern names
1295 ;; and those for intrinsics.
1297 ;; Float widening operations.
1299 (define_insn "vec_unpacks_lo_v4sf"
1300 [(set (match_operand:V2DF 0 "register_operand" "=w")
1303 (match_operand:V4SF 1 "register_operand" "w")
1304 (parallel [(const_int 0) (const_int 1)])
1307 "fcvtl\\t%0.2d, %1.2s"
1308 [(set_attr "simd_type" "simd_fcvtl")
1309 (set_attr "simd_mode" "V2DF")]
1312 (define_insn "aarch64_float_extend_lo_v2df"
1313 [(set (match_operand:V2DF 0 "register_operand" "=w")
1315 (match_operand:V2SF 1 "register_operand" "w")))]
1317 "fcvtl\\t%0.2d, %1.2s"
1318 [(set_attr "simd_type" "simd_fcvtl")
1319 (set_attr "simd_mode" "V2DF")]
1322 (define_insn "vec_unpacks_hi_v4sf"
1323 [(set (match_operand:V2DF 0 "register_operand" "=w")
1326 (match_operand:V4SF 1 "register_operand" "w")
1327 (parallel [(const_int 2) (const_int 3)])
1330 "fcvtl2\\t%0.2d, %1.4s"
1331 [(set_attr "simd_type" "simd_fcvtl")
1332 (set_attr "simd_mode" "V2DF")]
1335 ;; Float narrowing operations.
1337 (define_insn "aarch64_float_truncate_lo_v2sf"
1338 [(set (match_operand:V2SF 0 "register_operand" "=w")
1339 (float_truncate:V2SF
1340 (match_operand:V2DF 1 "register_operand" "w")))]
1342 "fcvtn\\t%0.2s, %1.2d"
1343 [(set_attr "simd_type" "simd_fcvtl")
1344 (set_attr "simd_mode" "V2SF")]
1347 (define_insn "aarch64_float_truncate_hi_v4sf"
1348 [(set (match_operand:V4SF 0 "register_operand" "=w")
1350 (match_operand:V2SF 1 "register_operand" "0")
1351 (float_truncate:V2SF
1352 (match_operand:V2DF 2 "register_operand" "w"))))]
1354 "fcvtn2\\t%0.4s, %2.2d"
1355 [(set_attr "simd_type" "simd_fcvtl")
1356 (set_attr "simd_mode" "V4SF")]
1359 (define_expand "vec_pack_trunc_v2df"
1360 [(set (match_operand:V4SF 0 "register_operand")
1362 (float_truncate:V2SF
1363 (match_operand:V2DF 1 "register_operand"))
1364 (float_truncate:V2SF
1365 (match_operand:V2DF 2 "register_operand"))
1369 rtx tmp = gen_reg_rtx (V2SFmode);
1370 emit_insn (gen_aarch64_float_truncate_lo_v2sf (tmp, operands[1]));
1371 emit_insn (gen_aarch64_float_truncate_hi_v4sf (operands[0],
1377 (define_expand "vec_pack_trunc_df"
1378 [(set (match_operand:V2SF 0 "register_operand")
1381 (match_operand:DF 1 "register_operand"))
1383 (match_operand:DF 2 "register_operand"))
1387 rtx tmp = gen_reg_rtx (V2SFmode);
1388 emit_insn (gen_move_lo_quad_v2df (tmp, operands[1]));
1389 emit_insn (gen_move_hi_quad_v2df (tmp, operands[2]));
1390 emit_insn (gen_aarch64_float_truncate_lo_v2sf (operands[0], tmp));
1395 (define_insn "aarch64_vmls<mode>"
1396 [(set (match_operand:VDQF 0 "register_operand" "=w")
1397 (minus:VDQF (match_operand:VDQF 1 "register_operand" "0")
1398 (mult:VDQF (match_operand:VDQF 2 "register_operand" "w")
1399 (match_operand:VDQF 3 "register_operand" "w"))))]
1401 "fmls\\t%0.<Vtype>, %2.<Vtype>, %3.<Vtype>"
1402 [(set_attr "simd_type" "simd_fmla")
1403 (set_attr "simd_mode" "<MODE>")]
1407 ;; Max/Min are introduced by idiom recognition by GCC's mid-end. An
1409 ;; a = (b < c) ? b : c;
1410 ;; is idiom-matched as MIN_EXPR<b,c> only if -ffinite-math-only is enabled
1411 ;; either explicitly or indirectly via -ffast-math.
1413 ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL.
1414 ;; The 'smax' and 'smin' RTL standard pattern names do not specify which
1415 ;; operand will be returned when both operands are zero (i.e. they may not
1416 ;; honour signed zeroes), or when either operand is NaN. Therefore GCC
1417 ;; only introduces MIN_EXPR/MAX_EXPR in fast math mode or when not honouring
1420 (define_insn "smax<mode>3"
1421 [(set (match_operand:VDQF 0 "register_operand" "=w")
1422 (smax:VDQF (match_operand:VDQF 1 "register_operand" "w")
1423 (match_operand:VDQF 2 "register_operand" "w")))]
1425 "fmaxnm\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
1426 [(set_attr "simd_type" "simd_fminmax")
1427 (set_attr "simd_mode" "<MODE>")]
1430 (define_insn "smin<mode>3"
1431 [(set (match_operand:VDQF 0 "register_operand" "=w")
1432 (smin:VDQF (match_operand:VDQF 1 "register_operand" "w")
1433 (match_operand:VDQF 2 "register_operand" "w")))]
1435 "fminnm\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
1436 [(set_attr "simd_type" "simd_fminmax")
1437 (set_attr "simd_mode" "<MODE>")]
1440 ;; FP 'across lanes' max and min ops.
1442 (define_insn "reduc_s<fmaxminv>_v4sf"
1443 [(set (match_operand:V4SF 0 "register_operand" "=w")
1444 (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "w")]
1447 "f<fmaxminv>nmv\\t%s0, %1.4s";
1448 [(set_attr "simd_type" "simd_fminmaxv")
1449 (set_attr "simd_mode" "V4SF")]
1452 (define_insn "reduc_s<fmaxminv>_<mode>"
1453 [(set (match_operand:V2F 0 "register_operand" "=w")
1454 (unspec:V2F [(match_operand:V2F 1 "register_operand" "w")]
1457 "f<fmaxminv>nmp\\t%0.<Vtype>, %1.<Vtype>, %1.<Vtype>";
1458 [(set_attr "simd_type" "simd_fminmax")
1459 (set_attr "simd_mode" "<MODE>")]
1462 ;; FP 'across lanes' add.
1464 (define_insn "aarch64_addpv4sf"
1465 [(set (match_operand:V4SF 0 "register_operand" "=w")
1466 (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "w")]
1469 "faddp\\t%0.4s, %1.4s, %1.4s"
1470 [(set_attr "simd_type" "simd_fadd")
1471 (set_attr "simd_mode" "V4SF")]
1474 (define_expand "reduc_uplus_v4sf"
1475 [(set (match_operand:V4SF 0 "register_operand" "=w")
1476 (match_operand:V4SF 1 "register_operand" "w"))]
1479 rtx tmp = gen_reg_rtx (V4SFmode);
1480 emit_insn (gen_aarch64_addpv4sf (tmp, operands[1]));
1481 emit_insn (gen_aarch64_addpv4sf (operands[0], tmp));
1485 (define_expand "reduc_splus_v4sf"
1486 [(set (match_operand:V4SF 0 "register_operand" "=w")
1487 (match_operand:V4SF 1 "register_operand" "w"))]
1490 rtx tmp = gen_reg_rtx (V4SFmode);
1491 emit_insn (gen_aarch64_addpv4sf (tmp, operands[1]));
1492 emit_insn (gen_aarch64_addpv4sf (operands[0], tmp));
1496 (define_expand "aarch64_addvv4sf"
1497 [(set (match_operand:V4SF 0 "register_operand" "=w")
1498 (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "w")]
1502 emit_insn (gen_reduc_splus_v4sf (operands[0], operands[1]));
1506 (define_insn "aarch64_addv<mode>"
1507 [(set (match_operand:V2F 0 "register_operand" "=w")
1508 (unspec:V2F [(match_operand:V2F 1 "register_operand" "w")]
1511 "faddp\\t%<Vetype>0, %1.<Vtype>"
1512 [(set_attr "simd_type" "simd_fadd")
1513 (set_attr "simd_mode" "<MODE>")]
1516 (define_expand "reduc_uplus_<mode>"
1517 [(set (match_operand:V2F 0 "register_operand" "=w")
1518 (unspec:V2F [(match_operand:V2F 1 "register_operand" "w")]
1524 (define_expand "reduc_splus_<mode>"
1525 [(set (match_operand:V2F 0 "register_operand" "=w")
1526 (unspec:V2F [(match_operand:V2F 1 "register_operand" "w")]
1532 ;; Reduction across lanes.
1534 (define_insn "aarch64_addv<mode>"
1535 [(set (match_operand:VDQV 0 "register_operand" "=w")
1536 (unspec:VDQV [(match_operand:VDQV 1 "register_operand" "w")]
1539 "addv\\t%<Vetype>0, %1.<Vtype>"
1540 [(set_attr "simd_type" "simd_addv")
1541 (set_attr "simd_mode" "<MODE>")]
1544 (define_expand "reduc_splus_<mode>"
1545 [(set (match_operand:VDQV 0 "register_operand" "=w")
1546 (unspec:VDQV [(match_operand:VDQV 1 "register_operand" "w")]
1552 (define_expand "reduc_uplus_<mode>"
1553 [(set (match_operand:VDQV 0 "register_operand" "=w")
1554 (unspec:VDQV [(match_operand:VDQV 1 "register_operand" "w")]
1560 (define_insn "aarch64_addvv2di"
1561 [(set (match_operand:V2DI 0 "register_operand" "=w")
1562 (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "w")]
1566 [(set_attr "simd_type" "simd_add")
1567 (set_attr "simd_mode" "V2DI")]
1570 (define_expand "reduc_uplus_v2di"
1571 [(set (match_operand:V2DI 0 "register_operand" "=w")
1572 (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "w")]
1578 (define_expand "reduc_splus_v2di"
1579 [(set (match_operand:V2DI 0 "register_operand" "=w")
1580 (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "w")]
1586 (define_insn "aarch64_addvv2si"
1587 [(set (match_operand:V2SI 0 "register_operand" "=w")
1588 (unspec:V2SI [(match_operand:V2SI 1 "register_operand" "w")]
1591 "addp\\t%0.2s, %1.2s, %1.2s"
1592 [(set_attr "simd_type" "simd_add")
1593 (set_attr "simd_mode" "V2SI")]
1596 (define_expand "reduc_uplus_v2si"
1597 [(set (match_operand:V2SI 0 "register_operand" "=w")
1598 (unspec:V2SI [(match_operand:V2SI 1 "register_operand" "w")]
1604 (define_expand "reduc_splus_v2si"
1605 [(set (match_operand:V2SI 0 "register_operand" "=w")
1606 (unspec:V2SI [(match_operand:V2SI 1 "register_operand" "w")]
1612 (define_insn "reduc_<maxminv>_<mode>"
1613 [(set (match_operand:VDQV 0 "register_operand" "=w")
1614 (unspec:VDQV [(match_operand:VDQV 1 "register_operand" "w")]
1617 "<maxminv>v\\t%<Vetype>0, %1.<Vtype>"
1618 [(set_attr "simd_type" "simd_minmaxv")
1619 (set_attr "simd_mode" "<MODE>")]
1622 (define_insn "reduc_<maxminv>_v2si"
1623 [(set (match_operand:V2SI 0 "register_operand" "=w")
1624 (unspec:V2SI [(match_operand:V2SI 1 "register_operand" "w")]
1627 "<maxminv>p\\t%0.2s, %1.2s, %1.2s"
1628 [(set_attr "simd_type" "simd_minmax")
1629 (set_attr "simd_mode" "V2SI")]
1632 ;; aarch64_simd_bsl may compile to any of bsl/bif/bit depending on register
1634 ;; Operand 1 is the mask, operands 2 and 3 are the bitfields from which
1637 ;; Thus our BSL is of the form:
1638 ;; op0 = bsl (mask, op2, op3)
1639 ;; We can use any of:
1642 ;; bsl mask, op1, op2
1643 ;; if (op0 = op1) (so 1-bits in mask choose bits from op2, else op0)
1644 ;; bit op0, op2, mask
1645 ;; if (op0 = op2) (so 0-bits in mask choose bits from op1, else op0)
1646 ;; bif op0, op1, mask
1648 (define_insn "aarch64_simd_bsl<mode>_internal"
1649 [(set (match_operand:VALL 0 "register_operand" "=w,w,w")
1652 (match_operand:<V_cmp_result> 1 "register_operand" " 0,w,w")
1653 (match_operand:VALL 2 "register_operand" " w,w,0"))
1656 (match_dup:<V_cmp_result> 1))
1657 (match_operand:VALL 3 "register_operand" " w,0,w"))
1661 bsl\\t%0.<Vbtype>, %2.<Vbtype>, %3.<Vbtype>
1662 bit\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>
1663 bif\\t%0.<Vbtype>, %3.<Vbtype>, %1.<Vbtype>"
1666 (define_expand "aarch64_simd_bsl<mode>"
1667 [(match_operand:VALL 0 "register_operand")
1668 (match_operand:<V_cmp_result> 1 "register_operand")
1669 (match_operand:VALL 2 "register_operand")
1670 (match_operand:VALL 3 "register_operand")]
1673 /* We can't alias operands together if they have different modes. */
1674 operands[1] = gen_lowpart (<V_cmp_result>mode, operands[1]);
1675 emit_insn (gen_aarch64_simd_bsl<mode>_internal (operands[0], operands[1],
1676 operands[2], operands[3]));
1680 (define_expand "aarch64_vcond_internal<mode>"
1681 [(set (match_operand:VDQ 0 "register_operand")
1683 (match_operator 3 "comparison_operator"
1684 [(match_operand:VDQ 4 "register_operand")
1685 (match_operand:VDQ 5 "nonmemory_operand")])
1686 (match_operand:VDQ 1 "nonmemory_operand")
1687 (match_operand:VDQ 2 "nonmemory_operand")))]
1690 int inverse = 0, has_zero_imm_form = 0;
1691 rtx op1 = operands[1];
1692 rtx op2 = operands[2];
1693 rtx mask = gen_reg_rtx (<MODE>mode);
1695 switch (GET_CODE (operands[3]))
1705 has_zero_imm_form = 1;
1715 if (!REG_P (operands[5])
1716 && (operands[5] != CONST0_RTX (<MODE>mode) || !has_zero_imm_form))
1717 operands[5] = force_reg (<MODE>mode, operands[5]);
1719 switch (GET_CODE (operands[3]))
1723 emit_insn (gen_aarch64_cmge<mode> (mask, operands[4], operands[5]));
1728 emit_insn (gen_aarch64_cmgt<mode> (mask, operands[4], operands[5]));
1733 emit_insn (gen_aarch64_cmgeu<mode> (mask, operands[4], operands[5]));
1738 emit_insn (gen_aarch64_cmgtu<mode> (mask, operands[4], operands[5]));
1743 emit_insn (gen_aarch64_cmeq<mode> (mask, operands[4], operands[5]));
1756 /* If we have (a = (b CMP c) ? -1 : 0);
1757 Then we can simply move the generated mask. */
1759 if (op1 == CONSTM1_RTX (<V_cmp_result>mode)
1760 && op2 == CONST0_RTX (<V_cmp_result>mode))
1761 emit_move_insn (operands[0], mask);
1765 op1 = force_reg (<MODE>mode, op1);
1767 op2 = force_reg (<MODE>mode, op2);
1768 emit_insn (gen_aarch64_simd_bsl<mode> (operands[0], mask,
1775 (define_expand "aarch64_vcond_internal<mode>"
1776 [(set (match_operand:VDQF 0 "register_operand")
1778 (match_operator 3 "comparison_operator"
1779 [(match_operand:VDQF 4 "register_operand")
1780 (match_operand:VDQF 5 "nonmemory_operand")])
1781 (match_operand:VDQF 1 "nonmemory_operand")
1782 (match_operand:VDQF 2 "nonmemory_operand")))]
1786 int use_zero_form = 0;
1787 int swap_bsl_operands = 0;
1788 rtx op1 = operands[1];
1789 rtx op2 = operands[2];
1790 rtx mask = gen_reg_rtx (<V_cmp_result>mode);
1791 rtx tmp = gen_reg_rtx (<V_cmp_result>mode);
1793 rtx (*base_comparison) (rtx, rtx, rtx);
1794 rtx (*complimentary_comparison) (rtx, rtx, rtx);
1796 switch (GET_CODE (operands[3]))
1803 if (operands[5] == CONST0_RTX (<MODE>mode))
1810 if (!REG_P (operands[5]))
1811 operands[5] = force_reg (<MODE>mode, operands[5]);
1814 switch (GET_CODE (operands[3]))
1824 base_comparison = gen_aarch64_cmge<mode>;
1825 complimentary_comparison = gen_aarch64_cmgt<mode>;
1833 base_comparison = gen_aarch64_cmgt<mode>;
1834 complimentary_comparison = gen_aarch64_cmge<mode>;
1839 base_comparison = gen_aarch64_cmeq<mode>;
1840 complimentary_comparison = gen_aarch64_cmeq<mode>;
1846 switch (GET_CODE (operands[3]))
1853 /* The easy case. Here we emit one of FCMGE, FCMGT or FCMEQ.
1854 As a LT b <=> b GE a && a LE b <=> b GT a. Our transformations are:
1860 Note that there also exist direct comparison against 0 forms,
1861 so catch those as a special case. */
1865 switch (GET_CODE (operands[3]))
1868 base_comparison = gen_aarch64_cmlt<mode>;
1871 base_comparison = gen_aarch64_cmle<mode>;
1874 /* Do nothing, other zero form cases already have the correct
1881 emit_insn (base_comparison (mask, operands[4], operands[5]));
1883 emit_insn (complimentary_comparison (mask, operands[5], operands[4]));
1890 /* FCM returns false for lanes which are unordered, so if we use
1891 the inverse of the comparison we actually want to emit, then
1892 swap the operands to BSL, we will end up with the correct result.
1893 Note that a NE NaN and NaN NE b are true for all a, b.
1895 Our transformations are:
1900 a NE b -> !(a EQ b) */
1903 emit_insn (base_comparison (mask, operands[4], operands[5]));
1905 emit_insn (complimentary_comparison (mask, operands[5], operands[4]));
1907 swap_bsl_operands = 1;
1910 /* We check (a > b || b > a). combining these comparisons give us
1911 true iff !(a != b && a ORDERED b), swapping the operands to BSL
1912 will then give us (a == b || a UNORDERED b) as intended. */
1914 emit_insn (gen_aarch64_cmgt<mode> (mask, operands[4], operands[5]));
1915 emit_insn (gen_aarch64_cmgt<mode> (tmp, operands[5], operands[4]));
1916 emit_insn (gen_ior<v_cmp_result>3 (mask, mask, tmp));
1917 swap_bsl_operands = 1;
1920 /* Operands are ORDERED iff (a > b || b >= a).
1921 Swapping the operands to BSL will give the UNORDERED case. */
1922 swap_bsl_operands = 1;
1925 emit_insn (gen_aarch64_cmgt<mode> (tmp, operands[4], operands[5]));
1926 emit_insn (gen_aarch64_cmge<mode> (mask, operands[5], operands[4]));
1927 emit_insn (gen_ior<v_cmp_result>3 (mask, mask, tmp));
1933 if (swap_bsl_operands)
1939 /* If we have (a = (b CMP c) ? -1 : 0);
1940 Then we can simply move the generated mask. */
1942 if (op1 == CONSTM1_RTX (<V_cmp_result>mode)
1943 && op2 == CONST0_RTX (<V_cmp_result>mode))
1944 emit_move_insn (operands[0], mask);
1948 op1 = force_reg (<MODE>mode, op1);
1950 op2 = force_reg (<MODE>mode, op2);
1951 emit_insn (gen_aarch64_simd_bsl<mode> (operands[0], mask,
1958 (define_expand "vcond<mode><mode>"
1959 [(set (match_operand:VALL 0 "register_operand")
1961 (match_operator 3 "comparison_operator"
1962 [(match_operand:VALL 4 "register_operand")
1963 (match_operand:VALL 5 "nonmemory_operand")])
1964 (match_operand:VALL 1 "nonmemory_operand")
1965 (match_operand:VALL 2 "nonmemory_operand")))]
1968 emit_insn (gen_aarch64_vcond_internal<mode> (operands[0], operands[1],
1969 operands[2], operands[3],
1970 operands[4], operands[5]));
1974 (define_expand "vcond<v_cmp_result><mode>"
1975 [(set (match_operand:<V_cmp_result> 0 "register_operand")
1976 (if_then_else:<V_cmp_result>
1977 (match_operator 3 "comparison_operator"
1978 [(match_operand:VDQF 4 "register_operand")
1979 (match_operand:VDQF 5 "nonmemory_operand")])
1980 (match_operand:<V_cmp_result> 1 "nonmemory_operand")
1981 (match_operand:<V_cmp_result> 2 "nonmemory_operand")))]
1984 emit_insn (gen_aarch64_vcond_internal<v_cmp_result> (
1985 operands[0], operands[1],
1986 operands[2], operands[3],
1987 operands[4], operands[5]));
1991 (define_expand "vcondu<mode><mode>"
1992 [(set (match_operand:VDQ 0 "register_operand")
1994 (match_operator 3 "comparison_operator"
1995 [(match_operand:VDQ 4 "register_operand")
1996 (match_operand:VDQ 5 "nonmemory_operand")])
1997 (match_operand:VDQ 1 "nonmemory_operand")
1998 (match_operand:VDQ 2 "nonmemory_operand")))]
2001 emit_insn (gen_aarch64_vcond_internal<mode> (operands[0], operands[1],
2002 operands[2], operands[3],
2003 operands[4], operands[5]));
2007 ;; Patterns for AArch64 SIMD Intrinsics.
2009 (define_expand "aarch64_create<mode>"
2010 [(match_operand:VD_RE 0 "register_operand" "")
2011 (match_operand:DI 1 "general_operand" "")]
2014 rtx src = gen_lowpart (<MODE>mode, operands[1]);
2015 emit_move_insn (operands[0], src);
2019 (define_insn "aarch64_get_lane_signed<mode>"
2020 [(set (match_operand:<VEL> 0 "register_operand" "=r")
2023 (match_operand:VQ_S 1 "register_operand" "w")
2024 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2026 "smov\\t%0, %1.<Vetype>[%2]"
2027 [(set_attr "simd_type" "simd_movgp")
2028 (set_attr "simd_mode" "<MODE>")]
2031 (define_insn "aarch64_get_lane_unsigned<mode>"
2032 [(set (match_operand:<VEL> 0 "register_operand" "=r")
2035 (match_operand:VDQ 1 "register_operand" "w")
2036 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
2038 "umov\\t%<vw>0, %1.<Vetype>[%2]"
2039 [(set_attr "simd_type" "simd_movgp")
2040 (set_attr "simd_mode" "<MODE>")]
2043 (define_insn "aarch64_get_lane<mode>"
2044 [(set (match_operand:<VEL> 0 "register_operand" "=w")
2046 (match_operand:VDQF 1 "register_operand" "w")
2047 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
2049 "mov\\t%0.<Vetype>[0], %1.<Vetype>[%2]"
2050 [(set_attr "simd_type" "simd_ins")
2051 (set_attr "simd_mode" "<MODE>")]
2054 (define_expand "aarch64_get_lanedi"
2055 [(match_operand:DI 0 "register_operand" "=r")
2056 (match_operand:DI 1 "register_operand" "w")
2057 (match_operand:SI 2 "immediate_operand" "i")]
2060 aarch64_simd_lane_bounds (operands[2], 0, 1);
2061 emit_move_insn (operands[0], operands[1]);
2065 (define_expand "aarch64_reinterpretv8qi<mode>"
2066 [(match_operand:V8QI 0 "register_operand" "")
2067 (match_operand:VDC 1 "register_operand" "")]
2070 aarch64_simd_reinterpret (operands[0], operands[1]);
2074 (define_expand "aarch64_reinterpretv4hi<mode>"
2075 [(match_operand:V4HI 0 "register_operand" "")
2076 (match_operand:VDC 1 "register_operand" "")]
2079 aarch64_simd_reinterpret (operands[0], operands[1]);
2083 (define_expand "aarch64_reinterpretv2si<mode>"
2084 [(match_operand:V2SI 0 "register_operand" "")
2085 (match_operand:VDC 1 "register_operand" "")]
2088 aarch64_simd_reinterpret (operands[0], operands[1]);
2092 (define_expand "aarch64_reinterpretv2sf<mode>"
2093 [(match_operand:V2SF 0 "register_operand" "")
2094 (match_operand:VDC 1 "register_operand" "")]
2097 aarch64_simd_reinterpret (operands[0], operands[1]);
2101 (define_expand "aarch64_reinterpretdi<mode>"
2102 [(match_operand:DI 0 "register_operand" "")
2103 (match_operand:VD_RE 1 "register_operand" "")]
2106 aarch64_simd_reinterpret (operands[0], operands[1]);
2110 (define_expand "aarch64_reinterpretv16qi<mode>"
2111 [(match_operand:V16QI 0 "register_operand" "")
2112 (match_operand:VQ 1 "register_operand" "")]
2115 aarch64_simd_reinterpret (operands[0], operands[1]);
2119 (define_expand "aarch64_reinterpretv8hi<mode>"
2120 [(match_operand:V8HI 0 "register_operand" "")
2121 (match_operand:VQ 1 "register_operand" "")]
2124 aarch64_simd_reinterpret (operands[0], operands[1]);
2128 (define_expand "aarch64_reinterpretv4si<mode>"
2129 [(match_operand:V4SI 0 "register_operand" "")
2130 (match_operand:VQ 1 "register_operand" "")]
2133 aarch64_simd_reinterpret (operands[0], operands[1]);
2137 (define_expand "aarch64_reinterpretv4sf<mode>"
2138 [(match_operand:V4SF 0 "register_operand" "")
2139 (match_operand:VQ 1 "register_operand" "")]
2142 aarch64_simd_reinterpret (operands[0], operands[1]);
2146 (define_expand "aarch64_reinterpretv2di<mode>"
2147 [(match_operand:V2DI 0 "register_operand" "")
2148 (match_operand:VQ 1 "register_operand" "")]
2151 aarch64_simd_reinterpret (operands[0], operands[1]);
2155 (define_expand "aarch64_reinterpretv2df<mode>"
2156 [(match_operand:V2DF 0 "register_operand" "")
2157 (match_operand:VQ 1 "register_operand" "")]
2160 aarch64_simd_reinterpret (operands[0], operands[1]);
2164 ;; In this insn, operand 1 should be low, and operand 2 the high part of the
2167 (define_insn "*aarch64_combinez<mode>"
2168 [(set (match_operand:<VDBL> 0 "register_operand" "=&w")
2170 (match_operand:VDIC 1 "register_operand" "w")
2171 (match_operand:VDIC 2 "aarch64_simd_imm_zero" "Dz")))]
2173 "mov\\t%0.8b, %1.8b"
2174 [(set_attr "simd_type" "simd_move")
2175 (set_attr "simd_mode" "<MODE>")]
2178 (define_insn "aarch64_combine<mode>"
2179 [(set (match_operand:<VDBL> 0 "register_operand" "=&w")
2180 (vec_concat:<VDBL> (match_operand:VDC 1 "register_operand" "w")
2181 (match_operand:VDC 2 "register_operand" "w")))]
2183 "mov\\t%0.d[0], %1.d[0]\;ins\\t%0.d[1], %2.d[0]"
2184 [(set_attr "simd_type" "simd_ins")
2185 (set_attr "simd_mode" "<MODE>")]
2188 ;; <su><addsub>l<q>.
2190 (define_insn "aarch64_<ANY_EXTEND:su><ADDSUB:optab>l2<mode>_internal"
2191 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2192 (ADDSUB:<VWIDE> (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
2193 (match_operand:VQW 1 "register_operand" "w")
2194 (match_operand:VQW 3 "vect_par_cnst_hi_half" "")))
2195 (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
2196 (match_operand:VQW 2 "register_operand" "w")
2199 "<ANY_EXTEND:su><ADDSUB:optab>l2 %0.<Vwtype>, %1.<Vtype>, %2.<Vtype>"
2200 [(set_attr "simd_type" "simd_addl")
2201 (set_attr "simd_mode" "<MODE>")]
2204 (define_expand "aarch64_saddl2<mode>"
2205 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2206 (match_operand:VQW 1 "register_operand" "w")
2207 (match_operand:VQW 2 "register_operand" "w")]
2210 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2211 emit_insn (gen_aarch64_saddl2<mode>_internal (operands[0], operands[1],
2216 (define_expand "aarch64_uaddl2<mode>"
2217 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2218 (match_operand:VQW 1 "register_operand" "w")
2219 (match_operand:VQW 2 "register_operand" "w")]
2222 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2223 emit_insn (gen_aarch64_uaddl2<mode>_internal (operands[0], operands[1],
2228 (define_expand "aarch64_ssubl2<mode>"
2229 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2230 (match_operand:VQW 1 "register_operand" "w")
2231 (match_operand:VQW 2 "register_operand" "w")]
2234 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2235 emit_insn (gen_aarch64_ssubl2<mode>_internal (operands[0], operands[1],
2240 (define_expand "aarch64_usubl2<mode>"
2241 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2242 (match_operand:VQW 1 "register_operand" "w")
2243 (match_operand:VQW 2 "register_operand" "w")]
2246 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2247 emit_insn (gen_aarch64_usubl2<mode>_internal (operands[0], operands[1],
2252 (define_insn "aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>"
2253 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2254 (ADDSUB:<VWIDE> (ANY_EXTEND:<VWIDE>
2255 (match_operand:VDW 1 "register_operand" "w"))
2257 (match_operand:VDW 2 "register_operand" "w"))))]
2259 "<ANY_EXTEND:su><ADDSUB:optab>l %0.<Vwtype>, %1.<Vtype>, %2.<Vtype>"
2260 [(set_attr "simd_type" "simd_addl")
2261 (set_attr "simd_mode" "<MODE>")]
2264 ;; <su><addsub>w<q>.
2266 (define_insn "aarch64_<ANY_EXTEND:su><ADDSUB:optab>w<mode>"
2267 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2268 (ADDSUB:<VWIDE> (match_operand:<VWIDE> 1 "register_operand" "w")
2270 (match_operand:VDW 2 "register_operand" "w"))))]
2272 "<ANY_EXTEND:su><ADDSUB:optab>w\\t%0.<Vwtype>, %1.<Vwtype>, %2.<Vtype>"
2273 [(set_attr "simd_type" "simd_addl")
2274 (set_attr "simd_mode" "<MODE>")]
2277 (define_insn "aarch64_<ANY_EXTEND:su><ADDSUB:optab>w2<mode>_internal"
2278 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2279 (ADDSUB:<VWIDE> (match_operand:<VWIDE> 1 "register_operand" "w")
2282 (match_operand:VQW 2 "register_operand" "w")
2283 (match_operand:VQW 3 "vect_par_cnst_hi_half" "")))))]
2285 "<ANY_EXTEND:su><ADDSUB:optab>w2\\t%0.<Vwtype>, %1.<Vwtype>, %2.<Vtype>"
2286 [(set_attr "simd_type" "simd_addl")
2287 (set_attr "simd_mode" "<MODE>")]
2290 (define_expand "aarch64_saddw2<mode>"
2291 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2292 (match_operand:<VWIDE> 1 "register_operand" "w")
2293 (match_operand:VQW 2 "register_operand" "w")]
2296 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2297 emit_insn (gen_aarch64_saddw2<mode>_internal (operands[0], operands[1],
2302 (define_expand "aarch64_uaddw2<mode>"
2303 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2304 (match_operand:<VWIDE> 1 "register_operand" "w")
2305 (match_operand:VQW 2 "register_operand" "w")]
2308 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2309 emit_insn (gen_aarch64_uaddw2<mode>_internal (operands[0], operands[1],
2315 (define_expand "aarch64_ssubw2<mode>"
2316 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2317 (match_operand:<VWIDE> 1 "register_operand" "w")
2318 (match_operand:VQW 2 "register_operand" "w")]
2321 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2322 emit_insn (gen_aarch64_ssubw2<mode>_internal (operands[0], operands[1],
2327 (define_expand "aarch64_usubw2<mode>"
2328 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2329 (match_operand:<VWIDE> 1 "register_operand" "w")
2330 (match_operand:VQW 2 "register_operand" "w")]
2333 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2334 emit_insn (gen_aarch64_usubw2<mode>_internal (operands[0], operands[1],
2339 ;; <su><r>h<addsub>.
2341 (define_insn "aarch64_<sur>h<addsub><mode>"
2342 [(set (match_operand:VQ_S 0 "register_operand" "=w")
2343 (unspec:VQ_S [(match_operand:VQ_S 1 "register_operand" "w")
2344 (match_operand:VQ_S 2 "register_operand" "w")]
2347 "<sur>h<addsub>\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
2348 [(set_attr "simd_type" "simd_add")
2349 (set_attr "simd_mode" "<MODE>")]
2352 ;; <r><addsub>hn<q>.
2354 (define_insn "aarch64_<sur><addsub>hn<mode>"
2355 [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
2356 (unspec:<VNARROWQ> [(match_operand:VQN 1 "register_operand" "w")
2357 (match_operand:VQN 2 "register_operand" "w")]
2360 "<sur><addsub>hn\\t%0.<Vntype>, %1.<Vtype>, %2.<Vtype>"
2361 [(set_attr "simd_type" "simd_addn")
2362 (set_attr "simd_mode" "<MODE>")]
2365 (define_insn "aarch64_<sur><addsub>hn2<mode>"
2366 [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
2367 (unspec:<VNARROWQ2> [(match_operand:<VNARROWQ> 1 "register_operand" "0")
2368 (match_operand:VQN 2 "register_operand" "w")
2369 (match_operand:VQN 3 "register_operand" "w")]
2372 "<sur><addsub>hn2\\t%0.<V2ntype>, %2.<Vtype>, %3.<Vtype>"
2373 [(set_attr "simd_type" "simd_addn2")
2374 (set_attr "simd_mode" "<MODE>")]
2379 (define_insn "aarch64_pmul<mode>"
2380 [(set (match_operand:VB 0 "register_operand" "=w")
2381 (unspec:VB [(match_operand:VB 1 "register_operand" "w")
2382 (match_operand:VB 2 "register_operand" "w")]
2385 "pmul\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
2386 [(set_attr "simd_type" "simd_mul")
2387 (set_attr "simd_mode" "<MODE>")]
2392 (define_insn "aarch64_<su_optab><optab><mode>"
2393 [(set (match_operand:VSDQ_I 0 "register_operand" "=w")
2394 (BINQOPS:VSDQ_I (match_operand:VSDQ_I 1 "register_operand" "w")
2395 (match_operand:VSDQ_I 2 "register_operand" "w")))]
2397 "<su_optab><optab>\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
2398 [(set_attr "simd_type" "simd_add")
2399 (set_attr "simd_mode" "<MODE>")]
2402 ;; suqadd and usqadd
2404 (define_insn "aarch64_<sur>qadd<mode>"
2405 [(set (match_operand:VSDQ_I 0 "register_operand" "=w")
2406 (unspec:VSDQ_I [(match_operand:VSDQ_I 1 "register_operand" "0")
2407 (match_operand:VSDQ_I 2 "register_operand" "w")]
2410 "<sur>qadd\\t%<v>0<Vmtype>, %<v>2<Vmtype>"
2411 [(set_attr "simd_type" "simd_sat_add")
2412 (set_attr "simd_mode" "<MODE>")]
2417 (define_insn "aarch64_sqmovun<mode>"
2418 [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
2419 (unspec:<VNARROWQ> [(match_operand:VSQN_HSDI 1 "register_operand" "w")]
2422 "sqxtun\\t%<vn2>0<Vmntype>, %<v>1<Vmtype>"
2423 [(set_attr "simd_type" "simd_sat_shiftn_imm")
2424 (set_attr "simd_mode" "<MODE>")]
2427 ;; sqmovn and uqmovn
2429 (define_insn "aarch64_<sur>qmovn<mode>"
2430 [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
2431 (unspec:<VNARROWQ> [(match_operand:VSQN_HSDI 1 "register_operand" "w")]
2434 "<sur>qxtn\\t%<vn2>0<Vmntype>, %<v>1<Vmtype>"
2435 [(set_attr "simd_type" "simd_sat_shiftn_imm")
2436 (set_attr "simd_mode" "<MODE>")]
2441 (define_insn "aarch64_s<optab><mode>"
2442 [(set (match_operand:VSDQ_I_BHSI 0 "register_operand" "=w")
2444 (match_operand:VSDQ_I_BHSI 1 "register_operand" "w")))]
2446 "s<optab>\\t%<v>0<Vmtype>, %<v>1<Vmtype>"
2447 [(set_attr "simd_type" "simd_sat_negabs")
2448 (set_attr "simd_mode" "<MODE>")]
2453 (define_insn "aarch64_sq<r>dmulh<mode>"
2454 [(set (match_operand:VSDQ_HSI 0 "register_operand" "=w")
2456 [(match_operand:VSDQ_HSI 1 "register_operand" "w")
2457 (match_operand:VSDQ_HSI 2 "register_operand" "w")]
2460 "sq<r>dmulh\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
2461 [(set_attr "simd_type" "simd_sat_mul")
2462 (set_attr "simd_mode" "<MODE>")]
2467 (define_insn "aarch64_sq<r>dmulh_lane<mode>"
2468 [(set (match_operand:VDQHS 0 "register_operand" "=w")
2470 [(match_operand:VDQHS 1 "register_operand" "w")
2472 (match_operand:<VCOND> 2 "register_operand" "<vwx>")
2473 (parallel [(match_operand:SI 3 "immediate_operand" "i")]))]
2477 aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<VCOND>mode));
2478 return \"sq<r>dmulh\\t%0.<Vtype>, %1.<Vtype>, %2.<Vetype>[%3]\";"
2479 [(set_attr "simd_type" "simd_sat_mul")
2480 (set_attr "simd_mode" "<MODE>")]
2483 (define_insn "aarch64_sq<r>dmulh_laneq<mode>"
2484 [(set (match_operand:VDQHS 0 "register_operand" "=w")
2486 [(match_operand:VDQHS 1 "register_operand" "w")
2488 (match_operand:<VCONQ> 2 "register_operand" "<vwx>")
2489 (parallel [(match_operand:SI 3 "immediate_operand" "i")]))]
2493 aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<VCONQ>mode));
2494 return \"sq<r>dmulh\\t%0.<Vtype>, %1.<Vtype>, %2.<Vetype>[%3]\";"
2495 [(set_attr "simd_type" "simd_sat_mul")
2496 (set_attr "simd_mode" "<MODE>")]
2499 (define_insn "aarch64_sq<r>dmulh_lane<mode>"
2500 [(set (match_operand:SD_HSI 0 "register_operand" "=w")
2502 [(match_operand:SD_HSI 1 "register_operand" "w")
2504 (match_operand:<VCONQ> 2 "register_operand" "<vwx>")
2505 (parallel [(match_operand:SI 3 "immediate_operand" "i")]))]
2509 aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<VCONQ>mode));
2510 return \"sq<r>dmulh\\t%<v>0, %<v>1, %2.<v>[%3]\";"
2511 [(set_attr "simd_type" "simd_sat_mul")
2512 (set_attr "simd_mode" "<MODE>")]
2517 (define_insn "aarch64_sqdml<SBINQOPS:as>l<mode>"
2518 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2520 (match_operand:<VWIDE> 1 "register_operand" "0")
2523 (sign_extend:<VWIDE>
2524 (match_operand:VSD_HSI 2 "register_operand" "w"))
2525 (sign_extend:<VWIDE>
2526 (match_operand:VSD_HSI 3 "register_operand" "w")))
2529 "sqdml<SBINQOPS:as>l\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %<v>3<Vmtype>"
2530 [(set_attr "simd_type" "simd_sat_mlal")
2531 (set_attr "simd_mode" "<MODE>")]
2536 (define_insn "aarch64_sqdml<SBINQOPS:as>l_lane<mode>_internal"
2537 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2539 (match_operand:<VWIDE> 1 "register_operand" "0")
2542 (sign_extend:<VWIDE>
2543 (match_operand:VD_HSI 2 "register_operand" "w"))
2544 (sign_extend:<VWIDE>
2545 (vec_duplicate:VD_HSI
2547 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2548 (parallel [(match_operand:SI 4 "immediate_operand" "i")])))
2552 "sqdml<SBINQOPS:as>l\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[%4]"
2553 [(set_attr "simd_type" "simd_sat_mlal")
2554 (set_attr "simd_mode" "<MODE>")]
2557 (define_insn "aarch64_sqdml<SBINQOPS:as>l_lane<mode>_internal"
2558 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2560 (match_operand:<VWIDE> 1 "register_operand" "0")
2563 (sign_extend:<VWIDE>
2564 (match_operand:SD_HSI 2 "register_operand" "w"))
2565 (sign_extend:<VWIDE>
2567 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2568 (parallel [(match_operand:SI 4 "immediate_operand" "i")])))
2572 "sqdml<SBINQOPS:as>l\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[%4]"
2573 [(set_attr "simd_type" "simd_sat_mlal")
2574 (set_attr "simd_mode" "<MODE>")]
2577 (define_expand "aarch64_sqdmlal_lane<mode>"
2578 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2579 (match_operand:<VWIDE> 1 "register_operand" "0")
2580 (match_operand:VSD_HSI 2 "register_operand" "w")
2581 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2582 (match_operand:SI 4 "immediate_operand" "i")]
2585 aarch64_simd_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<VCON>mode) / 2);
2586 emit_insn (gen_aarch64_sqdmlal_lane<mode>_internal (operands[0], operands[1],
2587 operands[2], operands[3],
2592 (define_expand "aarch64_sqdmlal_laneq<mode>"
2593 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2594 (match_operand:<VWIDE> 1 "register_operand" "0")
2595 (match_operand:VSD_HSI 2 "register_operand" "w")
2596 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2597 (match_operand:SI 4 "immediate_operand" "i")]
2600 aarch64_simd_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<VCON>mode));
2601 emit_insn (gen_aarch64_sqdmlal_lane<mode>_internal (operands[0], operands[1],
2602 operands[2], operands[3],
2607 (define_expand "aarch64_sqdmlsl_lane<mode>"
2608 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2609 (match_operand:<VWIDE> 1 "register_operand" "0")
2610 (match_operand:VSD_HSI 2 "register_operand" "w")
2611 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2612 (match_operand:SI 4 "immediate_operand" "i")]
2615 aarch64_simd_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<VCON>mode) / 2);
2616 emit_insn (gen_aarch64_sqdmlsl_lane<mode>_internal (operands[0], operands[1],
2617 operands[2], operands[3],
2622 (define_expand "aarch64_sqdmlsl_laneq<mode>"
2623 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2624 (match_operand:<VWIDE> 1 "register_operand" "0")
2625 (match_operand:VSD_HSI 2 "register_operand" "w")
2626 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2627 (match_operand:SI 4 "immediate_operand" "i")]
2630 aarch64_simd_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<VCON>mode));
2631 emit_insn (gen_aarch64_sqdmlsl_lane<mode>_internal (operands[0], operands[1],
2632 operands[2], operands[3],
2639 (define_insn "aarch64_sqdml<SBINQOPS:as>l_n<mode>"
2640 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2642 (match_operand:<VWIDE> 1 "register_operand" "0")
2645 (sign_extend:<VWIDE>
2646 (match_operand:VD_HSI 2 "register_operand" "w"))
2647 (sign_extend:<VWIDE>
2648 (vec_duplicate:VD_HSI
2649 (match_operand:<VEL> 3 "register_operand" "w"))))
2652 "sqdml<SBINQOPS:as>l\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[0]"
2653 [(set_attr "simd_type" "simd_sat_mlal")
2654 (set_attr "simd_mode" "<MODE>")]
2659 (define_insn "aarch64_sqdml<SBINQOPS:as>l2<mode>_internal"
2660 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2662 (match_operand:<VWIDE> 1 "register_operand" "0")
2665 (sign_extend:<VWIDE>
2667 (match_operand:VQ_HSI 2 "register_operand" "w")
2668 (match_operand:VQ_HSI 4 "vect_par_cnst_hi_half" "")))
2669 (sign_extend:<VWIDE>
2671 (match_operand:VQ_HSI 3 "register_operand" "w")
2675 "sqdml<SBINQOPS:as>l2\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %<v>3<Vmtype>"
2676 [(set_attr "simd_type" "simd_sat_mlal")
2677 (set_attr "simd_mode" "<MODE>")]
2680 (define_expand "aarch64_sqdmlal2<mode>"
2681 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2682 (match_operand:<VWIDE> 1 "register_operand" "w")
2683 (match_operand:VQ_HSI 2 "register_operand" "w")
2684 (match_operand:VQ_HSI 3 "register_operand" "w")]
2687 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2688 emit_insn (gen_aarch64_sqdmlal2<mode>_internal (operands[0], operands[1],
2689 operands[2], operands[3], p));
2693 (define_expand "aarch64_sqdmlsl2<mode>"
2694 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2695 (match_operand:<VWIDE> 1 "register_operand" "w")
2696 (match_operand:VQ_HSI 2 "register_operand" "w")
2697 (match_operand:VQ_HSI 3 "register_operand" "w")]
2700 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2701 emit_insn (gen_aarch64_sqdmlsl2<mode>_internal (operands[0], operands[1],
2702 operands[2], operands[3], p));
2708 (define_insn "aarch64_sqdml<SBINQOPS:as>l2_lane<mode>_internal"
2709 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2711 (match_operand:<VWIDE> 1 "register_operand" "0")
2714 (sign_extend:<VWIDE>
2716 (match_operand:VQ_HSI 2 "register_operand" "w")
2717 (match_operand:VQ_HSI 5 "vect_par_cnst_hi_half" "")))
2718 (sign_extend:<VWIDE>
2719 (vec_duplicate:<VHALF>
2721 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2722 (parallel [(match_operand:SI 4 "immediate_operand" "i")])
2726 "sqdml<SBINQOPS:as>l2\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[%4]"
2727 [(set_attr "simd_type" "simd_sat_mlal")
2728 (set_attr "simd_mode" "<MODE>")]
2731 (define_expand "aarch64_sqdmlal2_lane<mode>"
2732 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2733 (match_operand:<VWIDE> 1 "register_operand" "w")
2734 (match_operand:VQ_HSI 2 "register_operand" "w")
2735 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2736 (match_operand:SI 4 "immediate_operand" "i")]
2739 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2740 aarch64_simd_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode) / 2);
2741 emit_insn (gen_aarch64_sqdmlal2_lane<mode>_internal (operands[0], operands[1],
2742 operands[2], operands[3],
2747 (define_expand "aarch64_sqdmlal2_laneq<mode>"
2748 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2749 (match_operand:<VWIDE> 1 "register_operand" "w")
2750 (match_operand:VQ_HSI 2 "register_operand" "w")
2751 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2752 (match_operand:SI 4 "immediate_operand" "i")]
2755 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2756 aarch64_simd_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
2757 emit_insn (gen_aarch64_sqdmlal2_lane<mode>_internal (operands[0], operands[1],
2758 operands[2], operands[3],
2763 (define_expand "aarch64_sqdmlsl2_lane<mode>"
2764 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2765 (match_operand:<VWIDE> 1 "register_operand" "w")
2766 (match_operand:VQ_HSI 2 "register_operand" "w")
2767 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2768 (match_operand:SI 4 "immediate_operand" "i")]
2771 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2772 aarch64_simd_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode) / 2);
2773 emit_insn (gen_aarch64_sqdmlsl2_lane<mode>_internal (operands[0], operands[1],
2774 operands[2], operands[3],
2779 (define_expand "aarch64_sqdmlsl2_laneq<mode>"
2780 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2781 (match_operand:<VWIDE> 1 "register_operand" "w")
2782 (match_operand:VQ_HSI 2 "register_operand" "w")
2783 (match_operand:<VCON> 3 "register_operand" "<vwx>")
2784 (match_operand:SI 4 "immediate_operand" "i")]
2787 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2788 aarch64_simd_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
2789 emit_insn (gen_aarch64_sqdmlsl2_lane<mode>_internal (operands[0], operands[1],
2790 operands[2], operands[3],
2795 (define_insn "aarch64_sqdml<SBINQOPS:as>l2_n<mode>_internal"
2796 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2798 (match_operand:<VWIDE> 1 "register_operand" "0")
2801 (sign_extend:<VWIDE>
2803 (match_operand:VQ_HSI 2 "register_operand" "w")
2804 (match_operand:VQ_HSI 4 "vect_par_cnst_hi_half" "")))
2805 (sign_extend:<VWIDE>
2806 (vec_duplicate:<VHALF>
2807 (match_operand:<VEL> 3 "register_operand" "w"))))
2810 "sqdml<SBINQOPS:as>l2\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[0]"
2811 [(set_attr "simd_type" "simd_sat_mlal")
2812 (set_attr "simd_mode" "<MODE>")]
2815 (define_expand "aarch64_sqdmlal2_n<mode>"
2816 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2817 (match_operand:<VWIDE> 1 "register_operand" "w")
2818 (match_operand:VQ_HSI 2 "register_operand" "w")
2819 (match_operand:<VEL> 3 "register_operand" "w")]
2822 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2823 emit_insn (gen_aarch64_sqdmlal2_n<mode>_internal (operands[0], operands[1],
2824 operands[2], operands[3],
2829 (define_expand "aarch64_sqdmlsl2_n<mode>"
2830 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2831 (match_operand:<VWIDE> 1 "register_operand" "w")
2832 (match_operand:VQ_HSI 2 "register_operand" "w")
2833 (match_operand:<VEL> 3 "register_operand" "w")]
2836 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2837 emit_insn (gen_aarch64_sqdmlsl2_n<mode>_internal (operands[0], operands[1],
2838 operands[2], operands[3],
2845 (define_insn "aarch64_sqdmull<mode>"
2846 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2849 (sign_extend:<VWIDE>
2850 (match_operand:VSD_HSI 1 "register_operand" "w"))
2851 (sign_extend:<VWIDE>
2852 (match_operand:VSD_HSI 2 "register_operand" "w")))
2855 "sqdmull\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
2856 [(set_attr "simd_type" "simd_sat_mul")
2857 (set_attr "simd_mode" "<MODE>")]
2862 (define_insn "aarch64_sqdmull_lane<mode>_internal"
2863 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2866 (sign_extend:<VWIDE>
2867 (match_operand:VD_HSI 1 "register_operand" "w"))
2868 (sign_extend:<VWIDE>
2869 (vec_duplicate:VD_HSI
2871 (match_operand:<VCON> 2 "register_operand" "<vwx>")
2872 (parallel [(match_operand:SI 3 "immediate_operand" "i")])))
2876 "sqdmull\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[%3]"
2877 [(set_attr "simd_type" "simd_sat_mul")
2878 (set_attr "simd_mode" "<MODE>")]
2881 (define_insn "aarch64_sqdmull_lane<mode>_internal"
2882 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2885 (sign_extend:<VWIDE>
2886 (match_operand:SD_HSI 1 "register_operand" "w"))
2887 (sign_extend:<VWIDE>
2889 (match_operand:<VCON> 2 "register_operand" "<vwx>")
2890 (parallel [(match_operand:SI 3 "immediate_operand" "i")]))
2894 "sqdmull\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[%3]"
2895 [(set_attr "simd_type" "simd_sat_mul")
2896 (set_attr "simd_mode" "<MODE>")]
2899 (define_expand "aarch64_sqdmull_lane<mode>"
2900 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2901 (match_operand:VSD_HSI 1 "register_operand" "w")
2902 (match_operand:<VCON> 2 "register_operand" "<vwx>")
2903 (match_operand:SI 3 "immediate_operand" "i")]
2906 aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<VCON>mode) / 2);
2907 emit_insn (gen_aarch64_sqdmull_lane<mode>_internal (operands[0], operands[1],
2908 operands[2], operands[3]));
2912 (define_expand "aarch64_sqdmull_laneq<mode>"
2913 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2914 (match_operand:VD_HSI 1 "register_operand" "w")
2915 (match_operand:<VCON> 2 "register_operand" "<vwx>")
2916 (match_operand:SI 3 "immediate_operand" "i")]
2919 aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<VCON>mode));
2920 emit_insn (gen_aarch64_sqdmull_lane<mode>_internal
2921 (operands[0], operands[1], operands[2], operands[3]));
2927 (define_insn "aarch64_sqdmull_n<mode>"
2928 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2931 (sign_extend:<VWIDE>
2932 (match_operand:VD_HSI 1 "register_operand" "w"))
2933 (sign_extend:<VWIDE>
2934 (vec_duplicate:VD_HSI
2935 (match_operand:<VEL> 2 "register_operand" "w")))
2939 "sqdmull\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[0]"
2940 [(set_attr "simd_type" "simd_sat_mul")
2941 (set_attr "simd_mode" "<MODE>")]
2948 (define_insn "aarch64_sqdmull2<mode>_internal"
2949 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2952 (sign_extend:<VWIDE>
2954 (match_operand:VQ_HSI 1 "register_operand" "w")
2955 (match_operand:VQ_HSI 3 "vect_par_cnst_hi_half" "")))
2956 (sign_extend:<VWIDE>
2958 (match_operand:VQ_HSI 2 "register_operand" "w")
2963 "sqdmull2\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
2964 [(set_attr "simd_type" "simd_sat_mul")
2965 (set_attr "simd_mode" "<MODE>")]
2968 (define_expand "aarch64_sqdmull2<mode>"
2969 [(match_operand:<VWIDE> 0 "register_operand" "=w")
2970 (match_operand:VQ_HSI 1 "register_operand" "w")
2971 (match_operand:<VCON> 2 "register_operand" "w")]
2974 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
2975 emit_insn (gen_aarch64_sqdmull2<mode>_internal (operands[0], operands[1],
2982 (define_insn "aarch64_sqdmull2_lane<mode>_internal"
2983 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2986 (sign_extend:<VWIDE>
2988 (match_operand:VQ_HSI 1 "register_operand" "w")
2989 (match_operand:VQ_HSI 4 "vect_par_cnst_hi_half" "")))
2990 (sign_extend:<VWIDE>
2991 (vec_duplicate:<VHALF>
2993 (match_operand:<VCON> 2 "register_operand" "<vwx>")
2994 (parallel [(match_operand:SI 3 "immediate_operand" "i")])))
2998 "sqdmull2\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[%3]"
2999 [(set_attr "simd_type" "simd_sat_mul")
3000 (set_attr "simd_mode" "<MODE>")]
3003 (define_expand "aarch64_sqdmull2_lane<mode>"
3004 [(match_operand:<VWIDE> 0 "register_operand" "=w")
3005 (match_operand:VQ_HSI 1 "register_operand" "w")
3006 (match_operand:<VCON> 2 "register_operand" "<vwx>")
3007 (match_operand:SI 3 "immediate_operand" "i")]
3010 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
3011 aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode) / 2);
3012 emit_insn (gen_aarch64_sqdmull2_lane<mode>_internal (operands[0], operands[1],
3013 operands[2], operands[3],
3018 (define_expand "aarch64_sqdmull2_laneq<mode>"
3019 [(match_operand:<VWIDE> 0 "register_operand" "=w")
3020 (match_operand:VQ_HSI 1 "register_operand" "w")
3021 (match_operand:<VCON> 2 "register_operand" "<vwx>")
3022 (match_operand:SI 3 "immediate_operand" "i")]
3025 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
3026 aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
3027 emit_insn (gen_aarch64_sqdmull2_lane<mode>_internal (operands[0], operands[1],
3028 operands[2], operands[3],
3035 (define_insn "aarch64_sqdmull2_n<mode>_internal"
3036 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
3039 (sign_extend:<VWIDE>
3041 (match_operand:VQ_HSI 1 "register_operand" "w")
3042 (match_operand:VQ_HSI 3 "vect_par_cnst_hi_half" "")))
3043 (sign_extend:<VWIDE>
3044 (vec_duplicate:<VHALF>
3045 (match_operand:<VEL> 2 "register_operand" "w")))
3049 "sqdmull2\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[0]"
3050 [(set_attr "simd_type" "simd_sat_mul")
3051 (set_attr "simd_mode" "<MODE>")]
3054 (define_expand "aarch64_sqdmull2_n<mode>"
3055 [(match_operand:<VWIDE> 0 "register_operand" "=w")
3056 (match_operand:VQ_HSI 1 "register_operand" "w")
3057 (match_operand:<VEL> 2 "register_operand" "w")]
3060 rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
3061 emit_insn (gen_aarch64_sqdmull2_n<mode>_internal (operands[0], operands[1],
3068 (define_insn "aarch64_<sur>shl<mode>"
3069 [(set (match_operand:VSDQ_I_DI 0 "register_operand" "=w")
3071 [(match_operand:VSDQ_I_DI 1 "register_operand" "w")
3072 (match_operand:VSDQ_I_DI 2 "register_operand" "w")]
3075 "<sur>shl\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>";
3076 [(set_attr "simd_type" "simd_shift")
3077 (set_attr "simd_mode" "<MODE>")]
3083 (define_insn "aarch64_<sur>q<r>shl<mode>"
3084 [(set (match_operand:VSDQ_I 0 "register_operand" "=w")
3086 [(match_operand:VSDQ_I 1 "register_operand" "w")
3087 (match_operand:VSDQ_I 2 "register_operand" "w")]
3090 "<sur>q<r>shl\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>";
3091 [(set_attr "simd_type" "simd_sat_shift")
3092 (set_attr "simd_mode" "<MODE>")]
3097 (define_insn "aarch64_<sur>shll_n<mode>"
3098 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
3099 (unspec:<VWIDE> [(match_operand:VDW 1 "register_operand" "w")
3100 (match_operand:SI 2 "immediate_operand" "i")]
3104 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
3105 aarch64_simd_const_bounds (operands[2], 0, bit_width + 1);
3106 if (INTVAL (operands[2]) == bit_width)
3108 return \"shll\\t%0.<Vwtype>, %1.<Vtype>, %2\";
3111 return \"<sur>shll\\t%0.<Vwtype>, %1.<Vtype>, %2\";
3113 [(set_attr "simd_type" "simd_shift_imm")
3114 (set_attr "simd_mode" "<MODE>")]
3119 (define_insn "aarch64_<sur>shll2_n<mode>"
3120 [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
3121 (unspec:<VWIDE> [(match_operand:VQW 1 "register_operand" "w")
3122 (match_operand:SI 2 "immediate_operand" "i")]
3126 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
3127 aarch64_simd_const_bounds (operands[2], 0, bit_width + 1);
3128 if (INTVAL (operands[2]) == bit_width)
3130 return \"shll2\\t%0.<Vwtype>, %1.<Vtype>, %2\";
3133 return \"<sur>shll2\\t%0.<Vwtype>, %1.<Vtype>, %2\";
3135 [(set_attr "simd_type" "simd_shift_imm")
3136 (set_attr "simd_mode" "<MODE>")]
3141 (define_insn "aarch64_<sur>shr_n<mode>"
3142 [(set (match_operand:VSDQ_I_DI 0 "register_operand" "=w")
3143 (unspec:VSDQ_I_DI [(match_operand:VSDQ_I_DI 1 "register_operand" "w")
3144 (match_operand:SI 2 "immediate_operand" "i")]
3148 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
3149 aarch64_simd_const_bounds (operands[2], 1, bit_width + 1);
3150 return \"<sur>shr\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %2\";"
3151 [(set_attr "simd_type" "simd_shift_imm")
3152 (set_attr "simd_mode" "<MODE>")]
3157 (define_insn "aarch64_<sur>sra_n<mode>"
3158 [(set (match_operand:VSDQ_I_DI 0 "register_operand" "=w")
3159 (unspec:VSDQ_I_DI [(match_operand:VSDQ_I_DI 1 "register_operand" "0")
3160 (match_operand:VSDQ_I_DI 2 "register_operand" "w")
3161 (match_operand:SI 3 "immediate_operand" "i")]
3165 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
3166 aarch64_simd_const_bounds (operands[3], 1, bit_width + 1);
3167 return \"<sur>sra\\t%<v>0<Vmtype>, %<v>2<Vmtype>, %3\";"
3168 [(set_attr "simd_type" "simd_shift_imm_acc")
3169 (set_attr "simd_mode" "<MODE>")]
3174 (define_insn "aarch64_<sur>s<lr>i_n<mode>"
3175 [(set (match_operand:VSDQ_I_DI 0 "register_operand" "=w")
3176 (unspec:VSDQ_I_DI [(match_operand:VSDQ_I_DI 1 "register_operand" "0")
3177 (match_operand:VSDQ_I_DI 2 "register_operand" "w")
3178 (match_operand:SI 3 "immediate_operand" "i")]
3182 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
3183 aarch64_simd_const_bounds (operands[3], 1 - <VSLRI:offsetlr>,
3184 bit_width - <VSLRI:offsetlr> + 1);
3185 return \"s<lr>i\\t%<v>0<Vmtype>, %<v>2<Vmtype>, %3\";"
3186 [(set_attr "simd_type" "simd_shift_imm")
3187 (set_attr "simd_mode" "<MODE>")]
3192 (define_insn "aarch64_<sur>qshl<u>_n<mode>"
3193 [(set (match_operand:VSDQ_I 0 "register_operand" "=w")
3194 (unspec:VSDQ_I [(match_operand:VSDQ_I 1 "register_operand" "w")
3195 (match_operand:SI 2 "immediate_operand" "i")]
3199 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
3200 aarch64_simd_const_bounds (operands[2], 0, bit_width);
3201 return \"<sur>qshl<u>\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %2\";"
3202 [(set_attr "simd_type" "simd_sat_shift_imm")
3203 (set_attr "simd_mode" "<MODE>")]
3209 (define_insn "aarch64_<sur>q<r>shr<u>n_n<mode>"
3210 [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w")
3211 (unspec:<VNARROWQ> [(match_operand:VSQN_HSDI 1 "register_operand" "w")
3212 (match_operand:SI 2 "immediate_operand" "i")]
3216 int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
3217 aarch64_simd_const_bounds (operands[2], 1, bit_width + 1);
3218 return \"<sur>q<r>shr<u>n\\t%<vn2>0<Vmntype>, %<v>1<Vmtype>, %2\";"
3219 [(set_attr "simd_type" "simd_sat_shiftn_imm")
3220 (set_attr "simd_mode" "<MODE>")]
3224 ;; cm(eq|ge|gt|lt|le)
3225 ;; Note, we have constraints for Dz and Z as different expanders
3226 ;; have different ideas of what should be passed to this pattern.
3228 (define_insn "aarch64_cm<optab><mode>"
3229 [(set (match_operand:<V_cmp_result> 0 "register_operand" "=w,w")
3231 (COMPARISONS:<V_cmp_result>
3232 (match_operand:VDQ 1 "register_operand" "w,w")
3233 (match_operand:VDQ 2 "aarch64_simd_reg_or_zero" "w,ZDz")
3237 cm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>
3238 cm<optab>\t%<v>0<Vmtype>, %<v>1<Vmtype>, #0"
3239 [(set_attr "simd_type" "simd_cmp")
3240 (set_attr "simd_mode" "<MODE>")]
3243 (define_insn_and_split "aarch64_cm<optab>di"
3244 [(set (match_operand:DI 0 "register_operand" "=w,w,r")
3247 (match_operand:DI 1 "register_operand" "w,w,r")
3248 (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,ZDz,r")
3252 cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
3253 cm<optab>\t%d0, %d1, #0
3256 /* We need to prevent the split from
3257 happening in the 'w' constraint cases. */
3258 && GP_REGNUM_P (REGNO (operands[0]))
3259 && GP_REGNUM_P (REGNO (operands[1]))"
3260 [(set (reg:CC CC_REGNUM)
3267 (match_operand 3 "cc_register" "")
3270 enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
3271 rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
3272 rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
3273 emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
3276 [(set_attr "simd_type" "simd_cmp")
3277 (set_attr "simd_mode" "DI")]
3282 (define_insn "aarch64_cm<optab><mode>"
3283 [(set (match_operand:<V_cmp_result> 0 "register_operand" "=w")
3285 (UCOMPARISONS:<V_cmp_result>
3286 (match_operand:VDQ 1 "register_operand" "w")
3287 (match_operand:VDQ 2 "register_operand" "w")
3290 "cm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>"
3291 [(set_attr "simd_type" "simd_cmp")
3292 (set_attr "simd_mode" "<MODE>")]
3295 (define_insn_and_split "aarch64_cm<optab>di"
3296 [(set (match_operand:DI 0 "register_operand" "=w,r")
3299 (match_operand:DI 1 "register_operand" "w,r")
3300 (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,r")
3304 cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
3307 /* We need to prevent the split from
3308 happening in the 'w' constraint cases. */
3309 && GP_REGNUM_P (REGNO (operands[0]))
3310 && GP_REGNUM_P (REGNO (operands[1]))"
3311 [(set (reg:CC CC_REGNUM)
3318 (match_operand 3 "cc_register" "")
3321 enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
3322 rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
3323 rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
3324 emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
3327 [(set_attr "simd_type" "simd_cmp")
3328 (set_attr "simd_mode" "DI")]
3333 (define_insn "aarch64_cmtst<mode>"
3334 [(set (match_operand:<V_cmp_result> 0 "register_operand" "=w")
3338 (match_operand:VDQ 1 "register_operand" "w")
3339 (match_operand:VDQ 2 "register_operand" "w"))
3340 (vec_duplicate:<V_cmp_result> (const_int 0)))))]
3342 "cmtst\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
3343 [(set_attr "simd_type" "simd_cmp")
3344 (set_attr "simd_mode" "<MODE>")]
3347 (define_insn_and_split "aarch64_cmtstdi"
3348 [(set (match_operand:DI 0 "register_operand" "=w,r")
3352 (match_operand:DI 1 "register_operand" "w,r")
3353 (match_operand:DI 2 "register_operand" "w,r"))
3357 cmtst\t%d0, %d1, %d2
3360 /* We need to prevent the split from
3361 happening in the 'w' constraint cases. */
3362 && GP_REGNUM_P (REGNO (operands[0]))
3363 && GP_REGNUM_P (REGNO (operands[1]))"
3364 [(set (reg:CC_NZ CC_REGNUM)
3366 (and:DI (match_dup 1)
3372 (match_operand 3 "cc_register" "")
3375 rtx and_tree = gen_rtx_AND (DImode, operands[1], operands[2]);
3376 enum machine_mode mode = SELECT_CC_MODE (NE, and_tree, const0_rtx);
3377 rtx cc_reg = aarch64_gen_compare_reg (NE, and_tree, const0_rtx);
3378 rtx comparison = gen_rtx_NE (mode, and_tree, const0_rtx);
3379 emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
3382 [(set_attr "simd_type" "simd_cmp")
3383 (set_attr "simd_mode" "DI")]
3386 ;; fcm(eq|ge|gt|le|lt)
3388 (define_insn "aarch64_cm<optab><mode>"
3389 [(set (match_operand:<V_cmp_result> 0 "register_operand" "=w,w")
3391 (COMPARISONS:<V_cmp_result>
3392 (match_operand:VALLF 1 "register_operand" "w,w")
3393 (match_operand:VALLF 2 "aarch64_simd_reg_or_zero" "w,YDz")
3397 fcm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>
3398 fcm<optab>\t%<v>0<Vmtype>, %<v>1<Vmtype>, 0"
3399 [(set_attr "simd_type" "simd_fcmp")
3400 (set_attr "simd_mode" "<MODE>")]
3404 ;; Note we can also handle what would be fac(le|lt) by
3405 ;; generating fac(ge|gt).
3407 (define_insn "*aarch64_fac<optab><mode>"
3408 [(set (match_operand:<V_cmp_result> 0 "register_operand" "=w")
3410 (FAC_COMPARISONS:<V_cmp_result>
3411 (abs:VALLF (match_operand:VALLF 1 "register_operand" "w"))
3412 (abs:VALLF (match_operand:VALLF 2 "register_operand" "w"))
3415 "fac<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>"
3416 [(set_attr "simd_type" "simd_fcmp")
3417 (set_attr "simd_mode" "<MODE>")]
3422 (define_insn "aarch64_addp<mode>"
3423 [(set (match_operand:VD_BHSI 0 "register_operand" "=w")
3425 [(match_operand:VD_BHSI 1 "register_operand" "w")
3426 (match_operand:VD_BHSI 2 "register_operand" "w")]
3429 "addp\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
3430 [(set_attr "simd_type" "simd_add")
3431 (set_attr "simd_mode" "<MODE>")]
3434 (define_insn "aarch64_addpdi"
3435 [(set (match_operand:DI 0 "register_operand" "=w")
3437 [(match_operand:V2DI 1 "register_operand" "w")]
3441 [(set_attr "simd_type" "simd_add")
3442 (set_attr "simd_mode" "DI")]
3445 (define_insn "aarch64_<fmaxmin><mode>"
3446 [(set (match_operand:VDQF 0 "register_operand" "=w")
3447 (unspec:VDQF [(match_operand:VDQF 1 "register_operand" "w")
3448 (match_operand:VDQF 2 "register_operand" "w")]
3451 "<fmaxmin>\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
3452 [(set_attr "simd_type" "simd_fminmax")
3453 (set_attr "simd_mode" "<MODE>")]
3458 (define_insn "sqrt<mode>2"
3459 [(set (match_operand:VDQF 0 "register_operand" "=w")
3460 (sqrt:VDQF (match_operand:VDQF 1 "register_operand" "w")))]
3462 "fsqrt\\t%0.<Vtype>, %1.<Vtype>"
3463 [(set_attr "simd_type" "simd_fsqrt")
3464 (set_attr "simd_mode" "<MODE>")]
3467 ;; Patterns for vector struct loads and stores.
3469 (define_insn "vec_load_lanesoi<mode>"
3470 [(set (match_operand:OI 0 "register_operand" "=w")
3471 (unspec:OI [(match_operand:OI 1 "aarch64_simd_struct_operand" "Utv")
3472 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3475 "ld2\\t{%S0.<Vtype> - %T0.<Vtype>}, %1"
3476 [(set_attr "simd_type" "simd_load2")
3477 (set_attr "simd_mode" "<MODE>")])
3479 (define_insn "vec_store_lanesoi<mode>"
3480 [(set (match_operand:OI 0 "aarch64_simd_struct_operand" "=Utv")
3481 (unspec:OI [(match_operand:OI 1 "register_operand" "w")
3482 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3485 "st2\\t{%S1.<Vtype> - %T1.<Vtype>}, %0"
3486 [(set_attr "simd_type" "simd_store2")
3487 (set_attr "simd_mode" "<MODE>")])
3489 (define_insn "vec_load_lanesci<mode>"
3490 [(set (match_operand:CI 0 "register_operand" "=w")
3491 (unspec:CI [(match_operand:CI 1 "aarch64_simd_struct_operand" "Utv")
3492 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3495 "ld3\\t{%S0.<Vtype> - %U0.<Vtype>}, %1"
3496 [(set_attr "simd_type" "simd_load3")
3497 (set_attr "simd_mode" "<MODE>")])
3499 (define_insn "vec_store_lanesci<mode>"
3500 [(set (match_operand:CI 0 "aarch64_simd_struct_operand" "=Utv")
3501 (unspec:CI [(match_operand:CI 1 "register_operand" "w")
3502 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3505 "st3\\t{%S1.<Vtype> - %U1.<Vtype>}, %0"
3506 [(set_attr "simd_type" "simd_store3")
3507 (set_attr "simd_mode" "<MODE>")])
3509 (define_insn "vec_load_lanesxi<mode>"
3510 [(set (match_operand:XI 0 "register_operand" "=w")
3511 (unspec:XI [(match_operand:XI 1 "aarch64_simd_struct_operand" "Utv")
3512 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3515 "ld4\\t{%S0.<Vtype> - %V0.<Vtype>}, %1"
3516 [(set_attr "simd_type" "simd_load4")
3517 (set_attr "simd_mode" "<MODE>")])
3519 (define_insn "vec_store_lanesxi<mode>"
3520 [(set (match_operand:XI 0 "aarch64_simd_struct_operand" "=Utv")
3521 (unspec:XI [(match_operand:XI 1 "register_operand" "w")
3522 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3525 "st4\\t{%S1.<Vtype> - %V1.<Vtype>}, %0"
3526 [(set_attr "simd_type" "simd_store4")
3527 (set_attr "simd_mode" "<MODE>")])
3529 ;; Reload patterns for AdvSIMD register list operands.
3531 (define_expand "mov<mode>"
3532 [(set (match_operand:VSTRUCT 0 "aarch64_simd_nonimmediate_operand" "")
3533 (match_operand:VSTRUCT 1 "aarch64_simd_general_operand" ""))]
3536 if (can_create_pseudo_p ())
3538 if (GET_CODE (operands[0]) != REG)
3539 operands[1] = force_reg (<MODE>mode, operands[1]);
3543 (define_insn "*aarch64_mov<mode>"
3544 [(set (match_operand:VSTRUCT 0 "aarch64_simd_nonimmediate_operand" "=w,Utv,w")
3545 (match_operand:VSTRUCT 1 "aarch64_simd_general_operand" " w,w,Utv"))]
3547 && (register_operand (operands[0], <MODE>mode)
3548 || register_operand (operands[1], <MODE>mode))"
3551 switch (which_alternative)
3554 case 1: return "st1\\t{%S1.16b - %<Vendreg>1.16b}, %0";
3555 case 2: return "ld1\\t{%S0.16b - %<Vendreg>0.16b}, %1";
3556 default: gcc_unreachable ();
3559 [(set_attr "simd_type" "simd_move,simd_store<nregs>,simd_load<nregs>")
3560 (set (attr "length") (symbol_ref "aarch64_simd_attr_length_move (insn)"))
3561 (set_attr "simd_mode" "<MODE>")])
3564 [(set (match_operand:OI 0 "register_operand" "")
3565 (match_operand:OI 1 "register_operand" ""))]
3566 "TARGET_SIMD && reload_completed"
3567 [(set (match_dup 0) (match_dup 1))
3568 (set (match_dup 2) (match_dup 3))]
3570 int rdest = REGNO (operands[0]);
3571 int rsrc = REGNO (operands[1]);
3572 rtx dest[2], src[2];
3574 dest[0] = gen_rtx_REG (TFmode, rdest);
3575 src[0] = gen_rtx_REG (TFmode, rsrc);
3576 dest[1] = gen_rtx_REG (TFmode, rdest + 1);
3577 src[1] = gen_rtx_REG (TFmode, rsrc + 1);
3579 aarch64_simd_disambiguate_copy (operands, dest, src, 2);
3583 [(set (match_operand:CI 0 "register_operand" "")
3584 (match_operand:CI 1 "register_operand" ""))]
3585 "TARGET_SIMD && reload_completed"
3586 [(set (match_dup 0) (match_dup 1))
3587 (set (match_dup 2) (match_dup 3))
3588 (set (match_dup 4) (match_dup 5))]
3590 int rdest = REGNO (operands[0]);
3591 int rsrc = REGNO (operands[1]);
3592 rtx dest[3], src[3];
3594 dest[0] = gen_rtx_REG (TFmode, rdest);
3595 src[0] = gen_rtx_REG (TFmode, rsrc);
3596 dest[1] = gen_rtx_REG (TFmode, rdest + 1);
3597 src[1] = gen_rtx_REG (TFmode, rsrc + 1);
3598 dest[2] = gen_rtx_REG (TFmode, rdest + 2);
3599 src[2] = gen_rtx_REG (TFmode, rsrc + 2);
3601 aarch64_simd_disambiguate_copy (operands, dest, src, 3);
3605 [(set (match_operand:XI 0 "register_operand" "")
3606 (match_operand:XI 1 "register_operand" ""))]
3607 "TARGET_SIMD && reload_completed"
3608 [(set (match_dup 0) (match_dup 1))
3609 (set (match_dup 2) (match_dup 3))
3610 (set (match_dup 4) (match_dup 5))
3611 (set (match_dup 6) (match_dup 7))]
3613 int rdest = REGNO (operands[0]);
3614 int rsrc = REGNO (operands[1]);
3615 rtx dest[4], src[4];
3617 dest[0] = gen_rtx_REG (TFmode, rdest);
3618 src[0] = gen_rtx_REG (TFmode, rsrc);
3619 dest[1] = gen_rtx_REG (TFmode, rdest + 1);
3620 src[1] = gen_rtx_REG (TFmode, rsrc + 1);
3621 dest[2] = gen_rtx_REG (TFmode, rdest + 2);
3622 src[2] = gen_rtx_REG (TFmode, rsrc + 2);
3623 dest[3] = gen_rtx_REG (TFmode, rdest + 3);
3624 src[3] = gen_rtx_REG (TFmode, rsrc + 3);
3626 aarch64_simd_disambiguate_copy (operands, dest, src, 4);
3629 (define_insn "aarch64_ld2<mode>_dreg"
3630 [(set (match_operand:OI 0 "register_operand" "=w")
3634 (unspec:VD [(match_operand:TI 1 "aarch64_simd_struct_operand" "Utv")]
3636 (vec_duplicate:VD (const_int 0)))
3638 (unspec:VD [(match_dup 1)]
3640 (vec_duplicate:VD (const_int 0)))) 0))]
3642 "ld2\\t{%S0.<Vtype> - %T0.<Vtype>}, %1"
3643 [(set_attr "simd_type" "simd_load2")
3644 (set_attr "simd_mode" "<MODE>")])
3646 (define_insn "aarch64_ld2<mode>_dreg"
3647 [(set (match_operand:OI 0 "register_operand" "=w")
3651 (unspec:DX [(match_operand:TI 1 "aarch64_simd_struct_operand" "Utv")]
3655 (unspec:DX [(match_dup 1)]
3657 (const_int 0))) 0))]
3659 "ld1\\t{%S0.1d - %T0.1d}, %1"
3660 [(set_attr "simd_type" "simd_load2")
3661 (set_attr "simd_mode" "<MODE>")])
3663 (define_insn "aarch64_ld3<mode>_dreg"
3664 [(set (match_operand:CI 0 "register_operand" "=w")
3669 (unspec:VD [(match_operand:EI 1 "aarch64_simd_struct_operand" "Utv")]
3671 (vec_duplicate:VD (const_int 0)))
3673 (unspec:VD [(match_dup 1)]
3675 (vec_duplicate:VD (const_int 0))))
3677 (unspec:VD [(match_dup 1)]
3679 (vec_duplicate:VD (const_int 0)))) 0))]
3681 "ld3\\t{%S0.<Vtype> - %U0.<Vtype>}, %1"
3682 [(set_attr "simd_type" "simd_load3")
3683 (set_attr "simd_mode" "<MODE>")])
3685 (define_insn "aarch64_ld3<mode>_dreg"
3686 [(set (match_operand:CI 0 "register_operand" "=w")
3691 (unspec:DX [(match_operand:EI 1 "aarch64_simd_struct_operand" "Utv")]
3695 (unspec:DX [(match_dup 1)]
3699 (unspec:DX [(match_dup 1)]
3701 (const_int 0))) 0))]
3703 "ld1\\t{%S0.1d - %U0.1d}, %1"
3704 [(set_attr "simd_type" "simd_load3")
3705 (set_attr "simd_mode" "<MODE>")])
3707 (define_insn "aarch64_ld4<mode>_dreg"
3708 [(set (match_operand:XI 0 "register_operand" "=w")
3713 (unspec:VD [(match_operand:OI 1 "aarch64_simd_struct_operand" "Utv")]
3715 (vec_duplicate:VD (const_int 0)))
3717 (unspec:VD [(match_dup 1)]
3719 (vec_duplicate:VD (const_int 0))))
3722 (unspec:VD [(match_dup 1)]
3724 (vec_duplicate:VD (const_int 0)))
3726 (unspec:VD [(match_dup 1)]
3728 (vec_duplicate:VD (const_int 0))))) 0))]
3730 "ld4\\t{%S0.<Vtype> - %V0.<Vtype>}, %1"
3731 [(set_attr "simd_type" "simd_load4")
3732 (set_attr "simd_mode" "<MODE>")])
3734 (define_insn "aarch64_ld4<mode>_dreg"
3735 [(set (match_operand:XI 0 "register_operand" "=w")
3740 (unspec:DX [(match_operand:OI 1 "aarch64_simd_struct_operand" "Utv")]
3744 (unspec:DX [(match_dup 1)]
3749 (unspec:DX [(match_dup 1)]
3753 (unspec:DX [(match_dup 1)]
3755 (const_int 0)))) 0))]
3757 "ld1\\t{%S0.1d - %V0.1d}, %1"
3758 [(set_attr "simd_type" "simd_load4")
3759 (set_attr "simd_mode" "<MODE>")])
3761 (define_expand "aarch64_ld<VSTRUCT:nregs><VDC:mode>"
3762 [(match_operand:VSTRUCT 0 "register_operand" "=w")
3763 (match_operand:DI 1 "register_operand" "r")
3764 (unspec:VDC [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3767 enum machine_mode mode = <VSTRUCT:VSTRUCT_DREG>mode;
3768 rtx mem = gen_rtx_MEM (mode, operands[1]);
3770 emit_insn (gen_aarch64_ld<VSTRUCT:nregs><VDC:mode>_dreg (operands[0], mem));
3774 (define_expand "aarch64_ld<VSTRUCT:nregs><VQ:mode>"
3775 [(match_operand:VSTRUCT 0 "register_operand" "=w")
3776 (match_operand:DI 1 "register_operand" "r")
3777 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3780 enum machine_mode mode = <VSTRUCT:MODE>mode;
3781 rtx mem = gen_rtx_MEM (mode, operands[1]);
3783 emit_insn (gen_vec_load_lanes<VSTRUCT:mode><VQ:mode> (operands[0], mem));
3787 ;; Expanders for builtins to extract vector registers from large
3788 ;; opaque integer modes.
3792 (define_expand "aarch64_get_dreg<VSTRUCT:mode><VDC:mode>"
3793 [(match_operand:VDC 0 "register_operand" "=w")
3794 (match_operand:VSTRUCT 1 "register_operand" "w")
3795 (match_operand:SI 2 "immediate_operand" "i")]
3798 int part = INTVAL (operands[2]);
3799 rtx temp = gen_reg_rtx (<VDC:VDBL>mode);
3800 int offset = part * 16;
3802 emit_move_insn (temp, gen_rtx_SUBREG (<VDC:VDBL>mode, operands[1], offset));
3803 emit_move_insn (operands[0], gen_lowpart (<VDC:MODE>mode, temp));
3809 (define_expand "aarch64_get_qreg<VSTRUCT:mode><VQ:mode>"
3810 [(match_operand:VQ 0 "register_operand" "=w")
3811 (match_operand:VSTRUCT 1 "register_operand" "w")
3812 (match_operand:SI 2 "immediate_operand" "i")]
3815 int part = INTVAL (operands[2]);
3816 int offset = part * 16;
3818 emit_move_insn (operands[0],
3819 gen_rtx_SUBREG (<VQ:MODE>mode, operands[1], offset));
3823 ;; Permuted-store expanders for neon intrinsics.
3825 ;; Permute instructions
3829 (define_expand "vec_perm_const<mode>"
3830 [(match_operand:VALL 0 "register_operand")
3831 (match_operand:VALL 1 "register_operand")
3832 (match_operand:VALL 2 "register_operand")
3833 (match_operand:<V_cmp_result> 3)]
3836 if (aarch64_expand_vec_perm_const (operands[0], operands[1],
3837 operands[2], operands[3]))
3843 (define_expand "vec_perm<mode>"
3844 [(match_operand:VB 0 "register_operand")
3845 (match_operand:VB 1 "register_operand")
3846 (match_operand:VB 2 "register_operand")
3847 (match_operand:VB 3 "register_operand")]
3850 aarch64_expand_vec_perm (operands[0], operands[1],
3851 operands[2], operands[3]);
3855 (define_insn "aarch64_tbl1<mode>"
3856 [(set (match_operand:VB 0 "register_operand" "=w")
3857 (unspec:VB [(match_operand:V16QI 1 "register_operand" "w")
3858 (match_operand:VB 2 "register_operand" "w")]
3861 "tbl\\t%0.<Vtype>, {%1.16b}, %2.<Vtype>"
3862 [(set_attr "simd_type" "simd_tbl")
3863 (set_attr "simd_mode" "<MODE>")]
3866 ;; Two source registers.
3868 (define_insn "aarch64_tbl2v16qi"
3869 [(set (match_operand:V16QI 0 "register_operand" "=w")
3870 (unspec:V16QI [(match_operand:OI 1 "register_operand" "w")
3871 (match_operand:V16QI 2 "register_operand" "w")]
3874 "tbl\\t%0.16b, {%S1.16b - %T1.16b}, %2.16b"
3875 [(set_attr "simd_type" "simd_tbl")
3876 (set_attr "simd_mode" "V16QI")]
3879 (define_insn_and_split "aarch64_combinev16qi"
3880 [(set (match_operand:OI 0 "register_operand" "=w")
3881 (unspec:OI [(match_operand:V16QI 1 "register_operand" "w")
3882 (match_operand:V16QI 2 "register_operand" "w")]
3886 "&& reload_completed"
3889 aarch64_split_combinev16qi (operands);
3893 (define_insn "aarch64_<PERMUTE:perm_insn><PERMUTE:perm_hilo><mode>"
3894 [(set (match_operand:VALL 0 "register_operand" "=w")
3895 (unspec:VALL [(match_operand:VALL 1 "register_operand" "w")
3896 (match_operand:VALL 2 "register_operand" "w")]
3899 "<PERMUTE:perm_insn><PERMUTE:perm_hilo>\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
3900 [(set_attr "simd_type" "simd_<PERMUTE:perm_insn>")
3901 (set_attr "simd_mode" "<MODE>")]
3904 (define_insn "aarch64_st2<mode>_dreg"
3905 [(set (match_operand:TI 0 "aarch64_simd_struct_operand" "=Utv")
3906 (unspec:TI [(match_operand:OI 1 "register_operand" "w")
3907 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3910 "st2\\t{%S1.<Vtype> - %T1.<Vtype>}, %0"
3911 [(set_attr "simd_type" "simd_store2")
3912 (set_attr "simd_mode" "<MODE>")])
3914 (define_insn "aarch64_st2<mode>_dreg"
3915 [(set (match_operand:TI 0 "aarch64_simd_struct_operand" "=Utv")
3916 (unspec:TI [(match_operand:OI 1 "register_operand" "w")
3917 (unspec:DX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3920 "st1\\t{%S1.1d - %T1.1d}, %0"
3921 [(set_attr "simd_type" "simd_store2")
3922 (set_attr "simd_mode" "<MODE>")])
3924 (define_insn "aarch64_st3<mode>_dreg"
3925 [(set (match_operand:EI 0 "aarch64_simd_struct_operand" "=Utv")
3926 (unspec:EI [(match_operand:CI 1 "register_operand" "w")
3927 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3930 "st3\\t{%S1.<Vtype> - %U1.<Vtype>}, %0"
3931 [(set_attr "simd_type" "simd_store3")
3932 (set_attr "simd_mode" "<MODE>")])
3934 (define_insn "aarch64_st3<mode>_dreg"
3935 [(set (match_operand:EI 0 "aarch64_simd_struct_operand" "=Utv")
3936 (unspec:EI [(match_operand:CI 1 "register_operand" "w")
3937 (unspec:DX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3940 "st1\\t{%S1.1d - %U1.1d}, %0"
3941 [(set_attr "simd_type" "simd_store3")
3942 (set_attr "simd_mode" "<MODE>")])
3944 (define_insn "aarch64_st4<mode>_dreg"
3945 [(set (match_operand:OI 0 "aarch64_simd_struct_operand" "=Utv")
3946 (unspec:OI [(match_operand:XI 1 "register_operand" "w")
3947 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3950 "st4\\t{%S1.<Vtype> - %V1.<Vtype>}, %0"
3951 [(set_attr "simd_type" "simd_store4")
3952 (set_attr "simd_mode" "<MODE>")])
3954 (define_insn "aarch64_st4<mode>_dreg"
3955 [(set (match_operand:OI 0 "aarch64_simd_struct_operand" "=Utv")
3956 (unspec:OI [(match_operand:XI 1 "register_operand" "w")
3957 (unspec:DX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3960 "st1\\t{%S1.1d - %V1.1d}, %0"
3961 [(set_attr "simd_type" "simd_store4")
3962 (set_attr "simd_mode" "<MODE>")])
3964 (define_expand "aarch64_st<VSTRUCT:nregs><VDC:mode>"
3965 [(match_operand:DI 0 "register_operand" "r")
3966 (match_operand:VSTRUCT 1 "register_operand" "w")
3967 (unspec:VDC [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3970 enum machine_mode mode = <VSTRUCT:VSTRUCT_DREG>mode;
3971 rtx mem = gen_rtx_MEM (mode, operands[0]);
3973 emit_insn (gen_aarch64_st<VSTRUCT:nregs><VDC:mode>_dreg (mem, operands[1]));
3977 (define_expand "aarch64_st<VSTRUCT:nregs><VQ:mode>"
3978 [(match_operand:DI 0 "register_operand" "r")
3979 (match_operand:VSTRUCT 1 "register_operand" "w")
3980 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
3983 enum machine_mode mode = <VSTRUCT:MODE>mode;
3984 rtx mem = gen_rtx_MEM (mode, operands[0]);
3986 emit_insn (gen_vec_store_lanes<VSTRUCT:mode><VQ:mode> (mem, operands[1]));
3990 ;; Expander for builtins to insert vector registers into large
3991 ;; opaque integer modes.
3993 ;; Q-register list. We don't need a D-reg inserter as we zero
3994 ;; extend them in arm_neon.h and insert the resulting Q-regs.
3996 (define_expand "aarch64_set_qreg<VSTRUCT:mode><VQ:mode>"
3997 [(match_operand:VSTRUCT 0 "register_operand" "+w")
3998 (match_operand:VSTRUCT 1 "register_operand" "0")
3999 (match_operand:VQ 2 "register_operand" "w")
4000 (match_operand:SI 3 "immediate_operand" "i")]
4003 int part = INTVAL (operands[3]);
4004 int offset = part * 16;
4006 emit_move_insn (operands[0], operands[1]);
4007 emit_move_insn (gen_rtx_SUBREG (<VQ:MODE>mode, operands[0], offset),
4012 ;; Standard pattern name vec_init<mode>.
4014 (define_expand "vec_init<mode>"
4015 [(match_operand:VALL 0 "register_operand" "")
4016 (match_operand 1 "" "")]
4019 aarch64_expand_vector_init (operands[0], operands[1]);
4023 (define_insn "*aarch64_simd_ld1r<mode>"
4024 [(set (match_operand:VALLDI 0 "register_operand" "=w")
4025 (vec_duplicate:VALLDI
4026 (match_operand:<VEL> 1 "aarch64_simd_struct_operand" "Utv")))]
4028 "ld1r\\t{%0.<Vtype>}, %1"
4029 [(set_attr "simd_type" "simd_load1r")
4030 (set_attr "simd_mode" "<MODE>")])
4032 (define_insn "aarch64_frecpe<mode>"
4033 [(set (match_operand:VDQF 0 "register_operand" "=w")
4034 (unspec:VDQF [(match_operand:VDQF 1 "register_operand" "w")]
4037 "frecpe\\t%0.<Vtype>, %1.<Vtype>"
4038 [(set_attr "simd_type" "simd_frecpe")
4039 (set_attr "simd_mode" "<MODE>")]
4042 (define_insn "aarch64_frecps<mode>"
4043 [(set (match_operand:VDQF 0 "register_operand" "=w")
4044 (unspec:VDQF [(match_operand:VDQF 1 "register_operand" "w")
4045 (match_operand:VDQF 2 "register_operand" "w")]
4048 "frecps\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
4049 [(set_attr "simd_type" "simd_frecps")
4050 (set_attr "simd_mode" "<MODE>")]