111
|
1 ;;- Instruction patterns for the System z vector facility
|
145
|
2 ;; Copyright (C) 2015-2020 Free Software Foundation, Inc.
|
111
|
3 ;; Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
|
|
4
|
|
5 ;; This file is part of GCC.
|
|
6
|
|
7 ;; GCC is free software; you can redistribute it and/or modify it under
|
|
8 ;; the terms of the GNU General Public License as published by the Free
|
|
9 ;; Software Foundation; either version 3, or (at your option) any later
|
|
10 ;; version.
|
|
11
|
|
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
13 ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
14 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
15 ;; for more details.
|
|
16
|
|
17 ;; You should have received a copy of the GNU General Public License
|
|
18 ;; along with GCC; see the file COPYING3. If not see
|
|
19 ;; <http://www.gnu.org/licenses/>.
|
|
20
|
|
21 ; All vector modes supported in a vector register
|
|
22 (define_mode_iterator V
|
|
23 [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF
|
|
24 V2SF V4SF V1DF V2DF])
|
|
25 (define_mode_iterator VT
|
|
26 [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF
|
|
27 V2SF V4SF V1DF V2DF V1TF V1TI TI])
|
|
28
|
|
29 ; All modes directly supported by the hardware having full vector reg size
|
|
30 ; V_HW2 is duplicate of V_HW for having two iterators expanding
|
|
31 ; independently e.g. vcond
|
145
|
32 (define_mode_iterator V_HW [V16QI V8HI V4SI V2DI (V1TI "TARGET_VXE") V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
|
111
|
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])
|
145
|
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])
|
111
|
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
|
145
|
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
|
111
|
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
|
145
|
203 vl\t%v0,%1%A1
|
|
204 vst\t%v1,%0%A0
|
111
|
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>"
|
145
|
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"
|
111
|
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
|
145
|
314 llc\t%0,%1
|
111
|
315 stc\t%1,%0
|
|
316 stcy\t%1,%0"
|
145
|
317 [(set_attr "op_type" "VRR,VRS,VRS,VRX,VRX,VRI,VRI,VRI,VRI,RR,SI,SIY,SI,SIY,RI,RI,RXY,RX,RXY")])
|
111
|
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
|
145
|
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
|
111
|
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
|
145
|
574 vl\t%v0,%1%A1
|
|
575 vst\t%v1,%0%A0
|
111
|
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
|
145
|
586 vl\t%v0,%1%A1
|
|
587 vst\t%v1,%0%A0
|
111
|
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
|
145
|
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_Z14;
|
|
626 default:
|
|
627 return true;
|
|
628 }
|
|
629 })
|
|
630
|
111
|
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
|
145
|
634 (match_operator 3 "vcond_comparison_operator"
|
111
|
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
|
145
|
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
|
111
|
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 [(subreg:V16QI (match_operand:V8HI 1 "register_operand" "v") 0)]
|
|
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[2] = gen_reg_rtx (V16QImode);
|
|
907 operands[3] = gen_reg_rtx (V16QImode);
|
|
908 operands[4] = gen_reg_rtx (V16QImode);
|
|
909 operands[5] = CONST0_RTX (V16QImode);
|
|
910 })
|
|
911
|
|
912 (define_expand "popcountv4si2_vx"
|
|
913 [(set (match_dup 2)
|
|
914 (unspec:V16QI [(subreg:V16QI (match_operand:V4SI 1 "register_operand" "v") 0)]
|
|
915 UNSPEC_POPCNT))
|
|
916 (set (match_operand:V4SI 0 "register_operand" "=v")
|
|
917 (unspec:V4SI [(match_dup 2) (match_dup 3)]
|
|
918 UNSPEC_VEC_VSUM))]
|
|
919 "TARGET_VX && !TARGET_VXE"
|
|
920 {
|
|
921 operands[2] = gen_reg_rtx (V16QImode);
|
|
922 operands[3] = force_reg (V16QImode, CONST0_RTX (V16QImode));
|
|
923 })
|
|
924
|
|
925 (define_expand "popcountv2di2_vx"
|
|
926 [(set (match_dup 2)
|
|
927 (unspec:V16QI [(subreg:V16QI (match_operand:V2DI 1 "register_operand" "v") 0)]
|
|
928 UNSPEC_POPCNT))
|
|
929 (set (match_dup 3)
|
|
930 (unspec:V4SI [(match_dup 2) (match_dup 4)]
|
|
931 UNSPEC_VEC_VSUM))
|
|
932 (set (match_operand:V2DI 0 "register_operand" "=v")
|
|
933 (unspec:V2DI [(match_dup 3) (match_dup 5)]
|
|
934 UNSPEC_VEC_VSUMG))]
|
|
935 "TARGET_VX && !TARGET_VXE"
|
|
936 {
|
|
937 operands[2] = gen_reg_rtx (V16QImode);
|
|
938 operands[3] = gen_reg_rtx (V4SImode);
|
|
939 operands[4] = force_reg (V16QImode, CONST0_RTX (V16QImode));
|
|
940 operands[5] = force_reg (V4SImode, CONST0_RTX (V4SImode));
|
|
941 })
|
|
942
|
|
943 ; Count leading zeros
|
|
944 ; vclzb, vclzh, vclzf, vclzg
|
|
945 (define_insn "clz<mode>2"
|
|
946 [(set (match_operand:V 0 "register_operand" "=v")
|
|
947 (clz:V (match_operand:V 1 "register_operand" "v")))]
|
|
948 "TARGET_VX"
|
|
949 "vclz<bhfgq>\t%v0,%v1"
|
|
950 [(set_attr "op_type" "VRR")])
|
|
951
|
|
952 ; Count trailing zeros
|
|
953 ; vctzb, vctzh, vctzf, vctzg
|
|
954 (define_insn "ctz<mode>2"
|
|
955 [(set (match_operand:V 0 "register_operand" "=v")
|
|
956 (ctz:V (match_operand:V 1 "register_operand" "v")))]
|
|
957 "TARGET_VX"
|
|
958 "vctz<bhfgq>\t%v0,%v1"
|
|
959 [(set_attr "op_type" "VRR")])
|
|
960
|
|
961
|
|
962
|
|
963 ; Each vector element rotated by the corresponding vector element
|
|
964 ; verllvb, verllvh, verllvf, verllvg
|
|
965 (define_insn "vrotl<mode>3"
|
|
966 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
967 (rotate:VI (match_operand:VI 1 "register_operand" "v")
|
|
968 (match_operand:VI 2 "register_operand" "v")))]
|
|
969 "TARGET_VX"
|
|
970 "verllv<bhfgq>\t%v0,%v1,%v2"
|
|
971 [(set_attr "op_type" "VRR")])
|
|
972
|
|
973
|
|
974 ; Vector rotate and shift by scalar instructions
|
|
975
|
|
976 (define_code_iterator VEC_SHIFTS [ashift ashiftrt lshiftrt rotate])
|
|
977 (define_code_attr vec_shifts_name [(ashift "ashl") (ashiftrt "ashr")
|
|
978 (lshiftrt "lshr") (rotate "rotl")])
|
|
979 (define_code_attr vec_shifts_mnem [(ashift "vesl") (ashiftrt "vesra")
|
|
980 (lshiftrt "vesrl") (rotate "verll")])
|
|
981
|
|
982 ; Each vector element rotated by a scalar
|
|
983 (define_expand "<vec_shifts_name><mode>3"
|
|
984 [(set (match_operand:VI 0 "register_operand" "")
|
|
985 (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "")
|
145
|
986 (match_operand:QI 2 "shift_count_operand" "")))]
|
111
|
987 "TARGET_VX")
|
|
988
|
|
989 ; verllb, verllh, verllf, verllg
|
|
990 ; veslb, veslh, veslf, veslg
|
|
991 ; vesrab, vesrah, vesraf, vesrag
|
|
992 ; vesrlb, vesrlh, vesrlf, vesrlg
|
145
|
993 (define_insn "*<vec_shifts_name><mode>3"
|
111
|
994 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
995 (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "v")
|
145
|
996 (match_operand:QI 2 "shift_count_operand_vec" "jsc")))]
|
|
997 "TARGET_VX
|
|
998 && s390_valid_shift_count (operands[2],
|
|
999 GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) - 1)
|
|
1000 "
|
111
|
1001 "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2"
|
|
1002 [(set_attr "op_type" "VRS")])
|
|
1003
|
145
|
1004
|
111
|
1005 ; Shift each element by corresponding vector element
|
|
1006
|
|
1007 ; veslvb, veslvh, veslvf, veslvg
|
|
1008 (define_insn "vashl<mode>3"
|
|
1009 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
1010 (ashift:VI (match_operand:VI 1 "register_operand" "v")
|
|
1011 (match_operand:VI 2 "register_operand" "v")))]
|
|
1012 "TARGET_VX"
|
|
1013 "veslv<bhfgq>\t%v0,%v1,%v2"
|
|
1014 [(set_attr "op_type" "VRR")])
|
|
1015
|
|
1016 ; vesravb, vesravh, vesravf, vesravg
|
|
1017 (define_insn "vashr<mode>3"
|
|
1018 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
1019 (ashiftrt:VI (match_operand:VI 1 "register_operand" "v")
|
|
1020 (match_operand:VI 2 "register_operand" "v")))]
|
|
1021 "TARGET_VX"
|
|
1022 "vesrav<bhfgq>\t%v0,%v1,%v2"
|
|
1023 [(set_attr "op_type" "VRR")])
|
|
1024
|
|
1025 ; vesrlvb, vesrlvh, vesrlvf, vesrlvg
|
|
1026 (define_insn "vlshr<mode>3"
|
|
1027 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
1028 (lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
|
|
1029 (match_operand:VI 2 "register_operand" "v")))]
|
|
1030 "TARGET_VX"
|
|
1031 "vesrlv<bhfgq>\t%v0,%v1,%v2"
|
|
1032 [(set_attr "op_type" "VRR")])
|
|
1033
|
|
1034 ; Vector shift right logical by byte
|
|
1035
|
|
1036 ; Pattern used by e.g. popcount
|
|
1037 (define_insn "*vec_srb<mode>"
|
|
1038 [(set (match_operand:V_128 0 "register_operand" "=v")
|
|
1039 (unspec:V_128 [(match_operand:V_128 1 "register_operand" "v")
|
|
1040 (match_operand:V16QI 2 "register_operand" "v")]
|
|
1041 UNSPEC_VEC_SRLB))]
|
|
1042 "TARGET_VX"
|
|
1043 "vsrlb\t%v0,%v1,%v2"
|
|
1044 [(set_attr "op_type" "VRR")])
|
|
1045
|
|
1046
|
|
1047 ; Vector shift left by byte
|
|
1048
|
|
1049 (define_insn "*vec_slb<mode>"
|
|
1050 [(set (match_operand:V_128 0 "register_operand" "=v")
|
|
1051 (unspec:V_128 [(match_operand:V_128 1 "register_operand" "v")
|
|
1052 (match_operand:V16QI 2 "register_operand" "v")]
|
|
1053 UNSPEC_VEC_SLB))]
|
|
1054 "TARGET_VX"
|
|
1055 "vslb\t%v0,%v1,%v2"
|
|
1056 [(set_attr "op_type" "VRR")])
|
|
1057
|
|
1058 ; vec_shr is defined as shift towards element 0
|
|
1059 ; this means it is a left shift on BE targets!
|
|
1060 (define_expand "vec_shr_<mode>"
|
|
1061 [(set (match_dup 3)
|
|
1062 (unspec:V16QI [(match_operand:SI 2 "const_shift_by_byte_operand" "")
|
|
1063 (const_int 7)
|
|
1064 (match_dup 3)]
|
|
1065 UNSPEC_VEC_SET))
|
|
1066 (set (match_operand:V_128 0 "register_operand" "")
|
|
1067 (unspec:V_128 [(match_operand:V_128 1 "register_operand" "")
|
|
1068 (match_dup 3)]
|
|
1069 UNSPEC_VEC_SLB))]
|
|
1070 "TARGET_VX"
|
|
1071 {
|
|
1072 operands[3] = gen_reg_rtx(V16QImode);
|
|
1073 })
|
|
1074
|
|
1075 ; vmnb, vmnh, vmnf, vmng
|
|
1076 (define_insn "smin<mode>3"
|
|
1077 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
1078 (smin:VI (match_operand:VI 1 "register_operand" "%v")
|
|
1079 (match_operand:VI 2 "register_operand" "v")))]
|
|
1080 "TARGET_VX"
|
|
1081 "vmn<bhfgq>\t%v0,%v1,%v2"
|
|
1082 [(set_attr "op_type" "VRR")])
|
|
1083
|
|
1084 ; vmxb, vmxh, vmxf, vmxg
|
|
1085 (define_insn "smax<mode>3"
|
|
1086 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
1087 (smax:VI (match_operand:VI 1 "register_operand" "%v")
|
|
1088 (match_operand:VI 2 "register_operand" "v")))]
|
|
1089 "TARGET_VX"
|
|
1090 "vmx<bhfgq>\t%v0,%v1,%v2"
|
|
1091 [(set_attr "op_type" "VRR")])
|
|
1092
|
|
1093 ; vmnlb, vmnlh, vmnlf, vmnlg
|
|
1094 (define_insn "umin<mode>3"
|
|
1095 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
1096 (umin:VI (match_operand:VI 1 "register_operand" "%v")
|
|
1097 (match_operand:VI 2 "register_operand" "v")))]
|
|
1098 "TARGET_VX"
|
|
1099 "vmnl<bhfgq>\t%v0,%v1,%v2"
|
|
1100 [(set_attr "op_type" "VRR")])
|
|
1101
|
|
1102 ; vmxlb, vmxlh, vmxlf, vmxlg
|
|
1103 (define_insn "umax<mode>3"
|
|
1104 [(set (match_operand:VI 0 "register_operand" "=v")
|
|
1105 (umax:VI (match_operand:VI 1 "register_operand" "%v")
|
|
1106 (match_operand:VI 2 "register_operand" "v")))]
|
|
1107 "TARGET_VX"
|
|
1108 "vmxl<bhfgq>\t%v0,%v1,%v2"
|
|
1109 [(set_attr "op_type" "VRR")])
|
|
1110
|
|
1111 ; vmeb, vmeh, vmef
|
|
1112 (define_insn "vec_widen_smult_even_<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_EVEN))]
|
|
1117 "TARGET_VX"
|
|
1118 "vme<bhfgq>\t%v0,%v1,%v2"
|
|
1119 [(set_attr "op_type" "VRR")])
|
|
1120
|
|
1121 ; vmleb, vmleh, vmlef
|
|
1122 (define_insn "vec_widen_umult_even_<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_EVEN))]
|
|
1127 "TARGET_VX"
|
|
1128 "vmle<bhfgq>\t%v0,%v1,%v2"
|
|
1129 [(set_attr "op_type" "VRR")])
|
|
1130
|
|
1131 ; vmob, vmoh, vmof
|
|
1132 (define_insn "vec_widen_smult_odd_<mode>"
|
|
1133 [(set (match_operand:<vec_double> 0 "register_operand" "=v")
|
|
1134 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
|
|
1135 (match_operand:VI_QHS 2 "register_operand" "v")]
|
|
1136 UNSPEC_VEC_SMULT_ODD))]
|
|
1137 "TARGET_VX"
|
|
1138 "vmo<bhfgq>\t%v0,%v1,%v2"
|
|
1139 [(set_attr "op_type" "VRR")])
|
|
1140
|
|
1141 ; vmlob, vmloh, vmlof
|
|
1142 (define_insn "vec_widen_umult_odd_<mode>"
|
|
1143 [(set (match_operand:<vec_double> 0 "register_operand" "=v")
|
|
1144 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
|
|
1145 (match_operand:VI_QHS 2 "register_operand" "v")]
|
|
1146 UNSPEC_VEC_UMULT_ODD))]
|
|
1147 "TARGET_VX"
|
|
1148 "vmlo<bhfgq>\t%v0,%v1,%v2"
|
|
1149 [(set_attr "op_type" "VRR")])
|
|
1150
|
|
1151
|
|
1152 ; Widening hi/lo multiplications
|
|
1153
|
|
1154 ; The S/390 instructions vml and vmh return the low or high parts of
|
|
1155 ; the double sized result elements in the corresponding elements of
|
|
1156 ; the target register. That's NOT what the vec_widen_umult_lo/hi
|
|
1157 ; patterns are expected to do.
|
|
1158
|
|
1159 ; We emulate the widening lo/hi multiplies with the even/odd versions
|
|
1160 ; followed by a vector merge
|
|
1161
|
|
1162
|
|
1163 (define_expand "vec_widen_umult_lo_<mode>"
|
|
1164 [(set (match_dup 3)
|
|
1165 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
|
|
1166 (match_operand:VI_QHS 2 "register_operand" "v")]
|
|
1167 UNSPEC_VEC_UMULT_EVEN))
|
|
1168 (set (match_dup 4)
|
|
1169 (unspec:<vec_double> [(match_dup 1) (match_dup 2)]
|
|
1170 UNSPEC_VEC_UMULT_ODD))
|
|
1171 (set (match_operand:<vec_double> 0 "register_operand" "=v")
|
|
1172 (unspec:<vec_double> [(match_dup 3) (match_dup 4)]
|
|
1173 UNSPEC_VEC_MERGEL))]
|
|
1174 "TARGET_VX"
|
|
1175 {
|
|
1176 operands[3] = gen_reg_rtx (<vec_double>mode);
|
|
1177 operands[4] = gen_reg_rtx (<vec_double>mode);
|
|
1178 })
|
|
1179
|
|
1180 (define_expand "vec_widen_umult_hi_<mode>"
|
|
1181 [(set (match_dup 3)
|
|
1182 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
|
|
1183 (match_operand:VI_QHS 2 "register_operand" "v")]
|
|
1184 UNSPEC_VEC_UMULT_EVEN))
|
|
1185 (set (match_dup 4)
|
|
1186 (unspec:<vec_double> [(match_dup 1) (match_dup 2)]
|
|
1187 UNSPEC_VEC_UMULT_ODD))
|
|
1188 (set (match_operand:<vec_double> 0 "register_operand" "=v")
|
|
1189 (unspec:<vec_double> [(match_dup 3) (match_dup 4)]
|
|
1190 UNSPEC_VEC_MERGEH))]
|
|
1191 "TARGET_VX"
|
|
1192 {
|
|
1193 operands[3] = gen_reg_rtx (<vec_double>mode);
|
|
1194 operands[4] = gen_reg_rtx (<vec_double>mode);
|
|
1195 })
|
|
1196
|
|
1197 (define_expand "vec_widen_smult_lo_<mode>"
|
|
1198 [(set (match_dup 3)
|
|
1199 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
|
|
1200 (match_operand:VI_QHS 2 "register_operand" "v")]
|
|
1201 UNSPEC_VEC_SMULT_EVEN))
|
|
1202 (set (match_dup 4)
|
|
1203 (unspec:<vec_double> [(match_dup 1) (match_dup 2)]
|
|
1204 UNSPEC_VEC_SMULT_ODD))
|
|
1205 (set (match_operand:<vec_double> 0 "register_operand" "=v")
|
|
1206 (unspec:<vec_double> [(match_dup 3) (match_dup 4)]
|
|
1207 UNSPEC_VEC_MERGEL))]
|
|
1208 "TARGET_VX"
|
|
1209 {
|
|
1210 operands[3] = gen_reg_rtx (<vec_double>mode);
|
|
1211 operands[4] = gen_reg_rtx (<vec_double>mode);
|
|
1212 })
|
|
1213
|
|
1214 (define_expand "vec_widen_smult_hi_<mode>"
|
|
1215 [(set (match_dup 3)
|
|
1216 (unspec:<vec_double> [(match_operand:VI_QHS 1 "register_operand" "%v")
|
|
1217 (match_operand:VI_QHS 2 "register_operand" "v")]
|
|
1218 UNSPEC_VEC_SMULT_EVEN))
|
|
1219 (set (match_dup 4)
|
|
1220 (unspec:<vec_double> [(match_dup 1) (match_dup 2)]
|
|
1221 UNSPEC_VEC_SMULT_ODD))
|
|
1222 (set (match_operand:<vec_double> 0 "register_operand" "=v")
|
|
1223 (unspec:<vec_double> [(match_dup 3) (match_dup 4)]
|
|
1224 UNSPEC_VEC_MERGEH))]
|
|
1225 "TARGET_VX"
|
|
1226 {
|
|
1227 operands[3] = gen_reg_rtx (<vec_double>mode);
|
|
1228 operands[4] = gen_reg_rtx (<vec_double>mode);
|
|
1229 })
|
|
1230
|
|
1231 ; vec_widen_ushiftl_hi
|
|
1232 ; vec_widen_ushiftl_lo
|
|
1233 ; vec_widen_sshiftl_hi
|
|
1234 ; vec_widen_sshiftl_lo
|
|
1235
|
|
1236 ;;
|
|
1237 ;; Vector floating point arithmetic instructions
|
|
1238 ;;
|
|
1239
|
|
1240 ; vfasb, vfadb, wfasb, wfadb, wfaxb
|
|
1241 (define_insn "add<mode>3"
|
|
1242 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1243 (plus:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1244 (match_operand:VF_HW 2 "register_operand" "v")))]
|
|
1245 "TARGET_VX"
|
|
1246 "<vw>fa<sdx>b\t%v0,%v1,%v2"
|
|
1247 [(set_attr "op_type" "VRR")])
|
|
1248
|
|
1249 ; vfssb, vfsdb, wfssb, wfsdb, wfsxb
|
|
1250 (define_insn "sub<mode>3"
|
|
1251 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1252 (minus:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1253 (match_operand:VF_HW 2 "register_operand" "v")))]
|
|
1254 "TARGET_VX"
|
|
1255 "<vw>fs<sdx>b\t%v0,%v1,%v2"
|
|
1256 [(set_attr "op_type" "VRR")])
|
|
1257
|
|
1258 ; vfmsb, vfmdb, wfmsb, wfmdb, wfmxb
|
|
1259 (define_insn "mul<mode>3"
|
|
1260 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1261 (mult:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1262 (match_operand:VF_HW 2 "register_operand" "v")))]
|
|
1263 "TARGET_VX"
|
|
1264 "<vw>fm<sdx>b\t%v0,%v1,%v2"
|
|
1265 [(set_attr "op_type" "VRR")])
|
|
1266
|
|
1267 ; vfdsb, vfddb, wfdsb, wfddb, wfdxb
|
|
1268 (define_insn "div<mode>3"
|
|
1269 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1270 (div:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
|
|
1271 (match_operand:VF_HW 2 "register_operand" "v")))]
|
|
1272 "TARGET_VX"
|
|
1273 "<vw>fd<sdx>b\t%v0,%v1,%v2"
|
|
1274 [(set_attr "op_type" "VRR")])
|
|
1275
|
|
1276 ; vfsqsb, vfsqdb, wfsqsb, wfsqdb, wfsqxb
|
|
1277 (define_insn "sqrt<mode>2"
|
|
1278 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1279 (sqrt:VF_HW (match_operand:VF_HW 1 "register_operand" "v")))]
|
|
1280 "TARGET_VX"
|
|
1281 "<vw>fsq<sdx>b\t%v0,%v1"
|
|
1282 [(set_attr "op_type" "VRR")])
|
|
1283
|
|
1284 ; vfmasb, vfmadb, wfmasb, wfmadb, wfmaxb
|
|
1285 (define_insn "fma<mode>4"
|
|
1286 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1287 (fma:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1288 (match_operand:VF_HW 2 "register_operand" "v")
|
|
1289 (match_operand:VF_HW 3 "register_operand" "v")))]
|
|
1290 "TARGET_VX"
|
|
1291 "<vw>fma<sdx>b\t%v0,%v1,%v2,%v3"
|
|
1292 [(set_attr "op_type" "VRR")])
|
|
1293
|
|
1294 ; vfmssb, vfmsdb, wfmssb, wfmsdb, wfmsxb
|
|
1295 (define_insn "fms<mode>4"
|
|
1296 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1297 (fma:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1298 (match_operand:VF_HW 2 "register_operand" "v")
|
|
1299 (neg:VF_HW (match_operand:VF_HW 3 "register_operand" "v"))))]
|
|
1300 "TARGET_VX"
|
|
1301 "<vw>fms<sdx>b\t%v0,%v1,%v2,%v3"
|
|
1302 [(set_attr "op_type" "VRR")])
|
|
1303
|
|
1304 ; vfnmasb, vfnmadb, wfnmasb, wfnmadb, wfnmaxb
|
|
1305 (define_insn "neg_fma<mode>4"
|
|
1306 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1307 (neg:VF_HW
|
|
1308 (fma:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1309 (match_operand:VF_HW 2 "register_operand" "v")
|
|
1310 (match_operand:VF_HW 3 "register_operand" "v"))))]
|
|
1311 "TARGET_VXE"
|
|
1312 "<vw>fnma<sdx>b\t%v0,%v1,%v2,%v3"
|
|
1313 [(set_attr "op_type" "VRR")])
|
|
1314
|
|
1315 ; vfnmssb, vfnmsdb, wfnmssb, wfnmsdb, wfnmsxb
|
|
1316 (define_insn "neg_fms<mode>4"
|
|
1317 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1318 (neg:VF_HW
|
|
1319 (fma:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1320 (match_operand:VF_HW 2 "register_operand" "v")
|
|
1321 (neg:VF_HW (match_operand:VF_HW 3 "register_operand" "v")))))]
|
|
1322 "TARGET_VXE"
|
|
1323 "<vw>fnms<sdx>b\t%v0,%v1,%v2,%v3"
|
|
1324 [(set_attr "op_type" "VRR")])
|
|
1325
|
|
1326 ; vflcsb, vflcdb, wflcsb, wflcdb, wflcxb
|
|
1327 (define_insn "neg<mode>2"
|
|
1328 [(set (match_operand:VFT 0 "register_operand" "=v")
|
|
1329 (neg:VFT (match_operand:VFT 1 "register_operand" "v")))]
|
|
1330 "TARGET_VX"
|
|
1331 "<vw>flc<sdx>b\t%v0,%v1"
|
|
1332 [(set_attr "op_type" "VRR")])
|
|
1333
|
|
1334 ; vflpsb, vflpdb, wflpsb, wflpdb, wflpxb
|
|
1335 (define_insn "abs<mode>2"
|
|
1336 [(set (match_operand:VFT 0 "register_operand" "=v")
|
|
1337 (abs:VFT (match_operand:VFT 1 "register_operand" "v")))]
|
|
1338 "TARGET_VX"
|
|
1339 "<vw>flp<sdx>b\t%v0,%v1"
|
|
1340 [(set_attr "op_type" "VRR")])
|
|
1341
|
|
1342 ; vflnsb, vflndb, wflnsb, wflndb, wflnxb
|
|
1343 (define_insn "negabs<mode>2"
|
|
1344 [(set (match_operand:VFT 0 "register_operand" "=v")
|
|
1345 (neg:VFT (abs:VFT (match_operand:VFT 1 "register_operand" "v"))))]
|
|
1346 "TARGET_VX"
|
|
1347 "<vw>fln<sdx>b\t%v0,%v1"
|
|
1348 [(set_attr "op_type" "VRR")])
|
|
1349
|
|
1350 (define_expand "smax<mode>3"
|
|
1351 [(set (match_operand:VF_HW 0 "register_operand")
|
|
1352 (smax:VF_HW (match_operand:VF_HW 1 "register_operand")
|
|
1353 (match_operand:VF_HW 2 "register_operand")))]
|
|
1354 "TARGET_VX")
|
|
1355
|
|
1356 ; vfmaxsb, vfmaxdb, wfmaxsb, wfmaxdb, wfmaxxb
|
|
1357 (define_insn "*smax<mode>3_vxe"
|
|
1358 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1359 (smax:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1360 (match_operand:VF_HW 2 "register_operand" "v")))]
|
|
1361 "TARGET_VXE"
|
|
1362 "<vw>fmax<sdx>b\t%v0,%v1,%v2,4"
|
|
1363 [(set_attr "op_type" "VRR")])
|
|
1364
|
|
1365 ; Emulate with compare + select
|
|
1366 (define_insn_and_split "*smaxv2df3_vx"
|
|
1367 [(set (match_operand:V2DF 0 "register_operand" "=v")
|
|
1368 (smax:V2DF (match_operand:V2DF 1 "register_operand" "%v")
|
|
1369 (match_operand:V2DF 2 "register_operand" "v")))]
|
|
1370 "TARGET_VX && !TARGET_VXE"
|
|
1371 "#"
|
|
1372 "&& 1"
|
|
1373 [(set (match_dup 3)
|
145
|
1374 (not:V2DI
|
|
1375 (unge:V2DI (match_dup 2) (match_dup 1))))
|
111
|
1376 (set (match_dup 0)
|
|
1377 (if_then_else:V2DF
|
|
1378 (eq (match_dup 3) (match_dup 4))
|
|
1379 (match_dup 2)
|
|
1380 (match_dup 1)))]
|
|
1381 {
|
|
1382 operands[3] = gen_reg_rtx (V2DImode);
|
|
1383 operands[4] = CONST0_RTX (V2DImode);
|
|
1384 })
|
|
1385
|
|
1386 (define_expand "smin<mode>3"
|
|
1387 [(set (match_operand:VF_HW 0 "register_operand")
|
|
1388 (smin:VF_HW (match_operand:VF_HW 1 "register_operand")
|
|
1389 (match_operand:VF_HW 2 "register_operand")))]
|
|
1390 "TARGET_VX")
|
|
1391
|
|
1392 ; vfminsb, vfmindb, wfminsb, wfmindb, wfminxb
|
|
1393 (define_insn "*smin<mode>3_vxe"
|
|
1394 [(set (match_operand:VF_HW 0 "register_operand" "=v")
|
|
1395 (smin:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
|
|
1396 (match_operand:VF_HW 2 "register_operand" "v")))]
|
|
1397 "TARGET_VXE"
|
|
1398 "<vw>fmin<sdx>b\t%v0,%v1,%v2,4"
|
|
1399 [(set_attr "op_type" "VRR")])
|
|
1400
|
|
1401 ; Emulate with compare + select
|
|
1402 (define_insn_and_split "*sminv2df3_vx"
|
|
1403 [(set (match_operand:V2DF 0 "register_operand" "=v")
|
|
1404 (smin:V2DF (match_operand:V2DF 1 "register_operand" "%v")
|
|
1405 (match_operand:V2DF 2 "register_operand" "v")))]
|
|
1406 "TARGET_VX && !TARGET_VXE"
|
|
1407 "#"
|
|
1408 "&& 1"
|
|
1409 [(set (match_dup 3)
|
145
|
1410 (not:V2DI
|
|
1411 (unge:V2DI (match_dup 2) (match_dup 1))))
|
111
|
1412 (set (match_dup 0)
|
|
1413 (if_then_else:V2DF
|
|
1414 (eq (match_dup 3) (match_dup 4))
|
|
1415 (match_dup 1)
|
|
1416 (match_dup 2)))]
|
|
1417 {
|
|
1418 operands[3] = gen_reg_rtx (V2DImode);
|
|
1419 operands[4] = CONST0_RTX (V2DImode);
|
|
1420 })
|
|
1421
|
145
|
1422 ; Vector copysign, implement using vector select
|
|
1423 (define_expand "copysign<mode>3"
|
|
1424 [(set (match_operand:VFT 0 "register_operand" "")
|
|
1425 (if_then_else:VFT
|
|
1426 (eq (match_dup 3)
|
|
1427 (match_dup 4))
|
|
1428 (match_operand:VFT 1 "register_operand" "")
|
|
1429 (match_operand:VFT 2 "register_operand" "")))]
|
|
1430 "TARGET_VX"
|
|
1431 {
|
|
1432 int sz = GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
|
|
1433 int prec = GET_MODE_PRECISION (GET_MODE_INNER (<tointvec>mode));
|
|
1434 wide_int mask_val = wi::shwi (1l << (sz - 1), prec);
|
|
1435
|
|
1436 rtx mask = gen_reg_rtx (<tointvec>mode);
|
|
1437
|
|
1438 int nunits = GET_MODE_NUNITS (<tointvec>mode);
|
|
1439 rtvec v = rtvec_alloc (nunits);
|
|
1440 for (int i = 0; i < nunits; i++)
|
|
1441 RTVEC_ELT (v, i) = GEN_INT (mask_val.to_shwi ());
|
|
1442
|
|
1443 mask = gen_rtx_CONST_VECTOR (<tointvec>mode, v);
|
|
1444 operands[3] = force_reg (<tointvec>mode, mask);
|
|
1445 operands[4] = CONST0_RTX (<tointvec>mode);
|
|
1446 })
|
111
|
1447
|
|
1448 ;;
|
|
1449 ;; Integer compares
|
|
1450 ;;
|
|
1451
|
|
1452 (define_insn "*vec_cmp<VICMP_HW_OP:code><VI:mode>_nocc"
|
|
1453 [(set (match_operand:VI 2 "register_operand" "=v")
|
|
1454 (VICMP_HW_OP:VI (match_operand:VI 0 "register_operand" "v")
|
|
1455 (match_operand:VI 1 "register_operand" "v")))]
|
|
1456 "TARGET_VX"
|
|
1457 "vc<VICMP_HW_OP:insn_cmp_op><VI:bhfgq>\t%v2,%v0,%v1"
|
|
1458 [(set_attr "op_type" "VRR")])
|
|
1459
|
|
1460
|
|
1461 ;;
|
|
1462 ;; Floating point compares
|
|
1463 ;;
|
|
1464
|
145
|
1465 ; vfcesb, vfcedb, wfcexb: non-signaling "==" comparison (a == b)
|
|
1466 (define_insn "*vec_cmpeq<mode>_quiet_nocc"
|
|
1467 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1468 (eq:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1469 (match_operand:VFT 2 "register_operand" "v")))]
|
|
1470 "TARGET_VX"
|
|
1471 "<vw>fce<sdx>b\t%v0,%v1,%v2"
|
|
1472 [(set_attr "op_type" "VRR")])
|
|
1473
|
|
1474 ; vfchsb, vfchdb, wfchxb: non-signaling > comparison (!(b u>= a))
|
|
1475 (define_insn "vec_cmpgt<mode>_quiet_nocc"
|
|
1476 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1477 (not:<tointvec>
|
|
1478 (unge:<tointvec> (match_operand:VFT 2 "register_operand" "v")
|
|
1479 (match_operand:VFT 1 "register_operand" "v"))))]
|
|
1480 "TARGET_VX"
|
|
1481 "<vw>fch<sdx>b\t%v0,%v1,%v2"
|
|
1482 [(set_attr "op_type" "VRR")])
|
|
1483
|
|
1484 (define_expand "vec_cmplt<mode>_quiet_nocc"
|
|
1485 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1486 (not:<tointvec>
|
|
1487 (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1488 (match_operand:VFT 2 "register_operand" "v"))))]
|
|
1489 "TARGET_VX")
|
|
1490
|
|
1491 ; vfchesb, vfchedb, wfchexb: non-signaling >= comparison (!(a u< b))
|
|
1492 (define_insn "vec_cmpge<mode>_quiet_nocc"
|
|
1493 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1494 (not:<tointvec>
|
|
1495 (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1496 (match_operand:VFT 2 "register_operand" "v"))))]
|
|
1497 "TARGET_VX"
|
|
1498 "<vw>fche<sdx>b\t%v0,%v1,%v2"
|
|
1499 [(set_attr "op_type" "VRR")])
|
|
1500
|
|
1501 (define_expand "vec_cmple<mode>_quiet_nocc"
|
|
1502 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1503 (not:<tointvec>
|
|
1504 (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
|
|
1505 (match_operand:VFT 1 "register_operand" "v"))))]
|
|
1506 "TARGET_VX")
|
|
1507
|
|
1508 ; vfkesb, vfkedb, wfkexb: signaling == comparison ((a >= b) & (b >= a))
|
|
1509 (define_insn "*vec_cmpeq<mode>_signaling_nocc"
|
|
1510 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1511 (and:<tointvec>
|
|
1512 (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1513 (match_operand:VFT 2 "register_operand" "v"))
|
|
1514 (ge:<tointvec> (match_dup 2)
|
|
1515 (match_dup 1))))]
|
|
1516 "TARGET_VXE"
|
|
1517 "<vw>fke<sdx>b\t%v0,%v1,%v2"
|
|
1518 [(set_attr "op_type" "VRR")])
|
|
1519
|
|
1520 ; vfkhsb, vfkhdb, wfkhxb: signaling > comparison (a > b)
|
|
1521 (define_insn "*vec_cmpgt<mode>_signaling_nocc"
|
|
1522 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1523 (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1524 (match_operand:VFT 2 "register_operand" "v")))]
|
|
1525 "TARGET_VXE"
|
|
1526 "<vw>fkh<sdx>b\t%v0,%v1,%v2"
|
|
1527 [(set_attr "op_type" "VRR")])
|
|
1528
|
|
1529 (define_insn "*vec_cmpgt<mode>_signaling_finite_nocc"
|
|
1530 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1531 (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1532 (match_operand:VFT 2 "register_operand" "v")))]
|
|
1533 "TARGET_VX && !TARGET_VXE && flag_finite_math_only"
|
|
1534 "<vw>fch<sdx>b\t%v0,%v1,%v2"
|
|
1535 [(set_attr "op_type" "VRR")])
|
|
1536
|
|
1537 ; vfkhesb, vfkhedb, wfkhexb: signaling >= comparison (a >= b)
|
|
1538 (define_insn "*vec_cmpge<mode>_signaling_nocc"
|
|
1539 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1540 (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1541 (match_operand:VFT 2 "register_operand" "v")))]
|
|
1542 "TARGET_VXE"
|
|
1543 "<vw>fkhe<sdx>b\t%v0,%v1,%v2"
|
|
1544 [(set_attr "op_type" "VRR")])
|
|
1545
|
|
1546 (define_insn "*vec_cmpge<mode>_signaling_finite_nocc"
|
|
1547 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1548 (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1549 (match_operand:VFT 2 "register_operand" "v")))]
|
|
1550 "TARGET_VX && !TARGET_VXE && flag_finite_math_only"
|
|
1551 "<vw>fche<sdx>b\t%v0,%v1,%v2"
|
111
|
1552 [(set_attr "op_type" "VRR")])
|
|
1553
|
|
1554 ; Expanders for not directly supported comparisons
|
145
|
1555 ; Signaling comparisons must be expressed via signaling rtxes only,
|
|
1556 ; and quiet comparisons must be expressed via quiet rtxes only.
|
111
|
1557
|
145
|
1558 ; UNGT a u> b -> !!(b u< a)
|
|
1559 (define_expand "vec_cmpungt<mode>"
|
|
1560 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1561 (not:<tointvec>
|
|
1562 (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
|
|
1563 (match_operand:VFT 1 "register_operand" "v"))))
|
|
1564 (set (match_dup 0)
|
|
1565 (not:<tointvec> (match_dup 0)))]
|
|
1566 "TARGET_VX")
|
|
1567
|
|
1568 ; UNGE a u>= b -> !!(a u>= b)
|
|
1569 (define_expand "vec_cmpunge<mode>"
|
|
1570 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1571 (not:<tointvec>
|
|
1572 (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1573 (match_operand:VFT 2 "register_operand" "v"))))
|
|
1574 (set (match_dup 0)
|
|
1575 (not:<tointvec> (match_dup 0)))]
|
|
1576 "TARGET_VX")
|
|
1577
|
|
1578 ; UNEQ a u== b -> !(!(a u>= b) | !(b u>= a))
|
111
|
1579 (define_expand "vec_cmpuneq<mode>"
|
145
|
1580 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1581 (not:<tointvec>
|
|
1582 (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1583 (match_operand:VFT 2 "register_operand" "v"))))
|
|
1584 (set (match_dup 3)
|
|
1585 (not:<tointvec>
|
|
1586 (unge:<tointvec> (match_dup 2)
|
|
1587 (match_dup 1))))
|
|
1588 (set (match_dup 0)
|
|
1589 (ior:<tointvec> (match_dup 0)
|
|
1590 (match_dup 3)))
|
|
1591 (set (match_dup 0)
|
|
1592 (not:<tointvec> (match_dup 0)))]
|
111
|
1593 "TARGET_VX"
|
|
1594 {
|
|
1595 operands[3] = gen_reg_rtx (<tointvec>mode);
|
|
1596 })
|
|
1597
|
|
1598 ; LTGT a <> b -> a > b | b > a
|
|
1599 (define_expand "vec_cmpltgt<mode>"
|
|
1600 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1601 (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1602 (match_operand:VFT 2 "register_operand" "v")))
|
|
1603 (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
|
|
1604 (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
|
145
|
1605 "TARGET_VXE"
|
111
|
1606 {
|
|
1607 operands[3] = gen_reg_rtx (<tointvec>mode);
|
|
1608 })
|
|
1609
|
145
|
1610 ; ORDERED (a, b): !(a u< b) | !(a u>= b)
|
|
1611 (define_expand "vec_cmpordered<mode>"
|
|
1612 [(set (match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1613 (not:<tointvec>
|
|
1614 (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
|
|
1615 (match_operand:VFT 2 "register_operand" "v"))))
|
|
1616 (set (match_dup 3)
|
|
1617 (not:<tointvec>
|
|
1618 (unge:<tointvec> (match_dup 1)
|
|
1619 (match_dup 2))))
|
|
1620 (set (match_dup 0)
|
|
1621 (ior:<tointvec> (match_dup 0)
|
|
1622 (match_dup 3)))]
|
111
|
1623 "TARGET_VX"
|
|
1624 {
|
|
1625 operands[3] = gen_reg_rtx (<tointvec>mode);
|
|
1626 })
|
|
1627
|
145
|
1628 ; UNORDERED (a, b): !ORDERED (a, b)
|
|
1629 (define_expand "vec_cmpunordered<mode>"
|
|
1630 [(match_operand:<tointvec> 0 "register_operand" "=v")
|
|
1631 (match_operand:VFT 1 "register_operand" "v")
|
|
1632 (match_operand:VFT 2 "register_operand" "v")]
|
111
|
1633 "TARGET_VX"
|
|
1634 {
|
145
|
1635 emit_insn (gen_vec_cmpordered<mode> (operands[0], operands[1], operands[2]));
|
|
1636 emit_insn (gen_rtx_SET (operands[0],
|
|
1637 gen_rtx_NOT (<tointvec>mode, operands[0])));
|
111
|
1638 DONE;
|
|
1639 })
|
|
1640
|
145
|
1641 (define_code_iterator VEC_CMP_EXPAND
|
|
1642 [ungt unge uneq ltgt ordered unordered])
|
111
|
1643
|
145
|
1644 (define_expand "vec_cmp<code>"
|
111
|
1645 [(match_operand 0 "register_operand" "")
|
145
|
1646 (VEC_CMP_EXPAND (match_operand 1 "register_operand" "")
|
|
1647 (match_operand 2 "register_operand" ""))]
|
111
|
1648 "TARGET_VX"
|
|
1649 {
|
|
1650 if (GET_MODE (operands[1]) == V4SFmode)
|
145
|
1651 emit_insn (gen_vec_cmp<code>v4sf (operands[0], operands[1], operands[2]));
|
111
|
1652 else if (GET_MODE (operands[1]) == V2DFmode)
|
145
|
1653 emit_insn (gen_vec_cmp<code>v2df (operands[0], operands[1], operands[2]));
|
111
|
1654 else
|
|
1655 gcc_unreachable ();
|
|
1656
|
|
1657 DONE;
|
|
1658 })
|
|
1659
|
|
1660 (define_insn "*vec_load_pair<mode>"
|
|
1661 [(set (match_operand:V_HW_64 0 "register_operand" "=v,v")
|
|
1662 (vec_concat:V_HW_64 (match_operand:<non_vec> 1 "register_operand" "d,v")
|
|
1663 (match_operand:<non_vec> 2 "register_operand" "d,v")))]
|
|
1664 "TARGET_VX"
|
|
1665 "@
|
|
1666 vlvgp\t%v0,%1,%2
|
|
1667 vmrhg\t%v0,%v1,%v2"
|
|
1668 [(set_attr "op_type" "VRR,VRR")])
|
|
1669
|
|
1670 (define_insn "vllv16qi"
|
|
1671 [(set (match_operand:V16QI 0 "register_operand" "=v")
|
|
1672 (unspec:V16QI [(match_operand:SI 1 "register_operand" "d")
|
|
1673 (match_operand:BLK 2 "memory_operand" "Q")]
|
|
1674 UNSPEC_VEC_LOAD_LEN))]
|
|
1675 "TARGET_VX"
|
|
1676 "vll\t%v0,%1,%2"
|
|
1677 [(set_attr "op_type" "VRS")])
|
|
1678
|
|
1679 ; vfenebs, vfenehs, vfenefs
|
|
1680 ; vfenezbs, vfenezhs, vfenezfs
|
|
1681 (define_insn "vec_vfenes<mode>"
|
|
1682 [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
|
|
1683 (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
|
|
1684 (match_operand:VI_HW_QHS 2 "register_operand" "v")
|
|
1685 (match_operand:QI 3 "const_mask_operand" "C")]
|
|
1686 UNSPEC_VEC_VFENE))
|
|
1687 (set (reg:CCRAW CC_REGNUM)
|
|
1688 (unspec:CCRAW [(match_dup 1)
|
|
1689 (match_dup 2)
|
|
1690 (match_dup 3)]
|
|
1691 UNSPEC_VEC_VFENECC))]
|
|
1692 "TARGET_VX"
|
|
1693 {
|
|
1694 unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
|
|
1695
|
|
1696 gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
|
|
1697 flags &= ~VSTRING_FLAG_CS;
|
|
1698
|
|
1699 if (flags == VSTRING_FLAG_ZS)
|
|
1700 return "vfenez<bhfgq>s\t%v0,%v1,%v2";
|
|
1701 return "vfene<bhfgq>s\t%v0,%v1,%v2";
|
|
1702 }
|
|
1703 [(set_attr "op_type" "VRR")])
|
|
1704
|
|
1705
|
|
1706 ; Vector select
|
|
1707
|
|
1708 ; The following splitters simplify vec_sel for constant 0 or -1
|
|
1709 ; selection sources. This is required to generate efficient code for
|
|
1710 ; vcond.
|
|
1711
|
|
1712 ; a = b == c;
|
|
1713 (define_split
|
|
1714 [(set (match_operand:V 0 "register_operand" "")
|
|
1715 (if_then_else:V
|
|
1716 (eq (match_operand:<tointvec> 3 "register_operand" "")
|
|
1717 (match_operand:V 4 "const0_operand" ""))
|
|
1718 (match_operand:V 1 "const0_operand" "")
|
|
1719 (match_operand:V 2 "all_ones_operand" "")))]
|
|
1720 "TARGET_VX"
|
|
1721 [(set (match_dup 0) (match_dup 3))]
|
|
1722 {
|
|
1723 PUT_MODE (operands[3], <V:MODE>mode);
|
|
1724 })
|
|
1725
|
|
1726 ; a = ~(b == c)
|
|
1727 (define_split
|
|
1728 [(set (match_operand:V 0 "register_operand" "")
|
|
1729 (if_then_else:V
|
|
1730 (eq (match_operand:<tointvec> 3 "register_operand" "")
|
|
1731 (match_operand:V 4 "const0_operand" ""))
|
|
1732 (match_operand:V 1 "all_ones_operand" "")
|
|
1733 (match_operand:V 2 "const0_operand" "")))]
|
|
1734 "TARGET_VX"
|
|
1735 [(set (match_dup 0) (not:V (match_dup 3)))]
|
|
1736 {
|
|
1737 PUT_MODE (operands[3], <V:MODE>mode);
|
|
1738 })
|
|
1739
|
|
1740 ; a = b != c
|
|
1741 (define_split
|
|
1742 [(set (match_operand:V 0 "register_operand" "")
|
|
1743 (if_then_else:V
|
|
1744 (ne (match_operand:<tointvec> 3 "register_operand" "")
|
|
1745 (match_operand:V 4 "const0_operand" ""))
|
|
1746 (match_operand:V 1 "all_ones_operand" "")
|
|
1747 (match_operand:V 2 "const0_operand" "")))]
|
|
1748 "TARGET_VX"
|
|
1749 [(set (match_dup 0) (match_dup 3))]
|
|
1750 {
|
|
1751 PUT_MODE (operands[3], <V:MODE>mode);
|
|
1752 })
|
|
1753
|
|
1754 ; a = ~(b != c)
|
|
1755 (define_split
|
|
1756 [(set (match_operand:V 0 "register_operand" "")
|
|
1757 (if_then_else:V
|
|
1758 (ne (match_operand:<tointvec> 3 "register_operand" "")
|
|
1759 (match_operand:V 4 "const0_operand" ""))
|
|
1760 (match_operand:V 1 "const0_operand" "")
|
|
1761 (match_operand:V 2 "all_ones_operand" "")))]
|
|
1762 "TARGET_VX"
|
|
1763 [(set (match_dup 0) (not:V (match_dup 3)))]
|
|
1764 {
|
|
1765 PUT_MODE (operands[3], <V:MODE>mode);
|
|
1766 })
|
|
1767
|
|
1768 ; op0 = op3 == 0 ? op1 : op2
|
|
1769 (define_insn "*vec_sel0<mode>"
|
|
1770 [(set (match_operand:V 0 "register_operand" "=v")
|
|
1771 (if_then_else:V
|
|
1772 (eq (match_operand:<tointvec> 3 "register_operand" "v")
|
|
1773 (match_operand:<tointvec> 4 "const0_operand" ""))
|
|
1774 (match_operand:V 1 "register_operand" "v")
|
|
1775 (match_operand:V 2 "register_operand" "v")))]
|
|
1776 "TARGET_VX"
|
|
1777 "vsel\t%v0,%2,%1,%3"
|
|
1778 [(set_attr "op_type" "VRR")])
|
|
1779
|
|
1780 ; op0 = !op3 == 0 ? op1 : op2
|
|
1781 (define_insn "*vec_sel0<mode>"
|
|
1782 [(set (match_operand:V 0 "register_operand" "=v")
|
|
1783 (if_then_else:V
|
|
1784 (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
|
|
1785 (match_operand:<tointvec> 4 "const0_operand" ""))
|
|
1786 (match_operand:V 1 "register_operand" "v")
|
|
1787 (match_operand:V 2 "register_operand" "v")))]
|
|
1788 "TARGET_VX"
|
|
1789 "vsel\t%v0,%1,%2,%3"
|
|
1790 [(set_attr "op_type" "VRR")])
|
|
1791
|
|
1792 ; op0 = op3 == -1 ? op1 : op2
|
|
1793 (define_insn "*vec_sel1<mode>"
|
|
1794 [(set (match_operand:V 0 "register_operand" "=v")
|
|
1795 (if_then_else:V
|
|
1796 (eq (match_operand:<tointvec> 3 "register_operand" "v")
|
|
1797 (match_operand:<tointvec> 4 "all_ones_operand" ""))
|
|
1798 (match_operand:V 1 "register_operand" "v")
|
|
1799 (match_operand:V 2 "register_operand" "v")))]
|
|
1800 "TARGET_VX"
|
|
1801 "vsel\t%v0,%1,%2,%3"
|
|
1802 [(set_attr "op_type" "VRR")])
|
|
1803
|
|
1804 ; op0 = !op3 == -1 ? op1 : op2
|
|
1805 (define_insn "*vec_sel1<mode>"
|
|
1806 [(set (match_operand:V 0 "register_operand" "=v")
|
|
1807 (if_then_else:V
|
|
1808 (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
|
|
1809 (match_operand:<tointvec> 4 "all_ones_operand" ""))
|
|
1810 (match_operand:V 1 "register_operand" "v")
|
|
1811 (match_operand:V 2 "register_operand" "v")))]
|
|
1812 "TARGET_VX"
|
|
1813 "vsel\t%v0,%2,%1,%3"
|
|
1814 [(set_attr "op_type" "VRR")])
|
|
1815
|
|
1816 ; vec_pack_trunc
|
|
1817
|
|
1818 ; vpkh, vpkf, vpkg
|
|
1819 (define_insn "vec_pack_trunc_<mode>"
|
|
1820 [(set (match_operand:<vec_half> 0 "register_operand" "=v")
|
|
1821 (vec_concat:<vec_half>
|
|
1822 (truncate:<vec_halfhalf>
|
|
1823 (match_operand:VI_HW_HSD 1 "register_operand" "v"))
|
|
1824 (truncate:<vec_halfhalf>
|
|
1825 (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
|
|
1826 "TARGET_VX"
|
|
1827 "vpk<bhfgq>\t%0,%1,%2"
|
|
1828 [(set_attr "op_type" "VRR")])
|
|
1829
|
|
1830 ; vpksh, vpksf, vpksg
|
|
1831 (define_insn "vec_pack_ssat_<mode>"
|
|
1832 [(set (match_operand:<vec_half> 0 "register_operand" "=v")
|
|
1833 (vec_concat:<vec_half>
|
|
1834 (ss_truncate:<vec_halfhalf>
|
|
1835 (match_operand:VI_HW_HSD 1 "register_operand" "v"))
|
|
1836 (ss_truncate:<vec_halfhalf>
|
|
1837 (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
|
|
1838 "TARGET_VX"
|
|
1839 "vpks<bhfgq>\t%0,%1,%2"
|
|
1840 [(set_attr "op_type" "VRR")])
|
|
1841
|
|
1842 ; vpklsh, vpklsf, vpklsg
|
|
1843 (define_insn "vec_pack_usat_<mode>"
|
|
1844 [(set (match_operand:<vec_half> 0 "register_operand" "=v")
|
|
1845 (vec_concat:<vec_half>
|
|
1846 (us_truncate:<vec_halfhalf>
|
|
1847 (match_operand:VI_HW_HSD 1 "register_operand" "v"))
|
|
1848 (us_truncate:<vec_halfhalf>
|
|
1849 (match_operand:VI_HW_HSD 2 "register_operand" "v"))))]
|
|
1850 "TARGET_VX"
|
|
1851 "vpkls<bhfgq>\t%0,%1,%2"
|
|
1852 [(set_attr "op_type" "VRR")])
|
|
1853
|
|
1854 ;; vector unpack v16qi
|
|
1855
|
|
1856 ; signed
|
|
1857
|
|
1858 (define_insn "vec_unpacks_hi_v16qi"
|
|
1859 [(set (match_operand:V8HI 0 "register_operand" "=v")
|
|
1860 (sign_extend:V8HI
|
|
1861 (vec_select:V8QI
|
|
1862 (match_operand:V16QI 1 "register_operand" "v")
|
|
1863 (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
|
|
1864 (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
|
|
1865 "TARGET_VX"
|
|
1866 "vuphb\t%0,%1"
|
|
1867 [(set_attr "op_type" "VRR")])
|
|
1868
|
|
1869 (define_insn "vec_unpacks_lo_v16qi"
|
|
1870 [(set (match_operand:V8HI 0 "register_operand" "=v")
|
|
1871 (sign_extend:V8HI
|
|
1872 (vec_select:V8QI
|
|
1873 (match_operand:V16QI 1 "register_operand" "v")
|
|
1874 (parallel [(const_int 8) (const_int 9) (const_int 10)(const_int 11)
|
|
1875 (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
|
|
1876 "TARGET_VX"
|
|
1877 "vuplb\t%0,%1"
|
|
1878 [(set_attr "op_type" "VRR")])
|
|
1879
|
|
1880 ; unsigned
|
|
1881
|
|
1882 (define_insn "vec_unpacku_hi_v16qi"
|
|
1883 [(set (match_operand:V8HI 0 "register_operand" "=v")
|
|
1884 (zero_extend:V8HI
|
|
1885 (vec_select:V8QI
|
|
1886 (match_operand:V16QI 1 "register_operand" "v")
|
|
1887 (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
|
|
1888 (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
|
|
1889 "TARGET_VX"
|
|
1890 "vuplhb\t%0,%1"
|
|
1891 [(set_attr "op_type" "VRR")])
|
|
1892
|
|
1893 (define_insn "vec_unpacku_lo_v16qi"
|
|
1894 [(set (match_operand:V8HI 0 "register_operand" "=v")
|
|
1895 (zero_extend:V8HI
|
|
1896 (vec_select:V8QI
|
|
1897 (match_operand:V16QI 1 "register_operand" "v")
|
|
1898 (parallel [(const_int 8) (const_int 9) (const_int 10)(const_int 11)
|
|
1899 (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
|
|
1900 "TARGET_VX"
|
|
1901 "vupllb\t%0,%1"
|
|
1902 [(set_attr "op_type" "VRR")])
|
|
1903
|
|
1904 ;; vector unpack v8hi
|
|
1905
|
|
1906 ; signed
|
|
1907
|
|
1908 (define_insn "vec_unpacks_hi_v8hi"
|
|
1909 [(set (match_operand:V4SI 0 "register_operand" "=v")
|
|
1910 (sign_extend:V4SI
|
|
1911 (vec_select:V4HI
|
|
1912 (match_operand:V8HI 1 "register_operand" "v")
|
|
1913 (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
|
|
1914 "TARGET_VX"
|
|
1915 "vuphh\t%0,%1"
|
|
1916 [(set_attr "op_type" "VRR")])
|
|
1917
|
|
1918 (define_insn "vec_unpacks_lo_v8hi"
|
|
1919 [(set (match_operand:V4SI 0 "register_operand" "=v")
|
|
1920 (sign_extend:V4SI
|
|
1921 (vec_select:V4HI
|
|
1922 (match_operand:V8HI 1 "register_operand" "v")
|
|
1923 (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
|
|
1924 "TARGET_VX"
|
|
1925 "vuplhw\t%0,%1"
|
|
1926 [(set_attr "op_type" "VRR")])
|
|
1927
|
|
1928 ; unsigned
|
|
1929
|
|
1930 (define_insn "vec_unpacku_hi_v8hi"
|
|
1931 [(set (match_operand:V4SI 0 "register_operand" "=v")
|
|
1932 (zero_extend:V4SI
|
|
1933 (vec_select:V4HI
|
|
1934 (match_operand:V8HI 1 "register_operand" "v")
|
|
1935 (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
|
|
1936 "TARGET_VX"
|
|
1937 "vuplhh\t%0,%1"
|
|
1938 [(set_attr "op_type" "VRR")])
|
|
1939
|
|
1940 (define_insn "vec_unpacku_lo_v8hi"
|
|
1941 [(set (match_operand:V4SI 0 "register_operand" "=v")
|
|
1942 (zero_extend:V4SI
|
|
1943 (vec_select:V4HI
|
|
1944 (match_operand:V8HI 1 "register_operand" "v")
|
|
1945 (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
|
|
1946 "TARGET_VX"
|
|
1947 "vupllh\t%0,%1"
|
|
1948 [(set_attr "op_type" "VRR")])
|
|
1949
|
|
1950 ;; vector unpack v4si
|
|
1951
|
|
1952 ; signed
|
|
1953
|
|
1954 (define_insn "vec_unpacks_hi_v4si"
|
|
1955 [(set (match_operand:V2DI 0 "register_operand" "=v")
|
|
1956 (sign_extend:V2DI
|
|
1957 (vec_select:V2SI
|
|
1958 (match_operand:V4SI 1 "register_operand" "v")
|
|
1959 (parallel [(const_int 0)(const_int 1)]))))]
|
|
1960 "TARGET_VX"
|
|
1961 "vuphf\t%0,%1"
|
|
1962 [(set_attr "op_type" "VRR")])
|
|
1963
|
|
1964 (define_insn "vec_unpacks_lo_v4si"
|
|
1965 [(set (match_operand:V2DI 0 "register_operand" "=v")
|
|
1966 (sign_extend:V2DI
|
|
1967 (vec_select:V2SI
|
|
1968 (match_operand:V4SI 1 "register_operand" "v")
|
|
1969 (parallel [(const_int 2)(const_int 3)]))))]
|
|
1970 "TARGET_VX"
|
|
1971 "vuplf\t%0,%1"
|
|
1972 [(set_attr "op_type" "VRR")])
|
|
1973
|
|
1974 ; unsigned
|
|
1975
|
|
1976 (define_insn "vec_unpacku_hi_v4si"
|
|
1977 [(set (match_operand:V2DI 0 "register_operand" "=v")
|
|
1978 (zero_extend:V2DI
|
|
1979 (vec_select:V2SI
|
|
1980 (match_operand:V4SI 1 "register_operand" "v")
|
|
1981 (parallel [(const_int 0)(const_int 1)]))))]
|
|
1982 "TARGET_VX"
|
|
1983 "vuplhf\t%0,%1"
|
|
1984 [(set_attr "op_type" "VRR")])
|
|
1985
|
|
1986 (define_insn "vec_unpacku_lo_v4si"
|
|
1987 [(set (match_operand:V2DI 0 "register_operand" "=v")
|
|
1988 (zero_extend:V2DI
|
|
1989 (vec_select:V2SI
|
|
1990 (match_operand:V4SI 1 "register_operand" "v")
|
|
1991 (parallel [(const_int 2)(const_int 3)]))))]
|
|
1992 "TARGET_VX"
|
|
1993 "vupllf\t%0,%1"
|
|
1994 [(set_attr "op_type" "VRR")])
|
|
1995
|
|
1996 ;; vector load lengthened
|
|
1997
|
|
1998 ; vflls float -> double
|
|
1999 (define_insn "*vec_extendv4sf"
|
|
2000 [(set (match_operand:V2DF 0 "register_operand" "=v")
|
|
2001 (float_extend:V2DF
|
|
2002 (vec_select:V2SF
|
|
2003 (match_operand:V4SF 1 "register_operand" "v")
|
|
2004 (parallel [(const_int 0) (const_int 2)]))))]
|
|
2005 "TARGET_VX"
|
|
2006 "vldeb\t%v0,%v1"
|
|
2007 [(set_attr "op_type" "VRR")])
|
|
2008
|
|
2009 (define_expand "vec_unpacks_lo_v4sf"
|
|
2010 [(set (match_dup 2)
|
|
2011 (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
|
|
2012 (match_dup 1)]
|
|
2013 UNSPEC_VEC_MERGEL))
|
|
2014 (set (match_operand:V2DF 0 "register_operand" "=v")
|
|
2015 (float_extend:V2DF
|
|
2016 (vec_select:V2SF
|
|
2017 (match_dup 2)
|
|
2018 (parallel [(const_int 0) (const_int 2)]))))]
|
|
2019 "TARGET_VX"
|
|
2020 { operands[2] = gen_reg_rtx(V4SFmode); })
|
|
2021
|
|
2022 (define_expand "vec_unpacks_hi_v4sf"
|
|
2023 [(set (match_dup 2)
|
|
2024 (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
|
|
2025 (match_dup 1)]
|
|
2026 UNSPEC_VEC_MERGEH))
|
|
2027 (set (match_operand:V2DF 0 "register_operand" "=v")
|
|
2028 (float_extend:V2DF
|
|
2029 (vec_select:V2SF
|
|
2030 (match_dup 2)
|
|
2031 (parallel [(const_int 0) (const_int 2)]))))]
|
|
2032 "TARGET_VX"
|
|
2033 { operands[2] = gen_reg_rtx(V4SFmode); })
|
|
2034
|
|
2035
|
|
2036 ; double -> long double
|
|
2037 (define_insn "*vec_extendv2df"
|
|
2038 [(set (match_operand:V1TF 0 "register_operand" "=v")
|
|
2039 (float_extend:V1TF
|
|
2040 (vec_select:V1DF
|
|
2041 (match_operand:V2DF 1 "register_operand" "v")
|
|
2042 (parallel [(const_int 0)]))))]
|
|
2043 "TARGET_VXE"
|
|
2044 "wflld\t%v0,%v1"
|
|
2045 [(set_attr "op_type" "VRR")])
|
|
2046
|
|
2047 (define_expand "vec_unpacks_lo_v2df"
|
|
2048 [(set (match_dup 2)
|
|
2049 (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "v")
|
|
2050 (match_dup 1)]
|
|
2051 UNSPEC_VEC_MERGEL))
|
|
2052 (set (match_operand:V1TF 0 "register_operand" "=v")
|
|
2053 (float_extend:V1TF
|
|
2054 (vec_select:V1DF
|
|
2055 (match_dup 2)
|
|
2056 (parallel [(const_int 0)]))))]
|
|
2057 "TARGET_VXE"
|
|
2058 { operands[2] = gen_reg_rtx (V2DFmode); })
|
|
2059
|
|
2060 (define_expand "vec_unpacks_hi_v2df"
|
|
2061 [(set (match_dup 2)
|
|
2062 (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "v")
|
|
2063 (match_dup 1)]
|
|
2064 UNSPEC_VEC_MERGEH))
|
|
2065 (set (match_operand:V1TF 0 "register_operand" "=v")
|
|
2066 (float_extend:V1TF
|
|
2067 (vec_select:V1DF
|
|
2068 (match_dup 2)
|
|
2069 (parallel [(const_int 0)]))))]
|
|
2070 "TARGET_VXE"
|
|
2071 { operands[2] = gen_reg_rtx (V2DFmode); })
|
|
2072
|
|
2073
|
|
2074 ; 2 x v2df -> 1 x v4sf
|
|
2075 (define_expand "vec_pack_trunc_v2df"
|
|
2076 [(set (match_dup 3)
|
|
2077 (unspec:V4SF [(match_operand:V2DF 1 "register_operand" "")
|
|
2078 (const_int VEC_INEXACT)
|
|
2079 (const_int VEC_RND_CURRENT)]
|
|
2080 UNSPEC_VEC_VFLR))
|
|
2081 (set (match_dup 4)
|
|
2082 (unspec:V4SF [(match_operand:V2DF 2 "register_operand" "")
|
|
2083 (const_int VEC_INEXACT)
|
|
2084 (const_int VEC_RND_CURRENT)]
|
|
2085 UNSPEC_VEC_VFLR))
|
|
2086 (set (match_dup 6)
|
|
2087 (unspec:V16QI [(subreg:V16QI (match_dup 3) 0)
|
|
2088 (subreg:V16QI (match_dup 4) 0)
|
|
2089 (match_dup 5)]
|
|
2090 UNSPEC_VEC_PERM))
|
|
2091 (set (match_operand:V4SF 0 "register_operand" "")
|
|
2092 (subreg:V4SF (match_dup 6) 0))]
|
|
2093 "TARGET_VX"
|
|
2094 {
|
|
2095 rtx constv, perm[16];
|
|
2096 int i;
|
|
2097
|
|
2098 for (i = 0; i < 4; ++i)
|
|
2099 {
|
|
2100 perm[i] = GEN_INT (i);
|
|
2101 perm[i + 4] = GEN_INT (i + 8);
|
|
2102 perm[i + 8] = GEN_INT (i + 16);
|
|
2103 perm[i + 12] = GEN_INT (i + 24);
|
|
2104 }
|
|
2105 constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm));
|
|
2106
|
|
2107 operands[3] = gen_reg_rtx (V4SFmode);
|
|
2108 operands[4] = gen_reg_rtx (V4SFmode);
|
|
2109 operands[5] = force_reg (V16QImode, constv);
|
|
2110 operands[6] = gen_reg_rtx (V16QImode);
|
|
2111 })
|
|
2112
|
145
|
2113 ;
|
|
2114 ; BFP <-> integer conversions
|
|
2115 ;
|
|
2116
|
|
2117 ; signed integer to floating point
|
|
2118
|
|
2119 ; op2: inexact exception not suppressed (IEEE 754 2008)
|
|
2120 ; op3: according to current rounding mode
|
|
2121 ; vcdgb, vcefb
|
|
2122 (define_insn "float<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
|
|
2123 [(set (match_operand:VX_VEC_CONV_BFP 0 "register_operand" "=v")
|
|
2124 (float:VX_VEC_CONV_BFP (match_operand:VX_VEC_CONV_INT 1 "register_operand" "v")))]
|
|
2125 "TARGET_VX
|
|
2126 && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
|
|
2127 "vc<VX_VEC_CONV_BFP:xde><VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
|
|
2128 [(set_attr "op_type" "VRR")])
|
|
2129
|
|
2130 ; unsigned integer to floating point
|
|
2131
|
|
2132 ; op2: inexact exception not suppressed (IEEE 754 2008)
|
|
2133 ; op3: according to current rounding mode
|
|
2134 ; vcdlgb, vcelfb
|
|
2135 (define_insn "floatuns<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
|
|
2136 [(set (match_operand:VX_VEC_CONV_BFP 0 "register_operand" "=v")
|
|
2137 (unsigned_float:VX_VEC_CONV_BFP (match_operand:VX_VEC_CONV_INT 1 "register_operand" "v")))]
|
|
2138 "TARGET_VX
|
|
2139 && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
|
|
2140 "vc<VX_VEC_CONV_BFP:xde>l<VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
|
|
2141 [(set_attr "op_type" "VRR")])
|
|
2142
|
|
2143 ; floating point to signed integer
|
|
2144
|
|
2145 ; op2: inexact exception not suppressed (IEEE 754 2008)
|
|
2146 ; op3: rounding mode 5 (round towards 0 C11 6.3.1.4)
|
|
2147 ; vcgdb, vcfeb
|
|
2148 (define_insn "fix_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
|
|
2149 [(set (match_operand:VX_VEC_CONV_INT 0 "register_operand" "=v")
|
|
2150 (fix:VX_VEC_CONV_INT (match_operand:VX_VEC_CONV_BFP 1 "register_operand" "v")))]
|
|
2151 "TARGET_VX
|
|
2152 && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
|
|
2153 "vc<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
|
|
2154 [(set_attr "op_type" "VRR")])
|
|
2155
|
|
2156 ; floating point to unsigned integer
|
|
2157
|
|
2158 ; op2: inexact exception not suppressed (IEEE 754 2008)
|
|
2159 ; op3: rounding mode 5 (round towards 0 C11 6.3.1.4)
|
|
2160 ; vclgdb, vclfeb
|
|
2161 (define_insn "fixuns_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
|
|
2162 [(set (match_operand:VX_VEC_CONV_INT 0 "register_operand" "=v")
|
|
2163 (unsigned_fix:VX_VEC_CONV_INT (match_operand:VX_VEC_CONV_BFP 1 "register_operand" "v")))]
|
|
2164 "TARGET_VX
|
|
2165 && GET_MODE_UNIT_SIZE (<VX_VEC_CONV_INT:MODE>mode) == GET_MODE_UNIT_SIZE (<VX_VEC_CONV_BFP:MODE>mode)"
|
|
2166 "vcl<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
|
|
2167 [(set_attr "op_type" "VRR")])
|
|
2168
|
|
2169 ;
|
|
2170 ; Vector byte swap patterns
|
|
2171 ;
|
|
2172
|
|
2173 ; FIXME: The bswap rtl standard name currently does not appear to be
|
|
2174 ; used for vector modes.
|
|
2175 (define_expand "bswap<mode>"
|
|
2176 [(parallel
|
|
2177 [(set (match_operand:VT_HW_HSDT 0 "nonimmediate_operand" "")
|
|
2178 (bswap:VT_HW_HSDT (match_operand:VT_HW_HSDT 1 "nonimmediate_operand" "")))
|
|
2179 (use (match_dup 2))])]
|
|
2180 "TARGET_VX"
|
|
2181 {
|
|
2182 static char p[4][16] =
|
|
2183 { { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 }, /* H */
|
|
2184 { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 }, /* S */
|
|
2185 { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }, /* D */
|
|
2186 { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } }; /* T */
|
|
2187 char *perm;
|
|
2188 rtx perm_rtx[16];
|
|
2189
|
|
2190 switch (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)))
|
|
2191 {
|
|
2192 case 2: perm = p[0]; break;
|
|
2193 case 4: perm = p[1]; break;
|
|
2194 case 8: perm = p[2]; break;
|
|
2195 case 16: perm = p[3]; break;
|
|
2196 default: gcc_unreachable ();
|
|
2197 }
|
|
2198 for (int i = 0; i < 16; i++)
|
|
2199 perm_rtx[i] = GEN_INT (perm[i]);
|
|
2200
|
|
2201 operands[2] = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm_rtx));
|
|
2202
|
|
2203 /* Without vxe2 we do not have byte swap instructions dealing
|
|
2204 directly with memory operands. So instead of waiting until
|
|
2205 reload to fix that up switch over to vector permute right
|
|
2206 now. */
|
|
2207 if (!TARGET_VXE2)
|
|
2208 {
|
|
2209 rtx in = force_reg (V16QImode, simplify_gen_subreg (V16QImode, operands[1], <MODE>mode, 0));
|
|
2210 rtx permute = force_reg (V16QImode, force_const_mem (V16QImode, operands[2]));
|
|
2211 rtx out = gen_reg_rtx (V16QImode);
|
|
2212
|
|
2213 emit_insn (gen_vec_permv16qi (out, in, in, permute));
|
|
2214 emit_move_insn (operands[0], simplify_gen_subreg (<MODE>mode, out, V16QImode, 0));
|
|
2215 DONE;
|
|
2216 }
|
|
2217 })
|
|
2218
|
|
2219 ; Switching late to the reg-reg variant requires the vector permute
|
|
2220 ; pattern to be pushed into literal pool and allocating a vector
|
|
2221 ; register to load it into. We rely on both being provided by LRA
|
|
2222 ; when fixing up the v constraint for operand 2.
|
|
2223
|
|
2224 ; permute_pattern_operand: general_operand would reject the permute
|
|
2225 ; pattern constants since these are not accepted by
|
|
2226 ; s390_legimitate_constant_p
|
|
2227
|
|
2228 ; ^R: Prevent these alternatives from being chosen if it would require
|
|
2229 ; pushing the operand into memory first
|
|
2230
|
|
2231 ; vlbrh, vlbrf, vlbrg, vlbrq, vstbrh, vstbrf, vstbrg, vstbrq
|
|
2232 (define_insn_and_split "*bswap<mode>"
|
|
2233 [(set (match_operand:VT_HW_HSDT 0 "nonimmediate_operand" "=v, v,^R")
|
|
2234 (bswap:VT_HW_HSDT (match_operand:VT_HW_HSDT 1 "nonimmediate_operand" "v,^R, v")))
|
|
2235 (use (match_operand:V16QI 2 "permute_pattern_operand" "v, X, X"))]
|
|
2236 "TARGET_VXE2"
|
|
2237 "@
|
|
2238 #
|
|
2239 vlbr<bhfgq>\t%v0,%v1
|
|
2240 vstbr<bhfgq>\t%v1,%v0"
|
|
2241 "&& reload_completed
|
|
2242 && !memory_operand (operands[0], <MODE>mode)
|
|
2243 && !memory_operand (operands[1], <MODE>mode)"
|
|
2244 [(set (match_dup 0)
|
|
2245 (subreg:VT_HW_HSDT
|
|
2246 (unspec:V16QI [(subreg:V16QI (match_dup 1) 0)
|
|
2247 (subreg:V16QI (match_dup 1) 0)
|
|
2248 (match_dup 2)]
|
|
2249 UNSPEC_VEC_PERM) 0))]
|
|
2250 ""
|
|
2251 [(set_attr "op_type" "*,VRX,VRX")])
|
|
2252
|
111
|
2253 ; reduc_smin
|
|
2254 ; reduc_smax
|
|
2255 ; reduc_umin
|
|
2256 ; reduc_umax
|
|
2257
|
|
2258 ; vec_pack_sfix_trunc: convert + pack ?
|
|
2259 ; vec_pack_ufix_trunc
|
|
2260 ; vec_unpacks_float_hi
|
|
2261 ; vec_unpacks_float_lo
|
|
2262 ; vec_unpacku_float_hi
|
|
2263 ; vec_unpacku_float_lo
|