1;;- Instruction patterns for the System z vector facility
2;;  Copyright (C) 2015-2020 Free Software Foundation, Inc.
3;;  Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
4
5;; This file is part of GCC.
6
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
10;; version.
11
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
15;; for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
20
21; 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
24   V2SF V4SF V1DF V2DF])
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])
28
29; All 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 (V1TI "TARGET_VXE") V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
33(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
34
35(define_mode_iterator V_HW_64 [V2DI V2DF])
36(define_mode_iterator VT_HW_HSDT [V8HI V4SI V4SF V2DI V2DF V1TI V1TF TI TF])
37(define_mode_iterator V_HW_HSD [V8HI V4SI (V4SF "TARGET_VXE") V2DI V2DF])
38
39; Including TI for instructions that support it (va, vn, ...)
40(define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
41
42; All full size integer vector modes supported in a vector register + TImode
43(define_mode_iterator VIT_HW    [V16QI V8HI V4SI V2DI V1TI TI])
44(define_mode_iterator VI_HW     [V16QI V8HI V4SI V2DI])
45(define_mode_iterator VI_HW_QHS [V16QI V8HI V4SI])
46(define_mode_iterator VI_HW_HSD [V8HI  V4SI V2DI])
47(define_mode_iterator VI_HW_HS  [V8HI  V4SI])
48(define_mode_iterator VI_HW_QH  [V16QI V8HI])
49(define_mode_iterator VI_HW_4   [V4SI V4SF])
50
51; All integer vector modes supported in a vector register + TImode
52(define_mode_iterator VIT [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1TI TI])
53(define_mode_iterator VI  [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI])
54(define_mode_iterator VI_QHS [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI])
55
56(define_mode_iterator VFT [(V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE")
57			   V1DF V2DF
58			   (V1TF "TARGET_VXE")])
59
60; FP vector modes directly supported by the HW.  This does not include
61; vector modes using only part of a vector register and should be used
62; for instructions which might trigger IEEE exceptions.
63(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")])
64
65(define_mode_iterator V_8   [V1QI])
66(define_mode_iterator V_16  [V2QI  V1HI])
67(define_mode_iterator V_32  [V4QI  V2HI V1SI V1SF])
68(define_mode_iterator V_64  [V8QI  V4HI V2SI V2SF V1DI V1DF])
69(define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF])
70
71(define_mode_iterator V_128_NOSINGLE [V16QI V8HI V4SI V4SF V2DI V2DF])
72
73; 32 bit int<->fp vector conversion instructions are available since VXE2 (z15).
74(define_mode_iterator VX_VEC_CONV_BFP [V2DF (V4SF "TARGET_VXE2")])
75(define_mode_iterator VX_VEC_CONV_INT [V2DI (V4SI "TARGET_VXE2")])
76
77; Empty string for all but TImode.  This is used to hide the TImode
78; expander name in case it is defined already.  See addti3 for an
79; example.
80(define_mode_attr ti* [(V1QI "")  (V2QI "") (V4QI "") (V8QI "") (V16QI "")
81		       (V1HI "")  (V2HI "") (V4HI "") (V8HI "")
82		       (V1SI "")  (V2SI "") (V4SI "")
83		       (V1DI "")  (V2DI "")
84		       (V1TI "")  (TI "*")
85		       (V1SF "")  (V2SF "") (V4SF "")
86		       (V1DF "")  (V2DF "")
87		       (V1TF "")  (TF "")])
88
89; The element type of the vector.
90(define_mode_attr non_vec[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI")
91			  (V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI")
92			  (V1SI "SI") (V2SI "SI") (V4SI "SI")
93			  (V1DI "DI") (V2DI "DI")
94			  (V1TI "TI") (TI "TI")
95			  (V1SF "SF") (V2SF "SF") (V4SF "SF")
96			  (V1DF "DF") (V2DF "DF")
97			  (V1TF "TF") (TF "TF")])
98
99; Like above, but in lower case.
100(define_mode_attr non_vec_l[(V1QI "qi") (V2QI "qi") (V4QI "qi") (V8QI "qi")
101			    (V16QI "qi")
102			    (V1HI "hi") (V2HI "hi") (V4HI "hi") (V8HI "hi")
103			    (V1SI "si") (V2SI "si") (V4SI "si")
104			    (V1DI "di") (V2DI "di")
105			    (V1TI "ti") (TI "ti")
106			    (V1SF "sf") (V2SF "sf") (V4SF "sf")
107			    (V1DF "df") (V2DF "df")
108			    (V1TF "tf") (TF "tf")])
109
110; The instruction suffix for integer instructions and instructions
111; which do not care about whether it is floating point or integer.
112(define_mode_attr bhfgq[(V1QI "b") (V2QI "b") (V4QI "b") (V8QI "b") (V16QI "b")
113			(V1HI "h") (V2HI "h") (V4HI "h") (V8HI "h")
114			(V1SI "f") (V2SI "f") (V4SI "f")
115			(V1DI "g") (V2DI "g")
116			(V1TI "q") (TI "q")
117			(V1SF "f") (V2SF "f") (V4SF "f")
118			(V1DF "g") (V2DF "g")
119			(V1TF "q")])
120
121; This is for vmalhw. It gets an 'w' attached to avoid confusion with
122; multiply and add logical high vmalh.
123(define_mode_attr w [(V1QI "")  (V2QI "")  (V4QI "")  (V8QI "") (V16QI "")
124		     (V1HI "w") (V2HI "w") (V4HI "w") (V8HI "w")
125		     (V1SI "")  (V2SI "")  (V4SI "")
126		     (V1DI "")  (V2DI "")])
127
128; Resulting mode of a vector comparison.  For floating point modes an
129; integer vector mode with the same element size is picked.
130(define_mode_attr tointvec [(V1QI "V1QI") (V2QI "V2QI") (V4QI "V4QI") (V8QI "V8QI") (V16QI "V16QI")
131			    (V1HI "V1HI") (V2HI "V2HI") (V4HI "V4HI") (V8HI "V8HI")
132			    (V1SI "V1SI") (V2SI "V2SI") (V4SI "V4SI")
133			    (V1DI "V1DI") (V2DI "V2DI")
134			    (V1TI "V1TI")
135			    (V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI")
136			    (V1DF "V1DI") (V2DF "V2DI")
137			    (V1TF "V1TI")])
138(define_mode_attr vw [(SF "w") (V1SF "w") (V2SF "v") (V4SF "v")
139		      (DF "w") (V1DF "w") (V2DF "v")
140		      (TF "w") (V1TF "w")])
141
142(define_mode_attr sdx [(SF "s") (V1SF "s") (V2SF "s") (V4SF "s")
143		       (DF "d") (V1DF "d") (V2DF "d")
144		       (TF "x") (V1TF "x")])
145
146; Vector with doubled element size.
147(define_mode_attr vec_double [(V1QI "V1HI") (V2QI "V1HI") (V4QI "V2HI") (V8QI "V4HI") (V16QI "V8HI")
148			      (V1HI "V1SI") (V2HI "V1SI") (V4HI "V2SI") (V8HI "V4SI")
149			      (V1SI "V1DI") (V2SI "V1DI") (V4SI "V2DI")
150			      (V1DI "V1TI") (V2DI "V1TI")
151			      (V1SF "V1DF") (V2SF "V1DF") (V4SF "V2DF")])
152
153; Vector with half the element size.
154(define_mode_attr vec_half [(V1HI "V2QI") (V2HI "V4QI") (V4HI "V8QI") (V8HI "V16QI")
155			    (V1SI "V2HI") (V2SI "V4HI") (V4SI "V8HI")
156			    (V1DI "V2SI") (V2DI "V4SI")
157			    (V1TI "V2DI")
158			    (V1DF "V2SF") (V2DF "V4SF")
159			    (V1TF "V1DF")])
160
161; Vector with half the element size AND half the number of elements.
162(define_mode_attr vec_halfhalf
163  [(V2HI "V2QI") (V4HI "V4QI") (V8HI "V8QI")
164   (V2SI "V2HI") (V4SI "V4HI")
165   (V2DI "V2SI")
166   (V2DF "V2SF")])
167
168(define_mode_attr vec_halfnumelts
169  [(V4SF "V2SF") (V4SI "V2SI")])
170
171
172
173; Comparison operators on int and fp compares which are directly
174; supported by the HW.
175(define_code_iterator VICMP_HW_OP [eq gt gtu])
176; For int insn_cmp_op can be used in the insn name as well as in the asm output.
177(define_code_attr insn_cmp_op [(eq "eq") (gt "h") (gtu "hl") (ge "he")])
178
179; Flags for vector string instructions (vfae all 4, vfee only ZS and CS, vstrc all 4)
180(define_constants
181  [(VSTRING_FLAG_IN         8)   ; invert result
182   (VSTRING_FLAG_RT         4)   ; result type
183   (VSTRING_FLAG_ZS         2)   ; zero search
184   (VSTRING_FLAG_CS         1)]) ; condition code set
185
186(include "vx-builtins.md")
187
188; Full HW vector size moves
189
190; We don't use lm/stm for 128 bit moves since these are slower than
191; splitting it into separate moves.
192
193; FIXME: More constants are possible by enabling jxx, jyy constraints
194; for TImode (use double-int for the calculations)
195
196; vgmb, vgmh, vgmf, vgmg, vrepib, vrepih, vrepif, vrepig
197(define_insn "mov<mode>"
198  [(set (match_operand:V_128 0 "nonimmediate_operand" "=v,v,R,  v,  v,  v,  v,  v,v,*d,*d,?o")
199	(match_operand:V_128 1 "general_operand"      " v,R,v,j00,jm1,jyy,jxx,jKK,d, v,dT,*d"))]
200  ""
201  "@
202   vlr\t%v0,%v1
203   vl\t%v0,%1%A1
204   vst\t%v1,%0%A0
205   vzero\t%v0
206   vone\t%v0
207   vgbm\t%v0,%t1
208   vgm<bhfgq>\t%v0,%s1,%e1
209   vrepi<bhfgq>\t%v0,%h1
210   vlvgp\t%v0,%1,%N1
211   #
212   #
213   #"
214  [(set_attr "cpu_facility" "vx,vx,vx,vx,vx,vx,vx,vx,vx,vx,*,*")
215   (set_attr "op_type"      "VRR,VRX,VRX,VRI,VRI,VRI,VRI,VRI,VRR,*,*,*")])
216
217; VR -> GPR, no instruction so split it into 64 element sets.
218(define_split
219  [(set (match_operand:V_128 0 "register_operand" "")
220	(match_operand:V_128 1 "register_operand" ""))]
221  "TARGET_VX && GENERAL_REG_P (operands[0]) && VECTOR_REG_P (operands[1])"
222  [(set (match_dup 2)
223	(unspec:DI [(subreg:V2DI (match_dup 1) 0)
224		    (const_int 0)] UNSPEC_VEC_EXTRACT))
225   (set (match_dup 3)
226	(unspec:DI [(subreg:V2DI (match_dup 1) 0)
227		    (const_int 1)] UNSPEC_VEC_EXTRACT))]
228{
229  operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
230  operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
231})
232
233; Split the 128 bit GPR move into two word mode moves
234; s390_split_ok_p decides which part needs to be moved first.
235
236(define_split
237  [(set (match_operand:V_128 0 "nonimmediate_operand" "")
238        (match_operand:V_128 1 "general_operand" ""))]
239  "reload_completed
240   && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 0)"
241  [(set (match_dup 2) (match_dup 4))
242   (set (match_dup 3) (match_dup 5))]
243{
244  operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
245  operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
246  operands[4] = operand_subword (operands[1], 0, 0, <MODE>mode);
247  operands[5] = operand_subword (operands[1], 1, 0, <MODE>mode);
248})
249
250(define_split
251  [(set (match_operand:V_128 0 "nonimmediate_operand" "")
252        (match_operand:V_128 1 "general_operand" ""))]
253  "reload_completed
254   && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 1)"
255  [(set (match_dup 2) (match_dup 4))
256   (set (match_dup 3) (match_dup 5))]
257{
258  operands[2] = operand_subword (operands[0], 1, 0, <MODE>mode);
259  operands[3] = operand_subword (operands[0], 0, 0, <MODE>mode);
260  operands[4] = operand_subword (operands[1], 1, 0, <MODE>mode);
261  operands[5] = operand_subword (operands[1], 0, 0, <MODE>mode);
262})
263
264; This is the vector equivalent to the TImode splitter in s390.md.  It
265; is required if both target GPRs occur in the source address operand.
266
267; For non-s_operands at least one of the target GPRs does not conflict
268; with the address operand and one of the splitters above will take
269; over.
270(define_split
271  [(set (match_operand:V_128 0 "register_operand" "")
272        (match_operand:V_128 1 "memory_operand" ""))]
273  "TARGET_ZARCH && reload_completed
274   && !VECTOR_REG_P (operands[0])
275   && !s_operand (operands[1], VOIDmode)"
276  [(set (match_dup 0) (match_dup 1))]
277{
278  rtx addr = operand_subword (operands[0], 1, 0, <MODE>mode);
279  addr = gen_lowpart (Pmode, addr);
280  s390_load_address (addr, XEXP (operands[1], 0));
281  operands[1] = replace_equiv_address (operands[1], addr);
282})
283
284; Moves for smaller vector modes.
285
286; In these patterns only the vlr, vone, and vzero instructions write
287; VR bytes outside the mode.  This should be ok since we disallow
288; formerly bigger modes being accessed with smaller modes via
289; subreg. Note: The vone, vzero instructions could easily be replaced
290; with vlei which would only access the bytes belonging to the mode.
291; However, this would probably be slower.
292
293(define_insn "mov<mode>"
294  [(set (match_operand:V_8 0 "nonimmediate_operand" "=v,v,d,v,R,  v,  v,  v,  v,d,  Q,  S,  Q,  S,  d,  d,d,R,T")
295        (match_operand:V_8 1 "general_operand"      " v,d,v,R,v,j00,jm1,jyy,jxx,d,j00,j00,jm1,jm1,j00,jm1,T,d,d"))]
296  "TARGET_VX"
297  "@
298   vlr\t%v0,%v1
299   vlvgb\t%v0,%1,0
300   vlgvb\t%0,%v1,0
301   vleb\t%v0,%1,0
302   vsteb\t%v1,%0,0
303   vzero\t%v0
304   vone\t%v0
305   vgbm\t%v0,%t1
306   vgm\t%v0,%s1,%e1
307   lr\t%0,%1
308   mvi\t%0,0
309   mviy\t%0,0
310   mvi\t%0,-1
311   mviy\t%0,-1
312   lhi\t%0,0
313   lhi\t%0,-1
314   llc\t%0,%1
315   stc\t%1,%0
316   stcy\t%1,%0"
317  [(set_attr "op_type"      "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SI,SIY,SI,SIY,RI,RI,RXY,RX,RXY")])
318
319(define_insn "mov<mode>"
320  [(set (match_operand:V_16 0 "nonimmediate_operand" "=v,v,d,v,R,  v,  v,  v,  v,d,  Q,  Q,  d,  d,d,d,d,R,T,b")
321        (match_operand:V_16 1 "general_operand"      " v,d,v,R,v,j00,jm1,jyy,jxx,d,j00,jm1,j00,jm1,R,T,b,d,d,d"))]
322  ""
323  "@
324   vlr\t%v0,%v1
325   vlvgh\t%v0,%1,0
326   vlgvh\t%0,%v1,0
327   vleh\t%v0,%1,0
328   vsteh\t%v1,%0,0
329   vzero\t%v0
330   vone\t%v0
331   vgbm\t%v0,%t1
332   vgm\t%v0,%s1,%e1
333   lr\t%0,%1
334   mvhhi\t%0,0
335   mvhhi\t%0,-1
336   lhi\t%0,0
337   lhi\t%0,-1
338   lh\t%0,%1
339   lhy\t%0,%1
340   lhrl\t%0,%1
341   sth\t%1,%0
342   sthy\t%1,%0
343   sthrl\t%1,%0"
344  [(set_attr "op_type"      "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SIL,SIL,RI,RI,RX,RXY,RIL,RX,RXY,RIL")])
345
346(define_insn "mov<mode>"
347  [(set (match_operand:V_32 0 "nonimmediate_operand" "=f,f,f,R,T,v,v,d,v,R,  f,  v,  v,  v,  v,  Q,  Q,  d,  d,d,d,d,d,R,T,b")
348	(match_operand:V_32 1 "general_operand"      " f,R,T,f,f,v,d,v,R,v,j00,j00,jm1,jyy,jxx,j00,jm1,j00,jm1,b,d,R,T,d,d,d"))]
349  "TARGET_VX"
350  "@
351   ldr\t%v0,%v1
352   lde\t%0,%1
353   ley\t%0,%1
354   ste\t%1,%0
355   stey\t%1,%0
356   vlr\t%v0,%v1
357   vlvgf\t%v0,%1,0
358   vlgvf\t%0,%v1,0
359   vlef\t%v0,%1,0
360   vstef\t%1,%0,0
361   lzer\t%v0
362   vzero\t%v0
363   vone\t%v0
364   vgbm\t%v0,%t1
365   vgm\t%v0,%s1,%e1
366   mvhi\t%0,0
367   mvhi\t%0,-1
368   lhi\t%0,0
369   lhi\t%0,-1
370   lrl\t%0,%1
371   lr\t%0,%1
372   l\t%0,%1
373   ly\t%0,%1
374   st\t%1,%0
375   sty\t%1,%0
376   strl\t%1,%0"
377  [(set_attr "op_type" "RR,RXE,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,SIL,SIL,RI,RI,
378                        RIL,RR,RX,RXY,RX,RXY,RIL")])
379
380(define_insn "mov<mode>"
381  [(set (match_operand:V_64 0 "nonimmediate_operand"
382         "=f,f,f,R,T,v,v,d,v,R,  f,  v,  v,  v,  v,  Q,  Q,  d,  d,f,d,d,d,d,T,b")
383        (match_operand:V_64 1 "general_operand"
384         " f,R,T,f,f,v,d,v,R,v,j00,j00,jm1,jyy,jxx,j00,jm1,j00,jm1,d,f,b,d,T,d,d"))]
385  "TARGET_ZARCH"
386  "@
387   ldr\t%0,%1
388   ld\t%0,%1
389   ldy\t%0,%1
390   std\t%1,%0
391   stdy\t%1,%0
392   vlr\t%v0,%v1
393   vlvgg\t%v0,%1,0
394   vlgvg\t%0,%v1,0
395   vleg\t%v0,%1,0
396   vsteg\t%v1,%0,0
397   lzdr\t%0
398   vzero\t%v0
399   vone\t%v0
400   vgbm\t%v0,%t1
401   vgm\t%v0,%s1,%e1
402   mvghi\t%0,0
403   mvghi\t%0,-1
404   lghi\t%0,0
405   lghi\t%0,-1
406   ldgr\t%0,%1
407   lgdr\t%0,%1
408   lgrl\t%0,%1
409   lgr\t%0,%1
410   lg\t%0,%1
411   stg\t%1,%0
412   stgrl\t%1,%0"
413  [(set_attr "op_type" "RRE,RX,RXY,RX,RXY,VRR,VRS,VRS,VRX,VRX,RRE,VRI,VRI,VRI,VRI,
414                        SIL,SIL,RI,RI,RRE,RRE,RIL,RR,RXY,RXY,RIL")])
415
416
417; vec_load_lanes?
418
419; vec_store_lanes?
420
421; vec_set is supposed to *modify* an existing vector so operand 0 is
422; duplicated as input operand.
423(define_expand "vec_set<mode>"
424  [(set (match_operand:V                    0 "register_operand"  "")
425	(unspec:V [(match_operand:<non_vec> 1 "general_operand"   "")
426		   (match_operand:SI        2 "nonmemory_operand" "")
427		   (match_dup 0)]
428		   UNSPEC_VEC_SET))]
429  "TARGET_VX")
430
431; FIXME: Support also vector mode operands for 1
432; FIXME: A target memory operand seems to be useful otherwise we end
433; up with vl vlvgg vst.  Shouldn't the middle-end be able to handle
434; that itself?
435; vlvgb, vlvgh, vlvgf, vlvgg, vleb, vleh, vlef, vleg, vleib, vleih, vleif, vleig
436(define_insn "*vec_set<mode>"
437  [(set (match_operand:V                    0 "register_operand"  "=v,v,v")
438	(unspec:V [(match_operand:<non_vec> 1 "general_operand"    "d,R,K")
439		   (match_operand:SI        2 "nonmemory_operand" "an,I,I")
440		   (match_operand:V         3 "register_operand"   "0,0,0")]
441		  UNSPEC_VEC_SET))]
442  "TARGET_VX
443   && (!CONST_INT_P (operands[2])
444       || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
445  "@
446   vlvg<bhfgq>\t%v0,%1,%Y2
447   vle<bhfgq>\t%v0,%1,%2
448   vlei<bhfgq>\t%v0,%1,%2"
449  [(set_attr "op_type" "VRS,VRX,VRI")])
450
451; vlvgb, vlvgh, vlvgf, vlvgg
452(define_insn "*vec_set<mode>_plus"
453  [(set (match_operand:V                      0 "register_operand" "=v")
454	(unspec:V [(match_operand:<non_vec>   1 "general_operand"   "d")
455		   (plus:SI (match_operand:SI 2 "register_operand"  "a")
456			    (match_operand:SI 4 "const_int_operand" "n"))
457		   (match_operand:V           3 "register_operand"  "0")]
458		  UNSPEC_VEC_SET))]
459  "TARGET_VX"
460  "vlvg<bhfgq>\t%v0,%1,%Y4(%2)"
461  [(set_attr "op_type" "VRS")])
462
463
464; FIXME: Support also vector mode operands for 0
465; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :(
466; This is used via RTL standard name as well as for expanding the builtin
467(define_expand "vec_extract<mode><non_vec_l>"
468  [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "")
469	(unspec:<non_vec> [(match_operand:V  1 "register_operand" "")
470			   (match_operand:SI 2 "nonmemory_operand" "")]
471			  UNSPEC_VEC_EXTRACT))]
472  "TARGET_VX")
473
474; vlgvb, vlgvh, vlgvf, vlgvg, vsteb, vsteh, vstef, vsteg
475(define_insn "*vec_extract<mode>"
476  [(set (match_operand:<non_vec> 0 "nonimmediate_operand"          "=d,R")
477	(unspec:<non_vec> [(match_operand:V  1 "register_operand"   "v,v")
478			   (match_operand:SI 2 "nonmemory_operand" "an,I")]
479			  UNSPEC_VEC_EXTRACT))]
480  "TARGET_VX
481   && (!CONST_INT_P (operands[2])
482       || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
483  "@
484   vlgv<bhfgq>\t%0,%v1,%Y2
485   vste<bhfgq>\t%v1,%0,%2"
486  [(set_attr "op_type" "VRS,VRX")])
487
488; vlgvb, vlgvh, vlgvf, vlgvg
489(define_insn "*vec_extract<mode>_plus"
490  [(set (match_operand:<non_vec>                      0 "nonimmediate_operand" "=d")
491	(unspec:<non_vec> [(match_operand:V           1 "register_operand"      "v")
492			   (plus:SI (match_operand:SI 2 "nonmemory_operand"     "a")
493				    (match_operand:SI 3 "const_int_operand"     "n"))]
494			   UNSPEC_VEC_EXTRACT))]
495  "TARGET_VX"
496  "vlgv<bhfgq>\t%0,%v1,%Y3(%2)"
497  [(set_attr "op_type" "VRS")])
498
499(define_expand "vec_init<mode><non_vec_l>"
500  [(match_operand:V_128 0 "register_operand" "")
501   (match_operand:V_128 1 "nonmemory_operand" "")]
502  "TARGET_VX"
503{
504  s390_expand_vec_init (operands[0], operands[1]);
505  DONE;
506})
507
508(define_insn "*vec_vllezlf<mode>"
509  [(set (match_operand:VI_HW_4              0 "register_operand" "=v")
510	(vec_concat:VI_HW_4
511	 (vec_concat:<vec_halfnumelts>
512	  (match_operand:<non_vec> 1 "memory_operand"    "R")
513	  (const_int 0))
514	 (vec_concat:<vec_halfnumelts>
515	  (const_int 0)
516	  (const_int 0))))]
517  "TARGET_VXE"
518  "vllezlf\t%v0,%1"
519  [(set_attr "op_type" "VRX")])
520
521; Replicate from vector element
522; vrepb, vreph, vrepf, vrepg
523(define_insn "*vec_splat<mode>"
524  [(set (match_operand:V_128_NOSINGLE   0 "register_operand" "=v")
525	(vec_duplicate:V_128_NOSINGLE
526	 (vec_select:<non_vec>
527	  (match_operand:V_128_NOSINGLE 1 "register_operand"  "v")
528	  (parallel
529	   [(match_operand:QI 2 "const_mask_operand" "C")]))))]
530  "TARGET_VX && UINTVAL (operands[2]) < GET_MODE_NUNITS (<MODE>mode)"
531  "vrep<bhfgq>\t%v0,%v1,%2"
532  [(set_attr "op_type" "VRI")])
533
534; vlrepb, vlreph, vlrepf, vlrepg, vrepib, vrepih, vrepif, vrepig, vrepb, vreph, vrepf, vrepg
535(define_insn "*vec_splats<mode>"
536  [(set (match_operand:V_128_NOSINGLE                          0 "register_operand" "=v,v,v,v")
537	(vec_duplicate:V_128_NOSINGLE (match_operand:<non_vec> 1 "general_operand"  " R,K,v,d")))]
538  "TARGET_VX"
539  "@
540   vlrep<bhfgq>\t%v0,%1
541   vrepi<bhfgq>\t%v0,%h1
542   vrep<bhfgq>\t%v0,%v1,0
543   #"
544  [(set_attr "op_type" "VRX,VRI,VRI,*")])
545
546; vlbrreph, vlbrrepf, vlbrrepg
547(define_insn "*vec_splats_bswap_vec<mode>"
548  [(set (match_operand:V_HW_HSD                           0 "register_operand"        "=v")
549	(bswap:V_HW_HSD
550	 (vec_duplicate:V_HW_HSD (match_operand:<non_vec> 1 "memory_operand"           "R"))))
551   (use (match_operand:V16QI                              2 "permute_pattern_operand"  "X"))]
552  "TARGET_VXE2"
553  "vlbrrep<bhfgq>\t%v0,%1"
554  [(set_attr "op_type" "VRX")])
555
556; Why do we need both? Shouldn't there be a canonical form?
557; vlbrreph, vlbrrepf, vlbrrepg
558(define_insn "*vec_splats_bswap_elem<mode>"
559  [(set (match_operand:V_HW_HSD                    0 "register_operand" "=v")
560	(vec_duplicate:V_HW_HSD
561	 (bswap:<non_vec> (match_operand:<non_vec> 1 "memory_operand"    "R"))))]
562  "TARGET_VXE2"
563  "vlbrrep<bhfgq>\t%v0,%1"
564  [(set_attr "op_type" "VRX")])
565
566; A TFmode operand resides in FPR register pairs while V1TF is in a
567; single vector register.
568(define_insn "*vec_tf_to_v1tf"
569  [(set (match_operand:V1TF                   0 "nonimmediate_operand" "=v,v,R,v,v")
570	(vec_duplicate:V1TF (match_operand:TF 1 "general_operand"       "v,R,v,G,d")))]
571  "TARGET_VX"
572  "@
573   vmrhg\t%v0,%1,%N1
574   vl\t%v0,%1%A1
575   vst\t%v1,%0%A0
576   vzero\t%v0
577   vlvgp\t%v0,%1,%N1"
578  [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRR")])
579
580(define_insn "*vec_ti_to_v1ti"
581  [(set (match_operand:V1TI                   0 "nonimmediate_operand" "=v,v,R,  v,  v,v")
582	(vec_duplicate:V1TI (match_operand:TI 1 "general_operand"       "v,R,v,j00,jm1,d")))]
583  "TARGET_VX"
584  "@
585   vlr\t%v0,%v1
586   vl\t%v0,%1%A1
587   vst\t%v1,%0%A0
588   vzero\t%v0
589   vone\t%v0
590   vlvgp\t%v0,%1,%N1"
591  [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRI,VRR")])
592
593; vec_splats is supposed to replicate op1 into all elements of op0
594; This splitter first sets the rightmost element of op0 to op1 and
595; then does a vec_splat to replicate that element into all other
596; elements.
597(define_split
598  [(set (match_operand:V_128_NOSINGLE                          0 "register_operand" "")
599	(vec_duplicate:V_128_NOSINGLE (match_operand:<non_vec> 1 "register_operand" "")))]
600  "TARGET_VX && GENERAL_REG_P (operands[1])"
601  [(set (match_dup 0)
602	(unspec:V_128_NOSINGLE [(match_dup 1) (match_dup 2) (match_dup 0)] UNSPEC_VEC_SET))
603   (set (match_dup 0)
604	(vec_duplicate:V_128_NOSINGLE
605	 (vec_select:<non_vec>
606	  (match_dup 0) (parallel [(match_dup 2)]))))]
607{
608  operands[2] = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1);
609})
610
611(define_predicate "vcond_comparison_operator"
612  (match_operand 0 "comparison_operator")
613{
614  if (!HONOR_NANS (GET_MODE (XEXP (op, 0)))
615      && !HONOR_NANS (GET_MODE (XEXP (op, 1))))
616    return true;
617  switch (GET_CODE (op))
618    {
619    case LE:
620    case LT:
621    case GE:
622    case GT:
623    case LTGT:
624      /* Signaling vector comparisons are supported only on z14+.  */
625      return TARGET_VXE || TARGET_NONSIGNALING_VECTOR_COMPARE_OK;
626    default:
627      return true;
628    }
629})
630
631(define_expand "vcond<V_HW:mode><V_HW2:mode>"
632  [(set (match_operand:V_HW 0 "register_operand" "")
633	(if_then_else:V_HW
634	 (match_operator 3 "vcond_comparison_operator"
635			 [(match_operand:V_HW2 4 "register_operand" "")
636			  (match_operand:V_HW2 5 "nonmemory_operand" "")])
637	 (match_operand:V_HW 1 "nonmemory_operand" "")
638	 (match_operand:V_HW 2 "nonmemory_operand" "")))]
639  "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)"
640{
641  s390_expand_vcond (operands[0], operands[1], operands[2],
642		     GET_CODE (operands[3]), operands[4], operands[5]);
643  DONE;
644})
645
646(define_expand "vcondu<V_HW:mode><V_HW2:mode>"
647  [(set (match_operand:V_HW 0 "register_operand" "")
648	(if_then_else:V_HW
649	 (match_operator 3 "comparison_operator"
650			 [(match_operand:V_HW2 4 "register_operand" "")
651			  (match_operand:V_HW2 5 "nonmemory_operand" "")])
652	 (match_operand:V_HW 1 "nonmemory_operand" "")
653	 (match_operand:V_HW 2 "nonmemory_operand" "")))]
654  "TARGET_VX && GET_MODE_NUNITS (<V_HW:MODE>mode) == GET_MODE_NUNITS (<V_HW2:MODE>mode)"
655{
656  s390_expand_vcond (operands[0], operands[1], operands[2],
657		     GET_CODE (operands[3]), operands[4], operands[5]);
658  DONE;
659})
660
661; We only have HW support for byte vectors.  The middle-end is
662; supposed to lower the mode if required.
663(define_insn "vec_permv16qi"
664  [(set (match_operand:V16QI 0 "register_operand"               "=v")
665	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
666		       (match_operand:V16QI 2 "register_operand" "v")
667		       (match_operand:V16QI 3 "register_operand" "v")]
668		      UNSPEC_VEC_PERM))]
669  "TARGET_VX"
670  "vperm\t%v0,%v1,%v2,%v3"
671  [(set_attr "op_type" "VRR")])
672
673(define_insn "*vec_perm<mode>"
674  [(set (match_operand:VT_HW                                            0 "register_operand" "=v")
675	(subreg:VT_HW (unspec:V16QI [(subreg:V16QI (match_operand:VT_HW 1 "register_operand"  "v") 0)
676				     (subreg:V16QI (match_operand:VT_HW 2 "register_operand"  "v") 0)
677				     (match_operand:V16QI               3 "register_operand"  "v")]
678				    UNSPEC_VEC_PERM) 0))]
679  "TARGET_VX"
680  "vperm\t%v0,%v1,%v2,%v3"
681  [(set_attr "op_type" "VRR")])
682
683
684; vec_perm_const for V2DI using vpdi?
685
686;;
687;; Vector integer arithmetic instructions
688;;
689
690; vab, vah, vaf, vag, vaq
691
692; We use nonimmediate_operand instead of register_operand since it is
693; better to have the reloads into VRs instead of splitting the
694; operation into two DImode ADDs.
695(define_insn "<ti*>add<mode>3"
696  [(set (match_operand:VIT           0 "nonimmediate_operand" "=v")
697	(plus:VIT (match_operand:VIT 1 "nonimmediate_operand"  "v")
698		  (match_operand:VIT 2 "general_operand"       "v")))]
699  "TARGET_VX"
700  "va<bhfgq>\t%v0,%v1,%v2"
701  [(set_attr "op_type" "VRR")])
702
703; vsb, vsh, vsf, vsg, vsq
704(define_insn "<ti*>sub<mode>3"
705  [(set (match_operand:VIT            0 "nonimmediate_operand" "=v")
706	(minus:VIT (match_operand:VIT 1 "nonimmediate_operand"  "v")
707		   (match_operand:VIT 2 "general_operand"       "v")))]
708  "TARGET_VX"
709  "vs<bhfgq>\t%v0,%v1,%v2"
710  [(set_attr "op_type" "VRR")])
711
712; vmlb, vmlhw, vmlf
713(define_insn "mul<mode>3"
714  [(set (match_operand:VI_QHS              0 "register_operand" "=v")
715	(mult:VI_QHS (match_operand:VI_QHS 1 "register_operand"  "v")
716		     (match_operand:VI_QHS 2 "register_operand"  "v")))]
717  "TARGET_VX"
718  "vml<bhfgq><w>\t%v0,%v1,%v2"
719  [(set_attr "op_type" "VRR")])
720
721; vlcb, vlch, vlcf, vlcg
722(define_insn "neg<mode>2"
723  [(set (match_operand:VI         0 "register_operand" "=v")
724	(neg:VI (match_operand:VI 1 "register_operand"  "v")))]
725  "TARGET_VX"
726  "vlc<bhfgq>\t%v0,%v1"
727  [(set_attr "op_type" "VRR")])
728
729; vlpb, vlph, vlpf, vlpg
730(define_insn "abs<mode>2"
731  [(set (match_operand:VI         0 "register_operand" "=v")
732	(abs:VI (match_operand:VI 1 "register_operand"  "v")))]
733  "TARGET_VX"
734  "vlp<bhfgq>\t%v0,%v1"
735  [(set_attr "op_type" "VRR")])
736
737
738; Vector sum across
739
740; Sum across DImode parts of the 1st operand and add the rightmost
741; element of 2nd operand
742; vsumgh, vsumgf
743(define_insn "*vec_sum2<mode>"
744  [(set (match_operand:V2DI 0 "register_operand" "=v")
745	(unspec:V2DI [(match_operand:VI_HW_HS 1 "register_operand" "v")
746		      (match_operand:VI_HW_HS 2 "register_operand" "v")]
747		     UNSPEC_VEC_VSUMG))]
748  "TARGET_VX"
749  "vsumg<bhfgq>\t%v0,%v1,%v2"
750  [(set_attr "op_type" "VRR")])
751
752; vsumb, vsumh
753(define_insn "*vec_sum4<mode>"
754  [(set (match_operand:V4SI 0 "register_operand" "=v")
755	(unspec:V4SI [(match_operand:VI_HW_QH 1 "register_operand" "v")
756		      (match_operand:VI_HW_QH 2 "register_operand" "v")]
757		     UNSPEC_VEC_VSUM))]
758  "TARGET_VX"
759  "vsum<bhfgq>\t%v0,%v1,%v2"
760  [(set_attr "op_type" "VRR")])
761
762;;
763;; Vector bit instructions (int + fp)
764;;
765
766; Vector and
767
768(define_insn "and<mode>3"
769  [(set (match_operand:VT         0 "register_operand" "=v")
770	(and:VT (match_operand:VT 1 "register_operand"  "v")
771		(match_operand:VT 2 "register_operand"  "v")))]
772  "TARGET_VX"
773  "vn\t%v0,%v1,%v2"
774  [(set_attr "op_type" "VRR")])
775
776; Vector not and
777
778(define_insn "notand<mode>3"
779  [(set (match_operand:VT                 0 "register_operand" "=v")
780	(ior:VT (not:VT (match_operand:VT 1 "register_operand"  "v"))
781		(not:VT	(match_operand:VT 2 "register_operand"  "v"))))]
782  "TARGET_VXE"
783  "vnn\t%v0,%v1,%v2"
784  [(set_attr "op_type" "VRR")])
785
786; Vector or
787
788(define_insn "ior<mode>3"
789  [(set (match_operand:VT         0 "register_operand" "=v")
790	(ior:VT (match_operand:VT 1 "register_operand"  "v")
791		(match_operand:VT 2 "register_operand"  "v")))]
792  "TARGET_VX"
793  "vo\t%v0,%v1,%v2"
794  [(set_attr "op_type" "VRR")])
795
796; Vector or with complement
797
798(define_insn "ior_not<mode>3"
799  [(set (match_operand:VT                 0 "register_operand" "=v")
800	(ior:VT (not:VT (match_operand:VT 2 "register_operand"  "v"))
801		(match_operand:VT         1 "register_operand"  "v")))]
802  "TARGET_VXE"
803  "voc\t%v0,%v1,%v2"
804  [(set_attr "op_type" "VRR")])
805
806; Vector xor
807
808(define_insn "xor<mode>3"
809  [(set (match_operand:VT         0 "register_operand" "=v")
810	(xor:VT (match_operand:VT 1 "register_operand"  "v")
811		(match_operand:VT 2 "register_operand"  "v")))]
812  "TARGET_VX"
813  "vx\t%v0,%v1,%v2"
814  [(set_attr "op_type" "VRR")])
815
816; Vector not xor
817
818(define_insn "notxor<mode>3"
819  [(set (match_operand:VT                 0 "register_operand" "=v")
820	(not:VT (xor:VT (match_operand:VT 1 "register_operand"  "v")
821			(match_operand:VT 2 "register_operand"  "v"))))]
822  "TARGET_VXE"
823  "vnx\t%v0,%v1,%v2"
824  [(set_attr "op_type" "VRR")])
825
826; Bitwise inversion of a vector
827(define_insn "one_cmpl<mode>2"
828  [(set (match_operand:VT         0 "register_operand" "=v")
829	(not:VT (match_operand:VT 1 "register_operand"  "v")))]
830  "TARGET_VX"
831  "vnot\t%v0,%v1"
832  [(set_attr "op_type" "VRR")])
833
834; Vector population count
835
836(define_expand "popcount<mode>2"
837  [(set (match_operand:VI_HW                0 "register_operand" "=v")
838	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "v")]
839		      UNSPEC_POPCNT))]
840  "TARGET_VX"
841{
842  if (TARGET_VXE)
843    emit_insn (gen_popcount<mode>2_vxe (operands[0], operands[1]));
844  else
845    emit_insn (gen_popcount<mode>2_vx (operands[0], operands[1]));
846  DONE;
847})
848
849; vpopctb, vpopcth, vpopctf, vpopctg
850(define_insn "popcount<mode>2_vxe"
851  [(set (match_operand:VI_HW                0 "register_operand" "=v")
852	(unspec:VI_HW [(match_operand:VI_HW 1 "register_operand"  "v")]
853		      UNSPEC_POPCNT))]
854  "TARGET_VXE"
855  "vpopct<bhfgq>\t%v0,%v1"
856  [(set_attr "op_type" "VRR")])
857
858(define_insn "popcountv16qi2_vx"
859  [(set (match_operand:V16QI                0 "register_operand" "=v")
860	(unspec:V16QI [(match_operand:V16QI 1 "register_operand"  "v")]
861		      UNSPEC_POPCNT))]
862  "TARGET_VX && !TARGET_VXE"
863  "vpopct\t%v0,%v1,0"
864  [(set_attr "op_type" "VRR")])
865
866; vpopct only counts bits in byte elements.  Bigger element sizes need
867; to be emulated.  Word and doubleword elements can use the sum across
868; instructions.  For halfword sized elements we do a shift of a copy
869; of the result, add it to the result and extend it to halfword
870; element size (unpack).
871
872(define_expand "popcountv8hi2_vx"
873  [(set (match_dup 2)
874	(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")]
875		      UNSPEC_POPCNT))
876   ; Make a copy of the result
877   (set (match_dup 3) (match_dup 2))
878   ; Generate the shift count operand in a VR (8->byte 7)
879   (set (match_dup 4) (match_dup 5))
880   (set (match_dup 4) (unspec:V16QI [(const_int 8)
881				     (const_int 7)
882				     (match_dup 4)] UNSPEC_VEC_SET))
883   ; Vector shift right logical by one byte
884   (set (match_dup 3)
885	(unspec:V16QI [(match_dup 3) (match_dup 4)] UNSPEC_VEC_SRLB))
886   ; Add the shifted and the original result
887   (set (match_dup 2)
888	(plus:V16QI (match_dup 2) (match_dup 3)))
889   ; Generate mask for the odd numbered byte elements
890   (set (match_dup 3)
891	(const_vector:V16QI [(const_int 0) (const_int 255)
892			     (const_int 0) (const_int 255)
893			     (const_int 0) (const_int 255)
894			     (const_int 0) (const_int 255)
895			     (const_int 0) (const_int 255)
896			     (const_int 0) (const_int 255)
897			     (const_int 0) (const_int 255)
898			     (const_int 0) (const_int 255)]))
899   ; Zero out the even indexed bytes
900   (set (match_operand:V8HI 0 "register_operand" "=v")
901	(and:V8HI (subreg:V8HI (match_dup 2) 0)
902		  (subreg:V8HI (match_dup 3) 0)))
903]
904  "TARGET_VX && !TARGET_VXE"
905{
906  operands[1] = simplify_gen_subreg (V16QImode, operands[1],
907				     V8HImode, 0);
908  operands[2] = gen_reg_rtx (V16QImode);
909  operands[3] = gen_reg_rtx (V16QImode);
910  operands[4] = gen_reg_rtx (V16QImode);
911  operands[5] = CONST0_RTX (V16QImode);
912})
913
914(define_expand "popcountv4si2_vx"
915  [(set (match_dup 2)
916	(unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v")]
917		      UNSPEC_POPCNT))
918   (set (match_operand:V4SI 0 "register_operand" "=v")
919	(unspec:V4SI [(match_dup 2) (match_dup 3)]
920		     UNSPEC_VEC_VSUM))]
921  "TARGET_VX && !TARGET_VXE"
922{
923  operands[1] = simplify_gen_subreg (V16QImode, operands[1], V4SImode, 0);
924  operands[2] = gen_reg_rtx (V16QImode);
925  operands[3] = force_reg (V16QImode, CONST0_RTX (V16QImode));
926})
927
928(define_expand "popcountv2di2_vx"
929  [(set (match_dup 2)
930	(unspec:V16QI [(match_operand:V2DI 1 "register_operand" "v")]
931		      UNSPEC_POPCNT))
932   (set (match_dup 3)
933	(unspec:V4SI [(match_dup 2) (match_dup 4)]
934		     UNSPEC_VEC_VSUM))
935   (set (match_operand:V2DI 0 "register_operand" "=v")
936	(unspec:V2DI [(match_dup 3) (match_dup 5)]
937		     UNSPEC_VEC_VSUMG))]
938  "TARGET_VX && !TARGET_VXE"
939{
940  operands[1] = simplify_gen_subreg (V16QImode, operands[1], V2DImode, 0);
941  operands[2] = gen_reg_rtx (V16QImode);
942  operands[3] = gen_reg_rtx (V4SImode);
943  operands[4] = force_reg (V16QImode, CONST0_RTX (V16QImode));
944  operands[5] = force_reg (V4SImode, CONST0_RTX (V4SImode));
945})
946
947; Count leading zeros
948; vclzb, vclzh, vclzf, vclzg
949(define_insn "clz<mode>2"
950  [(set (match_operand:V        0 "register_operand" "=v")
951	(clz:V (match_operand:V 1 "register_operand"  "v")))]
952  "TARGET_VX"
953  "vclz<bhfgq>\t%v0,%v1"
954  [(set_attr "op_type" "VRR")])
955
956; Count trailing zeros
957; vctzb, vctzh, vctzf, vctzg
958(define_insn "ctz<mode>2"
959  [(set (match_operand:V        0 "register_operand" "=v")
960	(ctz:V (match_operand:V 1 "register_operand"  "v")))]
961  "TARGET_VX"
962  "vctz<bhfgq>\t%v0,%v1"
963  [(set_attr "op_type" "VRR")])
964
965
966
967; Each vector element rotated by the corresponding vector element
968; verllvb, verllvh, verllvf, verllvg
969(define_insn "vrotl<mode>3"
970  [(set (match_operand:VI            0 "register_operand" "=v")
971	(rotate:VI (match_operand:VI 1 "register_operand"  "v")
972		   (match_operand:VI 2 "register_operand"  "v")))]
973  "TARGET_VX"
974  "verllv<bhfgq>\t%v0,%v1,%v2"
975  [(set_attr "op_type" "VRR")])
976
977
978; Vector rotate and shift by scalar instructions
979
980(define_code_iterator VEC_SHIFTS [ashift ashiftrt lshiftrt rotate])
981(define_code_attr vec_shifts_name [(ashift "ashl")    (ashiftrt "ashr")
982				   (lshiftrt "lshr")  (rotate "rotl")])
983(define_code_attr vec_shifts_mnem [(ashift "vesl")    (ashiftrt "vesra")
984				   (lshiftrt "vesrl") (rotate "verll")])
985
986; Each vector element rotated by a scalar
987(define_expand "<vec_shifts_name><mode>3"
988  [(set (match_operand:VI 0 "register_operand" "")
989	(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "")
990		       (match_operand:QI 2 "shift_count_operand" "")))]
991  "TARGET_VX")
992
993; verllb, verllh, verllf, verllg
994; veslb,  veslh,  veslf,  veslg
995; vesrab, vesrah, vesraf, vesrag
996; vesrlb, vesrlh, vesrlf, vesrlg
997(define_insn "*<vec_shifts_name><mode>3"
998  [(set (match_operand:VI                0 "register_operand"  "=v")
999	(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand"   "v")
1000		       (match_operand:QI 2 "shift_count_operand_vec" "jsc")))]
1001  "TARGET_VX
1002  && s390_valid_shift_count (operands[2],
1003    GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) - 1)
1004  "
1005  "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2"
1006  [(set_attr "op_type" "VRS")])
1007
1008
1009; Shift each element by corresponding vector element
1010
1011; veslvb, veslvh, veslvf, veslvg
1012(define_insn "vashl<mode>3"
1013  [(set (match_operand:VI            0 "register_operand" "=v")
1014	(ashift:VI (match_operand:VI 1 "register_operand"  "v")
1015		   (match_operand:VI 2 "register_operand"  "v")))]
1016  "TARGET_VX"
1017  "veslv<bhfgq>\t%v0,%v1,%v2"
1018  [(set_attr "op_type" "VRR")])
1019
1020; vesravb, vesravh, vesravf, vesravg
1021(define_insn "vashr<mode>3"
1022  [(set (match_operand:VI              0 "register_operand" "=v")
1023	(ashiftrt:VI (match_operand:VI 1 "register_operand"  "v")
1024		     (match_operand:VI 2 "register_operand"  "v")))]
1025  "TARGET_VX"
1026  "vesrav<bhfgq>\t%v0,%v1,%v2"
1027  [(set_attr "op_type" "VRR")])
1028
1029; vesrlvb, vesrlvh, vesrlvf, vesrlvg
1030(define_insn "vlshr<mode>3"
1031  [(set (match_operand:VI              0 "register_operand" "=v")
1032	(lshiftrt:VI (match_operand:VI 1 "register_operand"  "v")
1033		     (match_operand:VI 2 "register_operand"  "v")))]
1034  "TARGET_VX"
1035  "vesrlv<bhfgq>\t%v0,%v1,%v2"
1036  [(set_attr "op_type" "VRR")])
1037
1038; Vector shift right logical by byte
1039
1040; Pattern used by e.g. popcount
1041(define_insn "*vec_srb<mode>"
1042  [(set (match_operand:V_128                0 "register_operand" "=v")
1043	(unspec:V_128 [(match_operand:V_128 1 "register_operand"  "v")
1044		       (match_operand:V16QI 2 "register_operand"  "v")]
1045		   UNSPEC_VEC_SRLB))]
1046  "TARGET_VX"
1047  "vsrlb\t%v0,%v1,%v2"
1048  [(set_attr "op_type" "VRR")])
1049
1050
1051; Vector shift left by byte
1052
1053(define_insn "*vec_slb<mode>"
1054  [(set (match_operand:V_128                0 "register_operand" "=v")
1055	(unspec:V_128 [(match_operand:V_128 1 "register_operand"  "v")
1056		    (match_operand:V16QI    2 "register_operand"  "v")]
1057		   UNSPEC_VEC_SLB))]
1058  "TARGET_VX"
1059  "vslb\t%v0,%v1,%v2"
1060  [(set_attr "op_type" "VRR")])
1061
1062; vec_shr is defined as shift towards element 0
1063; this means it is a left shift on BE targets!
1064(define_expand "vec_shr_<mode>"
1065  [(set (match_dup 3)
1066	(unspec:V16QI [(match_operand:SI 2 "const_shift_by_byte_operand" "")
1067		   (const_int 7)
1068		   (match_dup 3)]
1069		   UNSPEC_VEC_SET))
1070   (set (match_operand:V_128 0 "register_operand" "")
1071	(unspec:V_128 [(match_operand:V_128 1 "register_operand" "")
1072		    (match_dup 3)]
1073		   UNSPEC_VEC_SLB))]
1074  "TARGET_VX"
1075 {
1076   operands[3] = gen_reg_rtx(V16QImode);
1077 })
1078
1079; vmnb, vmnh, vmnf, vmng
1080(define_insn "smin<mode>3"
1081  [(set (match_operand:VI          0 "register_operand" "=v")
1082	(smin:VI (match_operand:VI 1 "register_operand"  "v")
1083		 (match_operand:VI 2 "register_operand"  "v")))]
1084  "TARGET_VX"
1085  "vmn<bhfgq>\t%v0,%v1,%v2"
1086  [(set_attr "op_type" "VRR")])
1087
1088; vmxb, vmxh, vmxf, vmxg
1089(define_insn "smax<mode>3"
1090  [(set (match_operand:VI          0 "register_operand" "=v")
1091	(smax:VI (match_operand:VI 1 "register_operand"  "v")
1092		 (match_operand:VI 2 "register_operand"  "v")))]
1093  "TARGET_VX"
1094  "vmx<bhfgq>\t%v0,%v1,%v2"
1095  [(set_attr "op_type" "VRR")])
1096
1097; vmnlb, vmnlh, vmnlf, vmnlg
1098(define_insn "umin<mode>3"
1099  [(set (match_operand:VI          0 "register_operand" "=v")
1100	(umin:VI (match_operand:VI 1 "register_operand"  "v")
1101		 (match_operand:VI 2 "register_operand"  "v")))]
1102  "TARGET_VX"
1103  "vmnl<bhfgq>\t%v0,%v1,%v2"
1104  [(set_attr "op_type" "VRR")])
1105
1106; vmxlb, vmxlh, vmxlf, vmxlg
1107(define_insn "umax<mode>3"
1108  [(set (match_operand:VI          0 "register_operand" "=v")
1109	(umax:VI (match_operand:VI 1 "register_operand"  "v")
1110		 (match_operand:VI 2 "register_operand"  "v")))]
1111  "TARGET_VX"
1112  "vmxl<bhfgq>\t%v0,%v1,%v2"
1113  [(set_attr "op_type" "VRR")])
1114
1115; vmeb, vmeh, vmef
1116(define_insn "vec_widen_smult_even_<mode>"
1117  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1118	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand"  "v")
1119			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1120			     UNSPEC_VEC_SMULT_EVEN))]
1121  "TARGET_VX"
1122  "vme<bhfgq>\t%v0,%v1,%v2"
1123  [(set_attr "op_type" "VRR")])
1124
1125; vmleb, vmleh, vmlef
1126(define_insn "vec_widen_umult_even_<mode>"
1127  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1128	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand"  "v")
1129			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1130			     UNSPEC_VEC_UMULT_EVEN))]
1131  "TARGET_VX"
1132  "vmle<bhfgq>\t%v0,%v1,%v2"
1133  [(set_attr "op_type" "VRR")])
1134
1135; vmob, vmoh, vmof
1136(define_insn "vec_widen_smult_odd_<mode>"
1137  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1138	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand"  "v")
1139			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1140			     UNSPEC_VEC_SMULT_ODD))]
1141  "TARGET_VX"
1142  "vmo<bhfgq>\t%v0,%v1,%v2"
1143  [(set_attr "op_type" "VRR")])
1144
1145; vmlob, vmloh, vmlof
1146(define_insn "vec_widen_umult_odd_<mode>"
1147  [(set (match_operand:<vec_double>                 0 "register_operand" "=v")
1148	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand"  "v")
1149			      (match_operand:VI_QHS 2 "register_operand"  "v")]
1150			     UNSPEC_VEC_UMULT_ODD))]
1151  "TARGET_VX"
1152  "vmlo<bhfgq>\t%v0,%v1,%v2"
1153  [(set_attr "op_type" "VRR")])
1154
1155
1156; Widening hi/lo multiplications
1157
1158; The S/390 instructions vml and vmh return the low or high parts of
1159; the double sized result elements in the corresponding elements of
1160; the target register.  That's NOT what the vec_widen_umult_lo/hi
1161; patterns are expected to do.
1162
1163; We emulate the widening lo/hi multiplies with the even/odd versions
1164; followed by a vector merge
1165
1166
1167(define_expand "vec_widen_umult_lo_<mode>"
1168  [(set (match_dup 3)
1169	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "")
1170			      (match_operand:VI_QHS 2 "register_operand" "")]
1171			     UNSPEC_VEC_UMULT_EVEN))
1172   (set (match_dup 4)
1173	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1174			     UNSPEC_VEC_UMULT_ODD))
1175   (set (match_operand:<vec_double>                 0 "register_operand" "")
1176	(unspec:<vec_double> [(match_dup 3) (match_dup 4)]
1177			     UNSPEC_VEC_MERGEL))]
1178  "TARGET_VX"
1179 {
1180   operands[3] = gen_reg_rtx (<vec_double>mode);
1181   operands[4] = gen_reg_rtx (<vec_double>mode);
1182 })
1183
1184(define_expand "vec_widen_umult_hi_<mode>"
1185  [(set (match_dup 3)
1186	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "")
1187			      (match_operand:VI_QHS 2 "register_operand" "")]
1188			     UNSPEC_VEC_UMULT_EVEN))
1189   (set (match_dup 4)
1190	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1191			     UNSPEC_VEC_UMULT_ODD))
1192   (set (match_operand:<vec_double>                 0 "register_operand" "")
1193	(unspec:<vec_double> [(match_dup 3) (match_dup 4)]
1194			     UNSPEC_VEC_MERGEH))]
1195  "TARGET_VX"
1196 {
1197   operands[3] = gen_reg_rtx (<vec_double>mode);
1198   operands[4] = gen_reg_rtx (<vec_double>mode);
1199 })
1200
1201(define_expand "vec_widen_smult_lo_<mode>"
1202  [(set (match_dup 3)
1203	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "")
1204			      (match_operand:VI_QHS 2 "register_operand" "")]
1205			     UNSPEC_VEC_SMULT_EVEN))
1206   (set (match_dup 4)
1207	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1208			     UNSPEC_VEC_SMULT_ODD))
1209   (set (match_operand:<vec_double>                 0 "register_operand" "")
1210	(unspec:<vec_double> [(match_dup 3) (match_dup 4)]
1211			     UNSPEC_VEC_MERGEL))]
1212  "TARGET_VX"
1213 {
1214   operands[3] = gen_reg_rtx (<vec_double>mode);
1215   operands[4] = gen_reg_rtx (<vec_double>mode);
1216 })
1217
1218(define_expand "vec_widen_smult_hi_<mode>"
1219  [(set (match_dup 3)
1220	(unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "")
1221			      (match_operand:VI_QHS 2 "register_operand" "")]
1222			     UNSPEC_VEC_SMULT_EVEN))
1223   (set (match_dup 4)
1224	(unspec:<vec_double> [(match_dup 1) (match_dup 2)]
1225			     UNSPEC_VEC_SMULT_ODD))
1226   (set (match_operand:<vec_double>                 0 "register_operand" "")
1227	(unspec:<vec_double> [(match_dup 3) (match_dup 4)]
1228			     UNSPEC_VEC_MERGEH))]
1229  "TARGET_VX"
1230 {
1231   operands[3] = gen_reg_rtx (<vec_double>mode);
1232   operands[4] = gen_reg_rtx (<vec_double>mode);
1233 })
1234
1235; vec_widen_ushiftl_hi
1236; vec_widen_ushiftl_lo
1237; vec_widen_sshiftl_hi
1238; vec_widen_sshiftl_lo
1239
1240;;
1241;; Vector floating point arithmetic instructions
1242;;
1243
1244; vfasb, vfadb, wfasb, wfadb, wfaxb
1245(define_insn "add<mode>3"
1246  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1247	(plus:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1248		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1249  "TARGET_VX"
1250  "<vw>fa<sdx>b\t%v0,%v1,%v2"
1251  [(set_attr "op_type" "VRR")])
1252
1253; vfssb, vfsdb, wfssb, wfsdb, wfsxb
1254(define_insn "sub<mode>3"
1255  [(set (match_operand:VF_HW              0 "register_operand" "=v")
1256	(minus:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1257		     (match_operand:VF_HW 2 "register_operand"  "v")))]
1258  "TARGET_VX"
1259  "<vw>fs<sdx>b\t%v0,%v1,%v2"
1260  [(set_attr "op_type" "VRR")])
1261
1262; vfmsb, vfmdb, wfmsb, wfmdb, wfmxb
1263(define_insn "mul<mode>3"
1264  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1265	(mult:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1266		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1267  "TARGET_VX"
1268  "<vw>fm<sdx>b\t%v0,%v1,%v2"
1269  [(set_attr "op_type" "VRR")])
1270
1271; vfdsb, vfddb, wfdsb, wfddb, wfdxb
1272(define_insn "div<mode>3"
1273  [(set (match_operand:VF_HW            0 "register_operand" "=v")
1274	(div:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1275		   (match_operand:VF_HW 2 "register_operand"  "v")))]
1276  "TARGET_VX"
1277  "<vw>fd<sdx>b\t%v0,%v1,%v2"
1278  [(set_attr "op_type" "VRR")])
1279
1280; vfsqsb, vfsqdb, wfsqsb, wfsqdb, wfsqxb
1281(define_insn "sqrt<mode>2"
1282  [(set (match_operand:VF_HW           0 "register_operand" "=v")
1283	(sqrt:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")))]
1284  "TARGET_VX"
1285  "<vw>fsq<sdx>b\t%v0,%v1"
1286  [(set_attr "op_type" "VRR")])
1287
1288; vfmasb, vfmadb, wfmasb, wfmadb, wfmaxb
1289(define_insn "fma<mode>4"
1290  [(set (match_operand:VF_HW            0 "register_operand" "=v")
1291	(fma:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1292		   (match_operand:VF_HW 2 "register_operand"  "v")
1293		   (match_operand:VF_HW 3 "register_operand"  "v")))]
1294  "TARGET_VX"
1295  "<vw>fma<sdx>b\t%v0,%v1,%v2,%v3"
1296  [(set_attr "op_type" "VRR")])
1297
1298; vfmssb, vfmsdb, wfmssb, wfmsdb, wfmsxb
1299(define_insn "fms<mode>4"
1300  [(set (match_operand:VF_HW                     0 "register_operand" "=v")
1301	(fma:VF_HW (match_operand:VF_HW          1 "register_operand"  "v")
1302		   (match_operand:VF_HW          2 "register_operand"  "v")
1303		 (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v"))))]
1304  "TARGET_VX"
1305  "<vw>fms<sdx>b\t%v0,%v1,%v2,%v3"
1306  [(set_attr "op_type" "VRR")])
1307
1308; vfnmasb, vfnmadb, wfnmasb, wfnmadb, wfnmaxb
1309(define_insn "neg_fma<mode>4"
1310  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1311	(neg:VF_HW
1312	 (fma:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1313		    (match_operand:VF_HW 2 "register_operand"  "v")
1314		    (match_operand:VF_HW 3 "register_operand"  "v"))))]
1315  "TARGET_VXE"
1316  "<vw>fnma<sdx>b\t%v0,%v1,%v2,%v3"
1317  [(set_attr "op_type" "VRR")])
1318
1319; vfnmssb, vfnmsdb, wfnmssb, wfnmsdb, wfnmsxb
1320(define_insn "neg_fms<mode>4"
1321  [(set (match_operand:VF_HW                      0 "register_operand" "=v")
1322	(neg:VF_HW
1323	 (fma:VF_HW (match_operand:VF_HW          1 "register_operand"  "v")
1324		    (match_operand:VF_HW          2 "register_operand"  "v")
1325		  (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v")))))]
1326  "TARGET_VXE"
1327  "<vw>fnms<sdx>b\t%v0,%v1,%v2,%v3"
1328  [(set_attr "op_type" "VRR")])
1329
1330; vflcsb, vflcdb, wflcsb, wflcdb, wflcxb
1331(define_insn "neg<mode>2"
1332  [(set (match_operand:VFT          0 "register_operand" "=v")
1333	(neg:VFT (match_operand:VFT 1 "register_operand"  "v")))]
1334  "TARGET_VX"
1335  "<vw>flc<sdx>b\t%v0,%v1"
1336  [(set_attr "op_type" "VRR")])
1337
1338; vflpsb, vflpdb, wflpsb, wflpdb, wflpxb
1339(define_insn "abs<mode>2"
1340  [(set (match_operand:VFT          0 "register_operand" "=v")
1341	(abs:VFT (match_operand:VFT 1 "register_operand"  "v")))]
1342  "TARGET_VX"
1343  "<vw>flp<sdx>b\t%v0,%v1"
1344  [(set_attr "op_type" "VRR")])
1345
1346; vflnsb, vflndb, wflnsb, wflndb, wflnxb
1347(define_insn "negabs<mode>2"
1348  [(set (match_operand:VFT                   0 "register_operand" "=v")
1349	(neg:VFT (abs:VFT (match_operand:VFT 1 "register_operand"  "v"))))]
1350  "TARGET_VX"
1351  "<vw>fln<sdx>b\t%v0,%v1"
1352  [(set_attr "op_type" "VRR")])
1353
1354(define_expand "smax<mode>3"
1355  [(set (match_operand:VF_HW             0 "register_operand")
1356	(smax:VF_HW (match_operand:VF_HW 1 "register_operand")
1357		    (match_operand:VF_HW 2 "register_operand")))]
1358  "TARGET_VX")
1359
1360; vfmaxsb, vfmaxdb, wfmaxsb, wfmaxdb, wfmaxxb
1361(define_insn "*smax<mode>3_vxe"
1362  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1363	(smax:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1364		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1365  "TARGET_VXE"
1366  "<vw>fmax<sdx>b\t%v0,%v1,%v2,4"
1367  [(set_attr "op_type" "VRR")])
1368
1369; Emulate with compare + select
1370(define_insn_and_split "*smaxv2df3_vx"
1371  [(set (match_operand:V2DF            0 "register_operand" "=v")
1372	(smax:V2DF (match_operand:V2DF 1 "register_operand"  "v")
1373		   (match_operand:V2DF 2 "register_operand"  "v")))]
1374  "TARGET_VX && !TARGET_VXE"
1375  "#"
1376  "&& 1"
1377  [(set (match_dup 3)
1378	(not:V2DI
1379	 (unge:V2DI (match_dup 2) (match_dup 1))))
1380   (set (match_dup 0)
1381	(if_then_else:V2DF
1382	 (eq (match_dup 3) (match_dup 4))
1383	 (match_dup 2)
1384	 (match_dup 1)))]
1385{
1386  operands[3] = gen_reg_rtx (V2DImode);
1387  operands[4] = CONST0_RTX (V2DImode);
1388})
1389
1390(define_expand "smin<mode>3"
1391  [(set (match_operand:VF_HW             0 "register_operand")
1392	(smin:VF_HW (match_operand:VF_HW 1 "register_operand")
1393		    (match_operand:VF_HW 2 "register_operand")))]
1394  "TARGET_VX")
1395
1396; vfminsb, vfmindb, wfminsb, wfmindb, wfminxb
1397(define_insn "*smin<mode>3_vxe"
1398  [(set (match_operand:VF_HW             0 "register_operand" "=v")
1399	(smin:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
1400		    (match_operand:VF_HW 2 "register_operand"  "v")))]
1401  "TARGET_VXE"
1402  "<vw>fmin<sdx>b\t%v0,%v1,%v2,4"
1403  [(set_attr "op_type" "VRR")])
1404
1405; Emulate with compare + select
1406(define_insn_and_split "*sminv2df3_vx"
1407  [(set (match_operand:V2DF            0 "register_operand" "=v")
1408	(smin:V2DF (match_operand:V2DF 1 "register_operand"  "v")
1409		   (match_operand:V2DF 2 "register_operand"  "v")))]
1410  "TARGET_VX && !TARGET_VXE"
1411  "#"
1412  "&& 1"
1413  [(set (match_dup 3)
1414	(not:V2DI
1415	 (unge:V2DI (match_dup 2) (match_dup 1))))
1416   (set (match_dup 0)
1417	(if_then_else:V2DF
1418	 (eq (match_dup 3) (match_dup 4))
1419	 (match_dup 1)
1420	 (match_dup 2)))]
1421{
1422  operands[3] = gen_reg_rtx (V2DImode);
1423  operands[4] = CONST0_RTX (V2DImode);
1424})
1425
1426; Vector copysign, implement using vector select
1427(define_expand "copysign<mode>3"
1428  [(set (match_operand:VFT 0 "register_operand" "")
1429	(if_then_else:VFT
1430	 (eq (match_dup 3)
1431	     (match_dup 4))
1432	 (match_operand:VFT 1 "register_operand"  "")
1433	 (match_operand:VFT 2 "register_operand"  "")))]
1434  "TARGET_VX"
1435{
1436  int sz = GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
1437  int prec = GET_MODE_PRECISION (GET_MODE_INNER (<tointvec>mode));
1438  wide_int mask_val = wi::shwi (1l << (sz - 1), prec);
1439
1440  rtx mask = gen_reg_rtx (<tointvec>mode);
1441
1442  int nunits = GET_MODE_NUNITS (<tointvec>mode);
1443  rtvec v = rtvec_alloc (nunits);
1444  for (int i = 0; i < nunits; i++)
1445    RTVEC_ELT (v, i) = GEN_INT (mask_val.to_shwi ());
1446
1447  mask = gen_rtx_CONST_VECTOR (<tointvec>mode, v);
1448  operands[3] = force_reg (<tointvec>mode, mask);
1449  operands[4] = CONST0_RTX (<tointvec>mode);
1450})
1451
1452;;
1453;; Integer compares
1454;;
1455
1456(define_insn "*vec_cmp<VICMP_HW_OP:code><VI:mode>_nocc"
1457  [(set (match_operand:VI                 2 "register_operand" "=v")
1458	(VICMP_HW_OP:VI (match_operand:VI 0 "register_operand"  "v")
1459			(match_operand:VI 1 "register_operand"  "v")))]
1460  "TARGET_VX"
1461  "vc<VICMP_HW_OP:insn_cmp_op><VI:bhfgq>\t%v2,%v0,%v1"
1462  [(set_attr "op_type" "VRR")])
1463
1464
1465;;
1466;; Floating point compares
1467;;
1468
1469; vfcesb, vfcedb, wfcexb: non-signaling "==" comparison (a == b)
1470(define_insn "*vec_cmpeq<mode>_quiet_nocc"
1471  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
1472	(eq:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1473		       (match_operand:VFT 2 "register_operand" "v")))]
1474  "TARGET_VX"
1475  "<vw>fce<sdx>b\t%v0,%v1,%v2"
1476  [(set_attr "op_type" "VRR")])
1477
1478; vfchsb, vfchdb, wfchxb: non-signaling > comparison (!(b u>= a))
1479(define_insn "vec_cmpgt<mode>_quiet_nocc"
1480  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
1481	(not:<tointvec>
1482	 (unge:<tointvec> (match_operand:VFT 2 "register_operand" "v")
1483			  (match_operand:VFT 1 "register_operand" "v"))))]
1484  "TARGET_VX"
1485  "<vw>fch<sdx>b\t%v0,%v1,%v2"
1486  [(set_attr "op_type" "VRR")])
1487
1488(define_expand "vec_cmplt<mode>_quiet_nocc"
1489  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
1490	(not:<tointvec>
1491	 (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1492			  (match_operand:VFT 2 "register_operand" "v"))))]
1493  "TARGET_VX")
1494
1495; vfchesb, vfchedb, wfchexb: non-signaling >= comparison (!(a u< b))
1496(define_insn "vec_cmpge<mode>_quiet_nocc"
1497  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
1498	(not:<tointvec>
1499	 (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1500			  (match_operand:VFT 2 "register_operand" "v"))))]
1501  "TARGET_VX"
1502  "<vw>fche<sdx>b\t%v0,%v1,%v2"
1503  [(set_attr "op_type" "VRR")])
1504
1505(define_expand "vec_cmple<mode>_quiet_nocc"
1506  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
1507	(not:<tointvec>
1508	 (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
1509			  (match_operand:VFT 1 "register_operand" "v"))))]
1510  "TARGET_VX")
1511
1512; vfkesb, vfkedb, wfkexb: signaling == comparison ((a >= b) & (b >= a))
1513(define_insn "*vec_cmpeq<mode>_signaling_nocc"
1514  [(set (match_operand:<tointvec>          0 "register_operand" "=v")
1515	(and:<tointvec>
1516	 (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1517			(match_operand:VFT 2 "register_operand" "v"))
1518	 (ge:<tointvec> (match_dup         2)
1519			(match_dup         1))))]
1520  "TARGET_VXE"
1521  "<vw>fke<sdx>b\t%v0,%v1,%v2"
1522  [(set_attr "op_type" "VRR")])
1523
1524; vfkhsb, vfkhdb, wfkhxb: signaling > comparison (a > b)
1525(define_insn "*vec_cmpgt<mode>_signaling_nocc"
1526  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
1527	(gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1528		       (match_operand:VFT 2 "register_operand" "v")))]
1529  "TARGET_VXE"
1530  "<vw>fkh<sdx>b\t%v0,%v1,%v2"
1531  [(set_attr "op_type" "VRR")])
1532
1533(define_insn "*vec_cmpgt<mode>_signaling_finite_nocc"
1534  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
1535	(gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1536		       (match_operand:VFT 2 "register_operand" "v")))]
1537  "TARGET_NONSIGNALING_VECTOR_COMPARE_OK"
1538  "<vw>fch<sdx>b\t%v0,%v1,%v2"
1539  [(set_attr "op_type" "VRR")])
1540
1541; vfkhesb, vfkhedb, wfkhexb: signaling >= comparison (a >= b)
1542(define_insn "*vec_cmpge<mode>_signaling_nocc"
1543  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
1544	(ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1545		       (match_operand:VFT 2 "register_operand" "v")))]
1546  "TARGET_VXE"
1547  "<vw>fkhe<sdx>b\t%v0,%v1,%v2"
1548  [(set_attr "op_type" "VRR")])
1549
1550(define_insn "*vec_cmpge<mode>_signaling_finite_nocc"
1551  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
1552	(ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1553		       (match_operand:VFT 2 "register_operand" "v")))]
1554  "TARGET_NONSIGNALING_VECTOR_COMPARE_OK"
1555  "<vw>fche<sdx>b\t%v0,%v1,%v2"
1556  [(set_attr "op_type" "VRR")])
1557
1558; Expanders for not directly supported comparisons
1559; Signaling comparisons must be expressed via signaling rtxes only,
1560; and quiet comparisons must be expressed via quiet rtxes only.
1561
1562; UNGT a u> b -> !!(b u< a)
1563(define_expand "vec_cmpungt<mode>"
1564  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
1565	(not:<tointvec>
1566	 (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
1567			  (match_operand:VFT 1 "register_operand" "v"))))
1568   (set (match_dup                           0)
1569	(not:<tointvec> (match_dup           0)))]
1570  "TARGET_VX")
1571
1572; UNGE a u>= b -> !!(a u>= b)
1573(define_expand "vec_cmpunge<mode>"
1574  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
1575	(not:<tointvec>
1576	 (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1577			  (match_operand:VFT 2 "register_operand" "v"))))
1578   (set (match_dup                           0)
1579	(not:<tointvec> (match_dup           0)))]
1580  "TARGET_VX")
1581
1582; UNEQ a u== b -> !(!(a u>= b) | !(b u>= a))
1583(define_expand "vec_cmpuneq<mode>"
1584  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
1585	(not:<tointvec>
1586	 (unge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
1587		          (match_operand:VFT 2 "register_operand"  "v"))))
1588   (set (match_dup                           3)
1589	(not:<tointvec>
1590	 (unge:<tointvec> (match_dup         2)
1591	                  (match_dup         1))))
1592   (set (match_dup                           0)
1593	(ior:<tointvec> (match_dup           0)
1594			(match_dup           3)))
1595   (set (match_dup                           0)
1596	(not:<tointvec> (match_dup           0)))]
1597  "TARGET_VX"
1598{
1599  operands[3] = gen_reg_rtx (<tointvec>mode);
1600})
1601
1602; LTGT a <> b -> a > b | b > a
1603(define_expand "vec_cmpltgt<mode>"
1604  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
1605	(gt:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
1606		    (match_operand:VFT 2 "register_operand"  "v")))
1607   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
1608   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
1609  "TARGET_VXE"
1610{
1611  operands[3] = gen_reg_rtx (<tointvec>mode);
1612})
1613
1614; ORDERED (a, b): !(a u< b) | !(a u>= b)
1615(define_expand "vec_cmpordered<mode>"
1616  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
1617	(not:<tointvec>
1618	 (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
1619		          (match_operand:VFT 2 "register_operand" "v"))))
1620   (set (match_dup                           3)
1621	(not:<tointvec>
1622	 (unge:<tointvec> (match_dup         1)
1623			  (match_dup         2))))
1624   (set (match_dup                           0)
1625	(ior:<tointvec> (match_dup           0)
1626			(match_dup           3)))]
1627  "TARGET_VX"
1628{
1629  operands[3] = gen_reg_rtx (<tointvec>mode);
1630})
1631
1632; UNORDERED (a, b): !ORDERED (a, b)
1633(define_expand "vec_cmpunordered<mode>"
1634  [(match_operand:<tointvec> 0 "register_operand" "=v")
1635   (match_operand:VFT        1 "register_operand" "v")
1636   (match_operand:VFT        2 "register_operand" "v")]
1637  "TARGET_VX"
1638{
1639  emit_insn (gen_vec_cmpordered<mode> (operands[0], operands[1], operands[2]));
1640  emit_insn (gen_rtx_SET (operands[0],
1641	     gen_rtx_NOT (<tointvec>mode, operands[0])));
1642  DONE;
1643})
1644
1645(define_code_iterator VEC_CMP_EXPAND
1646  [ungt unge uneq ltgt ordered unordered])
1647
1648(define_expand "vec_cmp<code>"
1649  [(match_operand 0 "register_operand" "")
1650   (VEC_CMP_EXPAND (match_operand 1 "register_operand" "")
1651                   (match_operand 2 "register_operand" ""))]
1652  "TARGET_VX"
1653{
1654  if (GET_MODE (operands[1]) == V4SFmode)
1655    emit_insn (gen_vec_cmp<code>v4sf (operands[0], operands[1], operands[2]));
1656  else if (GET_MODE (operands[1]) == V2DFmode)
1657    emit_insn (gen_vec_cmp<code>v2df (operands[0], operands[1], operands[2]));
1658  else
1659    gcc_unreachable ();
1660
1661  DONE;
1662})
1663
1664(define_insn "*vec_load_pair<mode>"
1665  [(set (match_operand:V_HW_64                       0 "register_operand" "=v,v")
1666	(vec_concat:V_HW_64 (match_operand:<non_vec> 1 "register_operand"  "d,v")
1667			    (match_operand:<non_vec> 2 "register_operand"  "d,v")))]
1668  "TARGET_VX"
1669  "@
1670   vlvgp\t%v0,%1,%2
1671   vmrhg\t%v0,%v1,%v2"
1672  [(set_attr "op_type" "VRR,VRR")])
1673
1674(define_insn "vllv16qi"
1675  [(set (match_operand:V16QI              0 "register_operand" "=v")
1676	(unspec:V16QI [(match_operand:SI  1 "register_operand"  "d")
1677		       (match_operand:BLK 2 "memory_operand"    "Q")]
1678		      UNSPEC_VEC_LOAD_LEN))]
1679  "TARGET_VX"
1680  "vll\t%v0,%1,%2"
1681  [(set_attr "op_type" "VRS")])
1682
1683; vfenebs, vfenehs, vfenefs
1684; vfenezbs, vfenezhs, vfenezfs
1685(define_insn "vec_vfenes<mode>"
1686  [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
1687	(unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
1688			   (match_operand:VI_HW_QHS 2 "register_operand" "v")
1689			   (match_operand:QI 3 "const_mask_operand" "C")]
1690			  UNSPEC_VEC_VFENE))
1691   (set (reg:CCRAW CC_REGNUM)
1692	(unspec:CCRAW [(match_dup 1)
1693		       (match_dup 2)
1694		       (match_dup 3)]
1695		      UNSPEC_VEC_VFENECC))]
1696  "TARGET_VX"
1697{
1698  unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
1699
1700  gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
1701  flags &= ~VSTRING_FLAG_CS;
1702
1703  if (flags == VSTRING_FLAG_ZS)
1704    return "vfenez<bhfgq>s\t%v0,%v1,%v2";
1705  return "vfene<bhfgq>s\t%v0,%v1,%v2";
1706}
1707  [(set_attr "op_type" "VRR")])
1708
1709
1710; Vector select
1711
1712; The following splitters simplify vec_sel for constant 0 or -1
1713; selection sources.  This is required to generate efficient code for
1714; vcond.
1715
1716; a = b == c;
1717(define_split
1718  [(set (match_operand:V 0 "register_operand" "")
1719	(if_then_else:V
1720	 (eq (match_operand:<tointvec> 3 "register_operand" "")
1721	     (match_operand:V 4 "const0_operand" ""))
1722	 (match_operand:V 1 "const0_operand" "")
1723	 (match_operand:V 2 "all_ones_operand" "")))]
1724  "TARGET_VX"
1725  [(set (match_dup 0) (match_dup 3))]
1726{
1727  PUT_MODE (operands[3], <V:MODE>mode);
1728})
1729
1730; a = ~(b == c)
1731(define_split
1732  [(set (match_operand:V 0 "register_operand" "")
1733	(if_then_else:V
1734	 (eq (match_operand:<tointvec> 3 "register_operand" "")
1735	     (match_operand:V 4 "const0_operand" ""))
1736	 (match_operand:V 1 "all_ones_operand" "")
1737	 (match_operand:V 2 "const0_operand" "")))]
1738  "TARGET_VX"
1739  [(set (match_dup 0) (not:V (match_dup 3)))]
1740{
1741  PUT_MODE (operands[3], <V:MODE>mode);
1742})
1743
1744; a = b != c
1745(define_split
1746  [(set (match_operand:V 0 "register_operand" "")
1747	(if_then_else:V
1748	 (ne (match_operand:<tointvec> 3 "register_operand" "")
1749	     (match_operand:V 4 "const0_operand" ""))
1750	 (match_operand:V 1 "all_ones_operand" "")
1751	 (match_operand:V 2 "const0_operand" "")))]
1752  "TARGET_VX"
1753  [(set (match_dup 0) (match_dup 3))]
1754{
1755  PUT_MODE (operands[3], <V:MODE>mode);
1756})
1757
1758; a = ~(b != c)
1759(define_split
1760  [(set (match_operand:V 0 "register_operand" "")
1761	(if_then_else:V
1762	 (ne (match_operand:<tointvec> 3 "register_operand" "")
1763	     (match_operand:V 4 "const0_operand" ""))
1764	 (match_operand:V 1 "const0_operand" "")
1765	 (match_operand:V 2 "all_ones_operand" "")))]
1766  "TARGET_VX"
1767  [(set (match_dup 0) (not:V (match_dup 3)))]
1768{
1769  PUT_MODE (operands[3], <V:MODE>mode);
1770})
1771
1772; op0 = op3 == 0 ? op1 : op2
1773(define_insn "*vec_sel0<mode>"
1774  [(set (match_operand:V 0 "register_operand" "=v")
1775	(if_then_else:V
1776	 (eq (match_operand:<tointvec> 3 "register_operand" "v")
1777	     (match_operand:<tointvec> 4 "const0_operand" ""))
1778	 (match_operand:V 1 "register_operand" "v")
1779	 (match_operand:V 2 "register_operand" "v")))]
1780  "TARGET_VX"
1781  "vsel\t%v0,%2,%1,%3"
1782  [(set_attr "op_type" "VRR")])
1783
1784; op0 = !op3 == 0 ? op1 : op2
1785(define_insn "*vec_sel0<mode>"
1786  [(set (match_operand:V 0 "register_operand" "=v")
1787	(if_then_else:V
1788	 (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
1789	     (match_operand:<tointvec> 4 "const0_operand" ""))
1790	 (match_operand:V 1 "register_operand" "v")
1791	 (match_operand:V 2 "register_operand" "v")))]
1792  "TARGET_VX"
1793  "vsel\t%v0,%1,%2,%3"
1794  [(set_attr "op_type" "VRR")])
1795
1796; op0 = op3 == -1 ? op1 : op2
1797(define_insn "*vec_sel1<mode>"
1798  [(set (match_operand:V 0 "register_operand" "=v")
1799	(if_then_else:V
1800	 (eq (match_operand:<tointvec> 3 "register_operand" "v")
1801	     (match_operand:<tointvec> 4 "all_ones_operand" ""))
1802	 (match_operand:V 1 "register_operand" "v")
1803	 (match_operand:V 2 "register_operand" "v")))]
1804  "TARGET_VX"
1805  "vsel\t%v0,%1,%2,%3"
1806  [(set_attr "op_type" "VRR")])
1807
1808; op0 = !op3 == -1 ? op1 : op2
1809(define_insn "*vec_sel1<mode>"
1810  [(set (match_operand:V 0 "register_operand" "=v")
1811	(if_then_else:V
1812	 (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
1813	     (match_operand:<tointvec> 4 "all_ones_operand" ""))
1814	 (match_operand:V 1 "register_operand" "v")
1815	 (match_operand:V 2 "register_operand" "v")))]
1816  "TARGET_VX"
1817  "vsel\t%v0,%2,%1,%3"
1818  [(set_attr "op_type" "VRR")])
1819
1820; vec_pack_trunc
1821
1822; vpkh, vpkf, vpkg
1823(define_insn "vec_pack_trunc_<mode>"
1824  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
1825	(vec_concat:<vec_half>
1826	 (truncate:<vec_halfhalf>
1827	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
1828	 (truncate:<vec_halfhalf>
1829	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
1830  "TARGET_VX"
1831  "vpk<bhfgq>\t%0,%1,%2"
1832  [(set_attr "op_type" "VRR")])
1833
1834; vpksh, vpksf, vpksg
1835(define_insn "vec_pack_ssat_<mode>"
1836  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
1837	(vec_concat:<vec_half>
1838	 (ss_truncate:<vec_halfhalf>
1839	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
1840	 (ss_truncate:<vec_halfhalf>
1841	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
1842  "TARGET_VX"
1843  "vpks<bhfgq>\t%0,%1,%2"
1844  [(set_attr "op_type" "VRR")])
1845
1846; vpklsh, vpklsf, vpklsg
1847(define_insn "vec_pack_usat_<mode>"
1848  [(set (match_operand:<vec_half> 0 "register_operand" "=v")
1849	(vec_concat:<vec_half>
1850	 (us_truncate:<vec_halfhalf>
1851	  (match_operand:VI_HW_HSD 1 "register_operand" "v"))
1852	 (us_truncate:<vec_halfhalf>
1853	  (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
1854  "TARGET_VX"
1855  "vpkls<bhfgq>\t%0,%1,%2"
1856  [(set_attr "op_type" "VRR")])
1857
1858;; vector unpack v16qi
1859
1860; signed
1861
1862(define_insn "vec_unpacks_hi_v16qi"
1863  [(set (match_operand:V8HI 0 "register_operand" "=v")
1864	(sign_extend:V8HI
1865	 (vec_select:V8QI
1866	  (match_operand:V16QI 1 "register_operand" "v")
1867	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
1868		     (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
1869  "TARGET_VX"
1870  "vuphb\t%0,%1"
1871  [(set_attr "op_type" "VRR")])
1872
1873(define_insn "vec_unpacks_lo_v16qi"
1874  [(set (match_operand:V8HI 0 "register_operand" "=v")
1875	(sign_extend:V8HI
1876	 (vec_select:V8QI
1877	  (match_operand:V16QI 1 "register_operand" "v")
1878	  (parallel [(const_int 8) (const_int 9) (const_int 10)(const_int 11)
1879		     (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
1880  "TARGET_VX"
1881  "vuplb\t%0,%1"
1882  [(set_attr "op_type" "VRR")])
1883
1884; unsigned
1885
1886(define_insn "vec_unpacku_hi_v16qi"
1887  [(set (match_operand:V8HI 0 "register_operand" "=v")
1888	(zero_extend:V8HI
1889	 (vec_select:V8QI
1890	  (match_operand:V16QI 1 "register_operand" "v")
1891	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
1892		     (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
1893  "TARGET_VX"
1894  "vuplhb\t%0,%1"
1895  [(set_attr "op_type" "VRR")])
1896
1897(define_insn "vec_unpacku_lo_v16qi"
1898  [(set (match_operand:V8HI 0 "register_operand" "=v")
1899	(zero_extend:V8HI
1900	 (vec_select:V8QI
1901	  (match_operand:V16QI 1 "register_operand" "v")
1902	  (parallel [(const_int 8) (const_int 9) (const_int 10)(const_int 11)
1903		     (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
1904  "TARGET_VX"
1905  "vupllb\t%0,%1"
1906  [(set_attr "op_type" "VRR")])
1907
1908;; vector unpack v8hi
1909
1910; signed
1911
1912(define_insn "vec_unpacks_hi_v8hi"
1913  [(set (match_operand:V4SI 0 "register_operand" "=v")
1914	(sign_extend:V4SI
1915	 (vec_select:V4HI
1916	  (match_operand:V8HI 1 "register_operand" "v")
1917	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
1918  "TARGET_VX"
1919  "vuphh\t%0,%1"
1920  [(set_attr "op_type" "VRR")])
1921
1922(define_insn "vec_unpacks_lo_v8hi"
1923  [(set (match_operand:V4SI 0 "register_operand" "=v")
1924	(sign_extend:V4SI
1925	 (vec_select:V4HI
1926	  (match_operand:V8HI 1 "register_operand" "v")
1927	  (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
1928  "TARGET_VX"
1929  "vuplhw\t%0,%1"
1930  [(set_attr "op_type" "VRR")])
1931
1932; unsigned
1933
1934(define_insn "vec_unpacku_hi_v8hi"
1935  [(set (match_operand:V4SI 0 "register_operand" "=v")
1936	(zero_extend:V4SI
1937	 (vec_select:V4HI
1938	  (match_operand:V8HI 1 "register_operand" "v")
1939	  (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
1940  "TARGET_VX"
1941  "vuplhh\t%0,%1"
1942  [(set_attr "op_type" "VRR")])
1943
1944(define_insn "vec_unpacku_lo_v8hi"
1945  [(set (match_operand:V4SI 0 "register_operand" "=v")
1946	(zero_extend:V4SI
1947	 (vec_select:V4HI
1948	  (match_operand:V8HI 1 "register_operand" "v")
1949	  (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
1950  "TARGET_VX"
1951  "vupllh\t%0,%1"
1952  [(set_attr "op_type" "VRR")])
1953
1954;; vector unpack v4si
1955
1956; signed
1957
1958(define_insn "vec_unpacks_hi_v4si"
1959  [(set (match_operand:V2DI 0 "register_operand" "=v")
1960	(sign_extend:V2DI
1961	 (vec_select:V2SI
1962	  (match_operand:V4SI 1 "register_operand" "v")
1963	  (parallel [(const_int 0)(const_int 1)]))))]
1964  "TARGET_VX"
1965  "vuphf\t%0,%1"
1966  [(set_attr "op_type" "VRR")])
1967
1968(define_insn "vec_unpacks_lo_v4si"
1969  [(set (match_operand:V2DI 0 "register_operand" "=v")
1970	(sign_extend:V2DI
1971	 (vec_select:V2SI
1972	  (match_operand:V4SI 1 "register_operand" "v")
1973	  (parallel [(const_int 2)(const_int 3)]))))]
1974  "TARGET_VX"
1975  "vuplf\t%0,%1"
1976  [(set_attr "op_type" "VRR")])
1977
1978; unsigned
1979
1980(define_insn "vec_unpacku_hi_v4si"
1981  [(set (match_operand:V2DI 0 "register_operand" "=v")
1982	(zero_extend:V2DI
1983	 (vec_select:V2SI
1984	  (match_operand:V4SI 1 "register_operand" "v")
1985	  (parallel [(const_int 0)(const_int 1)]))))]
1986  "TARGET_VX"
1987  "vuplhf\t%0,%1"
1988  [(set_attr "op_type" "VRR")])
1989
1990(define_insn "vec_unpacku_lo_v4si"
1991  [(set (match_operand:V2DI 0 "register_operand" "=v")
1992	(zero_extend:V2DI
1993	 (vec_select:V2SI
1994	  (match_operand:V4SI 1 "register_operand" "v")
1995	  (parallel [(const_int 2)(const_int 3)]))))]
1996  "TARGET_VX"
1997  "vupllf\t%0,%1"
1998  [(set_attr "op_type" "VRR")])
1999
2000;; vector load lengthened
2001
2002; vflls float -> double
2003(define_insn "*vec_extendv4sf"
2004  [(set (match_operand:V2DF 0 "register_operand" "=v")
2005	(float_extend:V2DF
2006	 (vec_select:V2SF
2007	  (match_operand:V4SF 1 "register_operand" "v")
2008	  (parallel [(const_int 0) (const_int 2)]))))]
2009  "TARGET_VX"
2010  "vldeb\t%v0,%v1"
2011  [(set_attr "op_type" "VRR")])
2012
2013(define_expand "vec_unpacks_lo_v4sf"
2014  [(set (match_dup 2)
2015	(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
2016		      (match_dup 1)]
2017		     UNSPEC_VEC_MERGEL))
2018   (set (match_operand:V2DF               0 "register_operand" "=v")
2019	(float_extend:V2DF
2020	 (vec_select:V2SF
2021	  (match_dup 2)
2022	  (parallel [(const_int 0) (const_int 2)]))))]
2023  "TARGET_VX"
2024{ operands[2] = gen_reg_rtx(V4SFmode); })
2025
2026(define_expand "vec_unpacks_hi_v4sf"
2027  [(set (match_dup 2)
2028	(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
2029		      (match_dup 1)]
2030		     UNSPEC_VEC_MERGEH))
2031   (set (match_operand:V2DF               0 "register_operand" "=v")
2032	(float_extend:V2DF
2033	 (vec_select:V2SF
2034	  (match_dup 2)
2035	  (parallel [(const_int 0) (const_int 2)]))))]
2036  "TARGET_VX"
2037{ operands[2] = gen_reg_rtx(V4SFmode); })
2038
2039
2040; double -> long double
2041(define_insn "*vec_extendv2df"
2042  [(set (match_operand:V1TF 0 "register_operand" "=v")
2043	(float_extend:V1TF
2044	 (vec_select:V1DF
2045	  (match_operand:V2DF 1 "register_operand" "v")
2046	  (parallel [(const_int 0)]))))]
2047  "TARGET_VXE"
2048  "wflld\t%v0,%v1"
2049  [(set_attr "op_type" "VRR")])
2050
2051(define_expand "vec_unpacks_lo_v2df"
2052  [(set (match_dup 2)
2053	(unspec:V2DF [(match_operand:V2DF 1 "register_operand" "v")
2054		      (match_dup 1)]
2055		     UNSPEC_VEC_MERGEL))
2056   (set (match_operand:V1TF               0 "register_operand" "=v")
2057	(float_extend:V1TF
2058	 (vec_select:V1DF
2059	  (match_dup 2)
2060	  (parallel [(const_int 0)]))))]
2061  "TARGET_VXE"
2062{ operands[2] = gen_reg_rtx (V2DFmode); })
2063
2064(define_expand "vec_unpacks_hi_v2df"
2065  [(set (match_dup 2)
2066	(unspec:V2DF [(match_operand:V2DF 1 "register_operand" "v")
2067		      (match_dup 1)]
2068		     UNSPEC_VEC_MERGEH))
2069   (set (match_operand:V1TF               0 "register_operand" "=v")
2070	(float_extend:V1TF
2071	 (vec_select:V1DF
2072	  (match_dup 2)
2073	  (parallel [(const_int 0)]))))]
2074  "TARGET_VXE"
2075{ operands[2] = gen_reg_rtx (V2DFmode); })
2076
2077
2078; 2 x v2df -> 1 x v4sf
2079(define_expand "vec_pack_trunc_v2df"
2080  [(set (match_dup 3)
2081	(unspec:V4SF [(match_operand:V2DF 1 "register_operand" "")
2082		      (const_int VEC_INEXACT)
2083		      (const_int VEC_RND_CURRENT)]
2084		     UNSPEC_VEC_VFLR))
2085   (set (match_dup 4)
2086	(unspec:V4SF [(match_operand:V2DF 2 "register_operand" "")
2087		      (const_int VEC_INEXACT)
2088		      (const_int VEC_RND_CURRENT)]
2089		     UNSPEC_VEC_VFLR))
2090   (set (match_dup 6)
2091	(unspec:V16QI [(subreg:V16QI (match_dup 3) 0)
2092		       (subreg:V16QI (match_dup 4) 0)
2093		       (match_dup 5)]
2094		      UNSPEC_VEC_PERM))
2095   (set (match_operand:V4SF 0 "register_operand" "")
2096	(subreg:V4SF (match_dup 6) 0))]
2097  "TARGET_VX"
2098{
2099  rtx constv, perm[16];
2100  int i;
2101
2102  for (i = 0; i < 4; ++i)
2103    {
2104      perm[i] = GEN_INT (i);
2105      perm[i + 4] = GEN_INT (i + 8);
2106      perm[i + 8] = GEN_INT (i + 16);
2107      perm[i + 12] = GEN_INT (i + 24);
2108    }
2109  constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm));
2110
2111  operands[3] = gen_reg_rtx (V4SFmode);
2112  operands[4] = gen_reg_rtx (V4SFmode);
2113  operands[5] = force_reg (V16QImode, constv);
2114  operands[6] = gen_reg_rtx (V16QImode);
2115})
2116
2117;
2118; BFP <-> integer conversions
2119;
2120
2121; signed integer to floating point
2122
2123; op2: inexact exception not suppressed (IEEE 754 2008)
2124; op3: according to current rounding mode
2125; vcdgb, vcefb
2126(define_insn "float<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
2127  [(set (match_operand:VX_VEC_CONV_BFP                        0 "register_operand" "=v")
2128	(float:VX_VEC_CONV_BFP (match_operand:VX_VEC_CONV_INT 1 "register_operand"  "v")))]
2129  "TARGET_VX
2130   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2131  "vc<VX_VEC_CONV_BFP:xde><VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
2132  [(set_attr "op_type" "VRR")])
2133
2134; unsigned integer to floating point
2135
2136; op2: inexact exception not suppressed (IEEE 754 2008)
2137; op3: according to current rounding mode
2138; vcdlgb, vcelfb
2139(define_insn "floatuns<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
2140  [(set (match_operand:VX_VEC_CONV_BFP                                 0 "register_operand" "=v")
2141	(unsigned_float:VX_VEC_CONV_BFP (match_operand:VX_VEC_CONV_INT 1 "register_operand"  "v")))]
2142  "TARGET_VX
2143   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2144  "vc<VX_VEC_CONV_BFP:xde>l<VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
2145  [(set_attr "op_type" "VRR")])
2146
2147; floating point to signed integer
2148
2149; op2: inexact exception not suppressed (IEEE 754 2008)
2150; op3: rounding mode 5 (round towards 0 C11 6.3.1.4)
2151; vcgdb, vcfeb
2152(define_insn "fix_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
2153  [(set (match_operand:VX_VEC_CONV_INT                      0 "register_operand" "=v")
2154	(fix:VX_VEC_CONV_INT (match_operand:VX_VEC_CONV_BFP 1 "register_operand"  "v")))]
2155  "TARGET_VX
2156   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2157  "vc<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
2158  [(set_attr "op_type" "VRR")])
2159
2160; floating point to unsigned integer
2161
2162; op2: inexact exception not suppressed (IEEE 754 2008)
2163; op3: rounding mode 5 (round towards 0 C11 6.3.1.4)
2164; vclgdb, vclfeb
2165(define_insn "fixuns_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
2166  [(set (match_operand:VX_VEC_CONV_INT                               0 "register_operand" "=v")
2167	(unsigned_fix:VX_VEC_CONV_INT (match_operand:VX_VEC_CONV_BFP 1 "register_operand"  "v")))]
2168  "TARGET_VX
2169   && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
2170  "vcl<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
2171  [(set_attr "op_type" "VRR")])
2172
2173;
2174; Vector byte swap patterns
2175;
2176
2177; FIXME: The bswap rtl standard name currently does not appear to be
2178; used for vector modes.
2179(define_expand "bswap<mode>"
2180  [(parallel
2181    [(set (match_operand:VT_HW_HSDT                   0 "nonimmediate_operand" "")
2182	  (bswap:VT_HW_HSDT (match_operand:VT_HW_HSDT 1 "nonimmediate_operand" "")))
2183     (use (match_dup 2))])]
2184  "TARGET_VX"
2185{
2186  static char p[4][16] =
2187    { { 1,  0,  3,  2,  5,  4,  7, 6, 9,  8,  11, 10, 13, 12, 15, 14 },   /* H */
2188      { 3,  2,  1,  0,  7,  6,  5, 4, 11, 10, 9,  8,  15, 14, 13, 12 },   /* S */
2189      { 7,  6,  5,  4,  3,  2,  1, 0, 15, 14, 13, 12, 11, 10, 9,  8  },   /* D */
2190      { 15, 14, 13, 12, 11, 10, 9, 8, 7,  6,  5,  4,  3,  2,  1,  0  } }; /* T */
2191  char *perm;
2192  rtx perm_rtx[16];
2193
2194  switch (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)))
2195    {
2196    case 2: perm = p[0]; break;
2197    case 4: perm = p[1]; break;
2198    case 8: perm = p[2]; break;
2199    case 16: perm = p[3]; break;
2200    default: gcc_unreachable ();
2201    }
2202  for (int i = 0; i < 16; i++)
2203    perm_rtx[i] = GEN_INT (perm[i]);
2204
2205  operands[2] = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm_rtx));
2206
2207  /* Without vxe2 we do not have byte swap instructions dealing
2208     directly with memory operands.  So instead of waiting until
2209     reload to fix that up switch over to vector permute right
2210     now.  */
2211  if (!TARGET_VXE2)
2212    {
2213      rtx in = force_reg (V16QImode, simplify_gen_subreg (V16QImode, operands[1], <MODE>mode, 0));
2214      rtx permute = force_reg (V16QImode, force_const_mem (V16QImode, operands[2]));
2215      rtx out = gen_reg_rtx (V16QImode);
2216
2217      emit_insn (gen_vec_permv16qi (out, in, in, permute));
2218      emit_move_insn (operands[0], simplify_gen_subreg (<MODE>mode, out, V16QImode, 0));
2219      DONE;
2220    }
2221})
2222
2223; Switching late to the reg-reg variant requires the vector permute
2224; pattern to be pushed into literal pool and allocating a vector
2225; register to load it into.  We rely on both being provided by LRA
2226; when fixing up the v constraint for operand 2.
2227
2228; permute_pattern_operand: general_operand would reject the permute
2229; pattern constants since these are not accepted by
2230; s390_legimitate_constant_p
2231
2232; ^R: Prevent these alternatives from being chosen if it would require
2233; pushing the operand into memory first
2234
2235; vlbrh, vlbrf, vlbrg, vlbrq, vstbrh, vstbrf, vstbrg, vstbrq
2236(define_insn_and_split "*bswap<mode>"
2237  [(set (match_operand:VT_HW_HSDT                   0 "nonimmediate_operand"    "=v, v,^R")
2238	(bswap:VT_HW_HSDT (match_operand:VT_HW_HSDT 1 "nonimmediate_operand"     "v,^R, v")))
2239   (use (match_operand:V16QI                        2 "permute_pattern_operand"  "v, X, X"))]
2240  "TARGET_VXE2"
2241  "@
2242   #
2243   vlbr<bhfgq>\t%v0,%v1
2244   vstbr<bhfgq>\t%v1,%v0"
2245  "&& reload_completed
2246   && !memory_operand (operands[0], <MODE>mode)
2247   && !memory_operand (operands[1], <MODE>mode)"
2248  [(set (match_dup 0)
2249	(subreg:VT_HW_HSDT
2250	 (unspec:V16QI [(subreg:V16QI (match_dup 1) 0)
2251			(subreg:V16QI (match_dup 1) 0)
2252			(match_dup 2)]
2253		       UNSPEC_VEC_PERM) 0))]
2254  ""
2255  [(set_attr "op_type"      "*,VRX,VRX")])
2256
2257; reduc_smin
2258; reduc_smax
2259; reduc_umin
2260; reduc_umax
2261
2262; vec_pack_sfix_trunc: convert + pack ?
2263; vec_pack_ufix_trunc
2264; vec_unpacks_float_hi
2265; vec_unpacks_float_lo
2266; vec_unpacku_float_hi
2267; vec_unpacku_float_lo
2268