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