vector.md (GPR move splitter): Do not split moves of vectors in GPRS if they are...
[gcc.git] / gcc / config / rs6000 / vector.md
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
5
6 ;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
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
27 (define_mode_iterator VEC_I [V16QI V8HI V4SI V2DI])
28
29 ;; Vector float modes
30 (define_mode_iterator VEC_F [V4SF V2DF])
31
32 ;; Vector arithmetic modes
33 (define_mode_iterator VEC_A [V16QI V8HI V4SI V2DI V4SF V2DF])
34
35 ;; Vector modes that need alginment via permutes
36 (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
37
38 ;; Vector logical modes
39 (define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
40
41 ;; Vector modes for moves. Don't do TImode here.
42 (define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF])
43
44 ;; Vector modes for types that don't need a realignment under VSX
45 (define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF])
46
47 ;; Vector comparison modes
48 (define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF])
49
50 ;; Vector init/extract modes
51 (define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF])
52
53 ;; Vector modes for 64-bit base types
54 (define_mode_iterator VEC_64 [V2DI V2DF])
55
56 ;; Vector reload iterator
57 (define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF SF SD SI DF DD DI TI])
58
59 ;; Base type from vector mode
60 (define_mode_attr VEC_base [(V16QI "QI")
61 (V8HI "HI")
62 (V4SI "SI")
63 (V2DI "DI")
64 (V4SF "SF")
65 (V2DF "DF")
66 (TI "TI")])
67
68 ;; Same size integer type for floating point data
69 (define_mode_attr VEC_int [(V4SF "v4si")
70 (V2DF "v2di")])
71
72 (define_mode_attr VEC_INT [(V4SF "V4SI")
73 (V2DF "V2DI")])
74
75 ;; constants for unspec
76 (define_c_enum "unspec" [UNSPEC_PREDICATE
77 UNSPEC_REDUC])
78
79 ;; Vector reduction code iterators
80 (define_code_iterator VEC_reduc [plus smin smax])
81
82 (define_code_attr VEC_reduc_name [(plus "splus")
83 (smin "smin")
84 (smax "smax")])
85
86 (define_code_attr VEC_reduc_rtx [(plus "add")
87 (smin "smin")
88 (smax "smax")])
89
90 \f
91 ;; Vector move instructions.
92 (define_expand "mov<mode>"
93 [(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
94 (match_operand:VEC_M 1 "any_operand" ""))]
95 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
96 {
97 if (can_create_pseudo_p ())
98 {
99 if (CONSTANT_P (operands[1])
100 && !easy_vector_constant (operands[1], <MODE>mode))
101 operands[1] = force_const_mem (<MODE>mode, operands[1]);
102
103 else if (!vlogical_operand (operands[0], <MODE>mode)
104 && !vlogical_operand (operands[1], <MODE>mode))
105 operands[1] = force_reg (<MODE>mode, operands[1]);
106 }
107 })
108
109 ;; Generic vector floating point load/store instructions. These will match
110 ;; insns defined in vsx.md or altivec.md depending on the switches.
111 (define_expand "vector_load_<mode>"
112 [(set (match_operand:VEC_M 0 "vfloat_operand" "")
113 (match_operand:VEC_M 1 "memory_operand" ""))]
114 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
115 "")
116
117 (define_expand "vector_store_<mode>"
118 [(set (match_operand:VEC_M 0 "memory_operand" "")
119 (match_operand:VEC_M 1 "vfloat_operand" ""))]
120 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
121 "")
122
123 ;; Splits if a GPR register was chosen for the move
124 (define_split
125 [(set (match_operand:VEC_L 0 "nonimmediate_operand" "")
126 (match_operand:VEC_L 1 "input_operand" ""))]
127 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
128 && reload_completed
129 && gpr_or_gpr_p (operands[0], operands[1])
130 && !direct_move_p (operands[0], operands[1])
131 && !quad_load_store_p (operands[0], operands[1])"
132 [(pc)]
133 {
134 rs6000_split_multireg_move (operands[0], operands[1]);
135 DONE;
136 })
137
138 ;; Vector floating point load/store instructions that uses the Altivec
139 ;; instructions even if we are compiling for VSX, since the Altivec
140 ;; instructions silently ignore the bottom 3 bits of the address, and VSX does
141 ;; not.
142 (define_expand "vector_altivec_load_<mode>"
143 [(set (match_operand:VEC_M 0 "vfloat_operand" "")
144 (match_operand:VEC_M 1 "memory_operand" ""))]
145 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
146 "
147 {
148 gcc_assert (VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode));
149
150 if (VECTOR_MEM_VSX_P (<MODE>mode))
151 {
152 operands[1] = rs6000_address_for_altivec (operands[1]);
153 emit_insn (gen_altivec_lvx_<mode> (operands[0], operands[1]));
154 DONE;
155 }
156 }")
157
158 (define_expand "vector_altivec_store_<mode>"
159 [(set (match_operand:VEC_M 0 "memory_operand" "")
160 (match_operand:VEC_M 1 "vfloat_operand" ""))]
161 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
162 "
163 {
164 gcc_assert (VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode));
165
166 if (VECTOR_MEM_VSX_P (<MODE>mode))
167 {
168 operands[0] = rs6000_address_for_altivec (operands[0]);
169 emit_insn (gen_altivec_stvx_<mode> (operands[0], operands[1]));
170 DONE;
171 }
172 }")
173
174
175 \f
176 ;; Reload patterns for vector operations. We may need an additional base
177 ;; register to convert the reg+offset addressing to reg+reg for vector
178 ;; registers and reg+reg or (reg+reg)&(-16) addressing to just an index
179 ;; register for gpr registers.
180 (define_expand "reload_<VEC_R:mode>_<P:mptrsize>_store"
181 [(parallel [(match_operand:VEC_R 0 "memory_operand" "m")
182 (match_operand:VEC_R 1 "gpc_reg_operand" "r")
183 (match_operand:P 2 "register_operand" "=&b")])]
184 "<P:tptrsize>"
185 {
186 rs6000_secondary_reload_inner (operands[1], operands[0], operands[2], true);
187 DONE;
188 })
189
190 (define_expand "reload_<VEC_R:mode>_<P:mptrsize>_load"
191 [(parallel [(match_operand:VEC_R 0 "gpc_reg_operand" "=&r")
192 (match_operand:VEC_R 1 "memory_operand" "m")
193 (match_operand:P 2 "register_operand" "=&b")])]
194 "<P:tptrsize>"
195 {
196 rs6000_secondary_reload_inner (operands[0], operands[1], operands[2], false);
197 DONE;
198 })
199
200 ;; Reload sometimes tries to move the address to a GPR, and can generate
201 ;; invalid RTL for addresses involving AND -16. Allow addresses involving
202 ;; reg+reg, reg+small constant, or just reg, all wrapped in an AND -16.
203
204 (define_insn_and_split "*vec_reload_and_plus_<mptrsize>"
205 [(set (match_operand:P 0 "gpc_reg_operand" "=b")
206 (and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
207 (match_operand:P 2 "reg_or_cint_operand" "rI"))
208 (const_int -16)))]
209 "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
210 "#"
211 "&& reload_completed"
212 [(set (match_dup 0)
213 (plus:P (match_dup 1)
214 (match_dup 2)))
215 (parallel [(set (match_dup 0)
216 (and:P (match_dup 0)
217 (const_int -16)))
218 (clobber:CC (scratch:CC))])])
219
220 ;; The normal ANDSI3/ANDDI3 won't match if reload decides to move an AND -16
221 ;; address to a register because there is no clobber of a (scratch), so we add
222 ;; it here.
223 (define_insn_and_split "*vec_reload_and_reg_<mptrsize>"
224 [(set (match_operand:P 0 "gpc_reg_operand" "=b")
225 (and:P (match_operand:P 1 "gpc_reg_operand" "r")
226 (const_int -16)))]
227 "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
228 "#"
229 "&& reload_completed"
230 [(parallel [(set (match_dup 0)
231 (and:P (match_dup 1)
232 (const_int -16)))
233 (clobber:CC (scratch:CC))])])
234 \f
235 ;; Generic floating point vector arithmetic support
236 (define_expand "add<mode>3"
237 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
238 (plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
239 (match_operand:VEC_F 2 "vfloat_operand" "")))]
240 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
241 "")
242
243 (define_expand "sub<mode>3"
244 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
245 (minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
246 (match_operand:VEC_F 2 "vfloat_operand" "")))]
247 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
248 "")
249
250 (define_expand "mul<mode>3"
251 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
252 (mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
253 (match_operand:VEC_F 2 "vfloat_operand" "")))]
254 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
255 {
256 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
257 {
258 emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
259 DONE;
260 }
261 })
262
263 (define_expand "div<mode>3"
264 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
265 (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
266 (match_operand:VEC_F 2 "vfloat_operand" "")))]
267 "VECTOR_UNIT_VSX_P (<MODE>mode)"
268 "")
269
270 (define_expand "neg<mode>2"
271 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
272 (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
273 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
274 "
275 {
276 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
277 {
278 emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
279 DONE;
280 }
281 }")
282
283 (define_expand "abs<mode>2"
284 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
285 (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
286 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
287 "
288 {
289 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
290 {
291 emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
292 DONE;
293 }
294 }")
295
296 (define_expand "smin<mode>3"
297 [(set (match_operand:VEC_F 0 "register_operand" "")
298 (smin:VEC_F (match_operand:VEC_F 1 "register_operand" "")
299 (match_operand:VEC_F 2 "register_operand" "")))]
300 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
301 "")
302
303 (define_expand "smax<mode>3"
304 [(set (match_operand:VEC_F 0 "register_operand" "")
305 (smax:VEC_F (match_operand:VEC_F 1 "register_operand" "")
306 (match_operand:VEC_F 2 "register_operand" "")))]
307 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
308 "")
309
310
311 (define_expand "sqrt<mode>2"
312 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
313 (sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
314 "VECTOR_UNIT_VSX_P (<MODE>mode)"
315 "")
316
317 (define_expand "rsqrte<mode>2"
318 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
319 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
320 UNSPEC_RSQRT))]
321 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
322 "")
323
324 (define_expand "re<mode>2"
325 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
326 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "f")]
327 UNSPEC_FRES))]
328 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
329 "")
330
331 (define_expand "ftrunc<mode>2"
332 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
333 (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
334 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
335 "")
336
337 (define_expand "vector_ceil<mode>2"
338 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
339 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
340 UNSPEC_FRIP))]
341 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
342 "")
343
344 (define_expand "vector_floor<mode>2"
345 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
346 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
347 UNSPEC_FRIM))]
348 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
349 "")
350
351 (define_expand "vector_btrunc<mode>2"
352 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
353 (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
354 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
355 "")
356
357 (define_expand "vector_copysign<mode>3"
358 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
359 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")
360 (match_operand:VEC_F 2 "vfloat_operand" "")] UNSPEC_COPYSIGN))]
361 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
362 "
363 {
364 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
365 {
366 emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1],
367 operands[2]));
368 DONE;
369 }
370 }")
371
372 \f
373 ;; Vector comparisons
374 (define_expand "vcond<mode><mode>"
375 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
376 (if_then_else:VEC_F
377 (match_operator 3 "comparison_operator"
378 [(match_operand:VEC_F 4 "vfloat_operand" "")
379 (match_operand:VEC_F 5 "vfloat_operand" "")])
380 (match_operand:VEC_F 1 "vfloat_operand" "")
381 (match_operand:VEC_F 2 "vfloat_operand" "")))]
382 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
383 "
384 {
385 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
386 operands[3], operands[4], operands[5]))
387 DONE;
388 else
389 FAIL;
390 }")
391
392 (define_expand "vcond<mode><mode>"
393 [(set (match_operand:VEC_I 0 "vint_operand" "")
394 (if_then_else:VEC_I
395 (match_operator 3 "comparison_operator"
396 [(match_operand:VEC_I 4 "vint_operand" "")
397 (match_operand:VEC_I 5 "vint_operand" "")])
398 (match_operand:VEC_I 1 "vint_operand" "")
399 (match_operand:VEC_I 2 "vint_operand" "")))]
400 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
401 "
402 {
403 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
404 operands[3], operands[4], operands[5]))
405 DONE;
406 else
407 FAIL;
408 }")
409
410 (define_expand "vcondv4sfv4si"
411 [(set (match_operand:V4SF 0 "vfloat_operand" "")
412 (if_then_else:V4SF
413 (match_operator 3 "comparison_operator"
414 [(match_operand:V4SI 4 "vint_operand" "")
415 (match_operand:V4SI 5 "vint_operand" "")])
416 (match_operand:V4SF 1 "vfloat_operand" "")
417 (match_operand:V4SF 2 "vfloat_operand" "")))]
418 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
419 && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
420 "
421 {
422 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
423 operands[3], operands[4], operands[5]))
424 DONE;
425 else
426 FAIL;
427 }")
428
429 (define_expand "vcondv4siv4sf"
430 [(set (match_operand:V4SI 0 "vint_operand" "")
431 (if_then_else:V4SI
432 (match_operator 3 "comparison_operator"
433 [(match_operand:V4SF 4 "vfloat_operand" "")
434 (match_operand:V4SF 5 "vfloat_operand" "")])
435 (match_operand:V4SI 1 "vint_operand" "")
436 (match_operand:V4SI 2 "vint_operand" "")))]
437 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
438 && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
439 "
440 {
441 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
442 operands[3], operands[4], operands[5]))
443 DONE;
444 else
445 FAIL;
446 }")
447
448 (define_expand "vcondu<mode><mode>"
449 [(set (match_operand:VEC_I 0 "vint_operand" "")
450 (if_then_else:VEC_I
451 (match_operator 3 "comparison_operator"
452 [(match_operand:VEC_I 4 "vint_operand" "")
453 (match_operand:VEC_I 5 "vint_operand" "")])
454 (match_operand:VEC_I 1 "vint_operand" "")
455 (match_operand:VEC_I 2 "vint_operand" "")))]
456 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
457 "
458 {
459 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
460 operands[3], operands[4], operands[5]))
461 DONE;
462 else
463 FAIL;
464 }")
465
466 (define_expand "vconduv4sfv4si"
467 [(set (match_operand:V4SF 0 "vfloat_operand" "")
468 (if_then_else:V4SF
469 (match_operator 3 "comparison_operator"
470 [(match_operand:V4SI 4 "vint_operand" "")
471 (match_operand:V4SI 5 "vint_operand" "")])
472 (match_operand:V4SF 1 "vfloat_operand" "")
473 (match_operand:V4SF 2 "vfloat_operand" "")))]
474 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
475 && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
476 "
477 {
478 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
479 operands[3], operands[4], operands[5]))
480 DONE;
481 else
482 FAIL;
483 }")
484
485 (define_expand "vector_eq<mode>"
486 [(set (match_operand:VEC_C 0 "vlogical_operand" "")
487 (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
488 (match_operand:VEC_C 2 "vlogical_operand" "")))]
489 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
490 "")
491
492 (define_expand "vector_gt<mode>"
493 [(set (match_operand:VEC_C 0 "vlogical_operand" "")
494 (gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
495 (match_operand:VEC_C 2 "vlogical_operand" "")))]
496 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
497 "")
498
499 (define_expand "vector_ge<mode>"
500 [(set (match_operand:VEC_C 0 "vlogical_operand" "")
501 (ge:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
502 (match_operand:VEC_C 2 "vlogical_operand" "")))]
503 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
504 "")
505
506 (define_expand "vector_gtu<mode>"
507 [(set (match_operand:VEC_I 0 "vint_operand" "")
508 (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
509 (match_operand:VEC_I 2 "vint_operand" "")))]
510 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
511 "")
512
513 (define_expand "vector_geu<mode>"
514 [(set (match_operand:VEC_I 0 "vint_operand" "")
515 (geu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
516 (match_operand:VEC_I 2 "vint_operand" "")))]
517 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
518 "")
519
520 (define_insn_and_split "*vector_uneq<mode>"
521 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
522 (uneq:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
523 (match_operand:VEC_F 2 "vfloat_operand" "")))]
524 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
525 "#"
526 ""
527 [(set (match_dup 3)
528 (gt:VEC_F (match_dup 1)
529 (match_dup 2)))
530 (set (match_dup 4)
531 (gt:VEC_F (match_dup 2)
532 (match_dup 1)))
533 (set (match_dup 0)
534 (not:VEC_F (ior:VEC_F (match_dup 3)
535 (match_dup 4))))]
536 "
537 {
538 operands[3] = gen_reg_rtx (<MODE>mode);
539 operands[4] = gen_reg_rtx (<MODE>mode);
540 }")
541
542 (define_insn_and_split "*vector_ltgt<mode>"
543 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
544 (ltgt:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
545 (match_operand:VEC_F 2 "vfloat_operand" "")))]
546 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
547 "#"
548 ""
549 [(set (match_dup 3)
550 (gt:VEC_F (match_dup 1)
551 (match_dup 2)))
552 (set (match_dup 4)
553 (gt:VEC_F (match_dup 2)
554 (match_dup 1)))
555 (set (match_dup 0)
556 (ior:VEC_F (match_dup 3)
557 (match_dup 4)))]
558 "
559 {
560 operands[3] = gen_reg_rtx (<MODE>mode);
561 operands[4] = gen_reg_rtx (<MODE>mode);
562 }")
563
564 (define_insn_and_split "*vector_ordered<mode>"
565 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
566 (ordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
567 (match_operand:VEC_F 2 "vfloat_operand" "")))]
568 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
569 "#"
570 ""
571 [(set (match_dup 3)
572 (ge:VEC_F (match_dup 1)
573 (match_dup 2)))
574 (set (match_dup 4)
575 (ge:VEC_F (match_dup 2)
576 (match_dup 1)))
577 (set (match_dup 0)
578 (ior:VEC_F (match_dup 3)
579 (match_dup 4)))]
580 "
581 {
582 operands[3] = gen_reg_rtx (<MODE>mode);
583 operands[4] = gen_reg_rtx (<MODE>mode);
584 }")
585
586 (define_insn_and_split "*vector_unordered<mode>"
587 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
588 (unordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
589 (match_operand:VEC_F 2 "vfloat_operand" "")))]
590 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
591 "#"
592 ""
593 [(set (match_dup 3)
594 (ge:VEC_F (match_dup 1)
595 (match_dup 2)))
596 (set (match_dup 4)
597 (ge:VEC_F (match_dup 2)
598 (match_dup 1)))
599 (set (match_dup 0)
600 (not:VEC_F (ior:VEC_F (match_dup 3)
601 (match_dup 4))))]
602 "
603 {
604 operands[3] = gen_reg_rtx (<MODE>mode);
605 operands[4] = gen_reg_rtx (<MODE>mode);
606 }")
607
608 ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
609 ;; which is in the reverse order that we want
610 (define_expand "vector_select_<mode>"
611 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
612 (if_then_else:VEC_L
613 (ne:CC (match_operand:VEC_L 3 "vlogical_operand" "")
614 (match_dup 4))
615 (match_operand:VEC_L 2 "vlogical_operand" "")
616 (match_operand:VEC_L 1 "vlogical_operand" "")))]
617 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
618 "operands[4] = CONST0_RTX (<MODE>mode);")
619
620 (define_expand "vector_select_<mode>_uns"
621 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
622 (if_then_else:VEC_L
623 (ne:CCUNS (match_operand:VEC_L 3 "vlogical_operand" "")
624 (match_dup 4))
625 (match_operand:VEC_L 2 "vlogical_operand" "")
626 (match_operand:VEC_L 1 "vlogical_operand" "")))]
627 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
628 "operands[4] = CONST0_RTX (<MODE>mode);")
629
630 ;; Expansions that compare vectors producing a vector result and a predicate,
631 ;; setting CR6 to indicate a combined status
632 (define_expand "vector_eq_<mode>_p"
633 [(parallel
634 [(set (reg:CC 74)
635 (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand" "")
636 (match_operand:VEC_A 2 "vlogical_operand" ""))]
637 UNSPEC_PREDICATE))
638 (set (match_operand:VEC_A 0 "vlogical_operand" "")
639 (eq:VEC_A (match_dup 1)
640 (match_dup 2)))])]
641 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
642 "")
643
644 (define_expand "vector_gt_<mode>_p"
645 [(parallel
646 [(set (reg:CC 74)
647 (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand" "")
648 (match_operand:VEC_A 2 "vlogical_operand" ""))]
649 UNSPEC_PREDICATE))
650 (set (match_operand:VEC_A 0 "vlogical_operand" "")
651 (gt:VEC_A (match_dup 1)
652 (match_dup 2)))])]
653 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
654 "")
655
656 (define_expand "vector_ge_<mode>_p"
657 [(parallel
658 [(set (reg:CC 74)
659 (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand" "")
660 (match_operand:VEC_F 2 "vfloat_operand" ""))]
661 UNSPEC_PREDICATE))
662 (set (match_operand:VEC_F 0 "vfloat_operand" "")
663 (ge:VEC_F (match_dup 1)
664 (match_dup 2)))])]
665 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
666 "")
667
668 (define_expand "vector_gtu_<mode>_p"
669 [(parallel
670 [(set (reg:CC 74)
671 (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand" "")
672 (match_operand:VEC_I 2 "vint_operand" ""))]
673 UNSPEC_PREDICATE))
674 (set (match_operand:VEC_I 0 "vlogical_operand" "")
675 (gtu:VEC_I (match_dup 1)
676 (match_dup 2)))])]
677 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
678 "")
679
680 ;; AltiVec/VSX predicates.
681
682 (define_expand "cr6_test_for_zero"
683 [(set (match_operand:SI 0 "register_operand" "=r")
684 (eq:SI (reg:CC 74)
685 (const_int 0)))]
686 "TARGET_ALTIVEC || TARGET_VSX"
687 "")
688
689 (define_expand "cr6_test_for_zero_reverse"
690 [(set (match_operand:SI 0 "register_operand" "=r")
691 (eq:SI (reg:CC 74)
692 (const_int 0)))
693 (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
694 "TARGET_ALTIVEC || TARGET_VSX"
695 "")
696
697 (define_expand "cr6_test_for_lt"
698 [(set (match_operand:SI 0 "register_operand" "=r")
699 (lt:SI (reg:CC 74)
700 (const_int 0)))]
701 "TARGET_ALTIVEC || TARGET_VSX"
702 "")
703
704 (define_expand "cr6_test_for_lt_reverse"
705 [(set (match_operand:SI 0 "register_operand" "=r")
706 (lt:SI (reg:CC 74)
707 (const_int 0)))
708 (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
709 "TARGET_ALTIVEC || TARGET_VSX"
710 "")
711
712 \f
713 ;; Vector logical instructions
714 ;; Do not support TImode logical instructions on 32-bit at present, because the
715 ;; compiler will see that we have a TImode and when it wanted DImode, and
716 ;; convert the DImode to TImode, store it on the stack, and load it in a VSX
717 ;; register.
718 (define_expand "xor<mode>3"
719 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
720 (xor:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
721 (match_operand:VEC_L 2 "vlogical_operand" "")))]
722 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
723 && (<MODE>mode != TImode || TARGET_POWERPC64)"
724 "")
725
726 (define_expand "ior<mode>3"
727 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
728 (ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
729 (match_operand:VEC_L 2 "vlogical_operand" "")))]
730 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
731 && (<MODE>mode != TImode || TARGET_POWERPC64)"
732 "")
733
734 (define_expand "and<mode>3"
735 [(parallel [(set (match_operand:VEC_L 0 "vlogical_operand" "")
736 (and:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
737 (match_operand:VEC_L 2 "vlogical_operand" "")))
738 (clobber (match_scratch:CC 3 ""))])]
739 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
740 && (<MODE>mode != TImode || TARGET_POWERPC64)"
741 "")
742
743 (define_expand "one_cmpl<mode>2"
744 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
745 (not:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")))]
746 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
747 && (<MODE>mode != TImode || TARGET_POWERPC64)"
748 "")
749
750 (define_expand "nor<mode>3"
751 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
752 (and:VEC_L (not:VEC_L (match_operand:VEC_L 1 "vlogical_operand" ""))
753 (not:VEC_L (match_operand:VEC_L 2 "vlogical_operand" ""))))]
754 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
755 && (<MODE>mode != TImode || TARGET_POWERPC64)"
756 "")
757
758 (define_expand "andc<mode>3"
759 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
760 (and:VEC_L (not:VEC_L (match_operand:VEC_L 2 "vlogical_operand" ""))
761 (match_operand:VEC_L 1 "vlogical_operand" "")))]
762 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
763 && (<MODE>mode != TImode || TARGET_POWERPC64)"
764 "")
765
766 ;; Power8 vector logical instructions.
767 (define_expand "eqv<mode>3"
768 [(set (match_operand:VEC_L 0 "register_operand" "")
769 (not:VEC_L
770 (xor:VEC_L (match_operand:VEC_L 1 "register_operand" "")
771 (match_operand:VEC_L 2 "register_operand" ""))))]
772 "TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)
773 && (<MODE>mode != TImode || TARGET_POWERPC64)")
774
775 ;; Rewrite nand into canonical form
776 (define_expand "nand<mode>3"
777 [(set (match_operand:VEC_L 0 "register_operand" "")
778 (ior:VEC_L
779 (not:VEC_L (match_operand:VEC_L 1 "register_operand" ""))
780 (not:VEC_L (match_operand:VEC_L 2 "register_operand" ""))))]
781 "TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)
782 && (<MODE>mode != TImode || TARGET_POWERPC64)")
783
784 ;; The canonical form is to have the negated elment first, so we need to
785 ;; reverse arguments.
786 (define_expand "orc<mode>3"
787 [(set (match_operand:VEC_L 0 "register_operand" "")
788 (ior:VEC_L
789 (not:VEC_L (match_operand:VEC_L 1 "register_operand" ""))
790 (match_operand:VEC_L 2 "register_operand" "")))]
791 "TARGET_P8_VECTOR && VECTOR_MEM_VSX_P (<MODE>mode)
792 && (<MODE>mode != TImode || TARGET_POWERPC64)")
793
794 ;; Vector count leading zeros
795 (define_expand "clz<mode>2"
796 [(set (match_operand:VEC_I 0 "register_operand" "")
797 (clz:VEC_I (match_operand:VEC_I 1 "register_operand" "")))]
798 "TARGET_P8_VECTOR")
799
800 ;; Vector population count
801 (define_expand "popcount<mode>2"
802 [(set (match_operand:VEC_I 0 "register_operand" "")
803 (popcount:VEC_I (match_operand:VEC_I 1 "register_operand" "")))]
804 "TARGET_P8_VECTOR")
805
806 \f
807 ;; Same size conversions
808 (define_expand "float<VEC_int><mode>2"
809 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
810 (float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
811 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
812 "
813 {
814 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
815 {
816 emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
817 DONE;
818 }
819 }")
820
821 (define_expand "floatuns<VEC_int><mode>2"
822 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
823 (unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
824 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
825 "
826 {
827 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
828 {
829 emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
830 DONE;
831 }
832 }")
833
834 (define_expand "fix_trunc<mode><VEC_int>2"
835 [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
836 (fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
837 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
838 "
839 {
840 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
841 {
842 emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
843 DONE;
844 }
845 }")
846
847 (define_expand "fixuns_trunc<mode><VEC_int>2"
848 [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
849 (unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
850 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
851 "
852 {
853 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
854 {
855 emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
856 DONE;
857 }
858 }")
859
860 \f
861 ;; Vector initialization, set, extract
862 (define_expand "vec_init<mode>"
863 [(match_operand:VEC_E 0 "vlogical_operand" "")
864 (match_operand:VEC_E 1 "" "")]
865 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
866 {
867 rs6000_expand_vector_init (operands[0], operands[1]);
868 DONE;
869 })
870
871 (define_expand "vec_set<mode>"
872 [(match_operand:VEC_E 0 "vlogical_operand" "")
873 (match_operand:<VEC_base> 1 "register_operand" "")
874 (match_operand 2 "const_int_operand" "")]
875 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
876 {
877 rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
878 DONE;
879 })
880
881 (define_expand "vec_extract<mode>"
882 [(match_operand:<VEC_base> 0 "register_operand" "")
883 (match_operand:VEC_E 1 "vlogical_operand" "")
884 (match_operand 2 "const_int_operand" "")]
885 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
886 {
887 rs6000_expand_vector_extract (operands[0], operands[1],
888 INTVAL (operands[2]));
889 DONE;
890 })
891 \f
892 ;; Convert double word types to single word types
893 (define_expand "vec_pack_trunc_v2df"
894 [(match_operand:V4SF 0 "vfloat_operand" "")
895 (match_operand:V2DF 1 "vfloat_operand" "")
896 (match_operand:V2DF 2 "vfloat_operand" "")]
897 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
898 {
899 rtx r1 = gen_reg_rtx (V4SFmode);
900 rtx r2 = gen_reg_rtx (V4SFmode);
901
902 emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
903 emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
904 rs6000_expand_extract_even (operands[0], r1, r2);
905 DONE;
906 })
907
908 (define_expand "vec_pack_sfix_trunc_v2df"
909 [(match_operand:V4SI 0 "vint_operand" "")
910 (match_operand:V2DF 1 "vfloat_operand" "")
911 (match_operand:V2DF 2 "vfloat_operand" "")]
912 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
913 {
914 rtx r1 = gen_reg_rtx (V4SImode);
915 rtx r2 = gen_reg_rtx (V4SImode);
916
917 emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
918 emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
919 rs6000_expand_extract_even (operands[0], r1, r2);
920 DONE;
921 })
922
923 (define_expand "vec_pack_ufix_trunc_v2df"
924 [(match_operand:V4SI 0 "vint_operand" "")
925 (match_operand:V2DF 1 "vfloat_operand" "")
926 (match_operand:V2DF 2 "vfloat_operand" "")]
927 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
928 {
929 rtx r1 = gen_reg_rtx (V4SImode);
930 rtx r2 = gen_reg_rtx (V4SImode);
931
932 emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
933 emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
934 rs6000_expand_extract_even (operands[0], r1, r2);
935 DONE;
936 })
937
938 ;; Convert single word types to double word
939 (define_expand "vec_unpacks_hi_v4sf"
940 [(match_operand:V2DF 0 "vfloat_operand" "")
941 (match_operand:V4SF 1 "vfloat_operand" "")]
942 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
943 {
944 rtx reg = gen_reg_rtx (V4SFmode);
945
946 rs6000_expand_interleave (reg, operands[1], operands[1], true);
947 emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
948 DONE;
949 })
950
951 (define_expand "vec_unpacks_lo_v4sf"
952 [(match_operand:V2DF 0 "vfloat_operand" "")
953 (match_operand:V4SF 1 "vfloat_operand" "")]
954 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
955 {
956 rtx reg = gen_reg_rtx (V4SFmode);
957
958 rs6000_expand_interleave (reg, operands[1], operands[1], false);
959 emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
960 DONE;
961 })
962
963 (define_expand "vec_unpacks_float_hi_v4si"
964 [(match_operand:V2DF 0 "vfloat_operand" "")
965 (match_operand:V4SI 1 "vint_operand" "")]
966 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
967 {
968 rtx reg = gen_reg_rtx (V4SImode);
969
970 rs6000_expand_interleave (reg, operands[1], operands[1], true);
971 emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
972 DONE;
973 })
974
975 (define_expand "vec_unpacks_float_lo_v4si"
976 [(match_operand:V2DF 0 "vfloat_operand" "")
977 (match_operand:V4SI 1 "vint_operand" "")]
978 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
979 {
980 rtx reg = gen_reg_rtx (V4SImode);
981
982 rs6000_expand_interleave (reg, operands[1], operands[1], false);
983 emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
984 DONE;
985 })
986
987 (define_expand "vec_unpacku_float_hi_v4si"
988 [(match_operand:V2DF 0 "vfloat_operand" "")
989 (match_operand:V4SI 1 "vint_operand" "")]
990 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
991 {
992 rtx reg = gen_reg_rtx (V4SImode);
993
994 rs6000_expand_interleave (reg, operands[1], operands[1], true);
995 emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
996 DONE;
997 })
998
999 (define_expand "vec_unpacku_float_lo_v4si"
1000 [(match_operand:V2DF 0 "vfloat_operand" "")
1001 (match_operand:V4SI 1 "vint_operand" "")]
1002 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1003 {
1004 rtx reg = gen_reg_rtx (V4SImode);
1005
1006 rs6000_expand_interleave (reg, operands[1], operands[1], false);
1007 emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
1008 DONE;
1009 })
1010
1011 \f
1012 ;; Align vector loads with a permute.
1013 (define_expand "vec_realign_load_<mode>"
1014 [(match_operand:VEC_K 0 "vlogical_operand" "")
1015 (match_operand:VEC_K 1 "vlogical_operand" "")
1016 (match_operand:VEC_K 2 "vlogical_operand" "")
1017 (match_operand:V16QI 3 "vlogical_operand" "")]
1018 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1019 {
1020 emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1], operands[2],
1021 operands[3]));
1022 DONE;
1023 })
1024
1025 ;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned
1026 ;; since the load already handles it.
1027 (define_expand "movmisalign<mode>"
1028 [(set (match_operand:VEC_N 0 "nonimmediate_operand" "")
1029 (match_operand:VEC_N 1 "any_operand" ""))]
1030 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN"
1031 "")
1032
1033 \f
1034 ;; Vector shift left in bits. Currently supported ony for shift
1035 ;; amounts that can be expressed as byte shifts (divisible by 8).
1036 ;; General shift amounts can be supported using vslo + vsl. We're
1037 ;; not expecting to see these yet (the vectorizer currently
1038 ;; generates only shifts divisible by byte_size).
1039 (define_expand "vec_shl_<mode>"
1040 [(match_operand:VEC_L 0 "vlogical_operand" "")
1041 (match_operand:VEC_L 1 "vlogical_operand" "")
1042 (match_operand:QI 2 "reg_or_short_operand" "")]
1043 "TARGET_ALTIVEC"
1044 "
1045 {
1046 rtx bitshift = operands[2];
1047 rtx shift;
1048 rtx insn;
1049 HOST_WIDE_INT bitshift_val;
1050 HOST_WIDE_INT byteshift_val;
1051
1052 if (! CONSTANT_P (bitshift))
1053 FAIL;
1054 bitshift_val = INTVAL (bitshift);
1055 if (bitshift_val & 0x7)
1056 FAIL;
1057 byteshift_val = bitshift_val >> 3;
1058 if (TARGET_VSX && (byteshift_val & 0x3) == 0)
1059 {
1060 shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
1061 insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1],
1062 shift);
1063 }
1064 else
1065 {
1066 shift = gen_rtx_CONST_INT (QImode, byteshift_val);
1067 insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
1068 shift);
1069 }
1070
1071 emit_insn (insn);
1072 DONE;
1073 }")
1074
1075 ;; Vector shift right in bits. Currently supported ony for shift
1076 ;; amounts that can be expressed as byte shifts (divisible by 8).
1077 ;; General shift amounts can be supported using vsro + vsr. We're
1078 ;; not expecting to see these yet (the vectorizer currently
1079 ;; generates only shifts divisible by byte_size).
1080 (define_expand "vec_shr_<mode>"
1081 [(match_operand:VEC_L 0 "vlogical_operand" "")
1082 (match_operand:VEC_L 1 "vlogical_operand" "")
1083 (match_operand:QI 2 "reg_or_short_operand" "")]
1084 "TARGET_ALTIVEC"
1085 "
1086 {
1087 rtx bitshift = operands[2];
1088 rtx shift;
1089 rtx insn;
1090 HOST_WIDE_INT bitshift_val;
1091 HOST_WIDE_INT byteshift_val;
1092
1093 if (! CONSTANT_P (bitshift))
1094 FAIL;
1095 bitshift_val = INTVAL (bitshift);
1096 if (bitshift_val & 0x7)
1097 FAIL;
1098 byteshift_val = 16 - (bitshift_val >> 3);
1099 if (TARGET_VSX && (byteshift_val & 0x3) == 0)
1100 {
1101 shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
1102 insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1],
1103 shift);
1104 }
1105 else
1106 {
1107 shift = gen_rtx_CONST_INT (QImode, byteshift_val);
1108 insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
1109 shift);
1110 }
1111
1112 emit_insn (insn);
1113 DONE;
1114 }")
1115
1116 ;; Expanders for rotate each element in a vector
1117 (define_expand "vrotl<mode>3"
1118 [(set (match_operand:VEC_I 0 "vint_operand" "")
1119 (rotate:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
1120 (match_operand:VEC_I 2 "vint_operand" "")))]
1121 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1122 "")
1123
1124 ;; Expanders for arithmetic shift left on each vector element
1125 (define_expand "vashl<mode>3"
1126 [(set (match_operand:VEC_I 0 "vint_operand" "")
1127 (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
1128 (match_operand:VEC_I 2 "vint_operand" "")))]
1129 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1130 "")
1131
1132 ;; Expanders for logical shift right on each vector element
1133 (define_expand "vlshr<mode>3"
1134 [(set (match_operand:VEC_I 0 "vint_operand" "")
1135 (lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
1136 (match_operand:VEC_I 2 "vint_operand" "")))]
1137 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1138 "")
1139
1140 ;; Expanders for arithmetic shift right on each vector element
1141 (define_expand "vashr<mode>3"
1142 [(set (match_operand:VEC_I 0 "vint_operand" "")
1143 (ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
1144 (match_operand:VEC_I 2 "vint_operand" "")))]
1145 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1146 "")
1147 \f
1148 ;; Vector reduction expanders for VSX
1149
1150 (define_expand "reduc_<VEC_reduc_name>_v2df"
1151 [(parallel [(set (match_operand:V2DF 0 "vfloat_operand" "")
1152 (VEC_reduc:V2DF
1153 (vec_concat:V2DF
1154 (vec_select:DF
1155 (match_operand:V2DF 1 "vfloat_operand" "")
1156 (parallel [(const_int 1)]))
1157 (vec_select:DF
1158 (match_dup 1)
1159 (parallel [(const_int 0)])))
1160 (match_dup 1)))
1161 (clobber (match_scratch:V2DF 2 ""))])]
1162 "VECTOR_UNIT_VSX_P (V2DFmode)"
1163 "")
1164
1165 ; The (VEC_reduc:V4SF
1166 ; (op1)
1167 ; (unspec:V4SF [(const_int 0)] UNSPEC_REDUC))
1168 ;
1169 ; is to allow us to use a code iterator, but not completely list all of the
1170 ; vector rotates, etc. to prevent canonicalization
1171
1172 (define_expand "reduc_<VEC_reduc_name>_v4sf"
1173 [(parallel [(set (match_operand:V4SF 0 "vfloat_operand" "")
1174 (VEC_reduc:V4SF
1175 (unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
1176 (match_operand:V4SF 1 "vfloat_operand" "")))
1177 (clobber (match_scratch:V4SF 2 ""))
1178 (clobber (match_scratch:V4SF 3 ""))])]
1179 "VECTOR_UNIT_VSX_P (V4SFmode)"
1180 "")
1181
1182 \f
1183 ;;; Expanders for vector insn patterns shared between the SPE and TARGET_PAIRED systems.
1184
1185 (define_expand "absv2sf2"
1186 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1187 (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")))]
1188 "TARGET_PAIRED_FLOAT || TARGET_SPE"
1189 "")
1190
1191 (define_expand "negv2sf2"
1192 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1193 (neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")))]
1194 "TARGET_PAIRED_FLOAT || TARGET_SPE"
1195 "")
1196
1197 (define_expand "addv2sf3"
1198 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1199 (plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
1200 (match_operand:V2SF 2 "gpc_reg_operand" "")))]
1201 "TARGET_PAIRED_FLOAT || TARGET_SPE"
1202 "
1203 {
1204 if (TARGET_SPE)
1205 {
1206 /* We need to make a note that we clobber SPEFSCR. */
1207 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1208
1209 XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1210 gen_rtx_PLUS (V2SFmode, operands[1], operands[2]));
1211 XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1212 emit_insn (par);
1213 DONE;
1214 }
1215 }")
1216
1217 (define_expand "subv2sf3"
1218 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1219 (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
1220 (match_operand:V2SF 2 "gpc_reg_operand" "")))]
1221 "TARGET_PAIRED_FLOAT || TARGET_SPE"
1222 "
1223 {
1224 if (TARGET_SPE)
1225 {
1226 /* We need to make a note that we clobber SPEFSCR. */
1227 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1228
1229 XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1230 gen_rtx_MINUS (V2SFmode, operands[1], operands[2]));
1231 XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1232 emit_insn (par);
1233 DONE;
1234 }
1235 }")
1236
1237 (define_expand "mulv2sf3"
1238 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1239 (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
1240 (match_operand:V2SF 2 "gpc_reg_operand" "")))]
1241 "TARGET_PAIRED_FLOAT || TARGET_SPE"
1242 "
1243 {
1244 if (TARGET_SPE)
1245 {
1246 /* We need to make a note that we clobber SPEFSCR. */
1247 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1248
1249 XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1250 gen_rtx_MULT (V2SFmode, operands[1], operands[2]));
1251 XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1252 emit_insn (par);
1253 DONE;
1254 }
1255 }")
1256
1257 (define_expand "divv2sf3"
1258 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1259 (div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
1260 (match_operand:V2SF 2 "gpc_reg_operand" "")))]
1261 "TARGET_PAIRED_FLOAT || TARGET_SPE"
1262 "
1263 {
1264 if (TARGET_SPE)
1265 {
1266 /* We need to make a note that we clobber SPEFSCR. */
1267 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1268
1269 XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1270 gen_rtx_DIV (V2SFmode, operands[1], operands[2]));
1271 XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1272 emit_insn (par);
1273 DONE;
1274 }
1275 }")