]>
Commit | Line | Data |
---|---|---|
29e6733c MM |
1 | ;; Expander definitions for vector support between altivec & vsx. No |
2 | ;; instructions are in this file, this file provides the generic vector | |
3 | ;; expander, and the actual vector instructions will be in altivec.md and | |
4 | ;; vsx.md | |
a72c65c7 | 5 | |
83ffe9cd | 6 | ;; Copyright (C) 2009-2023 Free Software Foundation, Inc. |
a72c65c7 MM |
7 | ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com> |
8 | ||
9 | ;; This file is part of GCC. | |
10 | ||
11 | ;; GCC is free software; you can redistribute it and/or modify it | |
12 | ;; under the terms of the GNU General Public License as published | |
13 | ;; by the Free Software Foundation; either version 3, or (at your | |
14 | ;; option) any later version. | |
15 | ||
16 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT | |
17 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
18 | ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
19 | ;; License for more details. | |
20 | ||
21 | ;; You should have received a copy of the GNU General Public License | |
22 | ;; along with GCC; see the file COPYING3. If not see | |
23 | ;; <http://www.gnu.org/licenses/>. | |
24 | ||
25 | ||
26 | ;; Vector int modes | |
a5965b52 | 27 | (define_mode_iterator VEC_I [V16QI V8HI V4SI V2DI]) |
a72c65c7 | 28 | |
8d1c6e70 HG |
29 | ;; Vector int modes for comparison, shift and rotation |
30 | (define_mode_iterator VEC_IC [V16QI V8HI V4SI V2DI (V1TI "TARGET_POWER10")]) | |
31 | ||
f1701864 CL |
32 | ;; 128-bit int modes |
33 | (define_mode_iterator VEC_TI [V1TI TI]) | |
34 | ||
4bfc9db7 MM |
35 | ;; Vector int modes for parity |
36 | (define_mode_iterator VEC_IP [V8HI | |
37 | V4SI | |
38 | V2DI | |
39 | V1TI | |
4a89b7e7 | 40 | TI]) |
4bfc9db7 | 41 | |
a72c65c7 | 42 | ;; Vector float modes |
29e6733c | 43 | (define_mode_iterator VEC_F [V4SF V2DF]) |
a72c65c7 MM |
44 | |
45 | ;; Vector arithmetic modes | |
a5965b52 | 46 | (define_mode_iterator VEC_A [V16QI V8HI V4SI V2DI V4SF V2DF]) |
a72c65c7 MM |
47 | |
48 | ;; Vector modes that need alginment via permutes | |
49 | (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF]) | |
50 | ||
51 | ;; Vector logical modes | |
c477a667 | 52 | (define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI KF TF]) |
a72c65c7 | 53 | |
c477a667 MM |
54 | ;; Vector modes for moves. Don't do TImode or TFmode here, since their |
55 | ;; moves are handled elsewhere. | |
56 | (define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI KF]) | |
a72c65c7 | 57 | |
29e6733c | 58 | ;; Vector modes for types that don't need a realignment under VSX |
c477a667 | 59 | (define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI KF TF]) |
29e6733c | 60 | |
a72c65c7 | 61 | ;; Vector comparison modes |
f03122f2 | 62 | (define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF V1TI]) |
a72c65c7 MM |
63 | |
64 | ;; Vector init/extract modes | |
7f5d5253 MM |
65 | (define_mode_iterator VEC_E [V16QI |
66 | V8HI | |
67 | V4SI | |
68 | V2DI | |
69 | V4SF | |
70 | V2DF | |
71 | (V32QI "TARGET_MMA") | |
72 | (V16HI "TARGET_MMA") | |
73 | (V8SI "TARGET_MMA") | |
74 | (V4DI "TARGET_MMA") | |
75 | (V8SF "TARGET_MMA") | |
76 | (V4DF "TARGET_MMA")]) | |
a72c65c7 | 77 | |
2fcd8e02 MM |
78 | ;; Vector modes for 64-bit base types |
79 | (define_mode_iterator VEC_64 [V2DI V2DF]) | |
80 | ||
902cb7b1 KN |
81 | ;; Vector integer modes |
82 | (define_mode_iterator VI [V4SI V8HI V16QI]) | |
83 | ||
a72c65c7 | 84 | ;; Base type from vector mode |
227b2d4a MM |
85 | (define_mode_attr VEC_base [(V32QI "QI") |
86 | (V16QI "QI") | |
87 | (V16HI "HI") | |
a72c65c7 | 88 | (V8HI "HI") |
227b2d4a | 89 | (V8SI "SI") |
a72c65c7 | 90 | (V4SI "SI") |
227b2d4a | 91 | (V4DI "DI") |
a72c65c7 | 92 | (V2DI "DI") |
227b2d4a | 93 | (V8SF "SF") |
a72c65c7 | 94 | (V4SF "SF") |
227b2d4a | 95 | (V4DF "DF") |
a72c65c7 | 96 | (V2DF "DF") |
a16a872d | 97 | (V1TI "TI") |
a72c65c7 MM |
98 | (TI "TI")]) |
99 | ||
ff03930a | 100 | ;; As above, but in lower case |
7f5d5253 MM |
101 | (define_mode_attr VEC_base_l [(V32QI "qi") |
102 | (V16QI "qi") | |
103 | (V16HI "hi") | |
ff03930a | 104 | (V8HI "hi") |
7f5d5253 | 105 | (V8SI "si") |
ff03930a | 106 | (V4SI "si") |
7f5d5253 | 107 | (V4DI "di") |
ff03930a | 108 | (V2DI "di") |
7f5d5253 | 109 | (V8SF "sf") |
ff03930a | 110 | (V4SF "sf") |
7f5d5253 | 111 | (V4DF "df") |
ff03930a JJ |
112 | (V2DF "df") |
113 | (V1TI "ti") | |
114 | (TI "ti")]) | |
115 | ||
a72c65c7 MM |
116 | ;; Same size integer type for floating point data |
117 | (define_mode_attr VEC_int [(V4SF "v4si") | |
118 | (V2DF "v2di")]) | |
119 | ||
120 | (define_mode_attr VEC_INT [(V4SF "V4SI") | |
121 | (V2DF "V2DI")]) | |
122 | ||
123 | ;; constants for unspec | |
df10b6d4 | 124 | (define_c_enum "unspec" [UNSPEC_PREDICATE |
902cb7b1 KN |
125 | UNSPEC_REDUC |
126 | UNSPEC_NEZ_P]) | |
df10b6d4 MM |
127 | |
128 | ;; Vector reduction code iterators | |
129 | (define_code_iterator VEC_reduc [plus smin smax]) | |
130 | ||
5e8edf67 | 131 | (define_code_attr VEC_reduc_name [(plus "plus") |
df10b6d4 MM |
132 | (smin "smin") |
133 | (smax "smax")]) | |
134 | ||
135 | (define_code_attr VEC_reduc_rtx [(plus "add") | |
136 | (smin "smin") | |
137 | (smax "smax")]) | |
a72c65c7 | 138 | |
bceb7181 KL |
139 | ;; code iterators and attributes for vector FP comparison operators: |
140 | (define_code_iterator | |
141 | vector_fp_comparison_simple [lt le ne ungt unge unlt unle]) | |
142 | (define_code_iterator | |
143 | vector_fp_comparison_complex [ltgt uneq unordered ordered]) | |
144 | ||
a72c65c7 | 145 | \f |
0cf68694 BS |
146 | ;; Vector move instructions. Little-endian VSX loads and stores require |
147 | ;; special handling to circumvent "element endianness." | |
a72c65c7 | 148 | (define_expand "mov<mode>" |
ad18eed2 SB |
149 | [(set (match_operand:VEC_M 0 "nonimmediate_operand") |
150 | (match_operand:VEC_M 1 "any_operand"))] | |
29e6733c | 151 | "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
152 | { |
153 | if (can_create_pseudo_p ()) | |
154 | { | |
c477a667 MM |
155 | if (CONSTANT_P (operands[1])) |
156 | { | |
157 | if (FLOAT128_VECTOR_P (<MODE>mode)) | |
158 | { | |
159 | if (!easy_fp_constant (operands[1], <MODE>mode)) | |
160 | operands[1] = force_const_mem (<MODE>mode, operands[1]); | |
161 | } | |
162 | else if (!easy_vector_constant (operands[1], <MODE>mode)) | |
163 | operands[1] = force_const_mem (<MODE>mode, operands[1]); | |
164 | } | |
165 | ||
166 | if (!vlogical_operand (operands[0], <MODE>mode) | |
167 | && !vlogical_operand (operands[1], <MODE>mode)) | |
a72c65c7 MM |
168 | operands[1] = force_reg (<MODE>mode, operands[1]); |
169 | } | |
75a741e8 PB |
170 | /* When generating load/store instructions to/from VSX registers on |
171 | pre-power9 hardware in little endian mode, we need to emit register | |
172 | permute instructions to byte swap the contents, since the VSX load/store | |
173 | instructions do not include a byte swap as part of their operation. | |
174 | Altivec loads and stores have no such problem, so we skip them below. */ | |
0cf68694 BS |
175 | if (!BYTES_BIG_ENDIAN |
176 | && VECTOR_MEM_VSX_P (<MODE>mode) | |
5d57fdc1 | 177 | && !TARGET_P9_VECTOR |
2d04cc30 | 178 | && !gpr_or_gpr_p (operands[0], operands[1]) |
75a741e8 PB |
179 | && ((memory_operand (operands[0], <MODE>mode) |
180 | && !altivec_indexed_or_indirect_operand(operands[0], <MODE>mode)) | |
181 | ^ (memory_operand (operands[1], <MODE>mode) | |
182 | && !altivec_indexed_or_indirect_operand(operands[1], <MODE>mode)))) | |
0cf68694 BS |
183 | { |
184 | rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode); | |
185 | DONE; | |
186 | } | |
a72c65c7 MM |
187 | }) |
188 | ||
29e6733c MM |
189 | ;; Generic vector floating point load/store instructions. These will match |
190 | ;; insns defined in vsx.md or altivec.md depending on the switches. | |
a72c65c7 | 191 | (define_expand "vector_load_<mode>" |
ad18eed2 SB |
192 | [(set (match_operand:VEC_M 0 "vfloat_operand") |
193 | (match_operand:VEC_M 1 "memory_operand"))] | |
29e6733c | 194 | "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
195 | "") |
196 | ||
197 | (define_expand "vector_store_<mode>" | |
ad18eed2 SB |
198 | [(set (match_operand:VEC_M 0 "memory_operand") |
199 | (match_operand:VEC_M 1 "vfloat_operand"))] | |
29e6733c | 200 | "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
201 | "") |
202 | ||
203 | ;; Splits if a GPR register was chosen for the move | |
204 | (define_split | |
ad18eed2 SB |
205 | [(set (match_operand:VEC_L 0 "nonimmediate_operand") |
206 | (match_operand:VEC_L 1 "input_operand"))] | |
29e6733c | 207 | "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode) |
a72c65c7 | 208 | && reload_completed |
19be72ab MM |
209 | && gpr_or_gpr_p (operands[0], operands[1]) |
210 | && !direct_move_p (operands[0], operands[1]) | |
211 | && !quad_load_store_p (operands[0], operands[1])" | |
a72c65c7 MM |
212 | [(pc)] |
213 | { | |
214 | rs6000_split_multireg_move (operands[0], operands[1]); | |
215 | DONE; | |
216 | }) | |
217 | ||
a72c65c7 MM |
218 | \f |
219 | ;; Generic floating point vector arithmetic support | |
220 | (define_expand "add<mode>3" | |
ad18eed2 SB |
221 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
222 | (plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand") | |
223 | (match_operand:VEC_F 2 "vfloat_operand")))] | |
29e6733c | 224 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
225 | "") |
226 | ||
227 | (define_expand "sub<mode>3" | |
ad18eed2 SB |
228 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
229 | (minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand") | |
230 | (match_operand:VEC_F 2 "vfloat_operand")))] | |
29e6733c | 231 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
232 | "") |
233 | ||
234 | (define_expand "mul<mode>3" | |
ad18eed2 SB |
235 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
236 | (mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand") | |
237 | (match_operand:VEC_F 2 "vfloat_operand")))] | |
c6d5ff83 | 238 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 239 | { |
29e6733c MM |
240 | if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) |
241 | { | |
242 | emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2])); | |
243 | DONE; | |
244 | } | |
d6613781 | 245 | }) |
a72c65c7 | 246 | |
29e6733c | 247 | (define_expand "div<mode>3" |
ad18eed2 SB |
248 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
249 | (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand") | |
250 | (match_operand:VEC_F 2 "vfloat_operand")))] | |
29e6733c | 251 | "VECTOR_UNIT_VSX_P (<MODE>mode)" |
b7fa8414 SB |
252 | { |
253 | if (RS6000_RECIP_AUTO_RE_P (<MODE>mode) | |
254 | && can_create_pseudo_p () && flag_finite_math_only | |
255 | && !flag_trapping_math && flag_reciprocal_math) | |
256 | { | |
257 | rs6000_emit_swdiv (operands[0], operands[1], operands[2], true); | |
258 | DONE; | |
259 | } | |
260 | }) | |
29e6733c | 261 | |
a72c65c7 | 262 | (define_expand "neg<mode>2" |
ad18eed2 SB |
263 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
264 | (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] | |
29e6733c | 265 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 266 | { |
29e6733c MM |
267 | if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) |
268 | { | |
269 | emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1])); | |
270 | DONE; | |
271 | } | |
6c332313 | 272 | }) |
a72c65c7 MM |
273 | |
274 | (define_expand "abs<mode>2" | |
ad18eed2 SB |
275 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
276 | (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] | |
29e6733c | 277 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 278 | { |
29e6733c MM |
279 | if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) |
280 | { | |
281 | emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1])); | |
282 | DONE; | |
283 | } | |
6c332313 | 284 | }) |
a72c65c7 MM |
285 | |
286 | (define_expand "smin<mode>3" | |
ad18eed2 SB |
287 | [(set (match_operand:VEC_F 0 "register_operand") |
288 | (smin:VEC_F (match_operand:VEC_F 1 "register_operand") | |
289 | (match_operand:VEC_F 2 "register_operand")))] | |
29e6733c | 290 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
291 | "") |
292 | ||
293 | (define_expand "smax<mode>3" | |
ad18eed2 SB |
294 | [(set (match_operand:VEC_F 0 "register_operand") |
295 | (smax:VEC_F (match_operand:VEC_F 1 "register_operand") | |
296 | (match_operand:VEC_F 2 "register_operand")))] | |
29e6733c | 297 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
298 | "") |
299 | ||
300 | ||
29e6733c | 301 | (define_expand "sqrt<mode>2" |
ad18eed2 SB |
302 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
303 | (sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] | |
29e6733c | 304 | "VECTOR_UNIT_VSX_P (<MODE>mode)" |
11c7bfe6 DE |
305 | { |
306 | if (<MODE>mode == V4SFmode | |
307 | && !optimize_function_for_size_p (cfun) | |
308 | && flag_finite_math_only && !flag_trapping_math | |
309 | && flag_unsafe_math_optimizations) | |
310 | { | |
311 | rs6000_emit_swsqrt (operands[0], operands[1], 0); | |
312 | DONE; | |
313 | } | |
314 | }) | |
29e6733c | 315 | |
92902797 | 316 | (define_expand "rsqrte<mode>2" |
ad18eed2 SB |
317 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
318 | (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")] | |
92902797 MM |
319 | UNSPEC_RSQRT))] |
320 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" | |
321 | "") | |
322 | ||
323 | (define_expand "re<mode>2" | |
ad18eed2 SB |
324 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
325 | (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")] | |
92902797 MM |
326 | UNSPEC_FRES))] |
327 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" | |
328 | "") | |
329 | ||
a72c65c7 | 330 | (define_expand "ftrunc<mode>2" |
ad18eed2 SB |
331 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
332 | (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] | |
29e6733c MM |
333 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
334 | "") | |
335 | ||
336 | (define_expand "vector_ceil<mode>2" | |
ad18eed2 SB |
337 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
338 | (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")] | |
29e6733c MM |
339 | UNSPEC_FRIP))] |
340 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" | |
341 | "") | |
342 | ||
343 | (define_expand "vector_floor<mode>2" | |
ad18eed2 SB |
344 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
345 | (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")] | |
29e6733c MM |
346 | UNSPEC_FRIM))] |
347 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" | |
a72c65c7 MM |
348 | "") |
349 | ||
29e6733c | 350 | (define_expand "vector_btrunc<mode>2" |
ad18eed2 SB |
351 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
352 | (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] | |
29e6733c MM |
353 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
354 | "") | |
355 | ||
356 | (define_expand "vector_copysign<mode>3" | |
ad18eed2 | 357 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
a70b158c MM |
358 | (copysign:VEC_F (match_operand:VEC_F 1 "vfloat_operand") |
359 | (match_operand:VEC_F 2 "vfloat_operand")))] | |
29e6733c | 360 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
29e6733c MM |
361 | { |
362 | if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) | |
363 | { | |
364 | emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1], | |
365 | operands[2])); | |
366 | DONE; | |
367 | } | |
6c332313 | 368 | }) |
29e6733c | 369 | |
a72c65c7 MM |
370 | \f |
371 | ;; Vector comparisons | |
e9e1d143 | 372 | (define_expand "vcond<mode><mode>" |
ad18eed2 | 373 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
a72c65c7 MM |
374 | (if_then_else:VEC_F |
375 | (match_operator 3 "comparison_operator" | |
ad18eed2 SB |
376 | [(match_operand:VEC_F 4 "vfloat_operand") |
377 | (match_operand:VEC_F 5 "vfloat_operand")]) | |
378 | (match_operand:VEC_F 1 "vfloat_operand") | |
379 | (match_operand:VEC_F 2 "vfloat_operand")))] | |
29e6733c | 380 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
381 | { |
382 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
383 | operands[3], operands[4], operands[5])) | |
384 | DONE; | |
385 | else | |
291f65f1 | 386 | gcc_unreachable (); |
6c332313 | 387 | }) |
a72c65c7 | 388 | |
e9e1d143 | 389 | (define_expand "vcond<mode><mode>" |
391675ac | 390 | [(set (match_operand:VEC_I 0 "vint_operand") |
a72c65c7 MM |
391 | (if_then_else:VEC_I |
392 | (match_operator 3 "comparison_operator" | |
391675ac MM |
393 | [(match_operand:VEC_I 4 "vint_operand") |
394 | (match_operand:VEC_I 5 "vint_operand")]) | |
395 | (match_operand:VEC_I 1 "vector_int_reg_or_same_bit") | |
396 | (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))] | |
c6d5ff83 | 397 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
398 | { |
399 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
400 | operands[3], operands[4], operands[5])) | |
401 | DONE; | |
402 | else | |
291f65f1 | 403 | gcc_unreachable (); |
6c332313 | 404 | }) |
a72c65c7 | 405 | |
69d3d957 | 406 | (define_expand "vcondv4sfv4si" |
ad18eed2 | 407 | [(set (match_operand:V4SF 0 "vfloat_operand") |
69d3d957 JJ |
408 | (if_then_else:V4SF |
409 | (match_operator 3 "comparison_operator" | |
ad18eed2 SB |
410 | [(match_operand:V4SI 4 "vint_operand") |
411 | (match_operand:V4SI 5 "vint_operand")]) | |
412 | (match_operand:V4SF 1 "vfloat_operand") | |
413 | (match_operand:V4SF 2 "vfloat_operand")))] | |
69d3d957 JJ |
414 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) |
415 | && VECTOR_UNIT_ALTIVEC_P (V4SImode)" | |
69d3d957 JJ |
416 | { |
417 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
418 | operands[3], operands[4], operands[5])) | |
419 | DONE; | |
420 | else | |
291f65f1 | 421 | gcc_unreachable (); |
6c332313 | 422 | }) |
69d3d957 JJ |
423 | |
424 | (define_expand "vcondv4siv4sf" | |
ad18eed2 | 425 | [(set (match_operand:V4SI 0 "vint_operand") |
69d3d957 JJ |
426 | (if_then_else:V4SI |
427 | (match_operator 3 "comparison_operator" | |
ad18eed2 SB |
428 | [(match_operand:V4SF 4 "vfloat_operand") |
429 | (match_operand:V4SF 5 "vfloat_operand")]) | |
430 | (match_operand:V4SI 1 "vint_operand") | |
431 | (match_operand:V4SI 2 "vint_operand")))] | |
69d3d957 JJ |
432 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) |
433 | && VECTOR_UNIT_ALTIVEC_P (V4SImode)" | |
69d3d957 JJ |
434 | { |
435 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
436 | operands[3], operands[4], operands[5])) | |
437 | DONE; | |
438 | else | |
291f65f1 | 439 | gcc_unreachable (); |
6c332313 | 440 | }) |
69d3d957 | 441 | |
95e5bea0 BS |
442 | (define_expand "vcondv2dfv2di" |
443 | [(set (match_operand:V2DF 0 "vfloat_operand") | |
444 | (if_then_else:V2DF | |
445 | (match_operator 3 "comparison_operator" | |
446 | [(match_operand:V2DI 4 "vint_operand") | |
447 | (match_operand:V2DI 5 "vint_operand")]) | |
448 | (match_operand:V2DF 1 "vfloat_operand") | |
449 | (match_operand:V2DF 2 "vfloat_operand")))] | |
450 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode) | |
451 | && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)" | |
452 | { | |
453 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
454 | operands[3], operands[4], operands[5])) | |
455 | DONE; | |
456 | else | |
291f65f1 | 457 | gcc_unreachable (); |
95e5bea0 BS |
458 | }) |
459 | ||
460 | (define_expand "vcondv2div2df" | |
461 | [(set (match_operand:V2DI 0 "vint_operand") | |
462 | (if_then_else:V2DI | |
463 | (match_operator 3 "comparison_operator" | |
464 | [(match_operand:V2DF 4 "vfloat_operand") | |
465 | (match_operand:V2DF 5 "vfloat_operand")]) | |
466 | (match_operand:V2DI 1 "vint_operand") | |
467 | (match_operand:V2DI 2 "vint_operand")))] | |
468 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode) | |
469 | && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)" | |
470 | { | |
471 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
472 | operands[3], operands[4], operands[5])) | |
473 | DONE; | |
474 | else | |
291f65f1 | 475 | gcc_unreachable (); |
95e5bea0 BS |
476 | }) |
477 | ||
e9e1d143 | 478 | (define_expand "vcondu<mode><mode>" |
391675ac | 479 | [(set (match_operand:VEC_I 0 "vint_operand") |
a72c65c7 MM |
480 | (if_then_else:VEC_I |
481 | (match_operator 3 "comparison_operator" | |
391675ac MM |
482 | [(match_operand:VEC_I 4 "vint_operand") |
483 | (match_operand:VEC_I 5 "vint_operand")]) | |
484 | (match_operand:VEC_I 1 "vector_int_reg_or_same_bit") | |
485 | (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))] | |
c6d5ff83 | 486 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
487 | { |
488 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
489 | operands[3], operands[4], operands[5])) | |
490 | DONE; | |
491 | else | |
291f65f1 | 492 | gcc_unreachable (); |
6c332313 | 493 | }) |
a72c65c7 | 494 | |
69d3d957 | 495 | (define_expand "vconduv4sfv4si" |
ad18eed2 | 496 | [(set (match_operand:V4SF 0 "vfloat_operand") |
69d3d957 JJ |
497 | (if_then_else:V4SF |
498 | (match_operator 3 "comparison_operator" | |
ad18eed2 SB |
499 | [(match_operand:V4SI 4 "vint_operand") |
500 | (match_operand:V4SI 5 "vint_operand")]) | |
501 | (match_operand:V4SF 1 "vfloat_operand") | |
502 | (match_operand:V4SF 2 "vfloat_operand")))] | |
69d3d957 JJ |
503 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) |
504 | && VECTOR_UNIT_ALTIVEC_P (V4SImode)" | |
69d3d957 JJ |
505 | { |
506 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
507 | operands[3], operands[4], operands[5])) | |
508 | DONE; | |
509 | else | |
291f65f1 | 510 | gcc_unreachable (); |
6c332313 | 511 | }) |
69d3d957 | 512 | |
95e5bea0 BS |
513 | (define_expand "vconduv2dfv2di" |
514 | [(set (match_operand:V2DF 0 "vfloat_operand") | |
515 | (if_then_else:V2DF | |
516 | (match_operator 3 "comparison_operator" | |
517 | [(match_operand:V2DI 4 "vint_operand") | |
518 | (match_operand:V2DI 5 "vint_operand")]) | |
519 | (match_operand:V2DF 1 "vfloat_operand") | |
520 | (match_operand:V2DF 2 "vfloat_operand")))] | |
521 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode) | |
522 | && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)" | |
523 | { | |
524 | if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], | |
525 | operands[3], operands[4], operands[5])) | |
526 | DONE; | |
527 | else | |
291f65f1 | 528 | gcc_unreachable (); |
95e5bea0 BS |
529 | }) |
530 | ||
bc5b2b68 KL |
531 | ;; To support vector condition vectorization, define vcond_mask and vec_cmp. |
532 | ||
533 | ;; Same mode for condition true/false values and predicate operand. | |
534 | (define_expand "vcond_mask_<mode><mode>" | |
535 | [(match_operand:VEC_I 0 "vint_operand") | |
536 | (match_operand:VEC_I 1 "vint_operand") | |
537 | (match_operand:VEC_I 2 "vint_operand") | |
538 | (match_operand:VEC_I 3 "vint_operand")] | |
539 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" | |
540 | { | |
541 | emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1], | |
542 | operands[3])); | |
543 | DONE; | |
544 | }) | |
545 | ||
546 | ;; Condition true/false values are float but predicate operand is of | |
547 | ;; type integer vector with same element size. | |
548 | (define_expand "vcond_mask_<mode><VEC_int>" | |
549 | [(match_operand:VEC_F 0 "vfloat_operand") | |
550 | (match_operand:VEC_F 1 "vfloat_operand") | |
551 | (match_operand:VEC_F 2 "vfloat_operand") | |
552 | (match_operand:<VEC_INT> 3 "vint_operand")] | |
553 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" | |
554 | { | |
555 | emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1], | |
556 | gen_lowpart (<MODE>mode, operands[3]))); | |
557 | DONE; | |
558 | }) | |
559 | ||
560 | ;; For signed integer vectors comparison. | |
561 | (define_expand "vec_cmp<mode><mode>" | |
8d1c6e70 | 562 | [(set (match_operand:VEC_IC 0 "vint_operand") |
bc5b2b68 | 563 | (match_operator 1 "signed_or_equality_comparison_operator" |
8d1c6e70 HG |
564 | [(match_operand:VEC_IC 2 "vint_operand") |
565 | (match_operand:VEC_IC 3 "vint_operand")]))] | |
bc5b2b68 KL |
566 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
567 | { | |
568 | enum rtx_code code = GET_CODE (operands[1]); | |
569 | rtx tmp = gen_reg_rtx (<MODE>mode); | |
570 | switch (code) | |
571 | { | |
572 | case NE: | |
573 | emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); | |
574 | emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); | |
575 | break; | |
576 | case EQ: | |
577 | emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); | |
578 | break; | |
579 | case GE: | |
580 | emit_insn (gen_vector_nlt<mode> (operands[0],operands[2], operands[3], | |
581 | tmp)); | |
582 | break; | |
583 | case GT: | |
584 | emit_insn (gen_vector_gt<mode> (operands[0], operands[2], operands[3])); | |
585 | break; | |
586 | case LE: | |
587 | emit_insn (gen_vector_ngt<mode> (operands[0], operands[2], operands[3], | |
588 | tmp)); | |
589 | break; | |
590 | case LT: | |
591 | emit_insn (gen_vector_gt<mode> (operands[0], operands[3], operands[2])); | |
592 | break; | |
593 | default: | |
594 | gcc_unreachable (); | |
595 | break; | |
596 | } | |
597 | DONE; | |
598 | }) | |
599 | ||
600 | ;; For unsigned integer vectors comparison. | |
601 | (define_expand "vec_cmpu<mode><mode>" | |
8d1c6e70 | 602 | [(set (match_operand:VEC_IC 0 "vint_operand") |
bc5b2b68 | 603 | (match_operator 1 "unsigned_or_equality_comparison_operator" |
8d1c6e70 HG |
604 | [(match_operand:VEC_IC 2 "vint_operand") |
605 | (match_operand:VEC_IC 3 "vint_operand")]))] | |
bc5b2b68 KL |
606 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
607 | { | |
608 | enum rtx_code code = GET_CODE (operands[1]); | |
609 | rtx tmp = gen_reg_rtx (<MODE>mode); | |
610 | switch (code) | |
611 | { | |
612 | case NE: | |
613 | emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); | |
614 | emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); | |
615 | break; | |
616 | case EQ: | |
617 | emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); | |
618 | break; | |
619 | case GEU: | |
620 | emit_insn (gen_vector_nltu<mode> (operands[0], operands[2], operands[3], | |
621 | tmp)); | |
622 | break; | |
623 | case GTU: | |
624 | emit_insn (gen_vector_gtu<mode> (operands[0], operands[2], operands[3])); | |
625 | break; | |
626 | case LEU: | |
627 | emit_insn (gen_vector_ngtu<mode> (operands[0], operands[2], operands[3], | |
628 | tmp)); | |
629 | break; | |
630 | case LTU: | |
631 | emit_insn (gen_vector_gtu<mode> (operands[0], operands[3], operands[2])); | |
632 | break; | |
633 | default: | |
634 | gcc_unreachable (); | |
635 | break; | |
636 | } | |
637 | DONE; | |
638 | }) | |
639 | ||
640 | ;; For float point vectors comparison. | |
641 | (define_expand "vec_cmp<mode><VEC_int>" | |
642 | [(set (match_operand:<VEC_INT> 0 "vint_operand") | |
643 | (match_operator 1 "comparison_operator" | |
644 | [(match_operand:VEC_F 2 "vfloat_operand") | |
645 | (match_operand:VEC_F 3 "vfloat_operand")]))] | |
646 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" | |
647 | { | |
648 | enum rtx_code code = GET_CODE (operands[1]); | |
649 | rtx res = gen_reg_rtx (<MODE>mode); | |
650 | switch (code) | |
651 | { | |
652 | case NE: | |
653 | emit_insn (gen_vector_ne<mode> (res, operands[2], operands[3])); | |
654 | break; | |
655 | case EQ: | |
656 | emit_insn (gen_vector_eq<mode> (res, operands[2], operands[3])); | |
657 | break; | |
658 | case GE: | |
659 | emit_insn (gen_vector_ge<mode> (res, operands[2], operands[3])); | |
660 | break; | |
661 | case GT: | |
662 | emit_insn (gen_vector_gt<mode> (res, operands[2], operands[3])); | |
663 | break; | |
664 | case LE: | |
665 | emit_insn (gen_vector_le<mode> (res, operands[2], operands[3])); | |
666 | break; | |
667 | case LT: | |
668 | emit_insn (gen_vector_lt<mode> (res, operands[2], operands[3])); | |
669 | break; | |
670 | case LTGT: | |
671 | emit_insn (gen_vector_ltgt<mode> (res, operands[2], operands[3])); | |
672 | break; | |
673 | case UNORDERED: | |
674 | emit_insn (gen_vector_unordered<mode> (res, operands[2], operands[3])); | |
675 | break; | |
676 | case ORDERED: | |
677 | emit_insn (gen_vector_ordered<mode> (res, operands[2], operands[3])); | |
678 | break; | |
679 | case UNEQ: | |
680 | emit_insn (gen_vector_uneq<mode> (res, operands[2], operands[3])); | |
681 | break; | |
682 | case UNGE: | |
683 | emit_insn (gen_vector_unge<mode> (res, operands[2], operands[3])); | |
684 | break; | |
685 | case UNGT: | |
686 | emit_insn (gen_vector_ungt<mode> (res, operands[2], operands[3])); | |
687 | break; | |
688 | case UNLE: | |
689 | emit_insn (gen_vector_unle<mode> (res, operands[2], operands[3])); | |
690 | break; | |
691 | case UNLT: | |
692 | emit_insn (gen_vector_unlt<mode> (res, operands[2], operands[3])); | |
693 | break; | |
694 | ||
695 | default: | |
696 | gcc_unreachable (); | |
697 | } | |
698 | ||
699 | emit_insn (gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); | |
700 | DONE; | |
701 | }) | |
702 | ||
a72c65c7 | 703 | (define_expand "vector_eq<mode>" |
ad18eed2 SB |
704 | [(set (match_operand:VEC_C 0 "vlogical_operand") |
705 | (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand") | |
706 | (match_operand:VEC_C 2 "vlogical_operand")))] | |
29e6733c | 707 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
708 | "") |
709 | ||
710 | (define_expand "vector_gt<mode>" | |
ad18eed2 SB |
711 | [(set (match_operand:VEC_C 0 "vlogical_operand") |
712 | (gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand") | |
713 | (match_operand:VEC_C 2 "vlogical_operand")))] | |
29e6733c | 714 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
715 | "") |
716 | ||
a05d02b2 BS |
717 | ; >= for integer vectors: swap operands and apply not-greater-than |
718 | (define_expand "vector_nlt<mode>" | |
8d1c6e70 HG |
719 | [(set (match_operand:VEC_IC 3 "vlogical_operand") |
720 | (gt:VEC_IC (match_operand:VEC_IC 2 "vlogical_operand") | |
721 | (match_operand:VEC_IC 1 "vlogical_operand"))) | |
722 | (set (match_operand:VEC_IC 0 "vlogical_operand") | |
723 | (not:VEC_IC (match_dup 3)))] | |
a05d02b2 | 724 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a05d02b2 BS |
725 | { |
726 | operands[3] = gen_reg_rtx_and_attrs (operands[0]); | |
6c332313 | 727 | }) |
a05d02b2 | 728 | |
a72c65c7 | 729 | (define_expand "vector_gtu<mode>" |
8d1c6e70 HG |
730 | [(set (match_operand:VEC_IC 0 "vint_operand") |
731 | (gtu:VEC_IC (match_operand:VEC_IC 1 "vint_operand") | |
732 | (match_operand:VEC_IC 2 "vint_operand")))] | |
c6d5ff83 | 733 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
734 | "") |
735 | ||
a05d02b2 BS |
736 | ; >= for integer vectors: swap operands and apply not-greater-than |
737 | (define_expand "vector_nltu<mode>" | |
8d1c6e70 HG |
738 | [(set (match_operand:VEC_IC 3 "vlogical_operand") |
739 | (gtu:VEC_IC (match_operand:VEC_IC 2 "vlogical_operand") | |
740 | (match_operand:VEC_IC 1 "vlogical_operand"))) | |
741 | (set (match_operand:VEC_IC 0 "vlogical_operand") | |
742 | (not:VEC_IC (match_dup 3)))] | |
a05d02b2 | 743 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a05d02b2 BS |
744 | { |
745 | operands[3] = gen_reg_rtx_and_attrs (operands[0]); | |
6c332313 | 746 | }) |
a05d02b2 | 747 | |
a72c65c7 | 748 | (define_expand "vector_geu<mode>" |
8d1c6e70 HG |
749 | [(set (match_operand:VEC_IC 0 "vint_operand") |
750 | (geu:VEC_IC (match_operand:VEC_IC 1 "vint_operand") | |
751 | (match_operand:VEC_IC 2 "vint_operand")))] | |
c6d5ff83 | 752 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
753 | "") |
754 | ||
a05d02b2 BS |
755 | ; <= for integer vectors: apply not-greater-than |
756 | (define_expand "vector_ngt<mode>" | |
8d1c6e70 HG |
757 | [(set (match_operand:VEC_IC 3 "vlogical_operand") |
758 | (gt:VEC_IC (match_operand:VEC_IC 1 "vlogical_operand") | |
759 | (match_operand:VEC_IC 2 "vlogical_operand"))) | |
760 | (set (match_operand:VEC_IC 0 "vlogical_operand") | |
761 | (not:VEC_IC (match_dup 3)))] | |
a05d02b2 | 762 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a05d02b2 BS |
763 | { |
764 | operands[3] = gen_reg_rtx_and_attrs (operands[0]); | |
6c332313 | 765 | }) |
a05d02b2 BS |
766 | |
767 | (define_expand "vector_ngtu<mode>" | |
8d1c6e70 HG |
768 | [(set (match_operand:VEC_IC 3 "vlogical_operand") |
769 | (gtu:VEC_IC (match_operand:VEC_IC 1 "vlogical_operand") | |
770 | (match_operand:VEC_IC 2 "vlogical_operand"))) | |
771 | (set (match_operand:VEC_IC 0 "vlogical_operand") | |
772 | (not:VEC_IC (match_dup 3)))] | |
a05d02b2 | 773 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a05d02b2 BS |
774 | { |
775 | operands[3] = gen_reg_rtx_and_attrs (operands[0]); | |
6c332313 | 776 | }) |
a05d02b2 | 777 | |
bceb7181 KL |
778 | ; There are 14 possible vector FP comparison operators, gt and eq of them have |
779 | ; been expanded above, so just support 12 remaining operators here. | |
46402cbe | 780 | |
bceb7181 KL |
781 | ; For ge: |
782 | (define_expand "vector_ge<mode>" | |
783 | [(set (match_operand:VEC_F 0 "vlogical_operand") | |
784 | (ge:VEC_F (match_operand:VEC_F 1 "vlogical_operand") | |
785 | (match_operand:VEC_F 2 "vlogical_operand")))] | |
46402cbe | 786 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
bceb7181 | 787 | "") |
46402cbe | 788 | |
bceb7181 KL |
789 | ; For lt/le/ne/ungt/unge/unlt/unle: |
790 | ; lt(a,b) = gt(b,a) | |
791 | ; le(a,b) = ge(b,a) | |
792 | ; unge(a,b) = ~lt(a,b) | |
793 | ; unle(a,b) = ~gt(a,b) | |
794 | ; ne(a,b) = ~eq(a,b) | |
795 | ; ungt(a,b) = ~le(a,b) | |
796 | ; unlt(a,b) = ~ge(a,b) | |
797 | (define_insn_and_split "vector_<code><mode>" | |
ad18eed2 | 798 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
bceb7181 KL |
799 | (vector_fp_comparison_simple:VEC_F |
800 | (match_operand:VEC_F 1 "vfloat_operand") | |
801 | (match_operand:VEC_F 2 "vfloat_operand")))] | |
802 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()" | |
46402cbe | 803 | "#" |
bceb7181 KL |
804 | "&& can_create_pseudo_p ()" |
805 | [(pc)] | |
46402cbe | 806 | { |
bceb7181 KL |
807 | enum rtx_code cond = <CODE>; |
808 | bool need_invert = false; | |
809 | ||
810 | if (cond == UNLE || cond == UNLT || cond == NE || cond == UNGE | |
811 | || cond == UNGT) | |
812 | { | |
813 | cond = reverse_condition_maybe_unordered (cond); | |
814 | need_invert = true; | |
815 | } | |
816 | ||
817 | if (cond == LT || cond == LE) | |
818 | { | |
819 | cond = swap_condition (cond); | |
820 | std::swap (operands[1], operands[2]); | |
821 | } | |
822 | ||
823 | gcc_assert (cond == EQ || cond == GE || cond == GT); | |
824 | ||
825 | rtx comp = gen_rtx_fmt_ee (cond, <MODE>mode, operands[1], operands[2]); | |
826 | ||
827 | if (need_invert) | |
828 | { | |
829 | rtx res = gen_reg_rtx (<MODE>mode); | |
830 | emit_insn (gen_rtx_SET (res, comp)); | |
831 | emit_insn (gen_one_cmpl<mode>2 (operands[0], res)); | |
832 | } | |
833 | else | |
834 | emit_insn (gen_rtx_SET (operands[0], comp)); | |
835 | ||
836 | DONE; | |
6c332313 | 837 | }) |
46402cbe | 838 | |
bceb7181 KL |
839 | ; For ltgt/uneq/ordered/unordered: |
840 | ; ltgt: gt(a,b) | gt(b,a) | |
841 | ; uneq: ~(gt(a,b) | gt(b,a)) | |
842 | ; ordered: ge(a,b) | ge(b,a) | |
843 | ; unordered: ~(ge(a,b) | ge(b,a)) | |
844 | (define_insn_and_split "vector_<code><mode>" | |
ad18eed2 | 845 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
bceb7181 KL |
846 | (vector_fp_comparison_complex:VEC_F |
847 | (match_operand:VEC_F 1 "vfloat_operand") | |
848 | (match_operand:VEC_F 2 "vfloat_operand")))] | |
849 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()" | |
46402cbe | 850 | "#" |
bceb7181 KL |
851 | "&& can_create_pseudo_p ()" |
852 | [(pc)] | |
46402cbe | 853 | { |
bceb7181 KL |
854 | enum rtx_code cond = <CODE>; |
855 | bool need_invert = false; | |
856 | ||
857 | if (cond == UNORDERED || cond == UNEQ) | |
858 | { | |
859 | cond = reverse_condition_maybe_unordered (cond); | |
860 | need_invert = true; | |
861 | } | |
862 | ||
863 | if (cond == LTGT) | |
864 | cond = GT; | |
865 | else if (cond == ORDERED) | |
866 | cond = GE; | |
867 | else | |
868 | gcc_unreachable (); | |
869 | ||
870 | rtx comp1 = gen_rtx_fmt_ee (cond, <MODE>mode, operands[1], operands[2]); | |
871 | rtx res1 = gen_reg_rtx (<MODE>mode); | |
872 | emit_insn (gen_rtx_SET (res1, comp1)); | |
873 | rtx comp2 = gen_rtx_fmt_ee (cond, <MODE>mode, operands[2], operands[1]); | |
874 | rtx res2 = gen_reg_rtx (<MODE>mode); | |
875 | emit_insn (gen_rtx_SET (res2, comp2)); | |
876 | ||
877 | if (need_invert) | |
878 | { | |
879 | rtx not1 = gen_rtx_fmt_e (NOT, <MODE>mode, res1); | |
880 | rtx not2 = gen_rtx_fmt_e (NOT, <MODE>mode, res2); | |
881 | rtx comp3 = gen_rtx_fmt_ee (AND, <MODE>mode, not1, not2); | |
882 | emit_insn (gen_rtx_SET (operands[0], comp3)); | |
883 | } | |
884 | else | |
885 | emit_insn (gen_ior<mode>3 (operands[0], res1, res2)); | |
886 | ||
887 | DONE; | |
6c332313 | 888 | }) |
46402cbe | 889 | |
a72c65c7 MM |
890 | ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask |
891 | ;; which is in the reverse order that we want | |
892 | (define_expand "vector_select_<mode>" | |
ad18eed2 | 893 | [(set (match_operand:VEC_L 0 "vlogical_operand") |
9222481f XL |
894 | (ior:VEC_L |
895 | (and:VEC_L (not:VEC_L (match_operand:VEC_L 3 "vlogical_operand")) | |
896 | (match_operand:VEC_L 1 "vlogical_operand")) | |
897 | (and:VEC_L (match_dup 3) | |
898 | (match_operand:VEC_L 2 "vlogical_operand"))))] | |
899 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)") | |
a72c65c7 MM |
900 | |
901 | (define_expand "vector_select_<mode>_uns" | |
ad18eed2 | 902 | [(set (match_operand:VEC_L 0 "vlogical_operand") |
9222481f XL |
903 | (ior:VEC_L |
904 | (and:VEC_L (not:VEC_L (match_operand:VEC_L 3 "vlogical_operand")) | |
905 | (match_operand:VEC_L 1 "vlogical_operand")) | |
906 | (and:VEC_L (match_dup 3) | |
907 | (match_operand:VEC_L 2 "vlogical_operand"))))] | |
908 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)") | |
a72c65c7 MM |
909 | |
910 | ;; Expansions that compare vectors producing a vector result and a predicate, | |
911 | ;; setting CR6 to indicate a combined status | |
912 | (define_expand "vector_eq_<mode>_p" | |
913 | [(parallel | |
b65261f6 | 914 | [(set (reg:CC CR6_REGNO) |
ad18eed2 SB |
915 | (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand") |
916 | (match_operand:VEC_A 2 "vlogical_operand"))] | |
a72c65c7 | 917 | UNSPEC_PREDICATE)) |
ad18eed2 | 918 | (set (match_operand:VEC_A 0 "vlogical_operand") |
a72c65c7 MM |
919 | (eq:VEC_A (match_dup 1) |
920 | (match_dup 2)))])] | |
29e6733c | 921 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
922 | "") |
923 | ||
f03122f2 CL |
924 | (define_expand "vector_eq_v1ti_p" |
925 | [(parallel | |
926 | [(set (reg:CC CR6_REGNO) | |
927 | (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand") | |
928 | (match_operand:V1TI 2 "altivec_register_operand"))] | |
929 | UNSPEC_PREDICATE)) | |
930 | (set (match_operand:V1TI 0 "vlogical_operand") | |
931 | (eq:V1TI (match_dup 1) | |
932 | (match_dup 2)))])] | |
933 | "TARGET_POWER10" | |
934 | "") | |
935 | ||
902cb7b1 | 936 | ;; This expansion handles the V16QI, V8HI, and V4SI modes in the |
50181506 | 937 | ;; implementation of the vec_all_ne built-in functions on Power9. |
902cb7b1 KN |
938 | (define_expand "vector_ne_<mode>_p" |
939 | [(parallel | |
940 | [(set (reg:CC CR6_REGNO) | |
941 | (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand") | |
942 | (match_operand:VI 2 "vlogical_operand"))] | |
943 | UNSPEC_PREDICATE)) | |
d36a53d6 | 944 | (set (match_dup 3) |
902cb7b1 | 945 | (ne:VI (match_dup 1) |
50181506 KN |
946 | (match_dup 2)))]) |
947 | (set (match_operand:SI 0 "register_operand" "=r") | |
948 | (lt:SI (reg:CC CR6_REGNO) | |
949 | (const_int 0)))] | |
902cb7b1 | 950 | "TARGET_P9_VECTOR" |
50181506 | 951 | { |
d36a53d6 | 952 | operands[3] = gen_reg_rtx (<MODE>mode); |
50181506 KN |
953 | }) |
954 | ||
955 | ;; This expansion handles the V16QI, V8HI, and V4SI modes in the | |
956 | ;; implementation of the vec_any_eq built-in functions on Power9. | |
957 | (define_expand "vector_ae_<mode>_p" | |
958 | [(parallel | |
959 | [(set (reg:CC CR6_REGNO) | |
960 | (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand") | |
961 | (match_operand:VI 2 "vlogical_operand"))] | |
962 | UNSPEC_PREDICATE)) | |
d36a53d6 | 963 | (set (match_dup 3) |
50181506 KN |
964 | (ne:VI (match_dup 1) |
965 | (match_dup 2)))]) | |
966 | (set (match_operand:SI 0 "register_operand" "=r") | |
967 | (lt:SI (reg:CC CR6_REGNO) | |
968 | (const_int 0))) | |
969 | (set (match_dup 0) | |
970 | (xor:SI (match_dup 0) | |
971 | (const_int 1)))] | |
972 | "TARGET_P9_VECTOR" | |
973 | { | |
d36a53d6 | 974 | operands[3] = gen_reg_rtx (<MODE>mode); |
50181506 | 975 | }) |
902cb7b1 KN |
976 | |
977 | ;; This expansion handles the V16QI, V8HI, and V4SI modes in the | |
978 | ;; implementation of the vec_all_nez and vec_any_eqz built-in | |
979 | ;; functions on Power9. | |
980 | (define_expand "vector_nez_<mode>_p" | |
981 | [(parallel | |
982 | [(set (reg:CC CR6_REGNO) | |
983 | (unspec:CC [(unspec:VI | |
984 | [(match_operand:VI 1 "vlogical_operand") | |
985 | (match_operand:VI 2 "vlogical_operand")] | |
986 | UNSPEC_NEZ_P)] | |
987 | UNSPEC_PREDICATE)) | |
988 | (set (match_operand:VI 0 "vlogical_operand") | |
989 | (unspec:VI [(match_dup 1) | |
990 | (match_dup 2)] | |
991 | UNSPEC_NEZ_P))])] | |
992 | "TARGET_P9_VECTOR" | |
993 | "") | |
994 | ||
50181506 KN |
995 | ;; This expansion handles the V2DI mode in the implementation of the |
996 | ;; vec_all_ne built-in function on Power9. | |
902cb7b1 | 997 | ;; |
50181506 KN |
998 | ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode, |
999 | ;; this expands into the same rtl that would be used for the Power8 | |
1000 | ;; architecture. | |
902cb7b1 KN |
1001 | (define_expand "vector_ne_v2di_p" |
1002 | [(parallel | |
1003 | [(set (reg:CC CR6_REGNO) | |
50181506 KN |
1004 | (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand") |
1005 | (match_operand:V2DI 2 "vlogical_operand"))] | |
1006 | UNSPEC_PREDICATE)) | |
d36a53d6 | 1007 | (set (match_dup 3) |
50181506 KN |
1008 | (eq:V2DI (match_dup 1) |
1009 | (match_dup 2)))]) | |
1010 | (set (match_operand:SI 0 "register_operand" "=r") | |
1011 | (eq:SI (reg:CC CR6_REGNO) | |
1012 | (const_int 0)))] | |
902cb7b1 | 1013 | "TARGET_P9_VECTOR" |
50181506 | 1014 | { |
d36a53d6 | 1015 | operands[3] = gen_reg_rtx (V2DImode); |
50181506 KN |
1016 | }) |
1017 | ||
f03122f2 CL |
1018 | (define_expand "vector_ne_v1ti_p" |
1019 | [(parallel | |
1020 | [(set (reg:CC CR6_REGNO) | |
1021 | (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand") | |
1022 | (match_operand:V1TI 2 "altivec_register_operand"))] | |
1023 | UNSPEC_PREDICATE)) | |
1024 | (set (match_dup 3) | |
1025 | (eq:V1TI (match_dup 1) | |
1026 | (match_dup 2)))]) | |
1027 | (set (match_operand:SI 0 "register_operand" "=r") | |
1028 | (eq:SI (reg:CC CR6_REGNO) | |
1029 | (const_int 0)))] | |
1030 | "TARGET_POWER10" | |
1031 | { | |
1032 | operands[3] = gen_reg_rtx (V1TImode); | |
1033 | }) | |
1034 | ||
50181506 KN |
1035 | ;; This expansion handles the V2DI mode in the implementation of the |
1036 | ;; vec_any_eq built-in function on Power9. | |
1037 | ;; | |
1038 | ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode, | |
1039 | ;; this expands into the same rtl that would be used for the Power8 | |
1040 | ;; architecture. | |
1041 | (define_expand "vector_ae_v2di_p" | |
1042 | [(parallel | |
1043 | [(set (reg:CC CR6_REGNO) | |
1044 | (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand") | |
1045 | (match_operand:V2DI 2 "vlogical_operand"))] | |
1046 | UNSPEC_PREDICATE)) | |
d36a53d6 | 1047 | (set (match_dup 3) |
50181506 KN |
1048 | (eq:V2DI (match_dup 1) |
1049 | (match_dup 2)))]) | |
1050 | (set (match_operand:SI 0 "register_operand" "=r") | |
b0ba96c2 | 1051 | (eq:SI (reg:CC CR6_REGNO) |
50181506 KN |
1052 | (const_int 0))) |
1053 | (set (match_dup 0) | |
1054 | (xor:SI (match_dup 0) | |
1055 | (const_int 1)))] | |
1056 | "TARGET_P9_VECTOR" | |
1057 | { | |
d36a53d6 | 1058 | operands[3] = gen_reg_rtx (V2DImode); |
50181506 | 1059 | }) |
902cb7b1 | 1060 | |
f03122f2 CL |
1061 | (define_expand "vector_ae_v1ti_p" |
1062 | [(parallel | |
1063 | [(set (reg:CC CR6_REGNO) | |
1064 | (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand") | |
1065 | (match_operand:V1TI 2 "altivec_register_operand"))] | |
1066 | UNSPEC_PREDICATE)) | |
1067 | (set (match_dup 3) | |
1068 | (eq:V1TI (match_dup 1) | |
1069 | (match_dup 2)))]) | |
1070 | (set (match_operand:SI 0 "register_operand" "=r") | |
1071 | (eq:SI (reg:CC CR6_REGNO) | |
1072 | (const_int 0))) | |
1073 | (set (match_dup 0) | |
1074 | (xor:SI (match_dup 0) | |
1075 | (const_int 1)))] | |
1076 | "TARGET_POWER10" | |
1077 | { | |
1078 | operands[3] = gen_reg_rtx (V1TImode); | |
1079 | }) | |
1080 | ||
902cb7b1 | 1081 | ;; This expansion handles the V4SF and V2DF modes in the Power9 |
50181506 KN |
1082 | ;; implementation of the vec_all_ne built-in functions. Note that the |
1083 | ;; expansions for this pattern with these modes makes no use of power9- | |
1084 | ;; specific instructions since there are no new power9 instructions | |
1085 | ;; for vector compare not equal with floating point arguments. | |
902cb7b1 KN |
1086 | (define_expand "vector_ne_<mode>_p" |
1087 | [(parallel | |
1088 | [(set (reg:CC CR6_REGNO) | |
50181506 | 1089 | (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand") |
902cb7b1 | 1090 | (match_operand:VEC_F 2 "vlogical_operand"))] |
50181506 | 1091 | UNSPEC_PREDICATE)) |
d36a53d6 | 1092 | (set (match_dup 3) |
50181506 KN |
1093 | (eq:VEC_F (match_dup 1) |
1094 | (match_dup 2)))]) | |
1095 | (set (match_operand:SI 0 "register_operand" "=r") | |
1096 | (eq:SI (reg:CC CR6_REGNO) | |
1097 | (const_int 0)))] | |
902cb7b1 | 1098 | "TARGET_P9_VECTOR" |
50181506 | 1099 | { |
d36a53d6 | 1100 | operands[3] = gen_reg_rtx (<MODE>mode); |
50181506 KN |
1101 | }) |
1102 | ||
1103 | ;; This expansion handles the V4SF and V2DF modes in the Power9 | |
1104 | ;; implementation of the vec_any_eq built-in functions. Note that the | |
1105 | ;; expansions for this pattern with these modes makes no use of power9- | |
1106 | ;; specific instructions since there are no new power9 instructions | |
1107 | ;; for vector compare not equal with floating point arguments. | |
1108 | (define_expand "vector_ae_<mode>_p" | |
1109 | [(parallel | |
1110 | [(set (reg:CC CR6_REGNO) | |
1111 | (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand") | |
1112 | (match_operand:VEC_F 2 "vlogical_operand"))] | |
1113 | UNSPEC_PREDICATE)) | |
d36a53d6 | 1114 | (set (match_dup 3) |
50181506 KN |
1115 | (eq:VEC_F (match_dup 1) |
1116 | (match_dup 2)))]) | |
1117 | (set (match_operand:SI 0 "register_operand" "=r") | |
b0ba96c2 | 1118 | (eq:SI (reg:CC CR6_REGNO) |
50181506 KN |
1119 | (const_int 0))) |
1120 | (set (match_dup 0) | |
1121 | (xor:SI (match_dup 0) | |
1122 | (const_int 1)))] | |
1123 | "TARGET_P9_VECTOR" | |
1124 | { | |
d36a53d6 | 1125 | operands[3] = gen_reg_rtx (<MODE>mode); |
50181506 | 1126 | }) |
902cb7b1 | 1127 | |
a72c65c7 MM |
1128 | (define_expand "vector_gt_<mode>_p" |
1129 | [(parallel | |
b65261f6 | 1130 | [(set (reg:CC CR6_REGNO) |
ad18eed2 SB |
1131 | (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand") |
1132 | (match_operand:VEC_A 2 "vlogical_operand"))] | |
a72c65c7 | 1133 | UNSPEC_PREDICATE)) |
ad18eed2 | 1134 | (set (match_operand:VEC_A 0 "vlogical_operand") |
a72c65c7 MM |
1135 | (gt:VEC_A (match_dup 1) |
1136 | (match_dup 2)))])] | |
29e6733c | 1137 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
1138 | "") |
1139 | ||
f03122f2 CL |
1140 | (define_expand "vector_gt_v1ti_p" |
1141 | [(parallel | |
1142 | [(set (reg:CC CR6_REGNO) | |
1143 | (unspec:CC [(gt:CC (match_operand:V1TI 1 "vlogical_operand") | |
1144 | (match_operand:V1TI 2 "vlogical_operand"))] | |
1145 | UNSPEC_PREDICATE)) | |
1146 | (set (match_operand:V1TI 0 "vlogical_operand") | |
1147 | (gt:V1TI (match_dup 1) | |
1148 | (match_dup 2)))])] | |
1149 | "TARGET_POWER10" | |
1150 | "") | |
1151 | ||
a72c65c7 MM |
1152 | (define_expand "vector_ge_<mode>_p" |
1153 | [(parallel | |
b65261f6 | 1154 | [(set (reg:CC CR6_REGNO) |
ad18eed2 SB |
1155 | (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand") |
1156 | (match_operand:VEC_F 2 "vfloat_operand"))] | |
a72c65c7 | 1157 | UNSPEC_PREDICATE)) |
ad18eed2 | 1158 | (set (match_operand:VEC_F 0 "vfloat_operand") |
a72c65c7 MM |
1159 | (ge:VEC_F (match_dup 1) |
1160 | (match_dup 2)))])] | |
29e6733c | 1161 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
1162 | "") |
1163 | ||
1164 | (define_expand "vector_gtu_<mode>_p" | |
1165 | [(parallel | |
b65261f6 | 1166 | [(set (reg:CC CR6_REGNO) |
8d1c6e70 HG |
1167 | (unspec:CC [(gtu:CC (match_operand:VEC_IC 1 "vint_operand") |
1168 | (match_operand:VEC_IC 2 "vint_operand"))] | |
a72c65c7 | 1169 | UNSPEC_PREDICATE)) |
8d1c6e70 HG |
1170 | (set (match_operand:VEC_IC 0 "vlogical_operand") |
1171 | (gtu:VEC_IC (match_dup 1) | |
1172 | (match_dup 2)))])] | |
29e6733c | 1173 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
1174 | "") |
1175 | ||
29e6733c | 1176 | ;; AltiVec/VSX predicates. |
a72c65c7 | 1177 | |
902cb7b1 KN |
1178 | ;; This expansion is triggered during expansion of predicate built-in |
1179 | ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the | |
1180 | ;; altivec_expand_predicate_builtin() function when the value of the | |
1181 | ;; integer constant first argument equals zero (aka __CR6_EQ in altivec.h). | |
a72c65c7 MM |
1182 | (define_expand "cr6_test_for_zero" |
1183 | [(set (match_operand:SI 0 "register_operand" "=r") | |
b65261f6 | 1184 | (eq:SI (reg:CC CR6_REGNO) |
a72c65c7 | 1185 | (const_int 0)))] |
29e6733c | 1186 | "TARGET_ALTIVEC || TARGET_VSX" |
2fcd8e02 | 1187 | "") |
a72c65c7 | 1188 | |
902cb7b1 KN |
1189 | ;; This expansion is triggered during expansion of predicate built-in |
1190 | ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the | |
1191 | ;; altivec_expand_predicate_builtin() function when the value of the | |
1192 | ;; integer constant first argument equals one (aka __CR6_EQ_REV in altivec.h). | |
a72c65c7 MM |
1193 | (define_expand "cr6_test_for_zero_reverse" |
1194 | [(set (match_operand:SI 0 "register_operand" "=r") | |
b65261f6 | 1195 | (eq:SI (reg:CC CR6_REGNO) |
a72c65c7 | 1196 | (const_int 0))) |
e4fb6f09 SB |
1197 | (set (match_dup 0) |
1198 | (xor:SI (match_dup 0) | |
1199 | (const_int 1)))] | |
29e6733c | 1200 | "TARGET_ALTIVEC || TARGET_VSX" |
a72c65c7 MM |
1201 | "") |
1202 | ||
902cb7b1 KN |
1203 | ;; This expansion is triggered during expansion of predicate built-in |
1204 | ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the | |
1205 | ;; altivec_expand_predicate_builtin() function when the value of the | |
1206 | ;; integer constant first argument equals two (aka __CR6_LT in altivec.h). | |
a72c65c7 MM |
1207 | (define_expand "cr6_test_for_lt" |
1208 | [(set (match_operand:SI 0 "register_operand" "=r") | |
b65261f6 | 1209 | (lt:SI (reg:CC CR6_REGNO) |
a72c65c7 | 1210 | (const_int 0)))] |
29e6733c | 1211 | "TARGET_ALTIVEC || TARGET_VSX" |
a72c65c7 MM |
1212 | "") |
1213 | ||
902cb7b1 KN |
1214 | ;; This expansion is triggered during expansion of predicate built-in |
1215 | ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the | |
1216 | ;; altivec_expand_predicate_builtin() function when the value of the | |
1217 | ;; integer constant first argument equals three | |
1218 | ;; (aka __CR6_LT_REV in altivec.h). | |
a72c65c7 MM |
1219 | (define_expand "cr6_test_for_lt_reverse" |
1220 | [(set (match_operand:SI 0 "register_operand" "=r") | |
b65261f6 | 1221 | (lt:SI (reg:CC CR6_REGNO) |
a72c65c7 | 1222 | (const_int 0))) |
e4fb6f09 SB |
1223 | (set (match_dup 0) |
1224 | (xor:SI (match_dup 0) | |
1225 | (const_int 1)))] | |
29e6733c | 1226 | "TARGET_ALTIVEC || TARGET_VSX" |
a72c65c7 MM |
1227 | "") |
1228 | ||
1229 | \f | |
0bd62dca MM |
1230 | ;; Vector count leading zeros |
1231 | (define_expand "clz<mode>2" | |
ad18eed2 SB |
1232 | [(set (match_operand:VEC_I 0 "register_operand") |
1233 | (clz:VEC_I (match_operand:VEC_I 1 "register_operand")))] | |
0bd62dca MM |
1234 | "TARGET_P8_VECTOR") |
1235 | ||
4bfc9db7 MM |
1236 | ;; Vector count trailing zeros |
1237 | (define_expand "ctz<mode>2" | |
ad18eed2 SB |
1238 | [(set (match_operand:VEC_I 0 "register_operand") |
1239 | (ctz:VEC_I (match_operand:VEC_I 1 "register_operand")))] | |
4bfc9db7 MM |
1240 | "TARGET_P9_VECTOR") |
1241 | ||
0bd62dca MM |
1242 | ;; Vector population count |
1243 | (define_expand "popcount<mode>2" | |
ad18eed2 SB |
1244 | [(set (match_operand:VEC_I 0 "register_operand") |
1245 | (popcount:VEC_I (match_operand:VEC_I 1 "register_operand")))] | |
0bd62dca MM |
1246 | "TARGET_P8_VECTOR") |
1247 | ||
4bfc9db7 MM |
1248 | ;; Vector parity |
1249 | (define_expand "parity<mode>2" | |
ad18eed2 SB |
1250 | [(set (match_operand:VEC_IP 0 "register_operand") |
1251 | (parity:VEC_IP (match_operand:VEC_IP 1 "register_operand")))] | |
cdd2d664 KL |
1252 | "TARGET_P9_VECTOR" |
1253 | { | |
1254 | rtx op1 = gen_lowpart (V16QImode, operands[1]); | |
1255 | rtx res = gen_reg_rtx (V16QImode); | |
1256 | emit_insn (gen_popcountv16qi2 (res, op1)); | |
1257 | emit_insn (gen_rs6000_vprtyb<mode>2 (operands[0], | |
1258 | gen_lowpart (<MODE>mode, res))); | |
1259 | ||
1260 | DONE; | |
1261 | }) | |
4bfc9db7 | 1262 | |
0bd62dca | 1263 | \f |
a72c65c7 MM |
1264 | ;; Same size conversions |
1265 | (define_expand "float<VEC_int><mode>2" | |
ad18eed2 SB |
1266 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
1267 | (float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))] | |
29e6733c | 1268 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 1269 | { |
29e6733c MM |
1270 | if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) |
1271 | { | |
1272 | emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx)); | |
1273 | DONE; | |
1274 | } | |
6c332313 | 1275 | }) |
a72c65c7 | 1276 | |
7fa14a01 | 1277 | (define_expand "floatuns<VEC_int><mode>2" |
ad18eed2 SB |
1278 | [(set (match_operand:VEC_F 0 "vfloat_operand") |
1279 | (unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))] | |
29e6733c | 1280 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 1281 | { |
29e6733c MM |
1282 | if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) |
1283 | { | |
1284 | emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx)); | |
1285 | DONE; | |
1286 | } | |
6c332313 | 1287 | }) |
a72c65c7 MM |
1288 | |
1289 | (define_expand "fix_trunc<mode><VEC_int>2" | |
ad18eed2 SB |
1290 | [(set (match_operand:<VEC_INT> 0 "vint_operand") |
1291 | (fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))] | |
29e6733c | 1292 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 1293 | { |
29e6733c MM |
1294 | if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) |
1295 | { | |
1296 | emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx)); | |
1297 | DONE; | |
1298 | } | |
6c332313 | 1299 | }) |
a72c65c7 MM |
1300 | |
1301 | (define_expand "fixuns_trunc<mode><VEC_int>2" | |
ad18eed2 SB |
1302 | [(set (match_operand:<VEC_INT> 0 "vint_operand") |
1303 | (unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))] | |
29e6733c | 1304 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 1305 | { |
29e6733c MM |
1306 | if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) |
1307 | { | |
1308 | emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx)); | |
1309 | DONE; | |
1310 | } | |
6c332313 | 1311 | }) |
a72c65c7 MM |
1312 | |
1313 | \f | |
1314 | ;; Vector initialization, set, extract | |
ff03930a | 1315 | (define_expand "vec_init<mode><VEC_base_l>" |
ad18eed2 SB |
1316 | [(match_operand:VEC_E 0 "vlogical_operand") |
1317 | (match_operand:VEC_E 1 "")] | |
29e6733c | 1318 | "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
1319 | { |
1320 | rs6000_expand_vector_init (operands[0], operands[1]); | |
1321 | DONE; | |
1322 | }) | |
1323 | ||
1324 | (define_expand "vec_set<mode>" | |
ad18eed2 SB |
1325 | [(match_operand:VEC_E 0 "vlogical_operand") |
1326 | (match_operand:<VEC_base> 1 "register_operand") | |
f64b9156 | 1327 | (match_operand 2 "vec_set_index_operand")] |
29e6733c | 1328 | "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 1329 | { |
5e9f814d | 1330 | rs6000_expand_vector_set (operands[0], operands[1], operands[2]); |
a72c65c7 MM |
1331 | DONE; |
1332 | }) | |
1333 | ||
ff03930a | 1334 | (define_expand "vec_extract<mode><VEC_base_l>" |
ad18eed2 SB |
1335 | [(match_operand:<VEC_base> 0 "register_operand") |
1336 | (match_operand:VEC_E 1 "vlogical_operand") | |
1337 | (match_operand 2 "const_int_operand")] | |
29e6733c | 1338 | "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 1339 | { |
98060bbe | 1340 | rs6000_expand_vector_extract (operands[0], operands[1], operands[2]); |
a72c65c7 MM |
1341 | DONE; |
1342 | }) | |
29e6733c MM |
1343 | \f |
1344 | ;; Convert double word types to single word types | |
1345 | (define_expand "vec_pack_trunc_v2df" | |
ad18eed2 SB |
1346 | [(match_operand:V4SF 0 "vfloat_operand") |
1347 | (match_operand:V2DF 1 "vfloat_operand") | |
1348 | (match_operand:V2DF 2 "vfloat_operand")] | |
29e6733c MM |
1349 | "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" |
1350 | { | |
1351 | rtx r1 = gen_reg_rtx (V4SFmode); | |
1352 | rtx r2 = gen_reg_rtx (V4SFmode); | |
1353 | ||
1354 | emit_insn (gen_vsx_xvcvdpsp (r1, operands[1])); | |
1355 | emit_insn (gen_vsx_xvcvdpsp (r2, operands[2])); | |
5b3f0a54 | 1356 | rs6000_expand_extract_even (operands[0], r1, r2); |
29e6733c MM |
1357 | DONE; |
1358 | }) | |
1359 | ||
1360 | (define_expand "vec_pack_sfix_trunc_v2df" | |
ad18eed2 SB |
1361 | [(match_operand:V4SI 0 "vint_operand") |
1362 | (match_operand:V2DF 1 "vfloat_operand") | |
1363 | (match_operand:V2DF 2 "vfloat_operand")] | |
29e6733c MM |
1364 | "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" |
1365 | { | |
1366 | rtx r1 = gen_reg_rtx (V4SImode); | |
1367 | rtx r2 = gen_reg_rtx (V4SImode); | |
1368 | ||
1369 | emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1])); | |
1370 | emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2])); | |
5b3f0a54 | 1371 | rs6000_expand_extract_even (operands[0], r1, r2); |
29e6733c MM |
1372 | DONE; |
1373 | }) | |
1374 | ||
1375 | (define_expand "vec_pack_ufix_trunc_v2df" | |
ad18eed2 SB |
1376 | [(match_operand:V4SI 0 "vint_operand") |
1377 | (match_operand:V2DF 1 "vfloat_operand") | |
1378 | (match_operand:V2DF 2 "vfloat_operand")] | |
29e6733c MM |
1379 | "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" |
1380 | { | |
1381 | rtx r1 = gen_reg_rtx (V4SImode); | |
1382 | rtx r2 = gen_reg_rtx (V4SImode); | |
1383 | ||
1384 | emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1])); | |
1385 | emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2])); | |
5b3f0a54 | 1386 | rs6000_expand_extract_even (operands[0], r1, r2); |
29e6733c MM |
1387 | DONE; |
1388 | }) | |
1389 | ||
1390 | ;; Convert single word types to double word | |
1391 | (define_expand "vec_unpacks_hi_v4sf" | |
ad18eed2 SB |
1392 | [(match_operand:V2DF 0 "vfloat_operand") |
1393 | (match_operand:V4SF 1 "vfloat_operand")] | |
29e6733c MM |
1394 | "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)" |
1395 | { | |
1396 | rtx reg = gen_reg_rtx (V4SFmode); | |
1397 | ||
90d3bd51 | 1398 | rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN); |
29e6733c MM |
1399 | emit_insn (gen_vsx_xvcvspdp (operands[0], reg)); |
1400 | DONE; | |
1401 | }) | |
1402 | ||
1403 | (define_expand "vec_unpacks_lo_v4sf" | |
ad18eed2 SB |
1404 | [(match_operand:V2DF 0 "vfloat_operand") |
1405 | (match_operand:V4SF 1 "vfloat_operand")] | |
29e6733c MM |
1406 | "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)" |
1407 | { | |
1408 | rtx reg = gen_reg_rtx (V4SFmode); | |
1409 | ||
90d3bd51 | 1410 | rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN); |
29e6733c MM |
1411 | emit_insn (gen_vsx_xvcvspdp (operands[0], reg)); |
1412 | DONE; | |
1413 | }) | |
1414 | ||
1415 | (define_expand "vec_unpacks_float_hi_v4si" | |
ad18eed2 SB |
1416 | [(match_operand:V2DF 0 "vfloat_operand") |
1417 | (match_operand:V4SI 1 "vint_operand")] | |
29e6733c MM |
1418 | "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" |
1419 | { | |
1420 | rtx reg = gen_reg_rtx (V4SImode); | |
1421 | ||
90d3bd51 | 1422 | rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN); |
29e6733c MM |
1423 | emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg)); |
1424 | DONE; | |
1425 | }) | |
1426 | ||
1427 | (define_expand "vec_unpacks_float_lo_v4si" | |
ad18eed2 SB |
1428 | [(match_operand:V2DF 0 "vfloat_operand") |
1429 | (match_operand:V4SI 1 "vint_operand")] | |
29e6733c MM |
1430 | "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" |
1431 | { | |
1432 | rtx reg = gen_reg_rtx (V4SImode); | |
1433 | ||
90d3bd51 | 1434 | rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN); |
29e6733c MM |
1435 | emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg)); |
1436 | DONE; | |
1437 | }) | |
1438 | ||
1439 | (define_expand "vec_unpacku_float_hi_v4si" | |
ad18eed2 SB |
1440 | [(match_operand:V2DF 0 "vfloat_operand") |
1441 | (match_operand:V4SI 1 "vint_operand")] | |
29e6733c MM |
1442 | "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" |
1443 | { | |
1444 | rtx reg = gen_reg_rtx (V4SImode); | |
1445 | ||
90d3bd51 | 1446 | rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN); |
29e6733c MM |
1447 | emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg)); |
1448 | DONE; | |
1449 | }) | |
1450 | ||
1451 | (define_expand "vec_unpacku_float_lo_v4si" | |
ad18eed2 SB |
1452 | [(match_operand:V2DF 0 "vfloat_operand") |
1453 | (match_operand:V4SI 1 "vint_operand")] | |
29e6733c MM |
1454 | "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" |
1455 | { | |
1456 | rtx reg = gen_reg_rtx (V4SImode); | |
1457 | ||
90d3bd51 | 1458 | rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN); |
29e6733c MM |
1459 | emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg)); |
1460 | DONE; | |
1461 | }) | |
1462 | ||
a72c65c7 MM |
1463 | \f |
1464 | ;; Align vector loads with a permute. | |
1465 | (define_expand "vec_realign_load_<mode>" | |
ad18eed2 SB |
1466 | [(match_operand:VEC_K 0 "vlogical_operand") |
1467 | (match_operand:VEC_K 1 "vlogical_operand") | |
1468 | (match_operand:VEC_K 2 "vlogical_operand") | |
1469 | (match_operand:V16QI 3 "vlogical_operand")] | |
29e6733c | 1470 | "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 | 1471 | { |
493f4c9e BS |
1472 | if (BYTES_BIG_ENDIAN) |
1473 | emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1], | |
1474 | operands[2], operands[3])); | |
1475 | else | |
f200869a | 1476 | { |
e19eea71 BS |
1477 | /* We have changed lvsr to lvsl, so to complete the transformation |
1478 | of vperm for LE, we must swap the inputs. */ | |
f200869a BS |
1479 | rtx unspec = gen_rtx_UNSPEC (<MODE>mode, |
1480 | gen_rtvec (3, operands[2], | |
1481 | operands[1], operands[3]), | |
1482 | UNSPEC_VPERM); | |
1483 | emit_move_insn (operands[0], unspec); | |
1484 | } | |
a72c65c7 MM |
1485 | DONE; |
1486 | }) | |
1487 | ||
29e6733c MM |
1488 | ;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned |
1489 | ;; since the load already handles it. | |
1490 | (define_expand "movmisalign<mode>" | |
ad18eed2 SB |
1491 | [(set (match_operand:VEC_N 0 "nonimmediate_operand") |
1492 | (match_operand:VEC_N 1 "any_operand"))] | |
29e6733c | 1493 | "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN" |
3885a122 JJ |
1494 | { |
1495 | rs6000_emit_move (operands[0], operands[1], <MODE>mode); | |
1496 | DONE; | |
1497 | }) | |
29e6733c | 1498 | |
a72c65c7 MM |
1499 | ;; Vector shift right in bits. Currently supported ony for shift |
1500 | ;; amounts that can be expressed as byte shifts (divisible by 8). | |
1501 | ;; General shift amounts can be supported using vsro + vsr. We're | |
1502 | ;; not expecting to see these yet (the vectorizer currently | |
ba067536 | 1503 | ;; generates only shifts by a whole number of vector elements). |
2b6fb4aa PH |
1504 | ;; Note that the vec_shr operation is actually defined as |
1505 | ;; 'shift toward element 0' so is a shr for LE and shl for BE. | |
a72c65c7 | 1506 | (define_expand "vec_shr_<mode>" |
ad18eed2 SB |
1507 | [(match_operand:VEC_L 0 "vlogical_operand") |
1508 | (match_operand:VEC_L 1 "vlogical_operand") | |
1509 | (match_operand:QI 2 "reg_or_short_operand")] | |
bfad7069 | 1510 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
1511 | { |
1512 | rtx bitshift = operands[2]; | |
1513 | rtx shift; | |
1514 | rtx insn; | |
2b6fb4aa | 1515 | rtx zero_reg, op1, op2; |
a72c65c7 MM |
1516 | HOST_WIDE_INT bitshift_val; |
1517 | HOST_WIDE_INT byteshift_val; | |
2fcd8e02 | 1518 | |
a72c65c7 MM |
1519 | if (! CONSTANT_P (bitshift)) |
1520 | FAIL; | |
1521 | bitshift_val = INTVAL (bitshift); | |
1522 | if (bitshift_val & 0x7) | |
1523 | FAIL; | |
ba067536 | 1524 | byteshift_val = (bitshift_val >> 3); |
2b6fb4aa PH |
1525 | zero_reg = gen_reg_rtx (<MODE>mode); |
1526 | emit_move_insn (zero_reg, CONST0_RTX (<MODE>mode)); | |
ba067536 | 1527 | if (!BYTES_BIG_ENDIAN) |
2b6fb4aa | 1528 | { |
9c725245 SB |
1529 | /* Note, byteshift_val can be 0! */ |
1530 | byteshift_val = -byteshift_val & 15; | |
2b6fb4aa PH |
1531 | op1 = zero_reg; |
1532 | op2 = operands[1]; | |
1533 | } | |
1534 | else | |
1535 | { | |
1536 | op1 = operands[1]; | |
1537 | op2 = zero_reg; | |
1538 | } | |
1539 | ||
29e6733c MM |
1540 | if (TARGET_VSX && (byteshift_val & 0x3) == 0) |
1541 | { | |
1542 | shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2); | |
2b6fb4aa | 1543 | insn = gen_vsx_xxsldwi_<mode> (operands[0], op1, op2, shift); |
29e6733c MM |
1544 | } |
1545 | else | |
1546 | { | |
1547 | shift = gen_rtx_CONST_INT (QImode, byteshift_val); | |
2b6fb4aa | 1548 | insn = gen_altivec_vsldoi_<mode> (operands[0], op1, op2, shift); |
29e6733c | 1549 | } |
a72c65c7 MM |
1550 | |
1551 | emit_insn (insn); | |
1552 | DONE; | |
6c332313 | 1553 | }) |
a72c65c7 MM |
1554 | |
1555 | ;; Expanders for rotate each element in a vector | |
1556 | (define_expand "vrotl<mode>3" | |
8d1c6e70 HG |
1557 | [(set (match_operand:VEC_IC 0 "vint_operand") |
1558 | (rotate:VEC_IC (match_operand:VEC_IC 1 "vint_operand") | |
1559 | (match_operand:VEC_IC 2 "vint_operand")))] | |
a5965b52 | 1560 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
f03122f2 | 1561 | { |
8d1c6e70 HG |
1562 | /* Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */ |
1563 | if (<MODE>mode == V1TImode) | |
1564 | { | |
1565 | rtx tmp = gen_reg_rtx (V1TImode); | |
f03122f2 | 1566 | |
8d1c6e70 HG |
1567 | emit_insn (gen_xxswapd_v1ti (tmp, operands[2])); |
1568 | emit_insn (gen_altivec_vrlq (operands[0], operands[1], tmp)); | |
1569 | DONE; | |
1570 | } | |
1571 | }) | |
f03122f2 | 1572 | |
4e708f5e KL |
1573 | ;; Expanders for rotatert to make use of vrotl |
1574 | (define_expand "vrotr<mode>3" | |
1575 | [(set (match_operand:VEC_I 0 "vint_operand") | |
1576 | (rotatert:VEC_I (match_operand:VEC_I 1 "vint_operand") | |
1577 | (match_operand:VEC_I 2 "vint_operand")))] | |
1578 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" | |
1579 | { | |
1580 | rtx rot_count = gen_reg_rtx (<MODE>mode); | |
1581 | emit_insn (gen_neg<mode>2 (rot_count, operands[2])); | |
1582 | emit_insn (gen_vrotl<mode>3 (operands[0], operands[1], rot_count)); | |
1583 | DONE; | |
1584 | }) | |
1585 | ||
a72c65c7 MM |
1586 | ;; Expanders for arithmetic shift left on each vector element |
1587 | (define_expand "vashl<mode>3" | |
ad18eed2 SB |
1588 | [(set (match_operand:VEC_I 0 "vint_operand") |
1589 | (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand") | |
1590 | (match_operand:VEC_I 2 "vint_operand")))] | |
a5965b52 | 1591 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
1592 | "") |
1593 | ||
f03122f2 | 1594 | ;; No immediate version of this 128-bit instruction |
f1701864 CL |
1595 | (define_expand "vashl<mode>3" |
1596 | [(set (match_operand:VEC_TI 0 "vsx_register_operand" "=v") | |
1597 | (ashift:VEC_TI (match_operand:VEC_TI 1 "vsx_register_operand") | |
1598 | (match_operand:VEC_TI 2 "vsx_register_operand")))] | |
f03122f2 CL |
1599 | "TARGET_POWER10" |
1600 | { | |
1601 | /* Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */ | |
f1701864 | 1602 | rtx tmp = gen_reg_rtx (<MODE>mode); |
f03122f2 CL |
1603 | |
1604 | emit_insn (gen_xxswapd_v1ti (tmp, operands[2])); | |
f1701864 | 1605 | emit_insn(gen_altivec_vslq_<mode> (operands[0], operands[1], tmp)); |
f03122f2 CL |
1606 | DONE; |
1607 | }) | |
1608 | ||
a72c65c7 MM |
1609 | ;; Expanders for logical shift right on each vector element |
1610 | (define_expand "vlshr<mode>3" | |
ad18eed2 SB |
1611 | [(set (match_operand:VEC_I 0 "vint_operand") |
1612 | (lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand") | |
1613 | (match_operand:VEC_I 2 "vint_operand")))] | |
a5965b52 | 1614 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
a72c65c7 MM |
1615 | "") |
1616 | ||
f03122f2 | 1617 | ;; No immediate version of this 128-bit instruction |
f1701864 CL |
1618 | (define_expand "vlshr<mode>3" |
1619 | [(set (match_operand:VEC_TI 0 "vsx_register_operand" "=v") | |
1620 | (lshiftrt:VEC_TI (match_operand:VEC_TI 1 "vsx_register_operand") | |
1621 | (match_operand:VEC_TI 2 "vsx_register_operand")))] | |
f03122f2 CL |
1622 | "TARGET_POWER10" |
1623 | { | |
1624 | /* Shift amount in needs to be put into bits[57:63] of 128-bit operand2. */ | |
f1701864 | 1625 | rtx tmp = gen_reg_rtx (<MODE>mode); |
f03122f2 CL |
1626 | |
1627 | emit_insn (gen_xxswapd_v1ti (tmp, operands[2])); | |
f1701864 | 1628 | emit_insn(gen_altivec_vsrq_<mode> (operands[0], operands[1], tmp)); |
f03122f2 CL |
1629 | DONE; |
1630 | }) | |
1631 | ||
a72c65c7 MM |
1632 | ;; Expanders for arithmetic shift right on each vector element |
1633 | (define_expand "vashr<mode>3" | |
8d1c6e70 HG |
1634 | [(set (match_operand:VEC_IC 0 "vint_operand") |
1635 | (ashiftrt:VEC_IC (match_operand:VEC_IC 1 "vint_operand") | |
1636 | (match_operand:VEC_IC 2 "vint_operand")))] | |
a5965b52 | 1637 | "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" |
f03122f2 | 1638 | { |
8d1c6e70 HG |
1639 | /* Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */ |
1640 | if (<MODE>mode == V1TImode) | |
1641 | { | |
1642 | rtx tmp = gen_reg_rtx (V1TImode); | |
f03122f2 | 1643 | |
8d1c6e70 HG |
1644 | emit_insn (gen_xxswapd_v1ti (tmp, operands[2])); |
1645 | emit_insn (gen_altivec_vsraq (operands[0], operands[1], tmp)); | |
1646 | DONE; | |
1647 | } | |
f03122f2 CL |
1648 | }) |
1649 | ||
ab8d2734 | 1650 | \f |
df10b6d4 | 1651 | ;; Vector reduction expanders for VSX |
5e8edf67 | 1652 | ; The (VEC_reduc:... |
df10b6d4 | 1653 | ; (op1) |
5e8edf67 | 1654 | ; (unspec:... [(const_int 0)] UNSPEC_REDUC)) |
df10b6d4 MM |
1655 | ; |
1656 | ; is to allow us to use a code iterator, but not completely list all of the | |
1657 | ; vector rotates, etc. to prevent canonicalization | |
1658 | ||
5e8edf67 AL |
1659 | |
1660 | (define_expand "reduc_<VEC_reduc:VEC_reduc_name>_scal_<VEC_F:mode>" | |
ad18eed2 SB |
1661 | [(match_operand:<VEC_base> 0 "register_operand") |
1662 | (VEC_reduc:VEC_F (match_operand:VEC_F 1 "vfloat_operand") | |
5e8edf67 AL |
1663 | (unspec:VEC_F [(const_int 0)] UNSPEC_REDUC))] |
1664 | "VECTOR_UNIT_VSX_P (<VEC_F:MODE>mode)" | |
1665 | { | |
1666 | rtx vec = gen_reg_rtx (<VEC_F:MODE>mode); | |
1667 | rtx elt = BYTES_BIG_ENDIAN | |
1668 | ? gen_int_mode (GET_MODE_NUNITS (<VEC_F:MODE>mode) - 1, QImode) | |
1669 | : const0_rtx; | |
1670 | emit_insn (gen_vsx_reduc_<VEC_reduc:VEC_reduc_name>_<VEC_F:mode> (vec, | |
1671 | operand1)); | |
1672 | emit_insn (gen_vsx_extract_<VEC_F:mode> (operand0, vec, elt)); | |
1673 | DONE; | |
1674 | }) |