Fix ICE in lto_symtab_merge_symbols_1 (PR lto/88004).
[official-gcc.git] / gcc / config / rs6000 / vector.md
blob21743c6be264931eb91d53f01d9a87f4b7a402f6
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-2018 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   /* When generating load/store instructions to/from VSX registers on
136      pre-power9 hardware in little endian mode, we need to emit register
137      permute instructions to byte swap the contents, since the VSX load/store
138      instructions do not include a byte swap as part of their operation.
139      Altivec loads and stores have no such problem, so we skip them below.  */
140   if (!BYTES_BIG_ENDIAN
141       && VECTOR_MEM_VSX_P (<MODE>mode)
142       && !TARGET_P9_VECTOR
143       && !gpr_or_gpr_p (operands[0], operands[1])
144       && ((memory_operand (operands[0], <MODE>mode)
145            && !altivec_indexed_or_indirect_operand(operands[0], <MODE>mode))
146           ^ (memory_operand (operands[1], <MODE>mode)
147              && !altivec_indexed_or_indirect_operand(operands[1], <MODE>mode))))
148     {
149       rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
150       DONE;
151     }
154 ;; Generic vector floating point load/store instructions.  These will match
155 ;; insns defined in vsx.md or altivec.md depending on the switches.
156 (define_expand "vector_load_<mode>"
157   [(set (match_operand:VEC_M 0 "vfloat_operand")
158         (match_operand:VEC_M 1 "memory_operand"))]
159   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
160   "")
162 (define_expand "vector_store_<mode>"
163   [(set (match_operand:VEC_M 0 "memory_operand")
164         (match_operand:VEC_M 1 "vfloat_operand"))]
165   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
166   "")
168 ;; Splits if a GPR register was chosen for the move
169 (define_split
170   [(set (match_operand:VEC_L 0 "nonimmediate_operand")
171         (match_operand:VEC_L 1 "input_operand"))]
172   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
173    && reload_completed
174    && gpr_or_gpr_p (operands[0], operands[1])
175    && !direct_move_p (operands[0], operands[1])
176    && !quad_load_store_p (operands[0], operands[1])"
177   [(pc)]
179   rs6000_split_multireg_move (operands[0], operands[1]);
180   DONE;
184 ;; Generic floating point vector arithmetic support
185 (define_expand "add<mode>3"
186   [(set (match_operand:VEC_F 0 "vfloat_operand")
187         (plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
188                     (match_operand:VEC_F 2 "vfloat_operand")))]
189   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
190   "")
192 (define_expand "sub<mode>3"
193   [(set (match_operand:VEC_F 0 "vfloat_operand")
194         (minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
195                      (match_operand:VEC_F 2 "vfloat_operand")))]
196   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
197   "")
199 (define_expand "mul<mode>3"
200   [(set (match_operand:VEC_F 0 "vfloat_operand")
201         (mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
202                     (match_operand:VEC_F 2 "vfloat_operand")))]
203   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
205   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
206     {
207       emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
208       DONE;
209     }
212 (define_expand "div<mode>3"
213   [(set (match_operand:VEC_F 0 "vfloat_operand")
214         (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
215                    (match_operand:VEC_F 2 "vfloat_operand")))]
216   "VECTOR_UNIT_VSX_P (<MODE>mode)"
218   if (RS6000_RECIP_AUTO_RE_P (<MODE>mode)
219       && can_create_pseudo_p () && flag_finite_math_only
220       && !flag_trapping_math && flag_reciprocal_math)
221     {
222       rs6000_emit_swdiv (operands[0], operands[1], operands[2], true);
223       DONE;
224     }
227 (define_expand "neg<mode>2"
228   [(set (match_operand:VEC_F 0 "vfloat_operand")
229         (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
230   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
232   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
233     {
234       emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
235       DONE;
236     }
239 (define_expand "abs<mode>2"
240   [(set (match_operand:VEC_F 0 "vfloat_operand")
241         (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
242   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
244   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
245     {
246       emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
247       DONE;
248     }
251 (define_expand "smin<mode>3"
252   [(set (match_operand:VEC_F 0 "register_operand")
253         (smin:VEC_F (match_operand:VEC_F 1 "register_operand")
254                     (match_operand:VEC_F 2 "register_operand")))]
255   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
256   "")
258 (define_expand "smax<mode>3"
259   [(set (match_operand:VEC_F 0 "register_operand")
260         (smax:VEC_F (match_operand:VEC_F 1 "register_operand")
261                     (match_operand:VEC_F 2 "register_operand")))]
262   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
263   "")
266 (define_expand "sqrt<mode>2"
267   [(set (match_operand:VEC_F 0 "vfloat_operand")
268         (sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
269   "VECTOR_UNIT_VSX_P (<MODE>mode)"
271   if (<MODE>mode == V4SFmode
272       && !optimize_function_for_size_p (cfun)
273       && flag_finite_math_only && !flag_trapping_math
274       && flag_unsafe_math_optimizations)
275     {
276       rs6000_emit_swsqrt (operands[0], operands[1], 0);
277       DONE;
278     }
281 (define_expand "rsqrte<mode>2"
282   [(set (match_operand:VEC_F 0 "vfloat_operand")
283         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")]
284                       UNSPEC_RSQRT))]
285   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
286   "")
288 (define_expand "re<mode>2"
289   [(set (match_operand:VEC_F 0 "vfloat_operand")
290         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")]
291                       UNSPEC_FRES))]
292   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
293   "")
295 (define_expand "ftrunc<mode>2"
296   [(set (match_operand:VEC_F 0 "vfloat_operand")
297         (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
298   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
299   "")
301 (define_expand "vector_ceil<mode>2"
302   [(set (match_operand:VEC_F 0 "vfloat_operand")
303         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")]
304                       UNSPEC_FRIP))]
305   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
306   "")
308 (define_expand "vector_floor<mode>2"
309   [(set (match_operand:VEC_F 0 "vfloat_operand")
310         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")]
311                       UNSPEC_FRIM))]
312   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
313   "")
315 (define_expand "vector_btrunc<mode>2"
316   [(set (match_operand:VEC_F 0 "vfloat_operand")
317         (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
318   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
319   "")
321 (define_expand "vector_copysign<mode>3"
322   [(set (match_operand:VEC_F 0 "vfloat_operand")
323         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")
324                        (match_operand:VEC_F 2 "vfloat_operand")] UNSPEC_COPYSIGN))]
325   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
327   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
328     {
329       emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1],
330                                              operands[2]));
331       DONE;
332     }
336 ;; Vector comparisons
337 (define_expand "vcond<mode><mode>"
338   [(set (match_operand:VEC_F 0 "vfloat_operand")
339         (if_then_else:VEC_F
340          (match_operator 3 "comparison_operator"
341                          [(match_operand:VEC_F 4 "vfloat_operand")
342                           (match_operand:VEC_F 5 "vfloat_operand")])
343          (match_operand:VEC_F 1 "vfloat_operand")
344          (match_operand:VEC_F 2 "vfloat_operand")))]
345   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
347   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
348                                     operands[3], operands[4], operands[5]))
349     DONE;
350   else
351     FAIL;
354 (define_expand "vcond<mode><mode>"
355   [(set (match_operand:VEC_I 0 "vint_operand")
356         (if_then_else:VEC_I
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 "vector_int_reg_or_same_bit")
361          (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))]
362   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
364   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
365                                     operands[3], operands[4], operands[5]))
366     DONE;
367   else
368     FAIL;
371 (define_expand "vcondv4sfv4si"
372   [(set (match_operand:V4SF 0 "vfloat_operand")
373         (if_then_else:V4SF
374          (match_operator 3 "comparison_operator"
375                          [(match_operand:V4SI 4 "vint_operand")
376                           (match_operand:V4SI 5 "vint_operand")])
377          (match_operand:V4SF 1 "vfloat_operand")
378          (match_operand:V4SF 2 "vfloat_operand")))]
379   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
380    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
382   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
383                                     operands[3], operands[4], operands[5]))
384     DONE;
385   else
386     FAIL;
389 (define_expand "vcondv4siv4sf"
390   [(set (match_operand:V4SI 0 "vint_operand")
391         (if_then_else:V4SI
392          (match_operator 3 "comparison_operator"
393                          [(match_operand:V4SF 4 "vfloat_operand")
394                           (match_operand:V4SF 5 "vfloat_operand")])
395          (match_operand:V4SI 1 "vint_operand")
396          (match_operand:V4SI 2 "vint_operand")))]
397   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
398    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
400   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
401                                     operands[3], operands[4], operands[5]))
402     DONE;
403   else
404     FAIL;
407 (define_expand "vcondv2dfv2di"
408   [(set (match_operand:V2DF 0 "vfloat_operand")
409         (if_then_else:V2DF
410          (match_operator 3 "comparison_operator"
411                          [(match_operand:V2DI 4 "vint_operand")
412                           (match_operand:V2DI 5 "vint_operand")])
413          (match_operand:V2DF 1 "vfloat_operand")
414          (match_operand:V2DF 2 "vfloat_operand")))]
415   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)
416    && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)"
418   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
419                                     operands[3], operands[4], operands[5]))
420     DONE;
421   else
422     FAIL;
425 (define_expand "vcondv2div2df"
426   [(set (match_operand:V2DI 0 "vint_operand")
427         (if_then_else:V2DI
428          (match_operator 3 "comparison_operator"
429                          [(match_operand:V2DF 4 "vfloat_operand")
430                           (match_operand:V2DF 5 "vfloat_operand")])
431          (match_operand:V2DI 1 "vint_operand")
432          (match_operand:V2DI 2 "vint_operand")))]
433   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)
434    && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)"
436   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
437                                     operands[3], operands[4], operands[5]))
438     DONE;
439   else
440     FAIL;
443 (define_expand "vcondu<mode><mode>"
444   [(set (match_operand:VEC_I 0 "vint_operand")
445         (if_then_else:VEC_I
446          (match_operator 3 "comparison_operator"
447                          [(match_operand:VEC_I 4 "vint_operand")
448                           (match_operand:VEC_I 5 "vint_operand")])
449          (match_operand:VEC_I 1 "vector_int_reg_or_same_bit")
450          (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))]
451   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
453   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
454                                     operands[3], operands[4], operands[5]))
455     DONE;
456   else
457     FAIL;
460 (define_expand "vconduv4sfv4si"
461   [(set (match_operand:V4SF 0 "vfloat_operand")
462         (if_then_else:V4SF
463          (match_operator 3 "comparison_operator"
464                          [(match_operand:V4SI 4 "vint_operand")
465                           (match_operand:V4SI 5 "vint_operand")])
466          (match_operand:V4SF 1 "vfloat_operand")
467          (match_operand:V4SF 2 "vfloat_operand")))]
468   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
469    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
471   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
472                                     operands[3], operands[4], operands[5]))
473     DONE;
474   else
475     FAIL;
478 (define_expand "vconduv2dfv2di"
479   [(set (match_operand:V2DF 0 "vfloat_operand")
480         (if_then_else:V2DF
481          (match_operator 3 "comparison_operator"
482                          [(match_operand:V2DI 4 "vint_operand")
483                           (match_operand:V2DI 5 "vint_operand")])
484          (match_operand:V2DF 1 "vfloat_operand")
485          (match_operand:V2DF 2 "vfloat_operand")))]
486   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)
487    && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)"
489   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
490                                     operands[3], operands[4], operands[5]))
491     DONE;
492   else
493     FAIL;
496 (define_expand "vector_eq<mode>"
497   [(set (match_operand:VEC_C 0 "vlogical_operand")
498         (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand")
499                   (match_operand:VEC_C 2 "vlogical_operand")))]
500   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
501   "")
503 (define_expand "vector_gt<mode>"
504   [(set (match_operand:VEC_C 0 "vlogical_operand")
505         (gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand")
506                   (match_operand:VEC_C 2 "vlogical_operand")))]
507   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
508   "")
510 (define_expand "vector_ge<mode>"
511   [(set (match_operand:VEC_F 0 "vlogical_operand")
512         (ge:VEC_F (match_operand:VEC_F 1 "vlogical_operand")
513                   (match_operand:VEC_F 2 "vlogical_operand")))]
514   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
515   "")
517 ; >= for integer vectors: swap operands and apply not-greater-than
518 (define_expand "vector_nlt<mode>"
519   [(set (match_operand:VEC_I 3 "vlogical_operand")
520         (gt:VEC_I (match_operand:VEC_I 2 "vlogical_operand")
521                   (match_operand:VEC_I 1 "vlogical_operand")))
522    (set (match_operand:VEC_I 0 "vlogical_operand")
523         (not:VEC_I (match_dup 3)))]
524   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
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)"
545   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
548 (define_expand "vector_geu<mode>"
549   [(set (match_operand:VEC_I 0 "vint_operand")
550         (geu:VEC_I (match_operand:VEC_I 1 "vint_operand")
551                    (match_operand:VEC_I 2 "vint_operand")))]
552   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
553   "")
555 ; <= for integer vectors: apply not-greater-than
556 (define_expand "vector_ngt<mode>"
557   [(set (match_operand:VEC_I 3 "vlogical_operand")
558         (gt:VEC_I (match_operand:VEC_I 1 "vlogical_operand")
559                   (match_operand:VEC_I 2 "vlogical_operand")))
560    (set (match_operand:VEC_I 0 "vlogical_operand")
561         (not:VEC_I (match_dup 3)))]
562   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
564   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
567 (define_expand "vector_ngtu<mode>"
568   [(set (match_operand:VEC_I 3 "vlogical_operand")
569         (gtu:VEC_I (match_operand:VEC_I 1 "vlogical_operand")
570                    (match_operand:VEC_I 2 "vlogical_operand")))
571    (set (match_operand:VEC_I 0 "vlogical_operand")
572         (not:VEC_I (match_dup 3)))]
573   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
575   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
578 (define_insn_and_split "*vector_uneq<mode>"
579   [(set (match_operand:VEC_F 0 "vfloat_operand")
580         (uneq:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
581                     (match_operand:VEC_F 2 "vfloat_operand")))]
582   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
583   "#"
584   ""
585   [(set (match_dup 3)
586         (gt:VEC_F (match_dup 1)
587                   (match_dup 2)))
588    (set (match_dup 4)
589         (gt:VEC_F (match_dup 2)
590                   (match_dup 1)))
591    (set (match_dup 0)
592         (and:VEC_F (not:VEC_F (match_dup 3))
593                    (not:VEC_F (match_dup 4))))]
595   operands[3] = gen_reg_rtx (<MODE>mode);
596   operands[4] = gen_reg_rtx (<MODE>mode);
599 (define_insn_and_split "*vector_ltgt<mode>"
600   [(set (match_operand:VEC_F 0 "vfloat_operand")
601         (ltgt:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
602                     (match_operand:VEC_F 2 "vfloat_operand")))]
603   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
604   "#"
605   ""
606   [(set (match_dup 3)
607         (gt:VEC_F (match_dup 1)
608                   (match_dup 2)))
609    (set (match_dup 4)
610         (gt:VEC_F (match_dup 2)
611                   (match_dup 1)))
612    (set (match_dup 0)
613         (ior:VEC_F (match_dup 3)
614                    (match_dup 4)))]
616   operands[3] = gen_reg_rtx (<MODE>mode);
617   operands[4] = gen_reg_rtx (<MODE>mode);
620 (define_insn_and_split "*vector_ordered<mode>"
621   [(set (match_operand:VEC_F 0 "vfloat_operand")
622         (ordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
623                        (match_operand:VEC_F 2 "vfloat_operand")))]
624   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
625   "#"
626   ""
627   [(set (match_dup 3)
628         (ge:VEC_F (match_dup 1)
629                   (match_dup 2)))
630    (set (match_dup 4)
631         (ge:VEC_F (match_dup 2)
632                   (match_dup 1)))
633    (set (match_dup 0)
634         (ior:VEC_F (match_dup 3)
635                    (match_dup 4)))]
637   operands[3] = gen_reg_rtx (<MODE>mode);
638   operands[4] = gen_reg_rtx (<MODE>mode);
641 (define_insn_and_split "*vector_unordered<mode>"
642   [(set (match_operand:VEC_F 0 "vfloat_operand")
643         (unordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
644                          (match_operand:VEC_F 2 "vfloat_operand")))]
645   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
646   "#"
647   ""
648   [(set (match_dup 3)
649         (ge:VEC_F (match_dup 1)
650                   (match_dup 2)))
651    (set (match_dup 4)
652         (ge:VEC_F (match_dup 2)
653                   (match_dup 1)))
654    (set (match_dup 0)
655         (and:VEC_F (not:VEC_F (match_dup 3))
656                    (not:VEC_F (match_dup 4))))]
658   operands[3] = gen_reg_rtx (<MODE>mode);
659   operands[4] = gen_reg_rtx (<MODE>mode);
662 ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
663 ;; which is in the reverse order that we want
664 (define_expand "vector_select_<mode>"
665   [(set (match_operand:VEC_L 0 "vlogical_operand")
666         (if_then_else:VEC_L
667          (ne:CC (match_operand:VEC_L 3 "vlogical_operand")
668                 (match_dup 4))
669          (match_operand:VEC_L 2 "vlogical_operand")
670          (match_operand:VEC_L 1 "vlogical_operand")))]
671   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
672   "operands[4] = CONST0_RTX (<MODE>mode);")
674 (define_expand "vector_select_<mode>_uns"
675   [(set (match_operand:VEC_L 0 "vlogical_operand")
676         (if_then_else:VEC_L
677          (ne:CCUNS (match_operand:VEC_L 3 "vlogical_operand")
678                    (match_dup 4))
679          (match_operand:VEC_L 2 "vlogical_operand")
680          (match_operand:VEC_L 1 "vlogical_operand")))]
681   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
682   "operands[4] = CONST0_RTX (<MODE>mode);")
684 ;; Expansions that compare vectors producing a vector result and a predicate,
685 ;; setting CR6 to indicate a combined status
686 (define_expand "vector_eq_<mode>_p"
687   [(parallel
688     [(set (reg:CC CR6_REGNO)
689           (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand")
690                              (match_operand:VEC_A 2 "vlogical_operand"))]
691                      UNSPEC_PREDICATE))
692      (set (match_operand:VEC_A 0 "vlogical_operand")
693           (eq:VEC_A (match_dup 1)
694                     (match_dup 2)))])]
695   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
696   "")
698 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
699 ;; implementation of the vec_all_ne built-in functions on Power9.
700 (define_expand "vector_ne_<mode>_p"
701   [(parallel
702     [(set (reg:CC CR6_REGNO)
703           (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand")
704                              (match_operand:VI 2 "vlogical_operand"))]
705            UNSPEC_PREDICATE))
706      (set (match_dup 3)
707           (ne:VI (match_dup 1)
708                  (match_dup 2)))])
709    (set (match_operand:SI 0 "register_operand" "=r")
710         (lt:SI (reg:CC CR6_REGNO)
711                (const_int 0)))]
712   "TARGET_P9_VECTOR"
714   operands[3] = gen_reg_rtx (<MODE>mode);
717 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
718 ;; implementation of the vec_any_eq built-in functions on Power9.
719 (define_expand "vector_ae_<mode>_p"
720   [(parallel
721     [(set (reg:CC CR6_REGNO)
722           (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand")
723                              (match_operand:VI 2 "vlogical_operand"))]
724            UNSPEC_PREDICATE))
725      (set (match_dup 3)
726           (ne:VI (match_dup 1)
727                  (match_dup 2)))])
728    (set (match_operand:SI 0 "register_operand" "=r")
729         (lt:SI (reg:CC CR6_REGNO)
730                (const_int 0)))
731    (set (match_dup 0)
732         (xor:SI (match_dup 0)
733                 (const_int 1)))]
734   "TARGET_P9_VECTOR"
736   operands[3] = gen_reg_rtx (<MODE>mode);
739 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
740 ;; implementation of the vec_all_nez and vec_any_eqz built-in
741 ;; functions on Power9.
742 (define_expand "vector_nez_<mode>_p"
743   [(parallel
744     [(set (reg:CC CR6_REGNO)
745           (unspec:CC [(unspec:VI
746                        [(match_operand:VI 1 "vlogical_operand")
747                         (match_operand:VI 2 "vlogical_operand")]
748                        UNSPEC_NEZ_P)]
749            UNSPEC_PREDICATE))
750      (set (match_operand:VI 0 "vlogical_operand")
751           (unspec:VI [(match_dup 1)
752                       (match_dup 2)]
753            UNSPEC_NEZ_P))])]
754   "TARGET_P9_VECTOR"
755   "")
757 ;; This expansion handles the V2DI mode in the implementation of the
758 ;; vec_all_ne built-in function on Power9.
760 ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode,
761 ;; this expands into the same rtl that would be used for the Power8
762 ;; architecture.
763 (define_expand "vector_ne_v2di_p"
764   [(parallel
765     [(set (reg:CC CR6_REGNO)
766           (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand")
767                              (match_operand:V2DI 2 "vlogical_operand"))]
768                      UNSPEC_PREDICATE))
769      (set (match_dup 3)
770           (eq:V2DI (match_dup 1)
771                    (match_dup 2)))])
772    (set (match_operand:SI 0 "register_operand" "=r")
773         (eq:SI (reg:CC CR6_REGNO)
774                (const_int 0)))]
775   "TARGET_P9_VECTOR"
777   operands[3] = gen_reg_rtx (V2DImode);
780 ;; This expansion handles the V2DI mode in the implementation of the
781 ;; vec_any_eq built-in function on Power9.
783 ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode,
784 ;; this expands into the same rtl that would be used for the Power8
785 ;; architecture.
786 (define_expand "vector_ae_v2di_p"
787   [(parallel
788     [(set (reg:CC CR6_REGNO)
789           (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand")
790                              (match_operand:V2DI 2 "vlogical_operand"))]
791                      UNSPEC_PREDICATE))
792      (set (match_dup 3)
793           (eq:V2DI (match_dup 1)
794                    (match_dup 2)))])
795    (set (match_operand:SI 0 "register_operand" "=r")
796         (eq:SI (reg:CC CR6_REGNO)
797                (const_int 0)))
798    (set (match_dup 0)
799         (xor:SI (match_dup 0)
800                 (const_int 1)))]
801   "TARGET_P9_VECTOR"
803   operands[3] = gen_reg_rtx (V2DImode);
806 ;; This expansion handles the V4SF and V2DF modes in the Power9
807 ;; implementation of the vec_all_ne built-in functions.  Note that the
808 ;; expansions for this pattern with these modes makes no use of power9-
809 ;; specific instructions since there are no new power9 instructions
810 ;; for vector compare not equal with floating point arguments.
811 (define_expand "vector_ne_<mode>_p"
812   [(parallel
813     [(set (reg:CC CR6_REGNO)
814           (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand")
815                              (match_operand:VEC_F 2 "vlogical_operand"))]
816                      UNSPEC_PREDICATE))
817      (set (match_dup 3)
818           (eq:VEC_F (match_dup 1)
819                     (match_dup 2)))])
820    (set (match_operand:SI 0 "register_operand" "=r")
821         (eq:SI (reg:CC CR6_REGNO)
822                (const_int 0)))]
823   "TARGET_P9_VECTOR"
825   operands[3] = gen_reg_rtx (<MODE>mode);
828 ;; This expansion handles the V4SF and V2DF modes in the Power9
829 ;; implementation of the vec_any_eq built-in functions.  Note that the
830 ;; expansions for this pattern with these modes makes no use of power9-
831 ;; specific instructions since there are no new power9 instructions
832 ;; for vector compare not equal with floating point arguments.
833 (define_expand "vector_ae_<mode>_p"
834   [(parallel
835     [(set (reg:CC CR6_REGNO)
836           (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand")
837                              (match_operand:VEC_F 2 "vlogical_operand"))]
838                      UNSPEC_PREDICATE))
839      (set (match_dup 3)
840           (eq:VEC_F (match_dup 1)
841                     (match_dup 2)))])
842    (set (match_operand:SI 0 "register_operand" "=r")
843         (eq:SI (reg:CC CR6_REGNO)
844                (const_int 0)))
845    (set (match_dup 0)
846         (xor:SI (match_dup 0)
847                 (const_int 1)))]
848   "TARGET_P9_VECTOR"
850   operands[3] = gen_reg_rtx (<MODE>mode);
853 (define_expand "vector_gt_<mode>_p"
854   [(parallel
855     [(set (reg:CC CR6_REGNO)
856           (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand")
857                              (match_operand:VEC_A 2 "vlogical_operand"))]
858                      UNSPEC_PREDICATE))
859      (set (match_operand:VEC_A 0 "vlogical_operand")
860           (gt:VEC_A (match_dup 1)
861                     (match_dup 2)))])]
862   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
863   "")
865 (define_expand "vector_ge_<mode>_p"
866   [(parallel
867     [(set (reg:CC CR6_REGNO)
868           (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand")
869                              (match_operand:VEC_F 2 "vfloat_operand"))]
870                      UNSPEC_PREDICATE))
871      (set (match_operand:VEC_F 0 "vfloat_operand")
872           (ge:VEC_F (match_dup 1)
873                     (match_dup 2)))])]
874   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
875   "")
877 (define_expand "vector_gtu_<mode>_p"
878   [(parallel
879     [(set (reg:CC CR6_REGNO)
880           (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand")
881                               (match_operand:VEC_I 2 "vint_operand"))]
882                      UNSPEC_PREDICATE))
883      (set (match_operand:VEC_I 0 "vlogical_operand")
884           (gtu:VEC_I (match_dup 1)
885                      (match_dup 2)))])]
886   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
887   "")
889 ;; AltiVec/VSX predicates.
891 ;; This expansion is triggered during expansion of predicate built-in
892 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
893 ;; altivec_expand_predicate_builtin() function when the value of the
894 ;; integer constant first argument equals zero (aka __CR6_EQ in altivec.h).
895 (define_expand "cr6_test_for_zero"
896   [(set (match_operand:SI 0 "register_operand" "=r")
897         (eq:SI (reg:CC CR6_REGNO)
898                (const_int 0)))]
899   "TARGET_ALTIVEC || TARGET_VSX"
900   "")
902 ;; This expansion is triggered during expansion of predicate built-in
903 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
904 ;; altivec_expand_predicate_builtin() function when the value of the
905 ;; integer constant first argument equals one (aka __CR6_EQ_REV in altivec.h).
906 (define_expand "cr6_test_for_zero_reverse"
907   [(set (match_operand:SI 0 "register_operand" "=r")
908         (eq:SI (reg:CC CR6_REGNO)
909                (const_int 0)))
910    (set (match_dup 0)
911         (xor:SI (match_dup 0)
912                 (const_int 1)))]
913   "TARGET_ALTIVEC || TARGET_VSX"
914   "")
916 ;; This expansion is triggered during expansion of predicate built-in
917 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
918 ;; altivec_expand_predicate_builtin() function when the value of the
919 ;; integer constant first argument equals two (aka __CR6_LT in altivec.h).
920 (define_expand "cr6_test_for_lt"
921   [(set (match_operand:SI 0 "register_operand" "=r")
922         (lt:SI (reg:CC CR6_REGNO)
923                (const_int 0)))]
924   "TARGET_ALTIVEC || TARGET_VSX"
925   "")
927 ;; This expansion is triggered during expansion of predicate built-in
928 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
929 ;; altivec_expand_predicate_builtin() function when the value of the
930 ;; integer constant first argument equals three
931 ;; (aka __CR6_LT_REV in altivec.h).
932 (define_expand "cr6_test_for_lt_reverse"
933   [(set (match_operand:SI 0 "register_operand" "=r")
934         (lt:SI (reg:CC CR6_REGNO)
935                (const_int 0)))
936    (set (match_dup 0)
937         (xor:SI (match_dup 0)
938                 (const_int 1)))]
939   "TARGET_ALTIVEC || TARGET_VSX"
940   "")
943 ;; Vector count leading zeros
944 (define_expand "clz<mode>2"
945   [(set (match_operand:VEC_I 0 "register_operand")
946         (clz:VEC_I (match_operand:VEC_I 1 "register_operand")))]
947   "TARGET_P8_VECTOR")
949 ;; Vector count trailing zeros
950 (define_expand "ctz<mode>2"
951   [(set (match_operand:VEC_I 0 "register_operand")
952         (ctz:VEC_I (match_operand:VEC_I 1 "register_operand")))]
953   "TARGET_P9_VECTOR")
955 ;; Vector population count
956 (define_expand "popcount<mode>2"
957   [(set (match_operand:VEC_I 0 "register_operand")
958         (popcount:VEC_I (match_operand:VEC_I 1 "register_operand")))]
959   "TARGET_P8_VECTOR")
961 ;; Vector parity
962 (define_expand "parity<mode>2"
963   [(set (match_operand:VEC_IP 0 "register_operand")
964         (parity:VEC_IP (match_operand:VEC_IP 1 "register_operand")))]
965   "TARGET_P9_VECTOR")
968 ;; Same size conversions
969 (define_expand "float<VEC_int><mode>2"
970   [(set (match_operand:VEC_F 0 "vfloat_operand")
971         (float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))]
972   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
974   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
975     {
976       emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
977       DONE;
978     }
981 (define_expand "floatuns<VEC_int><mode>2"
982   [(set (match_operand:VEC_F 0 "vfloat_operand")
983         (unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))]
984   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
986   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
987     {
988       emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
989       DONE;
990     }
993 (define_expand "fix_trunc<mode><VEC_int>2"
994   [(set (match_operand:<VEC_INT> 0 "vint_operand")
995         (fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))]
996   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
998   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
999     {
1000       emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
1001       DONE;
1002     }
1005 (define_expand "fixuns_trunc<mode><VEC_int>2"
1006   [(set (match_operand:<VEC_INT> 0 "vint_operand")
1007         (unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))]
1008   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1010   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
1011     {
1012       emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
1013       DONE;
1014     }
1018 ;; Vector initialization, set, extract
1019 (define_expand "vec_init<mode><VEC_base_l>"
1020   [(match_operand:VEC_E 0 "vlogical_operand")
1021    (match_operand:VEC_E 1 "")]
1022   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1024   rs6000_expand_vector_init (operands[0], operands[1]);
1025   DONE;
1028 (define_expand "vec_set<mode>"
1029   [(match_operand:VEC_E 0 "vlogical_operand")
1030    (match_operand:<VEC_base> 1 "register_operand")
1031    (match_operand 2 "const_int_operand")]
1032   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1034   rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
1035   DONE;
1038 (define_expand "vec_extract<mode><VEC_base_l>"
1039   [(match_operand:<VEC_base> 0 "register_operand")
1040    (match_operand:VEC_E 1 "vlogical_operand")
1041    (match_operand 2 "const_int_operand")]
1042   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1044   rs6000_expand_vector_extract (operands[0], operands[1], operands[2]);
1045   DONE;
1048 ;; Convert double word types to single word types
1049 (define_expand "vec_pack_trunc_v2df"
1050   [(match_operand:V4SF 0 "vfloat_operand")
1051    (match_operand:V2DF 1 "vfloat_operand")
1052    (match_operand:V2DF 2 "vfloat_operand")]
1053   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1055   rtx r1 = gen_reg_rtx (V4SFmode);
1056   rtx r2 = gen_reg_rtx (V4SFmode);
1058   emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
1059   emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
1060   rs6000_expand_extract_even (operands[0], r1, r2);
1061   DONE;
1064 (define_expand "vec_pack_sfix_trunc_v2df"
1065   [(match_operand:V4SI 0 "vint_operand")
1066    (match_operand:V2DF 1 "vfloat_operand")
1067    (match_operand:V2DF 2 "vfloat_operand")]
1068   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1070   rtx r1 = gen_reg_rtx (V4SImode);
1071   rtx r2 = gen_reg_rtx (V4SImode);
1073   emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
1074   emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
1075   rs6000_expand_extract_even (operands[0], r1, r2);
1076   DONE;
1079 (define_expand "vec_pack_ufix_trunc_v2df"
1080   [(match_operand:V4SI 0 "vint_operand")
1081    (match_operand:V2DF 1 "vfloat_operand")
1082    (match_operand:V2DF 2 "vfloat_operand")]
1083   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1085   rtx r1 = gen_reg_rtx (V4SImode);
1086   rtx r2 = gen_reg_rtx (V4SImode);
1088   emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
1089   emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
1090   rs6000_expand_extract_even (operands[0], r1, r2);
1091   DONE;
1094 ;; Convert single word types to double word
1095 (define_expand "vec_unpacks_hi_v4sf"
1096   [(match_operand:V2DF 0 "vfloat_operand")
1097    (match_operand:V4SF 1 "vfloat_operand")]
1098   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
1100   rtx reg = gen_reg_rtx (V4SFmode);
1102   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1103   emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
1104   DONE;
1107 (define_expand "vec_unpacks_lo_v4sf"
1108   [(match_operand:V2DF 0 "vfloat_operand")
1109    (match_operand:V4SF 1 "vfloat_operand")]
1110   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
1112   rtx reg = gen_reg_rtx (V4SFmode);
1114   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1115   emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
1116   DONE;
1119 (define_expand "vec_unpacks_float_hi_v4si"
1120   [(match_operand:V2DF 0 "vfloat_operand")
1121    (match_operand:V4SI 1 "vint_operand")]
1122   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1124   rtx reg = gen_reg_rtx (V4SImode);
1126   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1127   emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
1128   DONE;
1131 (define_expand "vec_unpacks_float_lo_v4si"
1132   [(match_operand:V2DF 0 "vfloat_operand")
1133    (match_operand:V4SI 1 "vint_operand")]
1134   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1136   rtx reg = gen_reg_rtx (V4SImode);
1138   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1139   emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
1140   DONE;
1143 (define_expand "vec_unpacku_float_hi_v4si"
1144   [(match_operand:V2DF 0 "vfloat_operand")
1145    (match_operand:V4SI 1 "vint_operand")]
1146   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1148   rtx reg = gen_reg_rtx (V4SImode);
1150   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1151   emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
1152   DONE;
1155 (define_expand "vec_unpacku_float_lo_v4si"
1156   [(match_operand:V2DF 0 "vfloat_operand")
1157    (match_operand:V4SI 1 "vint_operand")]
1158   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1160   rtx reg = gen_reg_rtx (V4SImode);
1162   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1163   emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
1164   DONE;
1168 ;; Align vector loads with a permute.
1169 (define_expand "vec_realign_load_<mode>"
1170   [(match_operand:VEC_K 0 "vlogical_operand")
1171    (match_operand:VEC_K 1 "vlogical_operand")
1172    (match_operand:VEC_K 2 "vlogical_operand")
1173    (match_operand:V16QI 3 "vlogical_operand")]
1174   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1176   if (BYTES_BIG_ENDIAN)
1177     emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
1178                                          operands[2], operands[3]));
1179   else
1180     {
1181       /* We have changed lvsr to lvsl, so to complete the transformation
1182          of vperm for LE, we must swap the inputs.  */
1183       rtx unspec = gen_rtx_UNSPEC (<MODE>mode,
1184                                    gen_rtvec (3, operands[2],
1185                                               operands[1], operands[3]),
1186                                    UNSPEC_VPERM);
1187       emit_move_insn (operands[0], unspec);
1188     }
1189   DONE;
1192 ;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned
1193 ;; since the load already handles it.
1194 (define_expand "movmisalign<mode>"
1195  [(set (match_operand:VEC_N 0 "nonimmediate_operand")
1196        (match_operand:VEC_N 1 "any_operand"))]
1197  "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN"
1198  "")
1200 ;; Vector shift right in bits. Currently supported ony for shift
1201 ;; amounts that can be expressed as byte shifts (divisible by 8).
1202 ;; General shift amounts can be supported using vsro + vsr. We're
1203 ;; not expecting to see these yet (the vectorizer currently
1204 ;; generates only shifts by a whole number of vector elements).
1205 ;; Note that the vec_shr operation is actually defined as 
1206 ;; 'shift toward element 0' so is a shr for LE and shl for BE.
1207 (define_expand "vec_shr_<mode>"
1208   [(match_operand:VEC_L 0 "vlogical_operand")
1209    (match_operand:VEC_L 1 "vlogical_operand")
1210    (match_operand:QI 2 "reg_or_short_operand")]
1211   "TARGET_ALTIVEC"
1213   rtx bitshift = operands[2];
1214   rtx shift;
1215   rtx insn;
1216   rtx zero_reg, op1, op2;
1217   HOST_WIDE_INT bitshift_val;
1218   HOST_WIDE_INT byteshift_val;
1220   if (! CONSTANT_P (bitshift))
1221     FAIL;
1222   bitshift_val = INTVAL (bitshift);
1223   if (bitshift_val & 0x7)
1224     FAIL;
1225   byteshift_val = (bitshift_val >> 3);
1226   zero_reg = gen_reg_rtx (<MODE>mode);
1227   emit_move_insn (zero_reg, CONST0_RTX (<MODE>mode));
1228   if (!BYTES_BIG_ENDIAN)
1229     {
1230       byteshift_val = 16 - byteshift_val;
1231       op1 = zero_reg;
1232       op2 = operands[1];
1233     }
1234   else
1235     {
1236       op1 = operands[1];
1237       op2 = zero_reg;
1238     }
1240   if (TARGET_VSX && (byteshift_val & 0x3) == 0)
1241     {
1242       shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
1243       insn = gen_vsx_xxsldwi_<mode> (operands[0], op1, op2, shift);
1244     }
1245   else
1246     {
1247       shift = gen_rtx_CONST_INT (QImode, byteshift_val);
1248       insn = gen_altivec_vsldoi_<mode> (operands[0], op1, op2, shift);
1249     }
1251   emit_insn (insn);
1252   DONE;
1255 ;; Expanders for rotate each element in a vector
1256 (define_expand "vrotl<mode>3"
1257   [(set (match_operand:VEC_I 0 "vint_operand")
1258         (rotate:VEC_I (match_operand:VEC_I 1 "vint_operand")
1259                       (match_operand:VEC_I 2 "vint_operand")))]
1260   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1261   "")
1263 ;; Expanders for arithmetic shift left on each vector element
1264 (define_expand "vashl<mode>3"
1265   [(set (match_operand:VEC_I 0 "vint_operand")
1266         (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand")
1267                       (match_operand:VEC_I 2 "vint_operand")))]
1268   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1269   "")
1271 ;; Expanders for logical shift right on each vector element
1272 (define_expand "vlshr<mode>3"
1273   [(set (match_operand:VEC_I 0 "vint_operand")
1274         (lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand")
1275                         (match_operand:VEC_I 2 "vint_operand")))]
1276   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1277   "")
1279 ;; Expanders for arithmetic shift right on each vector element
1280 (define_expand "vashr<mode>3"
1281   [(set (match_operand:VEC_I 0 "vint_operand")
1282         (ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand")
1283                         (match_operand:VEC_I 2 "vint_operand")))]
1284   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1285   "")
1287 ;; Vector reduction expanders for VSX
1288 ; The (VEC_reduc:...
1289 ;       (op1)
1290 ;       (unspec:... [(const_int 0)] UNSPEC_REDUC))
1292 ; is to allow us to use a code iterator, but not completely list all of the
1293 ; vector rotates, etc. to prevent canonicalization
1296 (define_expand "reduc_<VEC_reduc:VEC_reduc_name>_scal_<VEC_F:mode>"
1297   [(match_operand:<VEC_base> 0 "register_operand")
1298    (VEC_reduc:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
1299                     (unspec:VEC_F [(const_int 0)] UNSPEC_REDUC))]
1300   "VECTOR_UNIT_VSX_P (<VEC_F:MODE>mode)"
1301   {
1302     rtx vec = gen_reg_rtx (<VEC_F:MODE>mode);
1303     rtx elt = BYTES_BIG_ENDIAN
1304                 ? gen_int_mode (GET_MODE_NUNITS (<VEC_F:MODE>mode) - 1, QImode)
1305                 : const0_rtx;
1306     emit_insn (gen_vsx_reduc_<VEC_reduc:VEC_reduc_name>_<VEC_F:mode> (vec,
1307         operand1));
1308     emit_insn (gen_vsx_extract_<VEC_F:mode> (operand0, vec, elt));
1309     DONE;
1310   })