Add a VEC_SERIES rtl code
[official-gcc.git] / gcc / config / rs6000 / vector.md
blob5a9b1a8c10136239f3c7bc2ea0fb8723db99549d
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-2017 Free Software Foundation, Inc.
7 ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
9 ;; This file is part of GCC.
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.
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.
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/>.
26 ;; Vector int modes
27 (define_mode_iterator VEC_I [V16QI V8HI V4SI V2DI])
29 ;; Vector int modes for parity
30 (define_mode_iterator VEC_IP [V8HI
31                               V4SI
32                               V2DI
33                               V1TI
34                               TI])
36 ;; Vector float modes
37 (define_mode_iterator VEC_F [V4SF V2DF])
39 ;; Vector arithmetic modes
40 (define_mode_iterator VEC_A [V16QI V8HI V4SI V2DI V4SF V2DF])
42 ;; Vector modes that need alginment via permutes
43 (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
45 ;; Vector logical modes
46 (define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI KF TF])
48 ;; Vector modes for moves.  Don't do TImode or TFmode here, since their
49 ;; moves are handled elsewhere.
50 (define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI KF])
52 ;; Vector modes for types that don't need a realignment under VSX
53 (define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI KF TF])
55 ;; Vector comparison modes
56 (define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF])
58 ;; Vector init/extract modes
59 (define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF])
61 ;; Vector modes for 64-bit base types
62 (define_mode_iterator VEC_64 [V2DI V2DF])
64 ;; Vector integer modes
65 (define_mode_iterator VI [V4SI V8HI V16QI])
67 ;; Base type from vector mode
68 (define_mode_attr VEC_base [(V16QI "QI")
69                             (V8HI  "HI")
70                             (V4SI  "SI")
71                             (V2DI  "DI")
72                             (V4SF  "SF")
73                             (V2DF  "DF")
74                             (V1TI  "TI")
75                             (TI    "TI")])
77 ;; As above, but in lower case
78 (define_mode_attr VEC_base_l [(V16QI "qi")
79                               (V8HI  "hi")
80                               (V4SI  "si")
81                               (V2DI  "di")
82                               (V4SF  "sf")
83                               (V2DF  "df")
84                               (V1TI  "ti")
85                               (TI    "ti")])
87 ;; Same size integer type for floating point data
88 (define_mode_attr VEC_int [(V4SF  "v4si")
89                            (V2DF  "v2di")])
91 (define_mode_attr VEC_INT [(V4SF  "V4SI")
92                            (V2DF  "V2DI")])
94 ;; constants for unspec
95 (define_c_enum "unspec" [UNSPEC_PREDICATE
96                          UNSPEC_REDUC
97                          UNSPEC_NEZ_P])
99 ;; Vector reduction code iterators
100 (define_code_iterator VEC_reduc [plus smin smax])
102 (define_code_attr VEC_reduc_name [(plus "plus")
103                                   (smin "smin")
104                                   (smax "smax")])
106 (define_code_attr VEC_reduc_rtx [(plus "add")
107                                  (smin "smin")
108                                  (smax "smax")])
111 ;; Vector move instructions.  Little-endian VSX loads and stores require
112 ;; special handling to circumvent "element endianness."
113 (define_expand "mov<mode>"
114   [(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
115         (match_operand:VEC_M 1 "any_operand" ""))]
116   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
118   if (can_create_pseudo_p ())
119     {
120       if (CONSTANT_P (operands[1]))
121         {
122           if (FLOAT128_VECTOR_P (<MODE>mode))
123             {
124               if (!easy_fp_constant (operands[1], <MODE>mode))
125                 operands[1] = force_const_mem (<MODE>mode, operands[1]);
126             }
127           else if (!easy_vector_constant (operands[1], <MODE>mode))
128             operands[1] = force_const_mem (<MODE>mode, operands[1]);
129         }
131       if (!vlogical_operand (operands[0], <MODE>mode)
132           && !vlogical_operand (operands[1], <MODE>mode))
133         operands[1] = force_reg (<MODE>mode, operands[1]);
134     }
135   if (!BYTES_BIG_ENDIAN
136       && VECTOR_MEM_VSX_P (<MODE>mode)
137       && !TARGET_P9_VECTOR
138       && !gpr_or_gpr_p (operands[0], operands[1])
139       && (memory_operand (operands[0], <MODE>mode)
140           ^ memory_operand (operands[1], <MODE>mode)))
141     {
142       rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
143       DONE;
144     }
147 ;; Generic vector floating point load/store instructions.  These will match
148 ;; insns defined in vsx.md or altivec.md depending on the switches.
149 (define_expand "vector_load_<mode>"
150   [(set (match_operand:VEC_M 0 "vfloat_operand" "")
151         (match_operand:VEC_M 1 "memory_operand" ""))]
152   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
153   "")
155 (define_expand "vector_store_<mode>"
156   [(set (match_operand:VEC_M 0 "memory_operand" "")
157         (match_operand:VEC_M 1 "vfloat_operand" ""))]
158   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
159   "")
161 ;; Splits if a GPR register was chosen for the move
162 (define_split
163   [(set (match_operand:VEC_L 0 "nonimmediate_operand" "")
164         (match_operand:VEC_L 1 "input_operand" ""))]
165   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
166    && reload_completed
167    && gpr_or_gpr_p (operands[0], operands[1])
168    && !direct_move_p (operands[0], operands[1])
169    && !quad_load_store_p (operands[0], operands[1])"
170   [(pc)]
172   rs6000_split_multireg_move (operands[0], operands[1]);
173   DONE;
176 ;; Vector floating point load/store instructions that uses the Altivec
177 ;; instructions even if we are compiling for VSX, since the Altivec
178 ;; instructions silently ignore the bottom 3 bits of the address, and VSX does
179 ;; not.
180 (define_expand "vector_altivec_load_<mode>"
181   [(set (match_operand:VEC_M 0 "vfloat_operand" "")
182         (match_operand:VEC_M 1 "memory_operand" ""))]
183   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
184   "
186   gcc_assert (VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode));
188   if (VECTOR_MEM_VSX_P (<MODE>mode))
189     {
190       operands[1] = rs6000_address_for_altivec (operands[1]);
191       rtx and_op = XEXP (operands[1], 0);
192       gcc_assert (GET_CODE (and_op) == AND);
193       rtx addr = XEXP (and_op, 0);
194       if (GET_CODE (addr) == PLUS)
195         emit_insn (gen_altivec_lvx_<mode>_2op (operands[0], XEXP (addr, 0),
196                                                XEXP (addr, 1)));
197       else
198         emit_insn (gen_altivec_lvx_<mode>_1op (operands[0], operands[1]));
199       DONE;
200     }
203 (define_expand "vector_altivec_store_<mode>"
204   [(set (match_operand:VEC_M 0 "memory_operand" "")
205         (match_operand:VEC_M 1 "vfloat_operand" ""))]
206   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
207   "
209   gcc_assert (VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode));
211   if (VECTOR_MEM_VSX_P (<MODE>mode))
212     {
213       operands[0] = rs6000_address_for_altivec (operands[0]);
214       rtx and_op = XEXP (operands[0], 0);
215       gcc_assert (GET_CODE (and_op) == AND);
216       rtx addr = XEXP (and_op, 0);
217       if (GET_CODE (addr) == PLUS)
218         emit_insn (gen_altivec_stvx_<mode>_2op (operands[1], XEXP (addr, 0),
219                                                 XEXP (addr, 1)));
220       else
221         emit_insn (gen_altivec_stvx_<mode>_1op (operands[1], operands[0]));
222       DONE;
223     }
228 ;; Generic floating point vector arithmetic support
229 (define_expand "add<mode>3"
230   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
231         (plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
232                     (match_operand:VEC_F 2 "vfloat_operand" "")))]
233   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
234   "")
236 (define_expand "sub<mode>3"
237   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
238         (minus: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   "")
243 (define_expand "mul<mode>3"
244   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
245         (mult: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)"
249   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
250     {
251       emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
252       DONE;
253     }
256 (define_expand "div<mode>3"
257   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
258         (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
259                    (match_operand:VEC_F 2 "vfloat_operand" "")))]
260   "VECTOR_UNIT_VSX_P (<MODE>mode)"
262   if (RS6000_RECIP_AUTO_RE_P (<MODE>mode)
263       && can_create_pseudo_p () && flag_finite_math_only
264       && !flag_trapping_math && flag_reciprocal_math)
265     {
266       rs6000_emit_swdiv (operands[0], operands[1], operands[2], true);
267       DONE;
268     }
271 (define_expand "neg<mode>2"
272   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
273         (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
274   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
275   "
277   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
278     {
279       emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
280       DONE;
281     }
284 (define_expand "abs<mode>2"
285   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
286         (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
287   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
288   "
290   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
291     {
292       emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
293       DONE;
294     }
297 (define_expand "smin<mode>3"
298   [(set (match_operand:VEC_F 0 "register_operand" "")
299         (smin:VEC_F (match_operand:VEC_F 1 "register_operand" "")
300                     (match_operand:VEC_F 2 "register_operand" "")))]
301   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
302   "")
304 (define_expand "smax<mode>3"
305   [(set (match_operand:VEC_F 0 "register_operand" "")
306         (smax:VEC_F (match_operand:VEC_F 1 "register_operand" "")
307                     (match_operand:VEC_F 2 "register_operand" "")))]
308   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
309   "")
312 (define_expand "sqrt<mode>2"
313   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
314         (sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
315   "VECTOR_UNIT_VSX_P (<MODE>mode)"
317   if (<MODE>mode == V4SFmode
318       && !optimize_function_for_size_p (cfun)
319       && flag_finite_math_only && !flag_trapping_math
320       && flag_unsafe_math_optimizations)
321     {
322       rs6000_emit_swsqrt (operands[0], operands[1], 0);
323       DONE;
324     }
327 (define_expand "rsqrte<mode>2"
328   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
329         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
330                       UNSPEC_RSQRT))]
331   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
332   "")
334 (define_expand "re<mode>2"
335   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
336         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "f")]
337                       UNSPEC_FRES))]
338   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
339   "")
341 (define_expand "ftrunc<mode>2"
342   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
343         (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
344   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
345   "")
347 (define_expand "vector_ceil<mode>2"
348   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
349         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
350                       UNSPEC_FRIP))]
351   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
352   "")
354 (define_expand "vector_floor<mode>2"
355   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
356         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")]
357                       UNSPEC_FRIM))]
358   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
359   "")
361 (define_expand "vector_btrunc<mode>2"
362   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
363         (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")))]
364   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
365   "")
367 (define_expand "vector_copysign<mode>3"
368   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
369         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand" "")
370                        (match_operand:VEC_F 2 "vfloat_operand" "")] UNSPEC_COPYSIGN))]
371   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
372   "
374   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
375     {
376       emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1],
377                                              operands[2]));
378       DONE;
379     }
383 ;; Vector comparisons
384 (define_expand "vcond<mode><mode>"
385   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
386         (if_then_else:VEC_F
387          (match_operator 3 "comparison_operator"
388                          [(match_operand:VEC_F 4 "vfloat_operand" "")
389                           (match_operand:VEC_F 5 "vfloat_operand" "")])
390          (match_operand:VEC_F 1 "vfloat_operand" "")
391          (match_operand:VEC_F 2 "vfloat_operand" "")))]
392   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
393   "
395   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
396                                     operands[3], operands[4], operands[5]))
397     DONE;
398   else
399     FAIL;
402 (define_expand "vcond<mode><mode>"
403   [(set (match_operand:VEC_I 0 "vint_operand")
404         (if_then_else:VEC_I
405          (match_operator 3 "comparison_operator"
406                          [(match_operand:VEC_I 4 "vint_operand")
407                           (match_operand:VEC_I 5 "vint_operand")])
408          (match_operand:VEC_I 1 "vector_int_reg_or_same_bit")
409          (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))]
410   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
411   "
413   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
414                                     operands[3], operands[4], operands[5]))
415     DONE;
416   else
417     FAIL;
420 (define_expand "vcondv4sfv4si"
421   [(set (match_operand:V4SF 0 "vfloat_operand" "")
422         (if_then_else:V4SF
423          (match_operator 3 "comparison_operator"
424                          [(match_operand:V4SI 4 "vint_operand" "")
425                           (match_operand:V4SI 5 "vint_operand" "")])
426          (match_operand:V4SF 1 "vfloat_operand" "")
427          (match_operand:V4SF 2 "vfloat_operand" "")))]
428   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
429    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
430   "
432   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
433                                     operands[3], operands[4], operands[5]))
434     DONE;
435   else
436     FAIL;
439 (define_expand "vcondv4siv4sf"
440   [(set (match_operand:V4SI 0 "vint_operand" "")
441         (if_then_else:V4SI
442          (match_operator 3 "comparison_operator"
443                          [(match_operand:V4SF 4 "vfloat_operand" "")
444                           (match_operand:V4SF 5 "vfloat_operand" "")])
445          (match_operand:V4SI 1 "vint_operand" "")
446          (match_operand:V4SI 2 "vint_operand" "")))]
447   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
448    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
449   "
451   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
452                                     operands[3], operands[4], operands[5]))
453     DONE;
454   else
455     FAIL;
458 (define_expand "vcondu<mode><mode>"
459   [(set (match_operand:VEC_I 0 "vint_operand")
460         (if_then_else:VEC_I
461          (match_operator 3 "comparison_operator"
462                          [(match_operand:VEC_I 4 "vint_operand")
463                           (match_operand:VEC_I 5 "vint_operand")])
464          (match_operand:VEC_I 1 "vector_int_reg_or_same_bit")
465          (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))]
466   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
467   "
469   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
470                                     operands[3], operands[4], operands[5]))
471     DONE;
472   else
473     FAIL;
476 (define_expand "vconduv4sfv4si"
477   [(set (match_operand:V4SF 0 "vfloat_operand" "")
478         (if_then_else:V4SF
479          (match_operator 3 "comparison_operator"
480                          [(match_operand:V4SI 4 "vint_operand" "")
481                           (match_operand:V4SI 5 "vint_operand" "")])
482          (match_operand:V4SF 1 "vfloat_operand" "")
483          (match_operand:V4SF 2 "vfloat_operand" "")))]
484   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
485    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
486   "
488   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
489                                     operands[3], operands[4], operands[5]))
490     DONE;
491   else
492     FAIL;
495 (define_expand "vector_eq<mode>"
496   [(set (match_operand:VEC_C 0 "vlogical_operand" "")
497         (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
498                   (match_operand:VEC_C 2 "vlogical_operand" "")))]
499   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
500   "")
502 (define_expand "vector_gt<mode>"
503   [(set (match_operand:VEC_C 0 "vlogical_operand" "")
504         (gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand" "")
505                   (match_operand:VEC_C 2 "vlogical_operand" "")))]
506   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
507   "")
509 (define_expand "vector_ge<mode>"
510   [(set (match_operand:VEC_F 0 "vlogical_operand" "")
511         (ge:VEC_F (match_operand:VEC_F 1 "vlogical_operand" "")
512                   (match_operand:VEC_F 2 "vlogical_operand" "")))]
513   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
514   "")
516 ; >= for integer vectors: swap operands and apply not-greater-than
517 (define_expand "vector_nlt<mode>"
518   [(set (match_operand:VEC_I 3 "vlogical_operand" "")
519         (gt:VEC_I (match_operand:VEC_I 2 "vlogical_operand" "")
520                   (match_operand:VEC_I 1 "vlogical_operand" "")))
521    (set (match_operand:VEC_I 0 "vlogical_operand" "")
522         (not:VEC_I (match_dup 3)))]
523   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
524   "
526   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
529 (define_expand "vector_gtu<mode>"
530   [(set (match_operand:VEC_I 0 "vint_operand" "")
531         (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
532                    (match_operand:VEC_I 2 "vint_operand" "")))]
533   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
534   "")
536 ; >= for integer vectors: swap operands and apply not-greater-than
537 (define_expand "vector_nltu<mode>"
538   [(set (match_operand:VEC_I 3 "vlogical_operand" "")
539         (gtu:VEC_I (match_operand:VEC_I 2 "vlogical_operand" "")
540                    (match_operand:VEC_I 1 "vlogical_operand" "")))
541    (set (match_operand:VEC_I 0 "vlogical_operand" "")
542         (not:VEC_I (match_dup 3)))]
543   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
544   "
546   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
549 (define_expand "vector_geu<mode>"
550   [(set (match_operand:VEC_I 0 "vint_operand" "")
551         (geu:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
552                    (match_operand:VEC_I 2 "vint_operand" "")))]
553   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
554   "")
556 ; <= for integer vectors: apply not-greater-than
557 (define_expand "vector_ngt<mode>"
558   [(set (match_operand:VEC_I 3 "vlogical_operand" "")
559         (gt:VEC_I (match_operand:VEC_I 1 "vlogical_operand" "")
560                   (match_operand:VEC_I 2 "vlogical_operand" "")))
561    (set (match_operand:VEC_I 0 "vlogical_operand" "")
562         (not:VEC_I (match_dup 3)))]
563   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
564   "
566   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
569 (define_expand "vector_ngtu<mode>"
570   [(set (match_operand:VEC_I 3 "vlogical_operand" "")
571         (gtu:VEC_I (match_operand:VEC_I 1 "vlogical_operand" "")
572                    (match_operand:VEC_I 2 "vlogical_operand" "")))
573    (set (match_operand:VEC_I 0 "vlogical_operand" "")
574         (not:VEC_I (match_dup 3)))]
575   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
576   "
578   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
581 (define_insn_and_split "*vector_uneq<mode>"
582   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
583         (uneq:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
584                     (match_operand:VEC_F 2 "vfloat_operand" "")))]
585   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
586   "#"
587   ""
588   [(set (match_dup 3)
589         (gt:VEC_F (match_dup 1)
590                   (match_dup 2)))
591    (set (match_dup 4)
592         (gt:VEC_F (match_dup 2)
593                   (match_dup 1)))
594    (set (match_dup 0)
595         (and:VEC_F (not:VEC_F (match_dup 3))
596                    (not:VEC_F (match_dup 4))))]
598   operands[3] = gen_reg_rtx (<MODE>mode);
599   operands[4] = gen_reg_rtx (<MODE>mode);
602 (define_insn_and_split "*vector_ltgt<mode>"
603   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
604         (ltgt:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
605                     (match_operand:VEC_F 2 "vfloat_operand" "")))]
606   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
607   "#"
608   ""
609   [(set (match_dup 3)
610         (gt:VEC_F (match_dup 1)
611                   (match_dup 2)))
612    (set (match_dup 4)
613         (gt:VEC_F (match_dup 2)
614                   (match_dup 1)))
615    (set (match_dup 0)
616         (ior:VEC_F (match_dup 3)
617                    (match_dup 4)))]
618   "
620   operands[3] = gen_reg_rtx (<MODE>mode);
621   operands[4] = gen_reg_rtx (<MODE>mode);
624 (define_insn_and_split "*vector_ordered<mode>"
625   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
626         (ordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
627                        (match_operand:VEC_F 2 "vfloat_operand" "")))]
628   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
629   "#"
630   ""
631   [(set (match_dup 3)
632         (ge:VEC_F (match_dup 1)
633                   (match_dup 2)))
634    (set (match_dup 4)
635         (ge:VEC_F (match_dup 2)
636                   (match_dup 1)))
637    (set (match_dup 0)
638         (ior:VEC_F (match_dup 3)
639                    (match_dup 4)))]
640   "
642   operands[3] = gen_reg_rtx (<MODE>mode);
643   operands[4] = gen_reg_rtx (<MODE>mode);
646 (define_insn_and_split "*vector_unordered<mode>"
647   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
648         (unordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
649                          (match_operand:VEC_F 2 "vfloat_operand" "")))]
650   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
651   "#"
652   ""
653   [(set (match_dup 3)
654         (ge:VEC_F (match_dup 1)
655                   (match_dup 2)))
656    (set (match_dup 4)
657         (ge:VEC_F (match_dup 2)
658                   (match_dup 1)))
659    (set (match_dup 0)
660         (and:VEC_F (not:VEC_F (match_dup 3))
661                    (not:VEC_F (match_dup 4))))]
662   "
664   operands[3] = gen_reg_rtx (<MODE>mode);
665   operands[4] = gen_reg_rtx (<MODE>mode);
668 ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
669 ;; which is in the reverse order that we want
670 (define_expand "vector_select_<mode>"
671   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
672         (if_then_else:VEC_L
673          (ne:CC (match_operand:VEC_L 3 "vlogical_operand" "")
674                 (match_dup 4))
675          (match_operand:VEC_L 2 "vlogical_operand" "")
676          (match_operand:VEC_L 1 "vlogical_operand" "")))]
677   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
678   "operands[4] = CONST0_RTX (<MODE>mode);")
680 (define_expand "vector_select_<mode>_uns"
681   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
682         (if_then_else:VEC_L
683          (ne:CCUNS (match_operand:VEC_L 3 "vlogical_operand" "")
684                    (match_dup 4))
685          (match_operand:VEC_L 2 "vlogical_operand" "")
686          (match_operand:VEC_L 1 "vlogical_operand" "")))]
687   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
688   "operands[4] = CONST0_RTX (<MODE>mode);")
690 ;; Expansions that compare vectors producing a vector result and a predicate,
691 ;; setting CR6 to indicate a combined status
692 (define_expand "vector_eq_<mode>_p"
693   [(parallel
694     [(set (reg:CC CR6_REGNO)
695           (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand" "")
696                              (match_operand:VEC_A 2 "vlogical_operand" ""))]
697                      UNSPEC_PREDICATE))
698      (set (match_operand:VEC_A 0 "vlogical_operand" "")
699           (eq:VEC_A (match_dup 1)
700                     (match_dup 2)))])]
701   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
702   "")
704 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
705 ;; implementation of the vec_all_ne built-in functions on Power9.
706 (define_expand "vector_ne_<mode>_p"
707   [(parallel
708     [(set (reg:CC CR6_REGNO)
709           (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand")
710                              (match_operand:VI 2 "vlogical_operand"))]
711            UNSPEC_PREDICATE))
712      (set (match_dup 3)
713           (ne:VI (match_dup 1)
714                  (match_dup 2)))])
715    (set (match_operand:SI 0 "register_operand" "=r")
716         (lt:SI (reg:CC CR6_REGNO)
717                (const_int 0)))]
718   "TARGET_P9_VECTOR"
720   operands[3] = gen_reg_rtx (<MODE>mode);
723 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
724 ;; implementation of the vec_any_eq built-in functions on Power9.
725 (define_expand "vector_ae_<mode>_p"
726   [(parallel
727     [(set (reg:CC CR6_REGNO)
728           (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand")
729                              (match_operand:VI 2 "vlogical_operand"))]
730            UNSPEC_PREDICATE))
731      (set (match_dup 3)
732           (ne:VI (match_dup 1)
733                  (match_dup 2)))])
734    (set (match_operand:SI 0 "register_operand" "=r")
735         (lt:SI (reg:CC CR6_REGNO)
736                (const_int 0)))
737    (set (match_dup 0)
738         (xor:SI (match_dup 0)
739                 (const_int 1)))]
740   "TARGET_P9_VECTOR"
742   operands[3] = gen_reg_rtx (<MODE>mode);
745 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
746 ;; implementation of the vec_all_nez and vec_any_eqz built-in
747 ;; functions on Power9.
748 (define_expand "vector_nez_<mode>_p"
749   [(parallel
750     [(set (reg:CC CR6_REGNO)
751           (unspec:CC [(unspec:VI
752                        [(match_operand:VI 1 "vlogical_operand")
753                         (match_operand:VI 2 "vlogical_operand")]
754                        UNSPEC_NEZ_P)]
755            UNSPEC_PREDICATE))
756      (set (match_operand:VI 0 "vlogical_operand")
757           (unspec:VI [(match_dup 1)
758                       (match_dup 2)]
759            UNSPEC_NEZ_P))])]
760   "TARGET_P9_VECTOR"
761   "")
763 ;; This expansion handles the V2DI mode in the implementation of the
764 ;; vec_all_ne built-in function on Power9.
766 ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode,
767 ;; this expands into the same rtl that would be used for the Power8
768 ;; architecture.
769 (define_expand "vector_ne_v2di_p"
770   [(parallel
771     [(set (reg:CC CR6_REGNO)
772           (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand")
773                              (match_operand:V2DI 2 "vlogical_operand"))]
774                      UNSPEC_PREDICATE))
775      (set (match_dup 3)
776           (eq:V2DI (match_dup 1)
777                    (match_dup 2)))])
778    (set (match_operand:SI 0 "register_operand" "=r")
779         (eq:SI (reg:CC CR6_REGNO)
780                (const_int 0)))]
781   "TARGET_P9_VECTOR"
783   operands[3] = gen_reg_rtx (V2DImode);
786 ;; This expansion handles the V2DI mode in the implementation of the
787 ;; vec_any_eq built-in function on Power9.
789 ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode,
790 ;; this expands into the same rtl that would be used for the Power8
791 ;; architecture.
792 (define_expand "vector_ae_v2di_p"
793   [(parallel
794     [(set (reg:CC CR6_REGNO)
795           (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand")
796                              (match_operand:V2DI 2 "vlogical_operand"))]
797                      UNSPEC_PREDICATE))
798      (set (match_dup 3)
799           (eq:V2DI (match_dup 1)
800                    (match_dup 2)))])
801    (set (match_operand:SI 0 "register_operand" "=r")
802         (eq:SI (reg:CC CR6_REGNO)
803                (const_int 0)))
804    (set (match_dup 0)
805         (xor:SI (match_dup 0)
806                 (const_int 1)))]
807   "TARGET_P9_VECTOR"
809   operands[3] = gen_reg_rtx (V2DImode);
812 ;; This expansion handles the V4SF and V2DF modes in the Power9
813 ;; implementation of the vec_all_ne built-in functions.  Note that the
814 ;; expansions for this pattern with these modes makes no use of power9-
815 ;; specific instructions since there are no new power9 instructions
816 ;; for vector compare not equal with floating point arguments.
817 (define_expand "vector_ne_<mode>_p"
818   [(parallel
819     [(set (reg:CC CR6_REGNO)
820           (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand")
821                              (match_operand:VEC_F 2 "vlogical_operand"))]
822                      UNSPEC_PREDICATE))
823      (set (match_dup 3)
824           (eq:VEC_F (match_dup 1)
825                     (match_dup 2)))])
826    (set (match_operand:SI 0 "register_operand" "=r")
827         (eq:SI (reg:CC CR6_REGNO)
828                (const_int 0)))]
829   "TARGET_P9_VECTOR"
831   operands[3] = gen_reg_rtx (<MODE>mode);
834 ;; This expansion handles the V4SF and V2DF modes in the Power9
835 ;; implementation of the vec_any_eq built-in functions.  Note that the
836 ;; expansions for this pattern with these modes makes no use of power9-
837 ;; specific instructions since there are no new power9 instructions
838 ;; for vector compare not equal with floating point arguments.
839 (define_expand "vector_ae_<mode>_p"
840   [(parallel
841     [(set (reg:CC CR6_REGNO)
842           (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand")
843                              (match_operand:VEC_F 2 "vlogical_operand"))]
844                      UNSPEC_PREDICATE))
845      (set (match_dup 3)
846           (eq:VEC_F (match_dup 1)
847                     (match_dup 2)))])
848    (set (match_operand:SI 0 "register_operand" "=r")
849         (eq:SI (reg:CC CR6_REGNO)
850                (const_int 0)))
851    (set (match_dup 0)
852         (xor:SI (match_dup 0)
853                 (const_int 1)))]
854   "TARGET_P9_VECTOR"
856   operands[3] = gen_reg_rtx (<MODE>mode);
859 (define_expand "vector_gt_<mode>_p"
860   [(parallel
861     [(set (reg:CC CR6_REGNO)
862           (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand" "")
863                              (match_operand:VEC_A 2 "vlogical_operand" ""))]
864                      UNSPEC_PREDICATE))
865      (set (match_operand:VEC_A 0 "vlogical_operand" "")
866           (gt:VEC_A (match_dup 1)
867                     (match_dup 2)))])]
868   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
869   "")
871 (define_expand "vector_ge_<mode>_p"
872   [(parallel
873     [(set (reg:CC CR6_REGNO)
874           (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand" "")
875                              (match_operand:VEC_F 2 "vfloat_operand" ""))]
876                      UNSPEC_PREDICATE))
877      (set (match_operand:VEC_F 0 "vfloat_operand" "")
878           (ge:VEC_F (match_dup 1)
879                     (match_dup 2)))])]
880   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
881   "")
883 (define_expand "vector_gtu_<mode>_p"
884   [(parallel
885     [(set (reg:CC CR6_REGNO)
886           (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand" "")
887                               (match_operand:VEC_I 2 "vint_operand" ""))]
888                      UNSPEC_PREDICATE))
889      (set (match_operand:VEC_I 0 "vlogical_operand" "")
890           (gtu:VEC_I (match_dup 1)
891                      (match_dup 2)))])]
892   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
893   "")
895 ;; AltiVec/VSX predicates.
897 ;; This expansion is triggered during expansion of predicate built-in
898 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
899 ;; altivec_expand_predicate_builtin() function when the value of the
900 ;; integer constant first argument equals zero (aka __CR6_EQ in altivec.h).
901 (define_expand "cr6_test_for_zero"
902   [(set (match_operand:SI 0 "register_operand" "=r")
903         (eq:SI (reg:CC CR6_REGNO)
904                (const_int 0)))]
905   "TARGET_ALTIVEC || TARGET_VSX"
906   "")
908 ;; This expansion is triggered during expansion of predicate built-in
909 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
910 ;; altivec_expand_predicate_builtin() function when the value of the
911 ;; integer constant first argument equals one (aka __CR6_EQ_REV in altivec.h).
912 (define_expand "cr6_test_for_zero_reverse"
913   [(set (match_operand:SI 0 "register_operand" "=r")
914         (eq:SI (reg:CC CR6_REGNO)
915                (const_int 0)))
916    (set (match_dup 0)
917         (xor:SI (match_dup 0)
918                 (const_int 1)))]
919   "TARGET_ALTIVEC || TARGET_VSX"
920   "")
922 ;; This expansion is triggered during expansion of predicate built-in
923 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
924 ;; altivec_expand_predicate_builtin() function when the value of the
925 ;; integer constant first argument equals two (aka __CR6_LT in altivec.h).
926 (define_expand "cr6_test_for_lt"
927   [(set (match_operand:SI 0 "register_operand" "=r")
928         (lt:SI (reg:CC CR6_REGNO)
929                (const_int 0)))]
930   "TARGET_ALTIVEC || TARGET_VSX"
931   "")
933 ;; This expansion is triggered during expansion of predicate built-in
934 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
935 ;; altivec_expand_predicate_builtin() function when the value of the
936 ;; integer constant first argument equals three
937 ;; (aka __CR6_LT_REV in altivec.h).
938 (define_expand "cr6_test_for_lt_reverse"
939   [(set (match_operand:SI 0 "register_operand" "=r")
940         (lt:SI (reg:CC CR6_REGNO)
941                (const_int 0)))
942    (set (match_dup 0)
943         (xor:SI (match_dup 0)
944                 (const_int 1)))]
945   "TARGET_ALTIVEC || TARGET_VSX"
946   "")
949 ;; Vector count leading zeros
950 (define_expand "clz<mode>2"
951   [(set (match_operand:VEC_I 0 "register_operand" "")
952         (clz:VEC_I (match_operand:VEC_I 1 "register_operand" "")))]
953   "TARGET_P8_VECTOR")
955 ;; Vector count trailing zeros
956 (define_expand "ctz<mode>2"
957   [(set (match_operand:VEC_I 0 "register_operand" "")
958         (ctz:VEC_I (match_operand:VEC_I 1 "register_operand" "")))]
959   "TARGET_P9_VECTOR")
961 ;; Vector population count
962 (define_expand "popcount<mode>2"
963   [(set (match_operand:VEC_I 0 "register_operand" "")
964         (popcount:VEC_I (match_operand:VEC_I 1 "register_operand" "")))]
965   "TARGET_P8_VECTOR")
967 ;; Vector parity
968 (define_expand "parity<mode>2"
969   [(set (match_operand:VEC_IP 0 "register_operand" "")
970         (parity:VEC_IP (match_operand:VEC_IP 1 "register_operand" "")))]
971   "TARGET_P9_VECTOR")
974 ;; Same size conversions
975 (define_expand "float<VEC_int><mode>2"
976   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
977         (float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
978   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
979   "
981   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
982     {
983       emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
984       DONE;
985     }
988 (define_expand "floatuns<VEC_int><mode>2"
989   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
990         (unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand" "")))]
991   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
992   "
994   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
995     {
996       emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
997       DONE;
998     }
1001 (define_expand "fix_trunc<mode><VEC_int>2"
1002   [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
1003         (fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
1004   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1005   "
1007   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
1008     {
1009       emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
1010       DONE;
1011     }
1014 (define_expand "fixuns_trunc<mode><VEC_int>2"
1015   [(set (match_operand:<VEC_INT> 0 "vint_operand" "")
1016         (unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand" "")))]
1017   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1018   "
1020   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
1021     {
1022       emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
1023       DONE;
1024     }
1028 ;; Vector initialization, set, extract
1029 (define_expand "vec_init<mode><VEC_base_l>"
1030   [(match_operand:VEC_E 0 "vlogical_operand" "")
1031    (match_operand:VEC_E 1 "" "")]
1032   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1034   rs6000_expand_vector_init (operands[0], operands[1]);
1035   DONE;
1038 (define_expand "vec_set<mode>"
1039   [(match_operand:VEC_E 0 "vlogical_operand" "")
1040    (match_operand:<VEC_base> 1 "register_operand" "")
1041    (match_operand 2 "const_int_operand" "")]
1042   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1044   rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
1045   DONE;
1048 (define_expand "vec_extract<mode><VEC_base_l>"
1049   [(match_operand:<VEC_base> 0 "register_operand" "")
1050    (match_operand:VEC_E 1 "vlogical_operand" "")
1051    (match_operand 2 "const_int_operand" "")]
1052   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1054   rs6000_expand_vector_extract (operands[0], operands[1], operands[2]);
1055   DONE;
1058 ;; Convert double word types to single word types
1059 (define_expand "vec_pack_trunc_v2df"
1060   [(match_operand:V4SF 0 "vfloat_operand" "")
1061    (match_operand:V2DF 1 "vfloat_operand" "")
1062    (match_operand:V2DF 2 "vfloat_operand" "")]
1063   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1065   rtx r1 = gen_reg_rtx (V4SFmode);
1066   rtx r2 = gen_reg_rtx (V4SFmode);
1068   emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
1069   emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
1070   rs6000_expand_extract_even (operands[0], r1, r2);
1071   DONE;
1074 (define_expand "vec_pack_sfix_trunc_v2df"
1075   [(match_operand:V4SI 0 "vint_operand" "")
1076    (match_operand:V2DF 1 "vfloat_operand" "")
1077    (match_operand:V2DF 2 "vfloat_operand" "")]
1078   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1080   rtx r1 = gen_reg_rtx (V4SImode);
1081   rtx r2 = gen_reg_rtx (V4SImode);
1083   emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
1084   emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
1085   rs6000_expand_extract_even (operands[0], r1, r2);
1086   DONE;
1089 (define_expand "vec_pack_ufix_trunc_v2df"
1090   [(match_operand:V4SI 0 "vint_operand" "")
1091    (match_operand:V2DF 1 "vfloat_operand" "")
1092    (match_operand:V2DF 2 "vfloat_operand" "")]
1093   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1095   rtx r1 = gen_reg_rtx (V4SImode);
1096   rtx r2 = gen_reg_rtx (V4SImode);
1098   emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
1099   emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
1100   rs6000_expand_extract_even (operands[0], r1, r2);
1101   DONE;
1104 ;; Convert single word types to double word
1105 (define_expand "vec_unpacks_hi_v4sf"
1106   [(match_operand:V2DF 0 "vfloat_operand" "")
1107    (match_operand:V4SF 1 "vfloat_operand" "")]
1108   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
1110   rtx reg = gen_reg_rtx (V4SFmode);
1112   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1113   emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
1114   DONE;
1117 (define_expand "vec_unpacks_lo_v4sf"
1118   [(match_operand:V2DF 0 "vfloat_operand" "")
1119    (match_operand:V4SF 1 "vfloat_operand" "")]
1120   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
1122   rtx reg = gen_reg_rtx (V4SFmode);
1124   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1125   emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
1126   DONE;
1129 (define_expand "vec_unpacks_float_hi_v4si"
1130   [(match_operand:V2DF 0 "vfloat_operand" "")
1131    (match_operand:V4SI 1 "vint_operand" "")]
1132   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1134   rtx reg = gen_reg_rtx (V4SImode);
1136   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1137   emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
1138   DONE;
1141 (define_expand "vec_unpacks_float_lo_v4si"
1142   [(match_operand:V2DF 0 "vfloat_operand" "")
1143    (match_operand:V4SI 1 "vint_operand" "")]
1144   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1146   rtx reg = gen_reg_rtx (V4SImode);
1148   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1149   emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
1150   DONE;
1153 (define_expand "vec_unpacku_float_hi_v4si"
1154   [(match_operand:V2DF 0 "vfloat_operand" "")
1155    (match_operand:V4SI 1 "vint_operand" "")]
1156   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1158   rtx reg = gen_reg_rtx (V4SImode);
1160   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1161   emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
1162   DONE;
1165 (define_expand "vec_unpacku_float_lo_v4si"
1166   [(match_operand:V2DF 0 "vfloat_operand" "")
1167    (match_operand:V4SI 1 "vint_operand" "")]
1168   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1170   rtx reg = gen_reg_rtx (V4SImode);
1172   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1173   emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
1174   DONE;
1178 ;; Align vector loads with a permute.
1179 (define_expand "vec_realign_load_<mode>"
1180   [(match_operand:VEC_K 0 "vlogical_operand" "")
1181    (match_operand:VEC_K 1 "vlogical_operand" "")
1182    (match_operand:VEC_K 2 "vlogical_operand" "")
1183    (match_operand:V16QI 3 "vlogical_operand" "")]
1184   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1186   if (BYTES_BIG_ENDIAN)
1187     emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
1188                                          operands[2], operands[3]));
1189   else
1190     {
1191       /* We have changed lvsr to lvsl, so to complete the transformation
1192          of vperm for LE, we must swap the inputs.  */
1193       rtx unspec = gen_rtx_UNSPEC (<MODE>mode,
1194                                    gen_rtvec (3, operands[2],
1195                                               operands[1], operands[3]),
1196                                    UNSPEC_VPERM);
1197       emit_move_insn (operands[0], unspec);
1198     }
1199   DONE;
1202 ;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned
1203 ;; since the load already handles it.
1204 (define_expand "movmisalign<mode>"
1205  [(set (match_operand:VEC_N 0 "nonimmediate_operand" "")
1206        (match_operand:VEC_N 1 "any_operand" ""))]
1207  "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN"
1208  "")
1210 ;; Vector shift right in bits. Currently supported ony for shift
1211 ;; amounts that can be expressed as byte shifts (divisible by 8).
1212 ;; General shift amounts can be supported using vsro + vsr. We're
1213 ;; not expecting to see these yet (the vectorizer currently
1214 ;; generates only shifts by a whole number of vector elements).
1215 ;; Note that the vec_shr operation is actually defined as 
1216 ;; 'shift toward element 0' so is a shr for LE and shl for BE.
1217 (define_expand "vec_shr_<mode>"
1218   [(match_operand:VEC_L 0 "vlogical_operand" "")
1219    (match_operand:VEC_L 1 "vlogical_operand" "")
1220    (match_operand:QI 2 "reg_or_short_operand" "")]
1221   "TARGET_ALTIVEC"
1222   "
1224   rtx bitshift = operands[2];
1225   rtx shift;
1226   rtx insn;
1227   rtx zero_reg, op1, op2;
1228   HOST_WIDE_INT bitshift_val;
1229   HOST_WIDE_INT byteshift_val;
1231   if (! CONSTANT_P (bitshift))
1232     FAIL;
1233   bitshift_val = INTVAL (bitshift);
1234   if (bitshift_val & 0x7)
1235     FAIL;
1236   byteshift_val = (bitshift_val >> 3);
1237   zero_reg = gen_reg_rtx (<MODE>mode);
1238   emit_move_insn (zero_reg, CONST0_RTX (<MODE>mode));
1239   if (!BYTES_BIG_ENDIAN)
1240     {
1241       byteshift_val = 16 - byteshift_val;
1242       op1 = zero_reg;
1243       op2 = operands[1];
1244     }
1245   else
1246     {
1247       op1 = operands[1];
1248       op2 = zero_reg;
1249     }
1251   if (TARGET_VSX && (byteshift_val & 0x3) == 0)
1252     {
1253       shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
1254       insn = gen_vsx_xxsldwi_<mode> (operands[0], op1, op2, shift);
1255     }
1256   else
1257     {
1258       shift = gen_rtx_CONST_INT (QImode, byteshift_val);
1259       insn = gen_altivec_vsldoi_<mode> (operands[0], op1, op2, shift);
1260     }
1262   emit_insn (insn);
1263   DONE;
1266 ;; Expanders for rotate each element in a vector
1267 (define_expand "vrotl<mode>3"
1268   [(set (match_operand:VEC_I 0 "vint_operand" "")
1269         (rotate:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
1270                       (match_operand:VEC_I 2 "vint_operand" "")))]
1271   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1272   "")
1274 ;; Expanders for arithmetic shift left on each vector element
1275 (define_expand "vashl<mode>3"
1276   [(set (match_operand:VEC_I 0 "vint_operand" "")
1277         (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
1278                       (match_operand:VEC_I 2 "vint_operand" "")))]
1279   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1280   "")
1282 ;; Expanders for logical shift right on each vector element
1283 (define_expand "vlshr<mode>3"
1284   [(set (match_operand:VEC_I 0 "vint_operand" "")
1285         (lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
1286                         (match_operand:VEC_I 2 "vint_operand" "")))]
1287   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1288   "")
1290 ;; Expanders for arithmetic shift right on each vector element
1291 (define_expand "vashr<mode>3"
1292   [(set (match_operand:VEC_I 0 "vint_operand" "")
1293         (ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand" "")
1294                         (match_operand:VEC_I 2 "vint_operand" "")))]
1295   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1296   "")
1298 ;; Vector reduction expanders for VSX
1299 ; The (VEC_reduc:...
1300 ;       (op1)
1301 ;       (unspec:... [(const_int 0)] UNSPEC_REDUC))
1303 ; is to allow us to use a code iterator, but not completely list all of the
1304 ; vector rotates, etc. to prevent canonicalization
1307 (define_expand "reduc_<VEC_reduc:VEC_reduc_name>_scal_<VEC_F:mode>"
1308   [(match_operand:<VEC_base> 0 "register_operand" "")
1309    (VEC_reduc:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
1310                     (unspec:VEC_F [(const_int 0)] UNSPEC_REDUC))]
1311   "VECTOR_UNIT_VSX_P (<VEC_F:MODE>mode)"
1312   {
1313     rtx vec = gen_reg_rtx (<VEC_F:MODE>mode);
1314     rtx elt = BYTES_BIG_ENDIAN
1315                 ? gen_int_mode (GET_MODE_NUNITS (<VEC_F:MODE>mode) - 1, QImode)
1316                 : const0_rtx;
1317     emit_insn (gen_vsx_reduc_<VEC_reduc:VEC_reduc_name>_<VEC_F:mode> (vec,
1318         operand1));
1319     emit_insn (gen_vsx_extract_<VEC_F:mode> (operand0, vec, elt));
1320     DONE;
1321   })