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