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
6 ;; Copyright (C) 2009, 2010
7 ;; Free Software Foundation, Inc.
8 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
10 ;; This file is part of GCC.
12 ;; GCC is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published
14 ;; by the Free Software Foundation; either version 3, or (at your
15 ;; option) any later version.
17 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
18 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 ;; License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GCC; see the file COPYING3. If not see
24 ;; <http://www.gnu.org/licenses/>.
28 (define_mode_iterator VEC_I [V16QI V8HI V4SI])
31 (define_mode_iterator VEC_F [V4SF V2DF])
33 ;; Vector arithmetic modes
34 (define_mode_iterator VEC_A [V16QI V8HI V4SI V4SF V2DF])
36 ;; Vector modes that need alginment via permutes
37 (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
39 ;; Vector logical modes
40 (define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
42 ;; Vector modes for moves. Don't do TImode here.
43 (define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF])
45 ;; Vector modes for types that don't need a realignment under VSX
46 (define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF])
48 ;; Vector comparison modes
49 (define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
51 ;; Vector init/extract modes
52 (define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF])
54 ;; Vector modes for 64-bit base types
55 (define_mode_iterator VEC_64 [V2DI V2DF])
57 ;; Vector reload iterator
58 (define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF DF TI])
60 ;; Base type from vector mode
61 (define_mode_attr VEC_base [(V16QI "QI")
69 ;; Same size integer type for floating point data
70 (define_mode_attr VEC_int [(V4SF "v4si")
73 (define_mode_attr VEC_INT [(V4SF "V4SI")
76 ;; constants for unspec
78 [(UNSPEC_PREDICATE 400)])
81 ;; Vector move instructions.
82 (define_expand "mov<mode>"
83 [(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
84 (match_operand:VEC_M 1 "any_operand" ""))]
85 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
87 if (can_create_pseudo_p ())
89 if (CONSTANT_P (operands[1])
90 && !easy_vector_constant (operands[1], <MODE>mode))
91 operands[1] = force_const_mem (<MODE>mode, operands[1]);
93 else if (!vlogical_operand (operands[0], <MODE>mode)
94 && !vlogical_operand (operands[1], <MODE>mode))
95 operands[1] = force_reg (<MODE>mode, operands[1]);
99 ;; Generic vector floating point load/store instructions. These will match
100 ;; insns defined in vsx.md or altivec.md depending on the switches.
101 (define_expand "vector_load_<mode>"
102 [(set (match_operand:VEC_M 0 "vfloat_operand" "")
103 (match_operand:VEC_M 1 "memory_operand" ""))]
104 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
107 (define_expand "vector_store_<mode>"
108 [(set (match_operand:VEC_M 0 "memory_operand" "")
109 (match_operand:VEC_M 1 "vfloat_operand" ""))]
110 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
113 ;; Splits if a GPR register was chosen for the move
115 [(set (match_operand:VEC_L 0 "nonimmediate_operand" "")
116 (match_operand:VEC_L 1 "input_operand" ""))]
117 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
119 && gpr_or_gpr_p (operands[0], operands[1])"
122 rs6000_split_multireg_move (operands[0], operands[1]);
127 ;; Reload patterns for vector operations. We may need an addtional base
128 ;; register to convert the reg+offset addressing to reg+reg for vector
129 ;; registers and reg+reg or (reg+reg)&(-16) addressing to just an index
130 ;; register for gpr registers.
131 (define_expand "reload_<VEC_R:mode>_<P:mptrsize>_store"
132 [(parallel [(match_operand:VEC_R 0 "memory_operand" "m")
133 (match_operand:VEC_R 1 "gpc_reg_operand" "r")
134 (match_operand:P 2 "register_operand" "=&b")])]
137 rs6000_secondary_reload_inner (operands[1], operands[0], operands[2], true);
141 (define_expand "reload_<VEC_R:mode>_<P:mptrsize>_load"
142 [(parallel [(match_operand:VEC_R 0 "gpc_reg_operand" "=&r")
143 (match_operand:VEC_R 1 "memory_operand" "m")
144 (match_operand:P 2 "register_operand" "=&b")])]
147 rs6000_secondary_reload_inner (operands[0], operands[1], operands[2], false);
151 ;; Reload sometimes tries to move the address to a GPR, and can generate
152 ;; invalid RTL for addresses involving AND -16. Allow addresses involving
153 ;; reg+reg, reg+small constant, or just reg, all wrapped in an AND -16.
155 (define_insn_and_split "*vec_reload_and_plus_<mptrsize>"
156 [(set (match_operand:P 0 "gpc_reg_operand" "=b")
157 (and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
158 (match_operand:P 2 "reg_or_cint_operand" "rI"))
160 "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
162 "&& reload_completed"
164 (plus:P (match_dup 1)
166 (parallel [(set (match_dup 0)
169 (clobber:CC (scratch:CC))])])
171 ;; The normal ANDSI3/ANDDI3 won't match if reload decides to move an AND -16
172 ;; address to a register because there is no clobber of a (scratch), so we add
174 (define_insn_and_split "*vec_reload_and_reg_<mptrsize>"
175 [(set (match_operand:P 0 "gpc_reg_operand" "=b")
176 (and:P (match_operand:P 1 "gpc_reg_operand" "r")
178 "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
180 "&& reload_completed"
181 [(parallel [(set (match_dup 0)
184 (clobber:CC (scratch:CC))])])
186 ;; Generic floating point vector arithmetic support
187 (define_expand "add<mode>3"
188 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
189 (plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
190 (match_operand:VEC_F 2 "vfloat_operand" "")))]
191 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
194 (define_expand "sub<mode>3"
195 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
196 (minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
197 (match_operand:VEC_F 2 "vfloat_operand" "")))]
198 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
201 (define_expand "mul<mode>3"
202 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
203 (mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
204 (match_operand:VEC_F 2 "vfloat_operand" "")))]
205 "(VECTOR_UNIT_VSX_P (<MODE>mode)
206 || (VECTOR_UNIT_ALTIVEC_P (<MODE>mode) && TARGET_FUSED_MADD))"
209 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
211 emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
216 (define_expand "div<mode>3"
217 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
218 (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
219 (match_operand:VEC_F 2 "vfloat_operand" "")))]
220 "VECTOR_UNIT_VSX_P (<MODE>mode)"
223 (define_expand "neg<mode>2"
224 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
225 (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
226 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
229 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
231 emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
236 (define_expand "abs<mode>2"
237 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
238 (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
239 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
242 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
244 emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
249 (define_expand "smin<mode>3"
250 [(set (match_operand:VEC_F 0 "register_operand" "")
251 (smin:VEC_F (match_operand:VEC_F 1 "register_operand" "")
252 (match_operand:VEC_F 2 "register_operand" "")))]
253 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
256 (define_expand "smax<mode>3"
257 [(set (match_operand:VEC_F 0 "register_operand" "")
258 (smax:VEC_F (match_operand:VEC_F 1 "register_operand" "")
259 (match_operand:VEC_F 2 "register_operand" "")))]
260 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
264 (define_expand "sqrt<mode>2"
265 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
266 (sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
267 "VECTOR_UNIT_VSX_P (<MODE>mode)"
270 (define_expand "ftrunc<mode>2"
271 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
272 (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
273 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
276 (define_expand "vector_ceil<mode>2"
277 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
278 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
280 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
283 (define_expand "vector_floor<mode>2"
284 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
285 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
287 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
290 (define_expand "vector_btrunc<mode>2"
291 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
292 (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
293 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
296 (define_expand "vector_copysign<mode>3"
297 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
299 (ge:VEC_F (match_operand:VEC_F 2 "vfloat_operand" "")
301 (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" ""))
302 (neg:VEC_F (abs:VEC_F (match_dup 1)))))]
303 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
306 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
308 emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1],
313 operands[3] = CONST0_RTX (<MODE>mode);
317 ;; Vector comparisons
318 (define_expand "vcond<mode>"
319 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
321 (match_operator 3 "comparison_operator"
322 [(match_operand:VEC_F 4 "vfloat_operand" "")
323 (match_operand:VEC_F 5 "vfloat_operand" "")])
324 (match_operand:VEC_F 1 "vfloat_operand" "")
325 (match_operand:VEC_F 2 "vfloat_operand" "")))]
326 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
329 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
330 operands[3], operands[4], operands[5]))
336 (define_expand "vcond<mode>"
337 [(set (match_operand:VEC_I 0 "vint_operand" "")
339 (match_operator 3 "comparison_operator"
340 [(match_operand:VEC_I 4 "vint_operand" "")
341 (match_operand:VEC_I 5 "vint_operand" "")])
342 (match_operand:VEC_I 1 "vint_operand" "")
343 (match_operand:VEC_I 2 "vint_operand" "")))]
344 "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
347 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
348 operands[3], operands[4], operands[5]))
354 (define_expand "vcondu<mode>"
355 [(set (match_operand:VEC_I 0 "vint_operand" "")
357 (match_operator 3 "comparison_operator"
358 [(match_operand:VEC_I 4 "vint_operand" "")
359 (match_operand:VEC_I 5 "vint_operand" "")])
360 (match_operand:VEC_I 1 "vint_operand" "")
361 (match_operand:VEC_I 2 "vint_operand" "")))]
362 "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
365 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
366 operands[3], operands[4], operands[5]))
372 (define_expand "vector_eq<mode>"
373 [(set (match_operand:VEC_C 0 "vlogical_operand" "")
374 (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
375 (match_operand:VEC_C 2 "vlogical_operand" "")))]
376 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
379 (define_expand "vector_gt<mode>"
380 [(set (match_operand:VEC_C 0 "vlogical_operand" "")
381 (gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
382 (match_operand:VEC_C 2 "vlogical_operand" "")))]
383 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
386 (define_expand "vector_ge<mode>"
387 [(set (match_operand:VEC_C 0 "vlogical_operand" "")
388 (ge:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
389 (match_operand:VEC_C 2 "vlogical_operand" "")))]
390 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
393 (define_expand "vector_gtu<mode>"
394 [(set (match_operand:VEC_I 0 "vint_operand" "")
395 (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
396 (match_operand:VEC_I 2 "vint_operand" "")))]
397 "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
400 (define_expand "vector_geu<mode>"
401 [(set (match_operand:VEC_I 0 "vint_operand" "")
402 (geu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
403 (match_operand:VEC_I 2 "vint_operand" "")))]
404 "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
407 ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
408 ;; which is in the reverse order that we want
409 (define_expand "vector_select_<mode>"
410 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
412 (ne:CC (match_operand:VEC_L 3 "vlogical_operand" "")
414 (match_operand:VEC_L 2 "vlogical_operand" "")
415 (match_operand:VEC_L 1 "vlogical_operand" "")))]
416 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
419 (define_expand "vector_select_<mode>_uns"
420 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
422 (ne:CCUNS (match_operand:VEC_L 3 "vlogical_operand" "")
424 (match_operand:VEC_L 2 "vlogical_operand" "")
425 (match_operand:VEC_L 1 "vlogical_operand" "")))]
426 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
429 ;; Expansions that compare vectors producing a vector result and a predicate,
430 ;; setting CR6 to indicate a combined status
431 (define_expand "vector_eq_<mode>_p"
434 (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand" "")
435 (match_operand:VEC_A 2 "vlogical_operand" ""))]
437 (set (match_operand:VEC_A 0 "vlogical_operand" "")
438 (eq:VEC_A (match_dup 1)
440 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
443 (define_expand "vector_gt_<mode>_p"
446 (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand" "")
447 (match_operand:VEC_A 2 "vlogical_operand" ""))]
449 (set (match_operand:VEC_A 0 "vlogical_operand" "")
450 (gt:VEC_A (match_dup 1)
452 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
455 (define_expand "vector_ge_<mode>_p"
458 (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand" "")
459 (match_operand:VEC_F 2 "vfloat_operand" ""))]
461 (set (match_operand:VEC_F 0 "vfloat_operand" "")
462 (ge:VEC_F (match_dup 1)
464 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
467 (define_expand "vector_gtu_<mode>_p"
470 (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand" "")
471 (match_operand:VEC_I 2 "vint_operand" ""))]
473 (set (match_operand:VEC_I 0 "vlogical_operand" "")
474 (gtu:VEC_I (match_dup 1)
476 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
479 ;; AltiVec/VSX predicates.
481 (define_expand "cr6_test_for_zero"
482 [(set (match_operand:SI 0 "register_operand" "=r")
485 "TARGET_ALTIVEC || TARGET_VSX"
488 (define_expand "cr6_test_for_zero_reverse"
489 [(set (match_operand:SI 0 "register_operand" "=r")
492 (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
493 "TARGET_ALTIVEC || TARGET_VSX"
496 (define_expand "cr6_test_for_lt"
497 [(set (match_operand:SI 0 "register_operand" "=r")
500 "TARGET_ALTIVEC || TARGET_VSX"
503 (define_expand "cr6_test_for_lt_reverse"
504 [(set (match_operand:SI 0 "register_operand" "=r")
507 (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
508 "TARGET_ALTIVEC || TARGET_VSX"
512 ;; Vector logical instructions
513 (define_expand "xor<mode>3"
514 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
515 (xor:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
516 (match_operand:VEC_L 2 "vlogical_operand" "")))]
517 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
520 (define_expand "ior<mode>3"
521 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
522 (ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
523 (match_operand:VEC_L 2 "vlogical_operand" "")))]
524 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
527 (define_expand "and<mode>3"
528 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
529 (and:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
530 (match_operand:VEC_L 2 "vlogical_operand" "")))]
531 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
534 (define_expand "one_cmpl<mode>2"
535 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
536 (not:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")))]
537 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
540 (define_expand "nor<mode>3"
541 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
542 (not:VEC_L (ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
543 (match_operand:VEC_L 2 "vlogical_operand" ""))))]
544 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
547 (define_expand "andc<mode>3"
548 [(set (match_operand:VEC_L 0 "vlogical_operand" "")
549 (and:VEC_L (not:VEC_L (match_operand:VEC_L 2 "vlogical_operand" ""))
550 (match_operand:VEC_L 1 "vlogical_operand" "")))]
551 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
554 ;; Same size conversions
555 (define_expand "float<VEC_int><mode>2"
556 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
557 (float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
558 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
561 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
563 emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
568 (define_expand "unsigned_float<VEC_int><mode>2"
569 [(set (match_operand:VEC_F 0 "vfloat_operand" "")
570 (unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
571 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
574 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
576 emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
581 (define_expand "fix_trunc<mode><VEC_int>2"
582 [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
583 (fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
584 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
587 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
589 emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
594 (define_expand "fixuns_trunc<mode><VEC_int>2"
595 [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
596 (unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
597 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
600 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
602 emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
608 ;; Vector initialization, set, extract
609 (define_expand "vec_init<mode>"
610 [(match_operand:VEC_E 0 "vlogical_operand" "")
611 (match_operand:VEC_E 1 "" "")]
612 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
614 rs6000_expand_vector_init (operands[0], operands[1]);
618 (define_expand "vec_set<mode>"
619 [(match_operand:VEC_E 0 "vlogical_operand" "")
620 (match_operand:<VEC_base> 1 "register_operand" "")
621 (match_operand 2 "const_int_operand" "")]
622 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
624 rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
628 (define_expand "vec_extract<mode>"
629 [(match_operand:<VEC_base> 0 "register_operand" "")
630 (match_operand:VEC_E 1 "vlogical_operand" "")
631 (match_operand 2 "const_int_operand" "")]
632 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
634 rs6000_expand_vector_extract (operands[0], operands[1],
635 INTVAL (operands[2]));
639 ;; Interleave patterns
640 (define_expand "vec_interleave_highv4sf"
641 [(set (match_operand:V4SF 0 "vfloat_operand" "")
643 (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
644 (parallel [(const_int 0)
648 (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
649 (parallel [(const_int 2)
654 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
657 (define_expand "vec_interleave_lowv4sf"
658 [(set (match_operand:V4SF 0 "vfloat_operand" "")
660 (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
661 (parallel [(const_int 2)
665 (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
666 (parallel [(const_int 0)
671 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
674 (define_expand "vec_interleave_high<mode>"
675 [(set (match_operand:VEC_64 0 "vfloat_operand" "")
677 (vec_select:<VEC_base> (match_operand:VEC_64 1 "vfloat_operand" "")
678 (parallel [(const_int 0)]))
679 (vec_select:<VEC_base> (match_operand:VEC_64 2 "vfloat_operand" "")
680 (parallel [(const_int 0)]))))]
681 "VECTOR_UNIT_VSX_P (<MODE>mode)"
684 (define_expand "vec_interleave_low<mode>"
685 [(set (match_operand:VEC_64 0 "vfloat_operand" "")
687 (vec_select:<VEC_base> (match_operand:VEC_64 1 "vfloat_operand" "")
688 (parallel [(const_int 1)]))
689 (vec_select:<VEC_base> (match_operand:VEC_64 2 "vfloat_operand" "")
690 (parallel [(const_int 1)]))))]
691 "VECTOR_UNIT_VSX_P (<MODE>mode)"
695 ;; Convert double word types to single word types
696 (define_expand "vec_pack_trunc_v2df"
697 [(match_operand:V4SF 0 "vfloat_operand" "")
698 (match_operand:V2DF 1 "vfloat_operand" "")
699 (match_operand:V2DF 2 "vfloat_operand" "")]
700 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
702 rtx r1 = gen_reg_rtx (V4SFmode);
703 rtx r2 = gen_reg_rtx (V4SFmode);
705 emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
706 emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
707 emit_insn (gen_vec_extract_evenv4sf (operands[0], r1, r2));
711 (define_expand "vec_pack_sfix_trunc_v2df"
712 [(match_operand:V4SI 0 "vint_operand" "")
713 (match_operand:V2DF 1 "vfloat_operand" "")
714 (match_operand:V2DF 2 "vfloat_operand" "")]
715 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
717 rtx r1 = gen_reg_rtx (V4SImode);
718 rtx r2 = gen_reg_rtx (V4SImode);
720 emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
721 emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
722 emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
726 (define_expand "vec_pack_ufix_trunc_v2df"
727 [(match_operand:V4SI 0 "vint_operand" "")
728 (match_operand:V2DF 1 "vfloat_operand" "")
729 (match_operand:V2DF 2 "vfloat_operand" "")]
730 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
732 rtx r1 = gen_reg_rtx (V4SImode);
733 rtx r2 = gen_reg_rtx (V4SImode);
735 emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
736 emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
737 emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
741 ;; Convert single word types to double word
742 (define_expand "vec_unpacks_hi_v4sf"
743 [(match_operand:V2DF 0 "vfloat_operand" "")
744 (match_operand:V4SF 1 "vfloat_operand" "")]
745 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
747 rtx reg = gen_reg_rtx (V4SFmode);
749 emit_insn (gen_vec_interleave_highv4sf (reg, operands[1], operands[1]));
750 emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
754 (define_expand "vec_unpacks_lo_v4sf"
755 [(match_operand:V2DF 0 "vfloat_operand" "")
756 (match_operand:V4SF 1 "vfloat_operand" "")]
757 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
759 rtx reg = gen_reg_rtx (V4SFmode);
761 emit_insn (gen_vec_interleave_lowv4sf (reg, operands[1], operands[1]));
762 emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
766 (define_expand "vec_unpacks_float_hi_v4si"
767 [(match_operand:V2DF 0 "vfloat_operand" "")
768 (match_operand:V4SI 1 "vint_operand" "")]
769 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
771 rtx reg = gen_reg_rtx (V4SImode);
773 emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
774 emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
778 (define_expand "vec_unpacks_float_lo_v4si"
779 [(match_operand:V2DF 0 "vfloat_operand" "")
780 (match_operand:V4SI 1 "vint_operand" "")]
781 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
783 rtx reg = gen_reg_rtx (V4SImode);
785 emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
786 emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
790 (define_expand "vec_unpacku_float_hi_v4si"
791 [(match_operand:V2DF 0 "vfloat_operand" "")
792 (match_operand:V4SI 1 "vint_operand" "")]
793 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
795 rtx reg = gen_reg_rtx (V4SImode);
797 emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
798 emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
802 (define_expand "vec_unpacku_float_lo_v4si"
803 [(match_operand:V2DF 0 "vfloat_operand" "")
804 (match_operand:V4SI 1 "vint_operand" "")]
805 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
807 rtx reg = gen_reg_rtx (V4SImode);
809 emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
810 emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
815 ;; Align vector loads with a permute.
816 (define_expand "vec_realign_load_<mode>"
817 [(match_operand:VEC_K 0 "vlogical_operand" "")
818 (match_operand:VEC_K 1 "vlogical_operand" "")
819 (match_operand:VEC_K 2 "vlogical_operand" "")
820 (match_operand:V16QI 3 "vlogical_operand" "")]
821 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
823 emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1], operands[2],
828 ;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned
829 ;; since the load already handles it.
830 (define_expand "movmisalign<mode>"
831 [(set (match_operand:VEC_N 0 "vfloat_operand" "")
832 (match_operand:VEC_N 1 "vfloat_operand" ""))]
833 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN"
837 ;; Vector shift left in bits. Currently supported ony for shift
838 ;; amounts that can be expressed as byte shifts (divisible by 8).
839 ;; General shift amounts can be supported using vslo + vsl. We're
840 ;; not expecting to see these yet (the vectorizer currently
841 ;; generates only shifts divisible by byte_size).
842 (define_expand "vec_shl_<mode>"
843 [(match_operand:VEC_L 0 "vlogical_operand" "")
844 (match_operand:VEC_L 1 "vlogical_operand" "")
845 (match_operand:QI 2 "reg_or_short_operand" "")]
849 rtx bitshift = operands[2];
852 HOST_WIDE_INT bitshift_val;
853 HOST_WIDE_INT byteshift_val;
855 if (! CONSTANT_P (bitshift))
857 bitshift_val = INTVAL (bitshift);
858 if (bitshift_val & 0x7)
860 byteshift_val = bitshift_val >> 3;
861 if (TARGET_VSX && (byteshift_val & 0x3) == 0)
863 shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
864 insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1],
869 shift = gen_rtx_CONST_INT (QImode, byteshift_val);
870 insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
878 ;; Vector shift right in bits. Currently supported ony for shift
879 ;; amounts that can be expressed as byte shifts (divisible by 8).
880 ;; General shift amounts can be supported using vsro + vsr. We're
881 ;; not expecting to see these yet (the vectorizer currently
882 ;; generates only shifts divisible by byte_size).
883 (define_expand "vec_shr_<mode>"
884 [(match_operand:VEC_L 0 "vlogical_operand" "")
885 (match_operand:VEC_L 1 "vlogical_operand" "")
886 (match_operand:QI 2 "reg_or_short_operand" "")]
890 rtx bitshift = operands[2];
893 HOST_WIDE_INT bitshift_val;
894 HOST_WIDE_INT byteshift_val;
896 if (! CONSTANT_P (bitshift))
898 bitshift_val = INTVAL (bitshift);
899 if (bitshift_val & 0x7)
901 byteshift_val = 16 - (bitshift_val >> 3);
902 if (TARGET_VSX && (byteshift_val & 0x3) == 0)
904 shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
905 insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1],
910 shift = gen_rtx_CONST_INT (QImode, byteshift_val);
911 insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
919 ;; Expanders for rotate each element in a vector
920 (define_expand "vrotl<mode>3"
921 [(set (match_operand:VEC_I 0 "vint_operand" "")
922 (rotate:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
923 (match_operand:VEC_I 2 "vint_operand" "")))]
927 ;; Expanders for arithmetic shift left on each vector element
928 (define_expand "vashl<mode>3"
929 [(set (match_operand:VEC_I 0 "vint_operand" "")
930 (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
931 (match_operand:VEC_I 2 "vint_operand" "")))]
935 ;; Expanders for logical shift right on each vector element
936 (define_expand "vlshr<mode>3"
937 [(set (match_operand:VEC_I 0 "vint_operand" "")
938 (lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
939 (match_operand:VEC_I 2 "vint_operand" "")))]
943 ;; Expanders for arithmetic shift right on each vector element
944 (define_expand "vashr<mode>3"
945 [(set (match_operand:VEC_I 0 "vint_operand" "")
946 (ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
947 (match_operand:VEC_I 2 "vint_operand" "")))]
951 ;;; Expanders for vector insn patterns shared between the SPE and TARGET_PAIRED systems.
953 (define_expand "absv2sf2"
954 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
955 (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")))]
956 "TARGET_PAIRED_FLOAT || TARGET_SPE"
959 (define_expand "negv2sf2"
960 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
961 (neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")))]
962 "TARGET_PAIRED_FLOAT || TARGET_SPE"
965 (define_expand "addv2sf3"
966 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
967 (plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
968 (match_operand:V2SF 2 "gpc_reg_operand" "")))]
969 "TARGET_PAIRED_FLOAT || TARGET_SPE"
974 /* We need to make a note that we clobber SPEFSCR. */
975 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
977 XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
978 gen_rtx_PLUS (V2SFmode, operands[1], operands[2]));
979 XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
985 (define_expand "subv2sf3"
986 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
987 (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
988 (match_operand:V2SF 2 "gpc_reg_operand" "")))]
989 "TARGET_PAIRED_FLOAT || TARGET_SPE"
994 /* We need to make a note that we clobber SPEFSCR. */
995 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
997 XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
998 gen_rtx_MINUS (V2SFmode, operands[1], operands[2]));
999 XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1005 (define_expand "mulv2sf3"
1006 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1007 (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
1008 (match_operand:V2SF 2 "gpc_reg_operand" "")))]
1009 "TARGET_PAIRED_FLOAT || TARGET_SPE"
1014 /* We need to make a note that we clobber SPEFSCR. */
1015 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1017 XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1018 gen_rtx_MULT (V2SFmode, operands[1], operands[2]));
1019 XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1025 (define_expand "divv2sf3"
1026 [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1027 (div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
1028 (match_operand:V2SF 2 "gpc_reg_operand" "")))]
1029 "TARGET_PAIRED_FLOAT || TARGET_SPE"
1034 /* We need to make a note that we clobber SPEFSCR. */
1035 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1037 XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1038 gen_rtx_DIV (V2SFmode, operands[1], operands[2]));
1039 XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));