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