1 ;;- Instruction patterns for the System z vector facility
2 ;; Copyright (C) 2015 Free Software Foundation, Inc.
3 ;; Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it under
8 ;; the terms of the GNU General Public License as published by the Free
9 ;; Software Foundation; either version 3, or (at your option) any later
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
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/>.
21 ; All vector modes supported in a vector register
22 (define_mode_iterator V
23 [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF
25 (define_mode_iterator VT
26 [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF
27 V2SF V4SF V1DF V2DF V1TF V1TI TI])
29 ; All vector modes directly supported by the hardware having full vector reg size
30 ; V_HW2 is duplicate of V_HW for having two iterators expanding
31 ; independently e.g. vcond
32 (define_mode_iterator V_HW [V16QI V8HI V4SI V2DI V2DF])
33 (define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF])
34 ; Including TI for instructions that support it (va, vn, ...)
35 (define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI])
37 ; All full size integer vector modes supported in a vector register + TImode
38 (define_mode_iterator VIT_HW [V16QI V8HI V4SI V2DI V1TI TI])
39 (define_mode_iterator VI_HW [V16QI V8HI V4SI V2DI])
40 (define_mode_iterator VI_HW_QHS [V16QI V8HI V4SI])
41 (define_mode_iterator VI_HW_HS [V8HI V4SI])
42 (define_mode_iterator VI_HW_QH [V16QI V8HI])
44 ; All integer vector modes supported in a vector register + TImode
45 (define_mode_iterator VIT [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1TI TI])
46 (define_mode_iterator VI [V2QI V4QI V8QI V16QI V2HI V4HI V8HI V2SI V4SI V2DI])
47 (define_mode_iterator VI_QHS [V4QI V8QI V16QI V4HI V8HI V4SI])
49 (define_mode_iterator V_8 [V1QI])
50 (define_mode_iterator V_16 [V2QI V1HI])
51 (define_mode_iterator V_32 [V4QI V2HI V1SI V1SF])
52 (define_mode_iterator V_64 [V8QI V4HI V2SI V2SF V1DI V1DF])
53 (define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF])
55 ; A blank for vector modes and a * for TImode. This is used to hide
56 ; the TImode expander name in case it is defined already. See addti3
58 (define_mode_attr ti* [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "")
59 (V1HI "") (V2HI "") (V4HI "") (V8HI "")
60 (V1SI "") (V2SI "") (V4SI "")
64 ; The element type of the vector.
65 (define_mode_attr non_vec[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI")
66 (V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI")
67 (V1SI "SI") (V2SI "SI") (V4SI "SI")
68 (V1DI "DI") (V2DI "DI")
70 (V1SF "SF") (V2SF "SF") (V4SF "SF")
71 (V1DF "DF") (V2DF "DF")
74 ; The instruction suffix
75 (define_mode_attr bhfgq[(V1QI "b") (V2QI "b") (V4QI "b") (V8QI "b") (V16QI "b")
76 (V1HI "h") (V2HI "h") (V4HI "h") (V8HI "h")
77 (V1SI "f") (V2SI "f") (V4SI "f")
80 (V1SF "f") (V2SF "f") (V4SF "f")
84 ; This is for vmalhw. It gets an 'w' attached to avoid confusion with
85 ; multiply and add logical high vmalh.
86 (define_mode_attr w [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "")
87 (V1HI "w") (V2HI "w") (V4HI "w") (V8HI "w")
88 (V1SI "") (V2SI "") (V4SI "")
91 ; Resulting mode of a vector comparison. For floating point modes an
92 ; integer vector mode with the same element size is picked.
93 (define_mode_attr tointvec [(V1QI "V1QI") (V2QI "V2QI") (V4QI "V4QI") (V8QI "V8QI") (V16QI "V16QI")
94 (V1HI "V1HI") (V2HI "V2HI") (V4HI "V4HI") (V8HI "V8HI")
95 (V1SI "V1SI") (V2SI "V2SI") (V4SI "V4SI")
96 (V1DI "V1DI") (V2DI "V2DI")
98 (V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI")
99 (V1DF "V1DI") (V2DF "V2DI")
102 ; Vector with doubled element size.
103 (define_mode_attr vec_double [(V2QI "V1HI") (V4QI "V2HI") (V8QI "V4HI") (V16QI "V8HI")
104 (V2HI "V1SI") (V4HI "V2SI") (V8HI "V4SI")
105 (V2SI "V1DI") (V4SI "V2DI")
107 (V2SF "V1DF") (V4SF "V2DF")])
109 ; Vector with half the element size.
110 (define_mode_attr vec_half [(V1HI "V2QI") (V2HI "V4QI") (V4HI "V8QI") (V8HI "V16QI")
111 (V1SI "V2HI") (V2SI "V4HI") (V4SI "V8HI")
112 (V1DI "V2SI") (V2DI "V4SI")
114 (V1DF "V2SF") (V2DF "V4SF")
117 ; The comparisons not setting CC iterate over the rtx code.
118 (define_code_iterator VFCMP_HW_OP [eq gt ge])
119 (define_code_attr asm_fcmp_op [(eq "e") (gt "h") (ge "he")])
123 ; Comparison operators on int and fp compares which are directly
124 ; supported by the HW.
125 (define_code_iterator VICMP_HW_OP [eq gt gtu])
126 ; For int insn_cmp_op can be used in the insn name as well as in the asm output.
127 (define_code_attr insn_cmp_op [(eq "eq") (gt "h") (gtu "hl") (ge "he")])
129 ; Flags for vector string instructions (vfae all 4, vfee only ZS and CS, vstrc all 4)
131 [(VSTRING_FLAG_IN 8) ; invert result
132 (VSTRING_FLAG_RT 4) ; result type
133 (VSTRING_FLAG_ZS 2) ; zero search
134 (VSTRING_FLAG_CS 1)]) ; condition code set
136 (include "vx-builtins.md")
138 ; Full HW vector size moves
139 (define_insn "mov<mode>"
140 [(set (match_operand:V_128 0 "nonimmediate_operand" "=v, v,QR, v, v, v, v, v,v,d")
141 (match_operand:V_128 1 "general_operand" " v,QR, v,j00,jm1,jyy,jxx,jKK,d,v"))]
150 vgm<bhfgq>\t%v0,%s1,%e1
151 vrepi<bhfgq>\t%v0,%h1
154 [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRI,VRI,VRI,VRI,VRR,*")])
157 [(set (match_operand:V_128 0 "register_operand" "")
158 (match_operand:V_128 1 "register_operand" ""))]
159 "TARGET_VX && GENERAL_REG_P (operands[0]) && VECTOR_REG_P (operands[1])"
161 (unspec:DI [(subreg:V2DI (match_dup 1) 0)
162 (const_int 0)] UNSPEC_VEC_EXTRACT))
164 (unspec:DI [(subreg:V2DI (match_dup 1) 0)
165 (const_int 1)] UNSPEC_VEC_EXTRACT))]
167 operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
168 operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
171 ; Moves for smaller vector modes.
173 ; In these patterns only the vlr, vone, and vzero instructions write
174 ; VR bytes outside the mode. This should be ok since we disallow
175 ; formerly bigger modes being accessed with smaller modes via
176 ; subreg. Note: The vone, vzero instructions could easily be replaced
177 ; with vlei which would only access the bytes belonging to the mode.
178 ; However, this would probably be slower.
180 (define_insn "mov<mode>"
181 [(set (match_operand:V_8 0 "nonimmediate_operand" "=v,v,d, v,QR, v, v, v, v,d, Q, S, Q, S, d, d,d,d,d,R,T")
182 (match_operand:V_8 1 "general_operand" " v,d,v,QR, v,j00,jm1,jyy,jxx,d,j00,j00,jm1,jm1,j00,jm1,R,T,b,d,d"))]
206 [(set_attr "op_type" "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SI,SIY,SI,SIY,RI,RI,RX,RXY,RIL,RX,RXY")])
208 (define_insn "mov<mode>"
209 [(set (match_operand:V_16 0 "nonimmediate_operand" "=v,v,d, v,QR, v, v, v, v,d, Q, Q, d, d,d,d,d,R,T,b")
210 (match_operand:V_16 1 "general_operand" " v,d,v,QR, v,j00,jm1,jyy,jxx,d,j00,jm1,j00,jm1,R,T,b,d,d,d"))]
233 [(set_attr "op_type" "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SIL,SIL,RI,RI,RX,RXY,RIL,RX,RXY,RIL")])
235 (define_insn "mov<mode>"
236 [(set (match_operand:V_32 0 "nonimmediate_operand" "=f,f,f,R,T,v,v,d, v,QR, f, v, v, v, v, Q, Q, d, d,d,d,d,d,R,T,b")
237 (match_operand:V_32 1 "general_operand" " f,R,T,f,f,v,d,v,QR, v,j00,j00,jm1,jyy,jxx,j00,jm1,j00,jm1,b,d,R,T,d,d,d"))]
266 [(set_attr "op_type" "RRE,RXE,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,SIL,SIL,RI,RI,
267 RIL,RR,RX,RXY,RX,RXY,RIL")])
269 (define_insn "mov<mode>"
270 [(set (match_operand:V_64 0 "nonimmediate_operand"
271 "=f,f,f,R,T,v,v,d, v,QR, f, v, v, v, v, Q, Q, d, d,f,d,d,d, d,RT,b")
272 (match_operand:V_64 1 "general_operand"
273 " f,R,T,f,f,v,d,v,QR, v,j00,j00,jm1,jyy,jxx,j00,jm1,j00,jm1,d,f,b,d,RT, d,d"))]
302 [(set_attr "op_type" "RRE,RX,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,
303 SIL,SIL,RI,RI,RRE,RRE,RIL,RR,RXY,RXY,RIL")])
310 ; FIXME: Support also vector mode operands for 1
311 ; FIXME: A target memory operand seems to be useful otherwise we end
312 ; up with vl vlvgg vst. Shouldn't the middle-end be able to handle
314 (define_insn "*vec_set<mode>"
315 [(set (match_operand:V 0 "register_operand" "=v, v,v")
316 (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d,QR,K")
317 (match_operand:DI 2 "shift_count_or_setmem_operand" "Y, I,I")
318 (match_operand:V 3 "register_operand" "0, 0,0")]
322 vlvg<bhfgq>\t%v0,%1,%Y2
323 vle<bhfgq>\t%v0,%1,%2
324 vlei<bhfgq>\t%v0,%1,%2"
325 [(set_attr "op_type" "VRS,VRX,VRI")])
327 ; vec_set is supposed to *modify* an existing vector so operand 0 is
328 ; duplicated as input operand.
329 (define_expand "vec_set<mode>"
330 [(set (match_operand:V 0 "register_operand" "")
331 (unspec:V [(match_operand:<non_vec> 1 "general_operand" "")
332 (match_operand:SI 2 "shift_count_or_setmem_operand" "")
337 ; FIXME: Support also vector mode operands for 0
338 ; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :(
339 ; This is used via RTL standard name as well as for expanding the builtin
340 (define_insn "vec_extract<mode>"
341 [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,QR")
342 (unspec:<non_vec> [(match_operand:V 1 "register_operand" " v, v")
343 (match_operand:SI 2 "shift_count_or_setmem_operand" " Y, I")]
344 UNSPEC_VEC_EXTRACT))]
347 vlgv<bhfgq>\t%0,%v1,%Y2
348 vste<bhfgq>\t%v1,%0,%2"
349 [(set_attr "op_type" "VRS,VRX")])
351 (define_expand "vec_init<V_HW:mode>"
352 [(match_operand:V_HW 0 "register_operand" "")
353 (match_operand:V_HW 1 "nonmemory_operand" "")]
356 s390_expand_vec_init (operands[0], operands[1]);
360 ; Replicate from vector element
361 (define_insn "*vec_splat<mode>"
362 [(set (match_operand:V_HW 0 "register_operand" "=v")
364 (vec_select:<non_vec>
365 (match_operand:V_HW 1 "register_operand" "v")
367 [(match_operand:QI 2 "immediate_operand" "C")]))))]
369 "vrep<bhfgq>\t%v0,%v1,%2"
370 [(set_attr "op_type" "VRI")])
372 (define_insn "*vec_splats<mode>"
373 [(set (match_operand:V_HW 0 "register_operand" "=v,v,v,v")
374 (vec_duplicate:V_HW (match_operand:<non_vec> 1 "general_operand" "QR,K,v,d")))]
378 vrepi<bhfgq>\t%v0,%h1
379 vrep<bhfgq>\t%v0,%v1,0
381 [(set_attr "op_type" "VRX,VRI,VRI,*")])
383 ; vec_splats is supposed to replicate op1 into all elements of op0
384 ; This splitter first sets the rightmost element of op0 to op1 and
385 ; then does a vec_splat to replicate that element into all other
388 [(set (match_operand:V_HW 0 "register_operand" "")
389 (vec_duplicate:V_HW (match_operand:<non_vec> 1 "register_operand" "")))]
390 "TARGET_VX && GENERAL_REG_P (operands[1])"
392 (unspec:V_HW [(match_dup 1) (match_dup 2) (match_dup 0)] UNSPEC_VEC_SET))
395 (vec_select:<non_vec>
396 (match_dup 0) (parallel [(match_dup 2)]))))]
398 operands[2] = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1);
401 (define_expand "vcond<V_HW:mode><V_HW2:mode>"
402 [(set (match_operand:V_HW 0 "register_operand" "")
404 (match_operator 3 "comparison_operator"
405 [(match_operand:V_HW2 4 "register_operand" "")
406 (match_operand:V_HW2 5 "register_operand" "")])
407 (match_operand:V_HW 1 "nonmemory_operand" "")
408 (match_operand:V_HW 2 "nonmemory_operand" "")))]
409 "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)"
411 s390_expand_vcond (operands[0], operands[1], operands[2],
412 GET_CODE (operands[3]), operands[4], operands[5]);
416 (define_expand "vcondu<V_HW:mode><V_HW2:mode>"
417 [(set (match_operand:V_HW 0 "register_operand" "")
419 (match_operator 3 "comparison_operator"
420 [(match_operand:V_HW2 4 "register_operand" "")
421 (match_operand:V_HW2 5 "register_operand" "")])
422 (match_operand:V_HW 1 "nonmemory_operand" "")
423 (match_operand:V_HW 2 "nonmemory_operand" "")))]
424 "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)"
426 s390_expand_vcond (operands[0], operands[1], operands[2],
427 GET_CODE (operands[3]), operands[4], operands[5]);
431 ; We only have HW support for byte vectors. The middle-end is
432 ; supposed to lower the mode if required.
433 (define_insn "vec_permv16qi"
434 [(set (match_operand:V16QI 0 "register_operand" "=v")
435 (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
436 (match_operand:V16QI 2 "register_operand" "v")
437 (match_operand:V16QI 3 "register_operand" "v")]
440 "vperm\t%v0,%v1,%v2,%v3"
441 [(set_attr "op_type" "VRR")])
443 ; vec_perm_const for V2DI using vpdi?
446 ;; Vector integer arithmetic instructions
449 ; vab, vah, vaf, vag, vaq
451 ; We use nonimmediate_operand instead of register_operand since it is
452 ; better to have the reloads into VRs instead of splitting the
453 ; operation into two DImode ADDs.
454 (define_insn "<ti*>add<mode>3"
455 [(set (match_operand:VIT 0 "nonimmediate_operand" "=v")
456 (plus:VIT (match_operand:VIT 1 "nonimmediate_operand" "v")
457 (match_operand:VIT 2 "nonimmediate_operand" "v")))]
459 "va<bhfgq>\t%v0,%v1,%v2"
460 [(set_attr "op_type" "VRR")])
462 ; vsb, vsh, vsf, vsg, vsq
463 (define_insn "<ti*>sub<mode>3"
464 [(set (match_operand:VIT 0 "nonimmediate_operand" "=v")
465 (minus:VIT (match_operand:VIT 1 "nonimmediate_operand" "v")
466 (match_operand:VIT 2 "nonimmediate_operand" "v")))]
468 "vs<bhfgq>\t%v0,%v1,%v2"
469 [(set_attr "op_type" "VRR")])
472 (define_insn "mul<mode>3"
473 [(set (match_operand:VI_QHS 0 "register_operand" "=v")
474 (mult:VI_QHS (match_operand:VI_QHS 1 "register_operand" "v")
475 (match_operand:VI_QHS 2 "register_operand" "v")))]
477 "vml<bhfgq><w>\t%v0,%v1,%v2"
478 [(set_attr "op_type" "VRR")])
480 ; vlcb, vlch, vlcf, vlcg
481 (define_insn "neg<mode>2"
482 [(set (match_operand:VI 0 "register_operand" "=v")
483 (neg:VI (match_operand:VI 1 "register_operand" "v")))]
485 "vlc<bhfgq>\t%v0,%v1"
486 [(set_attr "op_type" "VRR")])
488 ; vlpb, vlph, vlpf, vlpg
489 (define_insn "abs<mode>2"
490 [(set (match_operand:VI 0 "register_operand" "=v")
491 (abs:VI (match_operand:VI 1 "register_operand" "v")))]
493 "vlp<bhfgq>\t%v0,%v1"
494 [(set_attr "op_type" "VRR")])
499 ; Sum across DImode parts of the 1st operand and add the rightmost
500 ; element of 2nd operand
502 (define_insn "*vec_sum2<mode>"
503 [(set (match_operand:V2DI 0 "register_operand" "=v")
504 (unspec:V2DI [(match_operand:VI_HW_HS 1 "register_operand" "v")
505 (match_operand:VI_HW_HS 2 "register_operand" "v")]
508 "vsumg<bhfgq>\t%v0,%v1,%v2"
509 [(set_attr "op_type" "VRR")])
512 (define_insn "*vec_sum4<mode>"
513 [(set (match_operand:V4SI 0 "register_operand" "=v")
514 (unspec:V4SI [(match_operand:VI_HW_QH 1 "register_operand" "v")
515 (match_operand:VI_HW_QH 2 "register_operand" "v")]
518 "vsum<bhfgq>\t%v0,%v1,%v2"
519 [(set_attr "op_type" "VRR")])
522 ;; Vector bit instructions (int + fp)
527 (define_insn "and<mode>3"
528 [(set (match_operand:VT 0 "register_operand" "=v")
529 (and:VT (match_operand:VT 1 "register_operand" "v")
530 (match_operand:VT 2 "register_operand" "v")))]
533 [(set_attr "op_type" "VRR")])
538 (define_insn "ior<mode>3"
539 [(set (match_operand:VT 0 "register_operand" "=v")
540 (ior:VT (match_operand:VT 1 "register_operand" "v")
541 (match_operand:VT 2 "register_operand" "v")))]
544 [(set_attr "op_type" "VRR")])
549 (define_insn "xor<mode>3"
550 [(set (match_operand:VT 0 "register_operand" "=v")
551 (xor:VT (match_operand:VT 1 "register_operand" "v")
552 (match_operand:VT 2 "register_operand" "v")))]
555 [(set_attr "op_type" "VRR")])
558 ; Bitwise inversion of a vector - used for vec_cmpne
559 (define_insn "*not<mode>"
560 [(set (match_operand:VT 0 "register_operand" "=v")
561 (not:VT (match_operand:VT 1 "register_operand" "v")))]
564 [(set_attr "op_type" "VRR")])
566 ; Vector population count
568 (define_insn "popcountv16qi2"
569 [(set (match_operand:V16QI 0 "register_operand" "=v")
570 (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")]
574 [(set_attr "op_type" "VRR")])
576 ; vpopct only counts bits in byte elements. Bigger element sizes need
577 ; to be emulated. Word and doubleword elements can use the sum across
578 ; instructions. For halfword sized elements we do a shift of a copy
579 ; of the result, add it to the result and extend it to halfword
580 ; element size (unpack).
582 (define_expand "popcountv8hi2"
584 (unspec:V16QI [(subreg:V16QI (match_operand:V8HI 1 "register_operand" "v") 0)]
586 ; Make a copy of the result
587 (set (match_dup 3) (match_dup 2))
588 ; Generate the shift count operand in a VR (8->byte 7)
589 (set (match_dup 4) (match_dup 5))
590 (set (match_dup 4) (unspec:V16QI [(const_int 8)
592 (match_dup 4)] UNSPEC_VEC_SET))
593 ; Vector shift right logical by one byte
595 (unspec:V16QI [(match_dup 3) (match_dup 4)] UNSPEC_VEC_SRLB))
596 ; Add the shifted and the original result
598 (plus:V16QI (match_dup 2) (match_dup 3)))
599 ; Generate mask for the odd numbered byte elements
601 (const_vector:V16QI [(const_int 0) (const_int 255)
602 (const_int 0) (const_int 255)
603 (const_int 0) (const_int 255)
604 (const_int 0) (const_int 255)
605 (const_int 0) (const_int 255)
606 (const_int 0) (const_int 255)
607 (const_int 0) (const_int 255)
608 (const_int 0) (const_int 255)]))
609 ; Zero out the even indexed bytes
610 (set (match_operand:V8HI 0 "register_operand" "=v")
611 (and:V8HI (subreg:V8HI (match_dup 2) 0)
612 (subreg:V8HI (match_dup 3) 0)))
616 operands[2] = gen_reg_rtx (V16QImode);
617 operands[3] = gen_reg_rtx (V16QImode);
618 operands[4] = gen_reg_rtx (V16QImode);
619 operands[5] = CONST0_RTX (V16QImode);
622 (define_expand "popcountv4si2"
624 (unspec:V16QI [(subreg:V16QI (match_operand:V4SI 1 "register_operand" "v") 0)]
626 (set (match_operand:V4SI 0 "register_operand" "=v")
627 (unspec:V4SI [(match_dup 2) (match_dup 3)]
631 operands[2] = gen_reg_rtx (V16QImode);
632 operands[3] = force_reg (V16QImode, CONST0_RTX (V16QImode));
635 (define_expand "popcountv2di2"
637 (unspec:V16QI [(subreg:V16QI (match_operand:V2DI 1 "register_operand" "v") 0)]
640 (unspec:V4SI [(match_dup 2) (match_dup 4)]
642 (set (match_operand:V2DI 0 "register_operand" "=v")
643 (unspec:V2DI [(match_dup 3) (match_dup 5)]
647 operands[2] = gen_reg_rtx (V16QImode);
648 operands[3] = gen_reg_rtx (V4SImode);
649 operands[4] = force_reg (V16QImode, CONST0_RTX (V16QImode));
650 operands[5] = force_reg (V4SImode, CONST0_RTX (V4SImode));
653 ; Count leading zeros
654 (define_insn "clz<mode>2"
655 [(set (match_operand:V 0 "register_operand" "=v")
656 (clz:V (match_operand:V 1 "register_operand" "v")))]
658 "vclz<bhfgq>\t%v0,%v1"
659 [(set_attr "op_type" "VRR")])
661 ; Count trailing zeros
662 (define_insn "ctz<mode>2"
663 [(set (match_operand:V 0 "register_operand" "=v")
664 (ctz:V (match_operand:V 1 "register_operand" "v")))]
666 "vctz<bhfgq>\t%v0,%v1"
667 [(set_attr "op_type" "VRR")])
670 ; Vector rotate instructions
672 ; Each vector element rotated by a scalar
673 ; verllb, verllh, verllf, verllg
674 (define_insn "rotl<mode>3"
675 [(set (match_operand:VI 0 "register_operand" "=v")
676 (rotate:VI (match_operand:VI 1 "register_operand" "v")
677 (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
679 "verll<bhfgq>\t%v0,%v1,%Y2"
680 [(set_attr "op_type" "VRS")])
682 ; Each vector element rotated by the corresponding vector element
683 ; verllvb, verllvh, verllvf, verllvg
684 (define_insn "vrotl<mode>3"
685 [(set (match_operand:VI 0 "register_operand" "=v")
686 (rotate:VI (match_operand:VI 1 "register_operand" "v")
687 (match_operand:VI 2 "register_operand" "v")))]
689 "verllv<bhfgq>\t%v0,%v1,%v2"
690 [(set_attr "op_type" "VRR")])
693 ; Shift each element by scalar value
695 ; veslb, veslh, veslf, veslg
696 (define_insn "ashl<mode>3"
697 [(set (match_operand:VI 0 "register_operand" "=v")
698 (ashift:VI (match_operand:VI 1 "register_operand" "v")
699 (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
701 "vesl<bhfgq>\t%v0,%v1,%Y2"
702 [(set_attr "op_type" "VRS")])
704 ; vesrab, vesrah, vesraf, vesrag
705 (define_insn "ashr<mode>3"
706 [(set (match_operand:VI 0 "register_operand" "=v")
707 (ashiftrt:VI (match_operand:VI 1 "register_operand" "v")
708 (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
710 "vesra<bhfgq>\t%v0,%v1,%Y2"
711 [(set_attr "op_type" "VRS")])
713 ; vesrlb, vesrlh, vesrlf, vesrlg
714 (define_insn "lshr<mode>3"
715 [(set (match_operand:VI 0 "register_operand" "=v")
716 (lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
717 (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
719 "vesrl<bhfgq>\t%v0,%v1,%Y2"
720 [(set_attr "op_type" "VRS")])
723 ; Shift each element by corresponding vector element
725 ; veslvb, veslvh, veslvf, veslvg
726 (define_insn "vashl<mode>3"
727 [(set (match_operand:VI 0 "register_operand" "=v")
728 (ashift:VI (match_operand:VI 1 "register_operand" "v")
729 (match_operand:VI 2 "register_operand" "v")))]
731 "veslv<bhfgq>\t%v0,%v1,%v2"
732 [(set_attr "op_type" "VRR")])
734 ; vesravb, vesravh, vesravf, vesravg
735 (define_insn "vashr<mode>3"
736 [(set (match_operand:VI 0 "register_operand" "=v")
737 (ashiftrt:VI (match_operand:VI 1 "register_operand" "v")
738 (match_operand:VI 2 "register_operand" "v")))]
740 "vesrav<bhfgq>\t%v0,%v1,%v2"
741 [(set_attr "op_type" "VRR")])
743 ; vesrlvb, vesrlvh, vesrlvf, vesrlvg
744 (define_insn "vlshr<mode>3"
745 [(set (match_operand:VI 0 "register_operand" "=v")
746 (lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
747 (match_operand:VI 2 "register_operand" "v")))]
749 "vesrlv<bhfgq>\t%v0,%v1,%v2"
750 [(set_attr "op_type" "VRR")])
752 ; Vector shift right logical by byte
754 ; Pattern used by e.g. popcount
755 (define_insn "*vec_srb<mode>"
756 [(set (match_operand:V_HW 0 "register_operand" "=v")
757 (unspec:V_HW [(match_operand:V_HW 1 "register_operand" "v")
758 (match_operand:<tointvec> 2 "register_operand" "v")]
762 [(set_attr "op_type" "VRR")])
765 ; vmnb, vmnh, vmnf, vmng
766 (define_insn "smin<mode>3"
767 [(set (match_operand:VI 0 "register_operand" "=v")
768 (smin:VI (match_operand:VI 1 "register_operand" "v")
769 (match_operand:VI 2 "register_operand" "v")))]
771 "vmn<bhfgq>\t%v0,%v1,%v2"
772 [(set_attr "op_type" "VRR")])
774 ; vmxb, vmxh, vmxf, vmxg
775 (define_insn "smax<mode>3"
776 [(set (match_operand:VI 0 "register_operand" "=v")
777 (smax:VI (match_operand:VI 1 "register_operand" "v")
778 (match_operand:VI 2 "register_operand" "v")))]
780 "vmx<bhfgq>\t%v0,%v1,%v2"
781 [(set_attr "op_type" "VRR")])
783 ; vmnlb, vmnlh, vmnlf, vmnlg
784 (define_insn "umin<mode>3"
785 [(set (match_operand:VI 0 "register_operand" "=v")
786 (umin:VI (match_operand:VI 1 "register_operand" "v")
787 (match_operand:VI 2 "register_operand" "v")))]
789 "vmnl<bhfgq>\t%v0,%v1,%v2"
790 [(set_attr "op_type" "VRR")])
792 ; vmxlb, vmxlh, vmxlf, vmxlg
793 (define_insn "umax<mode>3"
794 [(set (match_operand:VI 0 "register_operand" "=v")
795 (umax:VI (match_operand:VI 1 "register_operand" "v")
796 (match_operand:VI 2 "register_operand" "v")))]
798 "vmxl<bhfgq>\t%v0,%v1,%v2"
799 [(set_attr "op_type" "VRR")])
802 (define_insn "vec_widen_smult_even_<mode>"
803 [(set (match_operand:<vec_double> 0 "register_operand" "=v")
804 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "v")
805 (match_operand:VI_QHS 2 "register_operand" "v")]
806 UNSPEC_VEC_SMULT_EVEN))]
808 "vme<bhfgq>\t%v0,%v1,%v2"
809 [(set_attr "op_type" "VRR")])
811 ; vmleb, vmleh, vmlef
812 (define_insn "vec_widen_umult_even_<mode>"
813 [(set (match_operand:<vec_double> 0 "register_operand" "=v")
814 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "v")
815 (match_operand:VI_QHS 2 "register_operand" "v")]
816 UNSPEC_VEC_UMULT_EVEN))]
818 "vmle<bhfgq>\t%v0,%v1,%v2"
819 [(set_attr "op_type" "VRR")])
822 (define_insn "vec_widen_smult_odd_<mode>"
823 [(set (match_operand:<vec_double> 0 "register_operand" "=v")
824 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "v")
825 (match_operand:VI_QHS 2 "register_operand" "v")]
826 UNSPEC_VEC_SMULT_ODD))]
828 "vmo<bhfgq>\t%v0,%v1,%v2"
829 [(set_attr "op_type" "VRR")])
831 ; vmlob, vmloh, vmlof
832 (define_insn "vec_widen_umult_odd_<mode>"
833 [(set (match_operand:<vec_double> 0 "register_operand" "=v")
834 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "v")
835 (match_operand:VI_QHS 2 "register_operand" "v")]
836 UNSPEC_VEC_UMULT_ODD))]
838 "vmlo<bhfgq>\t%v0,%v1,%v2"
839 [(set_attr "op_type" "VRR")])
846 ; vec_widen_ushiftl_hi
847 ; vec_widen_ushiftl_lo
848 ; vec_widen_sshiftl_hi
849 ; vec_widen_sshiftl_lo
852 ;; Vector floating point arithmetic instructions
855 (define_insn "addv2df3"
856 [(set (match_operand:V2DF 0 "register_operand" "=v")
857 (plus:V2DF (match_operand:V2DF 1 "register_operand" "v")
858 (match_operand:V2DF 2 "register_operand" "v")))]
861 [(set_attr "op_type" "VRR")])
863 (define_insn "subv2df3"
864 [(set (match_operand:V2DF 0 "register_operand" "=v")
865 (minus:V2DF (match_operand:V2DF 1 "register_operand" "v")
866 (match_operand:V2DF 2 "register_operand" "v")))]
869 [(set_attr "op_type" "VRR")])
871 (define_insn "mulv2df3"
872 [(set (match_operand:V2DF 0 "register_operand" "=v")
873 (mult:V2DF (match_operand:V2DF 1 "register_operand" "v")
874 (match_operand:V2DF 2 "register_operand" "v")))]
877 [(set_attr "op_type" "VRR")])
879 (define_insn "divv2df3"
880 [(set (match_operand:V2DF 0 "register_operand" "=v")
881 (div:V2DF (match_operand:V2DF 1 "register_operand" "v")
882 (match_operand:V2DF 2 "register_operand" "v")))]
885 [(set_attr "op_type" "VRR")])
887 (define_insn "sqrtv2df2"
888 [(set (match_operand:V2DF 0 "register_operand" "=v")
889 (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "v")))]
892 [(set_attr "op_type" "VRR")])
894 (define_insn "fmav2df4"
895 [(set (match_operand:V2DF 0 "register_operand" "=v")
896 (fma:V2DF (match_operand:V2DF 1 "register_operand" "v")
897 (match_operand:V2DF 2 "register_operand" "v")
898 (match_operand:V2DF 3 "register_operand" "v")))]
900 "vfmadb\t%v0,%v1,%v2,%v3"
901 [(set_attr "op_type" "VRR")])
903 (define_insn "fmsv2df4"
904 [(set (match_operand:V2DF 0 "register_operand" "=v")
905 (fma:V2DF (match_operand:V2DF 1 "register_operand" "v")
906 (match_operand:V2DF 2 "register_operand" "v")
907 (neg:V2DF (match_operand:V2DF 3 "register_operand" "v"))))]
909 "vfmsdb\t%v0,%v1,%v2,%v3"
910 [(set_attr "op_type" "VRR")])
912 (define_insn "negv2df2"
913 [(set (match_operand:V2DF 0 "register_operand" "=v")
914 (neg:V2DF (match_operand:V2DF 1 "register_operand" "v")))]
917 [(set_attr "op_type" "VRR")])
919 (define_insn "absv2df2"
920 [(set (match_operand:V2DF 0 "register_operand" "=v")
921 (abs:V2DF (match_operand:V2DF 1 "register_operand" "v")))]
924 [(set_attr "op_type" "VRR")])
926 (define_insn "*negabsv2df2"
927 [(set (match_operand:V2DF 0 "register_operand" "=v")
928 (neg:V2DF (abs:V2DF (match_operand:V2DF 1 "register_operand" "v"))))]
931 [(set_attr "op_type" "VRR")])
933 ; Emulate with compare + select
934 (define_insn_and_split "smaxv2df3"
935 [(set (match_operand:V2DF 0 "register_operand" "=v")
936 (smax:V2DF (match_operand:V2DF 1 "register_operand" "v")
937 (match_operand:V2DF 2 "register_operand" "v")))]
942 (gt:V2DI (match_dup 1) (match_dup 2)))
945 (eq (match_dup 3) (match_dup 4))
949 operands[3] = gen_reg_rtx (V2DImode);
950 operands[4] = CONST0_RTX (V2DImode);
953 ; Emulate with compare + select
954 (define_insn_and_split "sminv2df3"
955 [(set (match_operand:V2DF 0 "register_operand" "=v")
956 (smin:V2DF (match_operand:V2DF 1 "register_operand" "v")
957 (match_operand:V2DF 2 "register_operand" "v")))]
962 (gt:V2DI (match_dup 1) (match_dup 2)))
965 (eq (match_dup 3) (match_dup 4))
969 operands[3] = gen_reg_rtx (V2DImode);
970 operands[4] = CONST0_RTX (V2DImode);
978 (define_insn "*vec_cmp<VICMP_HW_OP:code><VI:mode>_nocc"
979 [(set (match_operand:VI 2 "register_operand" "=v")
980 (VICMP_HW_OP:VI (match_operand:VI 0 "register_operand" "v")
981 (match_operand:VI 1 "register_operand" "v")))]
983 "vc<VICMP_HW_OP:insn_cmp_op><VI:bhfgq>\t%v2,%v0,%v1"
984 [(set_attr "op_type" "VRR")])
988 ;; Floating point compares
992 (define_insn "*vec_cmp<VFCMP_HW_OP:code>v2df_nocc"
993 [(set (match_operand:V2DI 0 "register_operand" "=v")
994 (VFCMP_HW_OP:V2DI (match_operand:V2DF 1 "register_operand" "v")
995 (match_operand:V2DF 2 "register_operand" "v")))]
997 "vfc<VFCMP_HW_OP:asm_fcmp_op>db\t%v0,%v1,%v2"
998 [(set_attr "op_type" "VRR")])
1000 ; Expanders for not directly supported comparisons
1002 ; UNEQ a u== b -> !(a > b | b > a)
1003 (define_expand "vec_cmpuneqv2df"
1004 [(set (match_operand:V2DI 0 "register_operand" "=v")
1005 (gt:V2DI (match_operand:V2DF 1 "register_operand" "v")
1006 (match_operand:V2DF 2 "register_operand" "v")))
1008 (gt:V2DI (match_dup 2) (match_dup 1)))
1009 (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))
1010 (set (match_dup 0) (not:V2DI (match_dup 0)))]
1013 operands[3] = gen_reg_rtx (V2DImode);
1016 ; LTGT a <> b -> a > b | b > a
1017 (define_expand "vec_cmpltgtv2df"
1018 [(set (match_operand:V2DI 0 "register_operand" "=v")
1019 (gt:V2DI (match_operand:V2DF 1 "register_operand" "v")
1020 (match_operand:V2DF 2 "register_operand" "v")))
1021 (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1)))
1022 (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))]
1025 operands[3] = gen_reg_rtx (V2DImode);
1028 ; ORDERED (a, b): a >= b | b > a
1029 (define_expand "vec_orderedv2df"
1030 [(set (match_operand:V2DI 0 "register_operand" "=v")
1031 (ge:V2DI (match_operand:V2DF 1 "register_operand" "v")
1032 (match_operand:V2DF 2 "register_operand" "v")))
1033 (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1)))
1034 (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))]
1037 operands[3] = gen_reg_rtx (V2DImode);
1040 ; UNORDERED (a, b): !ORDERED (a, b)
1041 (define_expand "vec_unorderedv2df"
1042 [(set (match_operand:V2DI 0 "register_operand" "=v")
1043 (ge:V2DI (match_operand:V2DF 1 "register_operand" "v")
1044 (match_operand:V2DF 2 "register_operand" "v")))
1045 (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1)))
1046 (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))
1047 (set (match_dup 0) (not:V2DI (match_dup 0)))]
1050 operands[3] = gen_reg_rtx (V2DImode);
1053 (define_insn "*vec_load_pairv2di"
1054 [(set (match_operand:V2DI 0 "register_operand" "=v")
1055 (vec_concat:V2DI (match_operand:DI 1 "register_operand" "d")
1056 (match_operand:DI 2 "register_operand" "d")))]
1059 [(set_attr "op_type" "VRR")])
1061 (define_insn "vllv16qi"
1062 [(set (match_operand:V16QI 0 "register_operand" "=v")
1063 (unspec:V16QI [(match_operand:SI 1 "register_operand" "d")
1064 (match_operand:BLK 2 "memory_operand" "Q")]
1065 UNSPEC_VEC_LOAD_LEN))]
1068 [(set_attr "op_type" "VRS")])
1070 ; vfenebs, vfenehs, vfenefs
1071 ; vfenezbs, vfenezhs, vfenezfs
1072 (define_insn "vec_vfenes<mode>"
1073 [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1074 (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
1075 (match_operand:VI_HW_QHS 2 "register_operand" "v")
1076 (match_operand:QI 3 "immediate_operand" "C")]
1078 (set (reg:CCRAW CC_REGNUM)
1079 (unspec:CCRAW [(match_dup 1)
1082 UNSPEC_VEC_VFENECC))]
1085 unsigned HOST_WIDE_INT flags = INTVAL (operands[3]);
1087 gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
1088 flags &= ~VSTRING_FLAG_CS;
1090 if (flags == VSTRING_FLAG_ZS)
1091 return "vfenez<bhfgq>s\t%v0,%v1,%v2";
1092 return "vfene<bhfgq>s\t%v0,%v1,%v2";
1094 [(set_attr "op_type" "VRR")])
1099 ; The following splitters simplify vec_sel for constant 0 or -1
1100 ; selection sources. This is required to generate efficient code for
1105 [(set (match_operand:V 0 "register_operand" "")
1107 (eq (match_operand:<tointvec> 3 "register_operand" "")
1108 (match_operand:V 4 "const0_operand" ""))
1109 (match_operand:V 1 "const0_operand" "")
1110 (match_operand:V 2 "constm1_operand" "")))]
1112 [(set (match_dup 0) (match_dup 3))]
1114 PUT_MODE (operands[3], <V:MODE>mode);
1119 [(set (match_operand:V 0 "register_operand" "")
1121 (eq (match_operand:<tointvec> 3 "register_operand" "")
1122 (match_operand:V 4 "const0_operand" ""))
1123 (match_operand:V 1 "constm1_operand" "")
1124 (match_operand:V 2 "const0_operand" "")))]
1126 [(set (match_dup 0) (not:V (match_dup 3)))]
1128 PUT_MODE (operands[3], <V:MODE>mode);
1133 [(set (match_operand:V 0 "register_operand" "")
1135 (ne (match_operand:<tointvec> 3 "register_operand" "")
1136 (match_operand:V 4 "const0_operand" ""))
1137 (match_operand:V 1 "constm1_operand" "")
1138 (match_operand:V 2 "const0_operand" "")))]
1140 [(set (match_dup 0) (match_dup 3))]
1142 PUT_MODE (operands[3], <V:MODE>mode);
1147 [(set (match_operand:V 0 "register_operand" "")
1149 (ne (match_operand:<tointvec> 3 "register_operand" "")
1150 (match_operand:V 4 "const0_operand" ""))
1151 (match_operand:V 1 "const0_operand" "")
1152 (match_operand:V 2 "constm1_operand" "")))]
1154 [(set (match_dup 0) (not:V (match_dup 3)))]
1156 PUT_MODE (operands[3], <V:MODE>mode);
1159 ; op0 = op3 == 0 ? op1 : op2
1160 (define_insn "*vec_sel0<mode>"
1161 [(set (match_operand:V 0 "register_operand" "=v")
1163 (eq (match_operand:<tointvec> 3 "register_operand" "v")
1164 (match_operand:<tointvec> 4 "const0_operand" ""))
1165 (match_operand:V 1 "register_operand" "v")
1166 (match_operand:V 2 "register_operand" "v")))]
1168 "vsel\t%v0,%2,%1,%3"
1169 [(set_attr "op_type" "VRR")])
1171 ; op0 = !op3 == 0 ? op1 : op2
1172 (define_insn "*vec_sel0<mode>"
1173 [(set (match_operand:V 0 "register_operand" "=v")
1175 (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
1176 (match_operand:<tointvec> 4 "const0_operand" ""))
1177 (match_operand:V 1 "register_operand" "v")
1178 (match_operand:V 2 "register_operand" "v")))]
1180 "vsel\t%v0,%1,%2,%3"
1181 [(set_attr "op_type" "VRR")])
1183 ; op0 = op3 == -1 ? op1 : op2
1184 (define_insn "*vec_sel1<mode>"
1185 [(set (match_operand:V 0 "register_operand" "=v")
1187 (eq (match_operand:<tointvec> 3 "register_operand" "v")
1188 (match_operand:<tointvec> 4 "constm1_operand" ""))
1189 (match_operand:V 1 "register_operand" "v")
1190 (match_operand:V 2 "register_operand" "v")))]
1192 "vsel\t%v0,%1,%2,%3"
1193 [(set_attr "op_type" "VRR")])
1195 ; op0 = !op3 == -1 ? op1 : op2
1196 (define_insn "*vec_sel1<mode>"
1197 [(set (match_operand:V 0 "register_operand" "=v")
1199 (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
1200 (match_operand:<tointvec> 4 "constm1_operand" ""))
1201 (match_operand:V 1 "register_operand" "v")
1202 (match_operand:V 2 "register_operand" "v")))]
1204 "vsel\t%v0,%2,%1,%3"
1205 [(set_attr "op_type" "VRR")])
1214 ; vec_shl vrep + vsl
1220 ; vec_pack_sfix_trunc
1221 ; vec_pack_ufix_trunc
1226 ; vec_unpacks_float_hi
1227 ; vec_unpacks_float_lo
1228 ; vec_unpacku_float_hi
1229 ; vec_unpacku_float_lo