Fix PR 47408 and 47385
[official-gcc.git] / gcc / config / rs6000 / vector.md
blob71961fbc57c42d9973fcdc19180d025c173a103a
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
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/>.
27 ;; Vector int modes
28 (define_mode_iterator VEC_I [V16QI V8HI V4SI])
30 ;; Vector float modes
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")
62                             (V8HI  "HI")
63                             (V4SI  "SI")
64                             (V2DI  "DI")
65                             (V4SF  "SF")
66                             (V2DF  "DF")
67                             (TI    "TI")])
69 ;; Same size integer type for floating point data
70 (define_mode_attr VEC_int [(V4SF  "v4si")
71                            (V2DF  "v2di")])
73 (define_mode_attr VEC_INT [(V4SF  "V4SI")
74                            (V2DF  "V2DI")])
76 ;; constants for unspec
77 (define_constants
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 ())
88     {
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]);
96     }
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)"
105   "")
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)"
111   "")
113 ;; Splits if a GPR register was chosen for the move
114 (define_split
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)
118    && reload_completed
119    && gpr_or_gpr_p (operands[0], operands[1])"
120   [(pc)]
122   rs6000_split_multireg_move (operands[0], operands[1]);
123   DONE;
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")])]
135   "<P:tptrsize>"
137   rs6000_secondary_reload_inner (operands[1], operands[0], operands[2], true);
138   DONE;
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")])]
145   "<P:tptrsize>"
147   rs6000_secondary_reload_inner (operands[0], operands[1], operands[2], false);
148   DONE;
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"))
159                (const_int -16)))]
160   "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
161   "#"
162   "&& reload_completed"
163   [(set (match_dup 0)
164         (plus:P (match_dup 1)
165                 (match_dup 2)))
166    (parallel [(set (match_dup 0)
167                    (and:P (match_dup 0)
168                           (const_int -16)))
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
173 ;; it here.
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")
177                (const_int -16)))]
178   "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
179   "#"
180   "&& reload_completed"
181   [(parallel [(set (match_dup 0)
182                    (and:P (match_dup 1)
183                           (const_int -16)))
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)"
192   "")
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)"
199   "")
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) || VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
207   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
208     {
209       emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
210       DONE;
211     }
214 (define_expand "div<mode>3"
215   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
216         (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
217                    (match_operand:VEC_F 2 "vfloat_operand" "")))]
218   "VECTOR_UNIT_VSX_P (<MODE>mode)"
219   "")
221 (define_expand "neg<mode>2"
222   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
223         (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
224   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
225   "
227   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
228     {
229       emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
230       DONE;
231     }
234 (define_expand "abs<mode>2"
235   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
236         (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
237   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
238   "
240   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
241     {
242       emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
243       DONE;
244     }
247 (define_expand "smin<mode>3"
248   [(set (match_operand:VEC_F 0 "register_operand" "")
249         (smin:VEC_F (match_operand:VEC_F 1 "register_operand" "")
250                     (match_operand:VEC_F 2 "register_operand" "")))]
251   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
252   "")
254 (define_expand "smax<mode>3"
255   [(set (match_operand:VEC_F 0 "register_operand" "")
256         (smax:VEC_F (match_operand:VEC_F 1 "register_operand" "")
257                     (match_operand:VEC_F 2 "register_operand" "")))]
258   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
259   "")
262 (define_expand "sqrt<mode>2"
263   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
264         (sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
265   "VECTOR_UNIT_VSX_P (<MODE>mode)"
266   "")
268 (define_expand "rsqrte<mode>2"
269   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
270         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
271                       UNSPEC_RSQRT))]
272   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
273   "")
275 (define_expand "re<mode>2"
276   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
277         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "f")]
278                       UNSPEC_FRES))]
279   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
280   "")
282 (define_expand "ftrunc<mode>2"
283   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
284         (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
285   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
286   "")
288 (define_expand "vector_ceil<mode>2"
289   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
290         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
291                       UNSPEC_FRIP))]
292   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
293   "")
295 (define_expand "vector_floor<mode>2"
296   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
297         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
298                       UNSPEC_FRIM))]
299   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
300   "")
302 (define_expand "vector_btrunc<mode>2"
303   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
304         (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
305   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
306   "")
308 (define_expand "vector_copysign<mode>3"
309   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
310         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")
311                        (match_operand:VEC_F 2 "vfloat_operand" "")] UNSPEC_COPYSIGN))]
312   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
313   "
315   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
316     {
317       emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1],
318                                              operands[2]));
319       DONE;
320     }
324 ;; Vector comparisons
325 (define_expand "vcond<mode>"
326   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
327         (if_then_else:VEC_F
328          (match_operator 3 "comparison_operator"
329                          [(match_operand:VEC_F 4 "vfloat_operand" "")
330                           (match_operand:VEC_F 5 "vfloat_operand" "")])
331          (match_operand:VEC_F 1 "vfloat_operand" "")
332          (match_operand:VEC_F 2 "vfloat_operand" "")))]
333   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
334   "
336   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
337                                     operands[3], operands[4], operands[5]))
338     DONE;
339   else
340     FAIL;
343 (define_expand "vcond<mode>"
344   [(set (match_operand:VEC_I 0 "vint_operand" "")
345         (if_then_else:VEC_I
346          (match_operator 3 "comparison_operator"
347                          [(match_operand:VEC_I 4 "vint_operand" "")
348                           (match_operand:VEC_I 5 "vint_operand" "")])
349          (match_operand:VEC_I 1 "vint_operand" "")
350          (match_operand:VEC_I 2 "vint_operand" "")))]
351   "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
352   "
354   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
355                                     operands[3], operands[4], operands[5]))
356     DONE;
357   else
358     FAIL;
361 (define_expand "vcondu<mode>"
362   [(set (match_operand:VEC_I 0 "vint_operand" "")
363         (if_then_else:VEC_I
364          (match_operator 3 "comparison_operator"
365                          [(match_operand:VEC_I 4 "vint_operand" "")
366                           (match_operand:VEC_I 5 "vint_operand" "")])
367          (match_operand:VEC_I 1 "vint_operand" "")
368          (match_operand:VEC_I 2 "vint_operand" "")))]
369   "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
370   "
372   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
373                                     operands[3], operands[4], operands[5]))
374     DONE;
375   else
376     FAIL;
379 (define_expand "vector_eq<mode>"
380   [(set (match_operand:VEC_C 0 "vlogical_operand" "")
381         (eq: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)"
384   "")
386 (define_expand "vector_gt<mode>"
387   [(set (match_operand:VEC_C 0 "vlogical_operand" "")
388         (gt: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)"
391   "")
393 (define_expand "vector_ge<mode>"
394   [(set (match_operand:VEC_C 0 "vlogical_operand" "")
395         (ge:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
396                   (match_operand:VEC_C 2 "vlogical_operand" "")))]
397   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
398   "")
400 (define_expand "vector_gtu<mode>"
401   [(set (match_operand:VEC_I 0 "vint_operand" "")
402         (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
403                    (match_operand:VEC_I 2 "vint_operand" "")))]
404   "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
405   "")
407 (define_expand "vector_geu<mode>"
408   [(set (match_operand:VEC_I 0 "vint_operand" "")
409         (geu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
410                    (match_operand:VEC_I 2 "vint_operand" "")))]
411   "VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
412   "")
414 ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
415 ;; which is in the reverse order that we want
416 (define_expand "vector_select_<mode>"
417   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
418         (if_then_else:VEC_L
419          (ne:CC (match_operand:VEC_L 3 "vlogical_operand" "")
420                 (const_int 0))
421          (match_operand:VEC_L 2 "vlogical_operand" "")
422          (match_operand:VEC_L 1 "vlogical_operand" "")))]
423   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
424   "")
426 (define_expand "vector_select_<mode>_uns"
427   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
428         (if_then_else:VEC_L
429          (ne:CCUNS (match_operand:VEC_L 3 "vlogical_operand" "")
430                    (const_int 0))
431          (match_operand:VEC_L 2 "vlogical_operand" "")
432          (match_operand:VEC_L 1 "vlogical_operand" "")))]
433   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
434   "")
436 ;; Expansions that compare vectors producing a vector result and a predicate,
437 ;; setting CR6 to indicate a combined status
438 (define_expand "vector_eq_<mode>_p"
439   [(parallel
440     [(set (reg:CC 74)
441           (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand" "")
442                              (match_operand:VEC_A 2 "vlogical_operand" ""))]
443                      UNSPEC_PREDICATE))
444      (set (match_operand:VEC_A 0 "vlogical_operand" "")
445           (eq:VEC_A (match_dup 1)
446                     (match_dup 2)))])]
447   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
448   "")
450 (define_expand "vector_gt_<mode>_p"
451   [(parallel
452     [(set (reg:CC 74)
453           (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand" "")
454                              (match_operand:VEC_A 2 "vlogical_operand" ""))]
455                      UNSPEC_PREDICATE))
456      (set (match_operand:VEC_A 0 "vlogical_operand" "")
457           (gt:VEC_A (match_dup 1)
458                     (match_dup 2)))])]
459   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
460   "")
462 (define_expand "vector_ge_<mode>_p"
463   [(parallel
464     [(set (reg:CC 74)
465           (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand" "")
466                              (match_operand:VEC_F 2 "vfloat_operand" ""))]
467                      UNSPEC_PREDICATE))
468      (set (match_operand:VEC_F 0 "vfloat_operand" "")
469           (ge:VEC_F (match_dup 1)
470                     (match_dup 2)))])]
471   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
472   "")
474 (define_expand "vector_gtu_<mode>_p"
475   [(parallel
476     [(set (reg:CC 74)
477           (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand" "")
478                               (match_operand:VEC_I 2 "vint_operand" ""))]
479                      UNSPEC_PREDICATE))
480      (set (match_operand:VEC_I 0 "vlogical_operand" "")
481           (gtu:VEC_I (match_dup 1)
482                      (match_dup 2)))])]
483   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
484   "")
486 ;; AltiVec/VSX predicates.
488 (define_expand "cr6_test_for_zero"
489   [(set (match_operand:SI 0 "register_operand" "=r")
490         (eq:SI (reg:CC 74)
491                (const_int 0)))]
492   "TARGET_ALTIVEC || TARGET_VSX"
493   "")
495 (define_expand "cr6_test_for_zero_reverse"
496   [(set (match_operand:SI 0 "register_operand" "=r")
497         (eq:SI (reg:CC 74)
498                (const_int 0)))
499    (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
500   "TARGET_ALTIVEC || TARGET_VSX"
501   "")
503 (define_expand "cr6_test_for_lt"
504   [(set (match_operand:SI 0 "register_operand" "=r")
505         (lt:SI (reg:CC 74)
506                (const_int 0)))]
507   "TARGET_ALTIVEC || TARGET_VSX"
508   "")
510 (define_expand "cr6_test_for_lt_reverse"
511   [(set (match_operand:SI 0 "register_operand" "=r")
512         (lt:SI (reg:CC 74)
513                (const_int 0)))
514    (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
515   "TARGET_ALTIVEC || TARGET_VSX"
516   "")
519 ;; Vector logical instructions
520 (define_expand "xor<mode>3"
521   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
522         (xor: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)"
525   "")
527 (define_expand "ior<mode>3"
528   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
529         (ior: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)"
532   "")
534 (define_expand "and<mode>3"
535   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
536         (and:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
537                    (match_operand:VEC_L 2 "vlogical_operand" "")))]
538   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
539   "")
541 (define_expand "one_cmpl<mode>2"
542   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
543         (not:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")))]
544   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
545   "")
547 (define_expand "nor<mode>3"
548   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
549         (not:VEC_L (ior:VEC_L (match_operand:VEC_L 1 "vlogical_operand" "")
550                               (match_operand:VEC_L 2 "vlogical_operand" ""))))]
551   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
552   "")
554 (define_expand "andc<mode>3"
555   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
556         (and:VEC_L (not:VEC_L (match_operand:VEC_L 2 "vlogical_operand" ""))
557                    (match_operand:VEC_L 1 "vlogical_operand" "")))]
558   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
559   "")
561 ;; Same size conversions
562 (define_expand "float<VEC_int><mode>2"
563   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
564         (float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
565   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
566   "
568   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
569     {
570       emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
571       DONE;
572     }
575 (define_expand "unsigned_float<VEC_int><mode>2"
576   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
577         (unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
578   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
579   "
581   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
582     {
583       emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
584       DONE;
585     }
588 (define_expand "fix_trunc<mode><VEC_int>2"
589   [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
590         (fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
591   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
592   "
594   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
595     {
596       emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
597       DONE;
598     }
601 (define_expand "fixuns_trunc<mode><VEC_int>2"
602   [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
603         (unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
604   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
605   "
607   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
608     {
609       emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
610       DONE;
611     }
615 ;; Vector initialization, set, extract
616 (define_expand "vec_init<mode>"
617   [(match_operand:VEC_E 0 "vlogical_operand" "")
618    (match_operand:VEC_E 1 "" "")]
619   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
621   rs6000_expand_vector_init (operands[0], operands[1]);
622   DONE;
625 (define_expand "vec_set<mode>"
626   [(match_operand:VEC_E 0 "vlogical_operand" "")
627    (match_operand:<VEC_base> 1 "register_operand" "")
628    (match_operand 2 "const_int_operand" "")]
629   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
631   rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
632   DONE;
635 (define_expand "vec_extract<mode>"
636   [(match_operand:<VEC_base> 0 "register_operand" "")
637    (match_operand:VEC_E 1 "vlogical_operand" "")
638    (match_operand 2 "const_int_operand" "")]
639   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
641   rs6000_expand_vector_extract (operands[0], operands[1],
642                                 INTVAL (operands[2]));
643   DONE;
646 ;; Interleave patterns
647 (define_expand "vec_interleave_highv4sf"
648   [(set (match_operand:V4SF 0 "vfloat_operand" "")
649         (vec_merge:V4SF
650          (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
651                           (parallel [(const_int 0)
652                                      (const_int 2)
653                                      (const_int 1)
654                                      (const_int 3)]))
655          (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
656                           (parallel [(const_int 2)
657                                      (const_int 0)
658                                      (const_int 3)
659                                      (const_int 1)]))
660          (const_int 5)))]
661   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
662   "")
664 (define_expand "vec_interleave_lowv4sf"
665   [(set (match_operand:V4SF 0 "vfloat_operand" "")
666         (vec_merge:V4SF
667          (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
668                           (parallel [(const_int 2)
669                                      (const_int 0)
670                                      (const_int 3)
671                                      (const_int 1)]))
672          (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
673                           (parallel [(const_int 0)
674                                      (const_int 2)
675                                      (const_int 1)
676                                      (const_int 3)]))
677          (const_int 5)))]
678   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
679   "")
681 (define_expand "vec_interleave_high<mode>"
682   [(set (match_operand:VEC_64 0 "vfloat_operand" "")
683         (vec_concat:VEC_64
684          (vec_select:<VEC_base> (match_operand:VEC_64 1 "vfloat_operand" "")
685                                 (parallel [(const_int 0)]))
686          (vec_select:<VEC_base> (match_operand:VEC_64 2 "vfloat_operand" "")
687                                 (parallel [(const_int 0)]))))]
688   "VECTOR_UNIT_VSX_P (<MODE>mode)"
689   "")
691 (define_expand "vec_interleave_low<mode>"
692   [(set (match_operand:VEC_64 0 "vfloat_operand" "")
693         (vec_concat:VEC_64
694          (vec_select:<VEC_base> (match_operand:VEC_64 1 "vfloat_operand" "")
695                                 (parallel [(const_int 1)]))
696          (vec_select:<VEC_base> (match_operand:VEC_64 2 "vfloat_operand" "")
697                                 (parallel [(const_int 1)]))))]
698   "VECTOR_UNIT_VSX_P (<MODE>mode)"
699   "")
702 ;; Convert double word types to single word types
703 (define_expand "vec_pack_trunc_v2df"
704   [(match_operand:V4SF 0 "vfloat_operand" "")
705    (match_operand:V2DF 1 "vfloat_operand" "")
706    (match_operand:V2DF 2 "vfloat_operand" "")]
707   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
709   rtx r1 = gen_reg_rtx (V4SFmode);
710   rtx r2 = gen_reg_rtx (V4SFmode);
712   emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
713   emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
714   emit_insn (gen_vec_extract_evenv4sf (operands[0], r1, r2));
715   DONE;
718 (define_expand "vec_pack_sfix_trunc_v2df"
719   [(match_operand:V4SI 0 "vint_operand" "")
720    (match_operand:V2DF 1 "vfloat_operand" "")
721    (match_operand:V2DF 2 "vfloat_operand" "")]
722   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
724   rtx r1 = gen_reg_rtx (V4SImode);
725   rtx r2 = gen_reg_rtx (V4SImode);
727   emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
728   emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
729   emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
730   DONE;
733 (define_expand "vec_pack_ufix_trunc_v2df"
734   [(match_operand:V4SI 0 "vint_operand" "")
735    (match_operand:V2DF 1 "vfloat_operand" "")
736    (match_operand:V2DF 2 "vfloat_operand" "")]
737   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
739   rtx r1 = gen_reg_rtx (V4SImode);
740   rtx r2 = gen_reg_rtx (V4SImode);
742   emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
743   emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
744   emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
745   DONE;
748 ;; Convert single word types to double word
749 (define_expand "vec_unpacks_hi_v4sf"
750   [(match_operand:V2DF 0 "vfloat_operand" "")
751    (match_operand:V4SF 1 "vfloat_operand" "")]
752   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
754   rtx reg = gen_reg_rtx (V4SFmode);
756   emit_insn (gen_vec_interleave_highv4sf (reg, operands[1], operands[1]));
757   emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
758   DONE;
761 (define_expand "vec_unpacks_lo_v4sf"
762   [(match_operand:V2DF 0 "vfloat_operand" "")
763    (match_operand:V4SF 1 "vfloat_operand" "")]
764   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
766   rtx reg = gen_reg_rtx (V4SFmode);
768   emit_insn (gen_vec_interleave_lowv4sf (reg, operands[1], operands[1]));
769   emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
770   DONE;
773 (define_expand "vec_unpacks_float_hi_v4si"
774   [(match_operand:V2DF 0 "vfloat_operand" "")
775    (match_operand:V4SI 1 "vint_operand" "")]
776   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
778   rtx reg = gen_reg_rtx (V4SImode);
780   emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
781   emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
782   DONE;
785 (define_expand "vec_unpacks_float_lo_v4si"
786   [(match_operand:V2DF 0 "vfloat_operand" "")
787    (match_operand:V4SI 1 "vint_operand" "")]
788   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
790   rtx reg = gen_reg_rtx (V4SImode);
792   emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
793   emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
794   DONE;
797 (define_expand "vec_unpacku_float_hi_v4si"
798   [(match_operand:V2DF 0 "vfloat_operand" "")
799    (match_operand:V4SI 1 "vint_operand" "")]
800   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
802   rtx reg = gen_reg_rtx (V4SImode);
804   emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
805   emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
806   DONE;
809 (define_expand "vec_unpacku_float_lo_v4si"
810   [(match_operand:V2DF 0 "vfloat_operand" "")
811    (match_operand:V4SI 1 "vint_operand" "")]
812   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
814   rtx reg = gen_reg_rtx (V4SImode);
816   emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
817   emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
818   DONE;
822 ;; Align vector loads with a permute.
823 (define_expand "vec_realign_load_<mode>"
824   [(match_operand:VEC_K 0 "vlogical_operand" "")
825    (match_operand:VEC_K 1 "vlogical_operand" "")
826    (match_operand:VEC_K 2 "vlogical_operand" "")
827    (match_operand:V16QI 3 "vlogical_operand" "")]
828   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
830   emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1], operands[2],
831                                        operands[3]));
832   DONE;
835 ;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned
836 ;; since the load already handles it.
837 (define_expand "movmisalign<mode>"
838  [(set (match_operand:VEC_N 0 "vfloat_operand" "")
839        (match_operand:VEC_N 1 "vfloat_operand" ""))]
840  "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN"
841  "")
844 ;; Vector shift left in bits.  Currently supported ony for shift
845 ;; amounts that can be expressed as byte shifts (divisible by 8).
846 ;; General shift amounts can be supported using vslo + vsl. We're
847 ;; not expecting to see these yet (the vectorizer currently
848 ;; generates only shifts divisible by byte_size).
849 (define_expand "vec_shl_<mode>"
850   [(match_operand:VEC_L 0 "vlogical_operand" "")
851    (match_operand:VEC_L 1 "vlogical_operand" "")
852    (match_operand:QI 2 "reg_or_short_operand" "")]
853   "TARGET_ALTIVEC"
854   "
856   rtx bitshift = operands[2];
857   rtx shift;
858   rtx insn;
859   HOST_WIDE_INT bitshift_val;
860   HOST_WIDE_INT byteshift_val;
862   if (! CONSTANT_P (bitshift))
863     FAIL;
864   bitshift_val = INTVAL (bitshift);
865   if (bitshift_val & 0x7)
866     FAIL;
867   byteshift_val = bitshift_val >> 3;
868   if (TARGET_VSX && (byteshift_val & 0x3) == 0)
869     {
870       shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
871       insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1],
872                                      shift);
873     }
874   else
875     {
876       shift = gen_rtx_CONST_INT (QImode, byteshift_val);
877       insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
878                                         shift);
879     }
881   emit_insn (insn);
882   DONE;
885 ;; Vector shift right in bits. Currently supported ony for shift
886 ;; amounts that can be expressed as byte shifts (divisible by 8).
887 ;; General shift amounts can be supported using vsro + vsr. We're
888 ;; not expecting to see these yet (the vectorizer currently
889 ;; generates only shifts divisible by byte_size).
890 (define_expand "vec_shr_<mode>"
891   [(match_operand:VEC_L 0 "vlogical_operand" "")
892    (match_operand:VEC_L 1 "vlogical_operand" "")
893    (match_operand:QI 2 "reg_or_short_operand" "")]
894   "TARGET_ALTIVEC"
895   "
897   rtx bitshift = operands[2];
898   rtx shift;
899   rtx insn;
900   HOST_WIDE_INT bitshift_val;
901   HOST_WIDE_INT byteshift_val;
903   if (! CONSTANT_P (bitshift))
904     FAIL;
905   bitshift_val = INTVAL (bitshift);
906   if (bitshift_val & 0x7)
907     FAIL;
908   byteshift_val = 16 - (bitshift_val >> 3);
909   if (TARGET_VSX && (byteshift_val & 0x3) == 0)
910     {
911       shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
912       insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1],
913                                      shift);
914     }
915   else
916     {
917       shift = gen_rtx_CONST_INT (QImode, byteshift_val);
918       insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
919                                         shift);
920     }
922   emit_insn (insn);
923   DONE;
926 ;; Expanders for rotate each element in a vector
927 (define_expand "vrotl<mode>3"
928   [(set (match_operand:VEC_I 0 "vint_operand" "")
929         (rotate:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
930                       (match_operand:VEC_I 2 "vint_operand" "")))]
931   "TARGET_ALTIVEC"
932   "")
934 ;; Expanders for arithmetic shift left on each vector element
935 (define_expand "vashl<mode>3"
936   [(set (match_operand:VEC_I 0 "vint_operand" "")
937         (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
938                       (match_operand:VEC_I 2 "vint_operand" "")))]
939   "TARGET_ALTIVEC"
940   "")
942 ;; Expanders for logical shift right on each vector element
943 (define_expand "vlshr<mode>3"
944   [(set (match_operand:VEC_I 0 "vint_operand" "")
945         (lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
946                         (match_operand:VEC_I 2 "vint_operand" "")))]
947   "TARGET_ALTIVEC"
948   "")
950 ;; Expanders for arithmetic shift right on each vector element
951 (define_expand "vashr<mode>3"
952   [(set (match_operand:VEC_I 0 "vint_operand" "")
953         (ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
954                         (match_operand:VEC_I 2 "vint_operand" "")))]
955   "TARGET_ALTIVEC"
956   "")
958 ;;; Expanders for vector insn patterns shared between the SPE and TARGET_PAIRED systems.
960 (define_expand "absv2sf2"
961   [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
962         (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")))]
963   "TARGET_PAIRED_FLOAT || TARGET_SPE"
964   "")
966 (define_expand "negv2sf2"
967   [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
968         (neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")))]
969   "TARGET_PAIRED_FLOAT || TARGET_SPE"
970   "")
972 (define_expand "addv2sf3"
973   [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
974         (plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
975                    (match_operand:V2SF 2 "gpc_reg_operand" "")))]
976   "TARGET_PAIRED_FLOAT || TARGET_SPE"
977   "
979   if (TARGET_SPE)
980     {
981       /* We need to make a note that we clobber SPEFSCR.  */
982       rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
984       XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
985                                          gen_rtx_PLUS (V2SFmode, operands[1], operands[2]));
986       XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
987       emit_insn (par);
988       DONE;
989     }
992 (define_expand "subv2sf3"
993   [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
994         (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
995                     (match_operand:V2SF 2 "gpc_reg_operand" "")))]
996   "TARGET_PAIRED_FLOAT || TARGET_SPE"
997   "
999   if (TARGET_SPE)
1000     {
1001       /* We need to make a note that we clobber SPEFSCR.  */
1002       rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1004       XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1005                                          gen_rtx_MINUS (V2SFmode, operands[1], operands[2]));
1006       XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1007       emit_insn (par);
1008       DONE;
1009     }
1012 (define_expand "mulv2sf3"
1013   [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1014         (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
1015                    (match_operand:V2SF 2 "gpc_reg_operand" "")))]
1016   "TARGET_PAIRED_FLOAT || TARGET_SPE"
1017   "
1019   if (TARGET_SPE)
1020     {
1021       /* We need to make a note that we clobber SPEFSCR.  */
1022       rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1024       XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1025                                          gen_rtx_MULT (V2SFmode, operands[1], operands[2]));
1026       XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1027       emit_insn (par);
1028       DONE;
1029     }
1032 (define_expand "divv2sf3"
1033   [(set (match_operand:V2SF 0 "gpc_reg_operand" "")
1034         (div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")
1035                   (match_operand:V2SF 2 "gpc_reg_operand" "")))]
1036   "TARGET_PAIRED_FLOAT || TARGET_SPE"
1037   "
1039   if (TARGET_SPE)
1040     {
1041       /* We need to make a note that we clobber SPEFSCR.  */
1042       rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1044       XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0],
1045                                          gen_rtx_DIV (V2SFmode, operands[1], operands[2]));
1046       XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO));
1047       emit_insn (par);
1048       DONE;
1049     }