xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/rs6000/vector.md (revision a04395531661c5e8d314125d5ae77d4cbedd5d73)
1;; Expander definitions for vector support between altivec & vsx.  No
2;; instructions are in this file, this file provides the generic vector
3;; expander, and the actual vector instructions will be in altivec.md and
4;; vsx.md
5
6;; Copyright (C) 2009-2019 Free Software Foundation, Inc.
7;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
8
9;; This file is part of GCC.
10
11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
13;; by the Free Software Foundation; either version 3, or (at your
14;; option) any later version.
15
16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19;; License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GCC; see the file COPYING3.  If not see
23;; <http://www.gnu.org/licenses/>.
24
25
26;; Vector int modes
27(define_mode_iterator VEC_I [V16QI V8HI V4SI V2DI])
28
29;; Vector int modes for parity
30(define_mode_iterator VEC_IP [V8HI
31			      V4SI
32			      V2DI
33			      V1TI
34			      TI])
35
36;; Vector float modes
37(define_mode_iterator VEC_F [V4SF V2DF])
38
39;; Vector arithmetic modes
40(define_mode_iterator VEC_A [V16QI V8HI V4SI V2DI V4SF V2DF])
41
42;; Vector modes that need alginment via permutes
43(define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
44
45;; Vector logical modes
46(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI KF TF])
47
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])
51
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])
54
55;; Vector comparison modes
56(define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF])
57
58;; Vector init/extract modes
59(define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF])
60
61;; Vector modes for 64-bit base types
62(define_mode_iterator VEC_64 [V2DI V2DF])
63
64;; Vector integer modes
65(define_mode_iterator VI [V4SI V8HI V16QI])
66
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")])
76
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")])
86
87;; Same size integer type for floating point data
88(define_mode_attr VEC_int [(V4SF  "v4si")
89			   (V2DF  "v2di")])
90
91(define_mode_attr VEC_INT [(V4SF  "V4SI")
92			   (V2DF  "V2DI")])
93
94;; constants for unspec
95(define_c_enum "unspec" [UNSPEC_PREDICATE
96			 UNSPEC_REDUC
97			 UNSPEC_NEZ_P])
98
99;; Vector reduction code iterators
100(define_code_iterator VEC_reduc [plus smin smax])
101
102(define_code_attr VEC_reduc_name [(plus "plus")
103				  (smin "smin")
104				  (smax "smax")])
105
106(define_code_attr VEC_reduc_rtx [(plus "add")
107				 (smin "smin")
108				 (smax "smax")])
109
110
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)"
117{
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	}
130
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    }
152})
153
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  "")
161
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  "")
167
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)]
178{
179  rs6000_split_multireg_move (operands[0], operands[1]);
180  DONE;
181})
182
183
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  "")
191
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  "")
198
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)"
204{
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    }
210})
211
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)"
217{
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    }
225})
226
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)"
231{
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    }
237})
238
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)"
243{
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    }
249})
250
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  "")
257
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  "")
264
265
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)"
270{
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    }
279})
280
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  "")
287
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  "")
294
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  "")
300
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  "")
307
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  "")
314
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  "")
320
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)"
326{
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    }
333})
334
335
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)"
346{
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;
352})
353
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)"
363{
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;
369})
370
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)"
381{
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;
387})
388
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)"
399{
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;
405})
406
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)"
417{
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;
423})
424
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)"
435{
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;
441})
442
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)"
452{
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;
458})
459
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)"
470{
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;
476})
477
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)"
488{
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;
494})
495
496;; To support vector condition vectorization, define vcond_mask and vec_cmp.
497
498;; Same mode for condition true/false values and predicate operand.
499(define_expand "vcond_mask_<mode><mode>"
500  [(match_operand:VEC_I 0 "vint_operand")
501   (match_operand:VEC_I 1 "vint_operand")
502   (match_operand:VEC_I 2 "vint_operand")
503   (match_operand:VEC_I 3 "vint_operand")]
504  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
505{
506  emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1],
507                                  operands[3]));
508  DONE;
509})
510
511;; For signed integer vectors comparison.
512(define_expand "vec_cmp<mode><mode>"
513  [(set (match_operand:VEC_I 0 "vint_operand")
514        (match_operator 1 "signed_or_equality_comparison_operator"
515          [(match_operand:VEC_I 2 "vint_operand")
516           (match_operand:VEC_I 3 "vint_operand")]))]
517  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
518{
519  enum rtx_code code = GET_CODE (operands[1]);
520  rtx tmp = gen_reg_rtx (<MODE>mode);
521  switch (code)
522    {
523    case NE:
524      emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3]));
525      emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0]));
526      break;
527    case EQ:
528      emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3]));
529      break;
530    case GE:
531      emit_insn (gen_vector_nlt<mode> (operands[0],operands[2], operands[3],
532                                       tmp));
533      break;
534    case GT:
535      emit_insn (gen_vector_gt<mode> (operands[0], operands[2], operands[3]));
536      break;
537    case LE:
538      emit_insn (gen_vector_ngt<mode> (operands[0], operands[2], operands[3],
539                                       tmp));
540      break;
541    case LT:
542      emit_insn (gen_vector_gt<mode> (operands[0], operands[3], operands[2]));
543      break;
544    default:
545      gcc_unreachable ();
546      break;
547    }
548  DONE;
549})
550
551;; For unsigned integer vectors comparison.
552(define_expand "vec_cmpu<mode><mode>"
553  [(set (match_operand:VEC_I 0 "vint_operand")
554        (match_operator 1 "unsigned_or_equality_comparison_operator"
555          [(match_operand:VEC_I 2 "vint_operand")
556           (match_operand:VEC_I 3 "vint_operand")]))]
557  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
558{
559  enum rtx_code code = GET_CODE (operands[1]);
560  rtx tmp = gen_reg_rtx (<MODE>mode);
561  switch (code)
562    {
563    case NE:
564      emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3]));
565      emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0]));
566      break;
567    case EQ:
568      emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3]));
569      break;
570    case GEU:
571      emit_insn (gen_vector_nltu<mode> (operands[0], operands[2], operands[3],
572                                        tmp));
573      break;
574    case GTU:
575      emit_insn (gen_vector_gtu<mode> (operands[0], operands[2], operands[3]));
576      break;
577    case LEU:
578      emit_insn (gen_vector_ngtu<mode> (operands[0], operands[2], operands[3],
579                                        tmp));
580      break;
581    case LTU:
582      emit_insn (gen_vector_gtu<mode> (operands[0], operands[3], operands[2]));
583      break;
584    default:
585      gcc_unreachable ();
586      break;
587    }
588  DONE;
589})
590
591(define_expand "vector_eq<mode>"
592  [(set (match_operand:VEC_C 0 "vlogical_operand")
593	(eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand")
594		  (match_operand:VEC_C 2 "vlogical_operand")))]
595  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
596  "")
597
598(define_expand "vector_gt<mode>"
599  [(set (match_operand:VEC_C 0 "vlogical_operand")
600	(gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand")
601		  (match_operand:VEC_C 2 "vlogical_operand")))]
602  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
603  "")
604
605(define_expand "vector_ge<mode>"
606  [(set (match_operand:VEC_F 0 "vlogical_operand")
607	(ge:VEC_F (match_operand:VEC_F 1 "vlogical_operand")
608		  (match_operand:VEC_F 2 "vlogical_operand")))]
609  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
610  "")
611
612; >= for integer vectors: swap operands and apply not-greater-than
613(define_expand "vector_nlt<mode>"
614  [(set (match_operand:VEC_I 3 "vlogical_operand")
615	(gt:VEC_I (match_operand:VEC_I 2 "vlogical_operand")
616		  (match_operand:VEC_I 1 "vlogical_operand")))
617   (set (match_operand:VEC_I 0 "vlogical_operand")
618        (not:VEC_I (match_dup 3)))]
619  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
620{
621  operands[3] = gen_reg_rtx_and_attrs (operands[0]);
622})
623
624(define_expand "vector_gtu<mode>"
625  [(set (match_operand:VEC_I 0 "vint_operand")
626	(gtu:VEC_I (match_operand:VEC_I 1 "vint_operand")
627		   (match_operand:VEC_I 2 "vint_operand")))]
628  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
629  "")
630
631; >= for integer vectors: swap operands and apply not-greater-than
632(define_expand "vector_nltu<mode>"
633  [(set (match_operand:VEC_I 3 "vlogical_operand")
634	(gtu:VEC_I (match_operand:VEC_I 2 "vlogical_operand")
635	 	   (match_operand:VEC_I 1 "vlogical_operand")))
636   (set (match_operand:VEC_I 0 "vlogical_operand")
637        (not:VEC_I (match_dup 3)))]
638  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
639{
640  operands[3] = gen_reg_rtx_and_attrs (operands[0]);
641})
642
643(define_expand "vector_geu<mode>"
644  [(set (match_operand:VEC_I 0 "vint_operand")
645	(geu:VEC_I (match_operand:VEC_I 1 "vint_operand")
646		   (match_operand:VEC_I 2 "vint_operand")))]
647  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
648  "")
649
650; <= for integer vectors: apply not-greater-than
651(define_expand "vector_ngt<mode>"
652  [(set (match_operand:VEC_I 3 "vlogical_operand")
653	(gt:VEC_I (match_operand:VEC_I 1 "vlogical_operand")
654		  (match_operand:VEC_I 2 "vlogical_operand")))
655   (set (match_operand:VEC_I 0 "vlogical_operand")
656        (not:VEC_I (match_dup 3)))]
657  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
658{
659  operands[3] = gen_reg_rtx_and_attrs (operands[0]);
660})
661
662(define_expand "vector_ngtu<mode>"
663  [(set (match_operand:VEC_I 3 "vlogical_operand")
664	(gtu:VEC_I (match_operand:VEC_I 1 "vlogical_operand")
665	 	   (match_operand:VEC_I 2 "vlogical_operand")))
666   (set (match_operand:VEC_I 0 "vlogical_operand")
667        (not:VEC_I (match_dup 3)))]
668  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
669{
670  operands[3] = gen_reg_rtx_and_attrs (operands[0]);
671})
672
673(define_insn_and_split "*vector_uneq<mode>"
674  [(set (match_operand:VEC_F 0 "vfloat_operand")
675	(uneq:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
676		    (match_operand:VEC_F 2 "vfloat_operand")))]
677  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
678  "#"
679  ""
680  [(set (match_dup 3)
681	(gt:VEC_F (match_dup 1)
682		  (match_dup 2)))
683   (set (match_dup 4)
684	(gt:VEC_F (match_dup 2)
685		  (match_dup 1)))
686   (set (match_dup 0)
687	(and:VEC_F (not:VEC_F (match_dup 3))
688		   (not:VEC_F (match_dup 4))))]
689{
690  operands[3] = gen_reg_rtx (<MODE>mode);
691  operands[4] = gen_reg_rtx (<MODE>mode);
692})
693
694(define_insn_and_split "*vector_ltgt<mode>"
695  [(set (match_operand:VEC_F 0 "vfloat_operand")
696	(ltgt:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
697		    (match_operand:VEC_F 2 "vfloat_operand")))]
698  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
699  "#"
700  ""
701  [(set (match_dup 3)
702	(gt:VEC_F (match_dup 1)
703		  (match_dup 2)))
704   (set (match_dup 4)
705	(gt:VEC_F (match_dup 2)
706		  (match_dup 1)))
707   (set (match_dup 0)
708	(ior:VEC_F (match_dup 3)
709		   (match_dup 4)))]
710{
711  operands[3] = gen_reg_rtx (<MODE>mode);
712  operands[4] = gen_reg_rtx (<MODE>mode);
713})
714
715(define_insn_and_split "*vector_ordered<mode>"
716  [(set (match_operand:VEC_F 0 "vfloat_operand")
717	(ordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
718		       (match_operand:VEC_F 2 "vfloat_operand")))]
719  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
720  "#"
721  ""
722  [(set (match_dup 3)
723	(ge:VEC_F (match_dup 1)
724		  (match_dup 2)))
725   (set (match_dup 4)
726	(ge:VEC_F (match_dup 2)
727		  (match_dup 1)))
728   (set (match_dup 0)
729	(ior:VEC_F (match_dup 3)
730		   (match_dup 4)))]
731{
732  operands[3] = gen_reg_rtx (<MODE>mode);
733  operands[4] = gen_reg_rtx (<MODE>mode);
734})
735
736(define_insn_and_split "*vector_unordered<mode>"
737  [(set (match_operand:VEC_F 0 "vfloat_operand")
738	(unordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
739			 (match_operand:VEC_F 2 "vfloat_operand")))]
740  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
741  "#"
742  ""
743  [(set (match_dup 3)
744	(ge:VEC_F (match_dup 1)
745		  (match_dup 2)))
746   (set (match_dup 4)
747	(ge:VEC_F (match_dup 2)
748		  (match_dup 1)))
749   (set (match_dup 0)
750        (and:VEC_F (not:VEC_F (match_dup 3))
751                   (not:VEC_F (match_dup 4))))]
752{
753  operands[3] = gen_reg_rtx (<MODE>mode);
754  operands[4] = gen_reg_rtx (<MODE>mode);
755})
756
757;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
758;; which is in the reverse order that we want
759(define_expand "vector_select_<mode>"
760  [(set (match_operand:VEC_L 0 "vlogical_operand")
761	(if_then_else:VEC_L
762	 (ne:CC (match_operand:VEC_L 3 "vlogical_operand")
763		(match_dup 4))
764	 (match_operand:VEC_L 2 "vlogical_operand")
765	 (match_operand:VEC_L 1 "vlogical_operand")))]
766  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
767  "operands[4] = CONST0_RTX (<MODE>mode);")
768
769(define_expand "vector_select_<mode>_uns"
770  [(set (match_operand:VEC_L 0 "vlogical_operand")
771	(if_then_else:VEC_L
772	 (ne:CCUNS (match_operand:VEC_L 3 "vlogical_operand")
773		   (match_dup 4))
774	 (match_operand:VEC_L 2 "vlogical_operand")
775	 (match_operand:VEC_L 1 "vlogical_operand")))]
776  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
777  "operands[4] = CONST0_RTX (<MODE>mode);")
778
779;; Expansions that compare vectors producing a vector result and a predicate,
780;; setting CR6 to indicate a combined status
781(define_expand "vector_eq_<mode>_p"
782  [(parallel
783    [(set (reg:CC CR6_REGNO)
784	  (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand")
785			     (match_operand:VEC_A 2 "vlogical_operand"))]
786		     UNSPEC_PREDICATE))
787     (set (match_operand:VEC_A 0 "vlogical_operand")
788	  (eq:VEC_A (match_dup 1)
789		    (match_dup 2)))])]
790  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
791  "")
792
793;; This expansion handles the V16QI, V8HI, and V4SI modes in the
794;; implementation of the vec_all_ne built-in functions on Power9.
795(define_expand "vector_ne_<mode>_p"
796  [(parallel
797    [(set (reg:CC CR6_REGNO)
798	  (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand")
799			     (match_operand:VI 2 "vlogical_operand"))]
800	   UNSPEC_PREDICATE))
801     (set (match_dup 3)
802	  (ne:VI (match_dup 1)
803		 (match_dup 2)))])
804   (set (match_operand:SI 0 "register_operand" "=r")
805	(lt:SI (reg:CC CR6_REGNO)
806	       (const_int 0)))]
807  "TARGET_P9_VECTOR"
808{
809  operands[3] = gen_reg_rtx (<MODE>mode);
810})
811
812;; This expansion handles the V16QI, V8HI, and V4SI modes in the
813;; implementation of the vec_any_eq built-in functions on Power9.
814(define_expand "vector_ae_<mode>_p"
815  [(parallel
816    [(set (reg:CC CR6_REGNO)
817	  (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand")
818			     (match_operand:VI 2 "vlogical_operand"))]
819	   UNSPEC_PREDICATE))
820     (set (match_dup 3)
821	  (ne:VI (match_dup 1)
822		 (match_dup 2)))])
823   (set (match_operand:SI 0 "register_operand" "=r")
824	(lt:SI (reg:CC CR6_REGNO)
825	       (const_int 0)))
826   (set (match_dup 0)
827	(xor:SI (match_dup 0)
828		(const_int 1)))]
829  "TARGET_P9_VECTOR"
830{
831  operands[3] = gen_reg_rtx (<MODE>mode);
832})
833
834;; This expansion handles the V16QI, V8HI, and V4SI modes in the
835;; implementation of the vec_all_nez and vec_any_eqz built-in
836;; functions on Power9.
837(define_expand "vector_nez_<mode>_p"
838  [(parallel
839    [(set (reg:CC CR6_REGNO)
840	  (unspec:CC [(unspec:VI
841		       [(match_operand:VI 1 "vlogical_operand")
842			(match_operand:VI 2 "vlogical_operand")]
843		       UNSPEC_NEZ_P)]
844	   UNSPEC_PREDICATE))
845     (set (match_operand:VI 0 "vlogical_operand")
846	  (unspec:VI [(match_dup 1)
847		      (match_dup 2)]
848	   UNSPEC_NEZ_P))])]
849  "TARGET_P9_VECTOR"
850  "")
851
852;; This expansion handles the V2DI mode in the implementation of the
853;; vec_all_ne built-in function on Power9.
854;;
855;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode,
856;; this expands into the same rtl that would be used for the Power8
857;; architecture.
858(define_expand "vector_ne_v2di_p"
859  [(parallel
860    [(set (reg:CC CR6_REGNO)
861	  (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand")
862			     (match_operand:V2DI 2 "vlogical_operand"))]
863		     UNSPEC_PREDICATE))
864     (set (match_dup 3)
865	  (eq:V2DI (match_dup 1)
866		   (match_dup 2)))])
867   (set (match_operand:SI 0 "register_operand" "=r")
868	(eq:SI (reg:CC CR6_REGNO)
869	       (const_int 0)))]
870  "TARGET_P9_VECTOR"
871{
872  operands[3] = gen_reg_rtx (V2DImode);
873})
874
875;; This expansion handles the V2DI mode in the implementation of the
876;; vec_any_eq built-in function on Power9.
877;;
878;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode,
879;; this expands into the same rtl that would be used for the Power8
880;; architecture.
881(define_expand "vector_ae_v2di_p"
882  [(parallel
883    [(set (reg:CC CR6_REGNO)
884	  (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand")
885			     (match_operand:V2DI 2 "vlogical_operand"))]
886		     UNSPEC_PREDICATE))
887     (set (match_dup 3)
888	  (eq:V2DI (match_dup 1)
889		   (match_dup 2)))])
890   (set (match_operand:SI 0 "register_operand" "=r")
891	(eq:SI (reg:CC CR6_REGNO)
892	       (const_int 0)))
893   (set (match_dup 0)
894	(xor:SI (match_dup 0)
895		(const_int 1)))]
896  "TARGET_P9_VECTOR"
897{
898  operands[3] = gen_reg_rtx (V2DImode);
899})
900
901;; This expansion handles the V4SF and V2DF modes in the Power9
902;; implementation of the vec_all_ne built-in functions.  Note that the
903;; expansions for this pattern with these modes makes no use of power9-
904;; specific instructions since there are no new power9 instructions
905;; for vector compare not equal with floating point arguments.
906(define_expand "vector_ne_<mode>_p"
907  [(parallel
908    [(set (reg:CC CR6_REGNO)
909	  (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand")
910			     (match_operand:VEC_F 2 "vlogical_operand"))]
911		     UNSPEC_PREDICATE))
912     (set (match_dup 3)
913	  (eq:VEC_F (match_dup 1)
914		    (match_dup 2)))])
915   (set (match_operand:SI 0 "register_operand" "=r")
916	(eq:SI (reg:CC CR6_REGNO)
917	       (const_int 0)))]
918  "TARGET_P9_VECTOR"
919{
920  operands[3] = gen_reg_rtx (<MODE>mode);
921})
922
923;; This expansion handles the V4SF and V2DF modes in the Power9
924;; implementation of the vec_any_eq built-in functions.  Note that the
925;; expansions for this pattern with these modes makes no use of power9-
926;; specific instructions since there are no new power9 instructions
927;; for vector compare not equal with floating point arguments.
928(define_expand "vector_ae_<mode>_p"
929  [(parallel
930    [(set (reg:CC CR6_REGNO)
931	  (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand")
932			     (match_operand:VEC_F 2 "vlogical_operand"))]
933		     UNSPEC_PREDICATE))
934     (set (match_dup 3)
935	  (eq:VEC_F (match_dup 1)
936		    (match_dup 2)))])
937   (set (match_operand:SI 0 "register_operand" "=r")
938	(eq:SI (reg:CC CR6_REGNO)
939	       (const_int 0)))
940   (set (match_dup 0)
941	(xor:SI (match_dup 0)
942		(const_int 1)))]
943  "TARGET_P9_VECTOR"
944{
945  operands[3] = gen_reg_rtx (<MODE>mode);
946})
947
948(define_expand "vector_gt_<mode>_p"
949  [(parallel
950    [(set (reg:CC CR6_REGNO)
951	  (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand")
952			     (match_operand:VEC_A 2 "vlogical_operand"))]
953		     UNSPEC_PREDICATE))
954     (set (match_operand:VEC_A 0 "vlogical_operand")
955	  (gt:VEC_A (match_dup 1)
956		    (match_dup 2)))])]
957  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
958  "")
959
960(define_expand "vector_ge_<mode>_p"
961  [(parallel
962    [(set (reg:CC CR6_REGNO)
963	  (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand")
964			     (match_operand:VEC_F 2 "vfloat_operand"))]
965		     UNSPEC_PREDICATE))
966     (set (match_operand:VEC_F 0 "vfloat_operand")
967	  (ge:VEC_F (match_dup 1)
968		    (match_dup 2)))])]
969  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
970  "")
971
972(define_expand "vector_gtu_<mode>_p"
973  [(parallel
974    [(set (reg:CC CR6_REGNO)
975	  (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand")
976			      (match_operand:VEC_I 2 "vint_operand"))]
977		     UNSPEC_PREDICATE))
978     (set (match_operand:VEC_I 0 "vlogical_operand")
979	  (gtu:VEC_I (match_dup 1)
980		     (match_dup 2)))])]
981  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
982  "")
983
984;; AltiVec/VSX predicates.
985
986;; This expansion is triggered during expansion of predicate built-in
987;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
988;; altivec_expand_predicate_builtin() function when the value of the
989;; integer constant first argument equals zero (aka __CR6_EQ in altivec.h).
990(define_expand "cr6_test_for_zero"
991  [(set (match_operand:SI 0 "register_operand" "=r")
992	(eq:SI (reg:CC CR6_REGNO)
993	       (const_int 0)))]
994  "TARGET_ALTIVEC || TARGET_VSX"
995  "")
996
997;; This expansion is triggered during expansion of predicate built-in
998;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
999;; altivec_expand_predicate_builtin() function when the value of the
1000;; integer constant first argument equals one (aka __CR6_EQ_REV in altivec.h).
1001(define_expand "cr6_test_for_zero_reverse"
1002  [(set (match_operand:SI 0 "register_operand" "=r")
1003	(eq:SI (reg:CC CR6_REGNO)
1004	       (const_int 0)))
1005   (set (match_dup 0)
1006	(xor:SI (match_dup 0)
1007		(const_int 1)))]
1008  "TARGET_ALTIVEC || TARGET_VSX"
1009  "")
1010
1011;; This expansion is triggered during expansion of predicate built-in
1012;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
1013;; altivec_expand_predicate_builtin() function when the value of the
1014;; integer constant first argument equals two (aka __CR6_LT in altivec.h).
1015(define_expand "cr6_test_for_lt"
1016  [(set (match_operand:SI 0 "register_operand" "=r")
1017	(lt:SI (reg:CC CR6_REGNO)
1018	       (const_int 0)))]
1019  "TARGET_ALTIVEC || TARGET_VSX"
1020  "")
1021
1022;; This expansion is triggered during expansion of predicate built-in
1023;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
1024;; altivec_expand_predicate_builtin() function when the value of the
1025;; integer constant first argument equals three
1026;; (aka __CR6_LT_REV in altivec.h).
1027(define_expand "cr6_test_for_lt_reverse"
1028  [(set (match_operand:SI 0 "register_operand" "=r")
1029	(lt:SI (reg:CC CR6_REGNO)
1030	       (const_int 0)))
1031   (set (match_dup 0)
1032	(xor:SI (match_dup 0)
1033		(const_int 1)))]
1034  "TARGET_ALTIVEC || TARGET_VSX"
1035  "")
1036
1037
1038;; Vector count leading zeros
1039(define_expand "clz<mode>2"
1040  [(set (match_operand:VEC_I 0 "register_operand")
1041	(clz:VEC_I (match_operand:VEC_I 1 "register_operand")))]
1042  "TARGET_P8_VECTOR")
1043
1044;; Vector count trailing zeros
1045(define_expand "ctz<mode>2"
1046  [(set (match_operand:VEC_I 0 "register_operand")
1047	(ctz:VEC_I (match_operand:VEC_I 1 "register_operand")))]
1048  "TARGET_P9_VECTOR")
1049
1050;; Vector population count
1051(define_expand "popcount<mode>2"
1052  [(set (match_operand:VEC_I 0 "register_operand")
1053        (popcount:VEC_I (match_operand:VEC_I 1 "register_operand")))]
1054  "TARGET_P8_VECTOR")
1055
1056;; Vector parity
1057(define_expand "parity<mode>2"
1058  [(set (match_operand:VEC_IP 0 "register_operand")
1059	(parity:VEC_IP (match_operand:VEC_IP 1 "register_operand")))]
1060  "TARGET_P9_VECTOR")
1061
1062
1063;; Same size conversions
1064(define_expand "float<VEC_int><mode>2"
1065  [(set (match_operand:VEC_F 0 "vfloat_operand")
1066	(float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))]
1067  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1068{
1069  if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
1070    {
1071      emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
1072      DONE;
1073    }
1074})
1075
1076(define_expand "floatuns<VEC_int><mode>2"
1077  [(set (match_operand:VEC_F 0 "vfloat_operand")
1078	(unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))]
1079  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1080{
1081  if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
1082    {
1083      emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
1084      DONE;
1085    }
1086})
1087
1088(define_expand "fix_trunc<mode><VEC_int>2"
1089  [(set (match_operand:<VEC_INT> 0 "vint_operand")
1090	(fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))]
1091  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1092{
1093  if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
1094    {
1095      emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
1096      DONE;
1097    }
1098})
1099
1100(define_expand "fixuns_trunc<mode><VEC_int>2"
1101  [(set (match_operand:<VEC_INT> 0 "vint_operand")
1102	(unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))]
1103  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1104{
1105  if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
1106    {
1107      emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
1108      DONE;
1109    }
1110})
1111
1112
1113;; Vector initialization, set, extract
1114(define_expand "vec_init<mode><VEC_base_l>"
1115  [(match_operand:VEC_E 0 "vlogical_operand")
1116   (match_operand:VEC_E 1 "")]
1117  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1118{
1119  rs6000_expand_vector_init (operands[0], operands[1]);
1120  DONE;
1121})
1122
1123(define_expand "vec_set<mode>"
1124  [(match_operand:VEC_E 0 "vlogical_operand")
1125   (match_operand:<VEC_base> 1 "register_operand")
1126   (match_operand 2 "const_int_operand")]
1127  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1128{
1129  rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
1130  DONE;
1131})
1132
1133(define_expand "vec_extract<mode><VEC_base_l>"
1134  [(match_operand:<VEC_base> 0 "register_operand")
1135   (match_operand:VEC_E 1 "vlogical_operand")
1136   (match_operand 2 "const_int_operand")]
1137  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1138{
1139  rs6000_expand_vector_extract (operands[0], operands[1], operands[2]);
1140  DONE;
1141})
1142
1143;; Convert double word types to single word types
1144(define_expand "vec_pack_trunc_v2df"
1145  [(match_operand:V4SF 0 "vfloat_operand")
1146   (match_operand:V2DF 1 "vfloat_operand")
1147   (match_operand:V2DF 2 "vfloat_operand")]
1148  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1149{
1150  rtx r1 = gen_reg_rtx (V4SFmode);
1151  rtx r2 = gen_reg_rtx (V4SFmode);
1152
1153  emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
1154  emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
1155  rs6000_expand_extract_even (operands[0], r1, r2);
1156  DONE;
1157})
1158
1159(define_expand "vec_pack_sfix_trunc_v2df"
1160  [(match_operand:V4SI 0 "vint_operand")
1161   (match_operand:V2DF 1 "vfloat_operand")
1162   (match_operand:V2DF 2 "vfloat_operand")]
1163  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1164{
1165  rtx r1 = gen_reg_rtx (V4SImode);
1166  rtx r2 = gen_reg_rtx (V4SImode);
1167
1168  emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
1169  emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
1170  rs6000_expand_extract_even (operands[0], r1, r2);
1171  DONE;
1172})
1173
1174(define_expand "vec_pack_ufix_trunc_v2df"
1175  [(match_operand:V4SI 0 "vint_operand")
1176   (match_operand:V2DF 1 "vfloat_operand")
1177   (match_operand:V2DF 2 "vfloat_operand")]
1178  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
1179{
1180  rtx r1 = gen_reg_rtx (V4SImode);
1181  rtx r2 = gen_reg_rtx (V4SImode);
1182
1183  emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
1184  emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
1185  rs6000_expand_extract_even (operands[0], r1, r2);
1186  DONE;
1187})
1188
1189;; Convert single word types to double word
1190(define_expand "vec_unpacks_hi_v4sf"
1191  [(match_operand:V2DF 0 "vfloat_operand")
1192   (match_operand:V4SF 1 "vfloat_operand")]
1193  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
1194{
1195  rtx reg = gen_reg_rtx (V4SFmode);
1196
1197  rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1198  emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
1199  DONE;
1200})
1201
1202(define_expand "vec_unpacks_lo_v4sf"
1203  [(match_operand:V2DF 0 "vfloat_operand")
1204   (match_operand:V4SF 1 "vfloat_operand")]
1205  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
1206{
1207  rtx reg = gen_reg_rtx (V4SFmode);
1208
1209  rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1210  emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
1211  DONE;
1212})
1213
1214(define_expand "vec_unpacks_float_hi_v4si"
1215  [(match_operand:V2DF 0 "vfloat_operand")
1216   (match_operand:V4SI 1 "vint_operand")]
1217  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1218{
1219  rtx reg = gen_reg_rtx (V4SImode);
1220
1221  rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1222  emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
1223  DONE;
1224})
1225
1226(define_expand "vec_unpacks_float_lo_v4si"
1227  [(match_operand:V2DF 0 "vfloat_operand")
1228   (match_operand:V4SI 1 "vint_operand")]
1229  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1230{
1231  rtx reg = gen_reg_rtx (V4SImode);
1232
1233  rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1234  emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
1235  DONE;
1236})
1237
1238(define_expand "vec_unpacku_float_hi_v4si"
1239  [(match_operand:V2DF 0 "vfloat_operand")
1240   (match_operand:V4SI 1 "vint_operand")]
1241  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1242{
1243  rtx reg = gen_reg_rtx (V4SImode);
1244
1245  rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
1246  emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
1247  DONE;
1248})
1249
1250(define_expand "vec_unpacku_float_lo_v4si"
1251  [(match_operand:V2DF 0 "vfloat_operand")
1252   (match_operand:V4SI 1 "vint_operand")]
1253  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
1254{
1255  rtx reg = gen_reg_rtx (V4SImode);
1256
1257  rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
1258  emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
1259  DONE;
1260})
1261
1262
1263;; Align vector loads with a permute.
1264(define_expand "vec_realign_load_<mode>"
1265  [(match_operand:VEC_K 0 "vlogical_operand")
1266   (match_operand:VEC_K 1 "vlogical_operand")
1267   (match_operand:VEC_K 2 "vlogical_operand")
1268   (match_operand:V16QI 3 "vlogical_operand")]
1269  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
1270{
1271  if (BYTES_BIG_ENDIAN)
1272    emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
1273    	      				 operands[2], operands[3]));
1274  else
1275    {
1276      /* We have changed lvsr to lvsl, so to complete the transformation
1277         of vperm for LE, we must swap the inputs.  */
1278      rtx unspec = gen_rtx_UNSPEC (<MODE>mode,
1279                                   gen_rtvec (3, operands[2],
1280                                              operands[1], operands[3]),
1281                                   UNSPEC_VPERM);
1282      emit_move_insn (operands[0], unspec);
1283    }
1284  DONE;
1285})
1286
1287;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned
1288;; since the load already handles it.
1289(define_expand "movmisalign<mode>"
1290 [(set (match_operand:VEC_N 0 "nonimmediate_operand")
1291       (match_operand:VEC_N 1 "any_operand"))]
1292 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN"
1293 "")
1294
1295;; Vector shift right in bits. Currently supported ony for shift
1296;; amounts that can be expressed as byte shifts (divisible by 8).
1297;; General shift amounts can be supported using vsro + vsr. We're
1298;; not expecting to see these yet (the vectorizer currently
1299;; generates only shifts by a whole number of vector elements).
1300;; Note that the vec_shr operation is actually defined as
1301;; 'shift toward element 0' so is a shr for LE and shl for BE.
1302(define_expand "vec_shr_<mode>"
1303  [(match_operand:VEC_L 0 "vlogical_operand")
1304   (match_operand:VEC_L 1 "vlogical_operand")
1305   (match_operand:QI 2 "reg_or_short_operand")]
1306  "TARGET_ALTIVEC"
1307{
1308  rtx bitshift = operands[2];
1309  rtx shift;
1310  rtx insn;
1311  rtx zero_reg, op1, op2;
1312  HOST_WIDE_INT bitshift_val;
1313  HOST_WIDE_INT byteshift_val;
1314
1315  if (! CONSTANT_P (bitshift))
1316    FAIL;
1317  bitshift_val = INTVAL (bitshift);
1318  if (bitshift_val & 0x7)
1319    FAIL;
1320  byteshift_val = (bitshift_val >> 3);
1321  zero_reg = gen_reg_rtx (<MODE>mode);
1322  emit_move_insn (zero_reg, CONST0_RTX (<MODE>mode));
1323  if (!BYTES_BIG_ENDIAN)
1324    {
1325      byteshift_val = 16 - byteshift_val;
1326      op1 = zero_reg;
1327      op2 = operands[1];
1328    }
1329  else
1330    {
1331      op1 = operands[1];
1332      op2 = zero_reg;
1333    }
1334
1335  if (TARGET_VSX && (byteshift_val & 0x3) == 0)
1336    {
1337      shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
1338      insn = gen_vsx_xxsldwi_<mode> (operands[0], op1, op2, shift);
1339    }
1340  else
1341    {
1342      shift = gen_rtx_CONST_INT (QImode, byteshift_val);
1343      insn = gen_altivec_vsldoi_<mode> (operands[0], op1, op2, shift);
1344    }
1345
1346  emit_insn (insn);
1347  DONE;
1348})
1349
1350;; Expanders for rotate each element in a vector
1351(define_expand "vrotl<mode>3"
1352  [(set (match_operand:VEC_I 0 "vint_operand")
1353	(rotate:VEC_I (match_operand:VEC_I 1 "vint_operand")
1354		      (match_operand:VEC_I 2 "vint_operand")))]
1355  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1356  "")
1357
1358;; Expanders for arithmetic shift left on each vector element
1359(define_expand "vashl<mode>3"
1360  [(set (match_operand:VEC_I 0 "vint_operand")
1361	(ashift:VEC_I (match_operand:VEC_I 1 "vint_operand")
1362		      (match_operand:VEC_I 2 "vint_operand")))]
1363  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1364  "")
1365
1366;; Expanders for logical shift right on each vector element
1367(define_expand "vlshr<mode>3"
1368  [(set (match_operand:VEC_I 0 "vint_operand")
1369	(lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand")
1370			(match_operand:VEC_I 2 "vint_operand")))]
1371  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1372  "")
1373
1374;; Expanders for arithmetic shift right on each vector element
1375(define_expand "vashr<mode>3"
1376  [(set (match_operand:VEC_I 0 "vint_operand")
1377	(ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand")
1378			(match_operand:VEC_I 2 "vint_operand")))]
1379  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
1380  "")
1381
1382;; Vector reduction expanders for VSX
1383; The (VEC_reduc:...
1384;	(op1)
1385;	(unspec:... [(const_int 0)] UNSPEC_REDUC))
1386;
1387; is to allow us to use a code iterator, but not completely list all of the
1388; vector rotates, etc. to prevent canonicalization
1389
1390
1391(define_expand "reduc_<VEC_reduc:VEC_reduc_name>_scal_<VEC_F:mode>"
1392  [(match_operand:<VEC_base> 0 "register_operand")
1393   (VEC_reduc:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
1394		    (unspec:VEC_F [(const_int 0)] UNSPEC_REDUC))]
1395  "VECTOR_UNIT_VSX_P (<VEC_F:MODE>mode)"
1396  {
1397    rtx vec = gen_reg_rtx (<VEC_F:MODE>mode);
1398    rtx elt = BYTES_BIG_ENDIAN
1399		? gen_int_mode (GET_MODE_NUNITS (<VEC_F:MODE>mode) - 1, QImode)
1400		: const0_rtx;
1401    emit_insn (gen_vsx_reduc_<VEC_reduc:VEC_reduc_name>_<VEC_F:mode> (vec,
1402	operand1));
1403    emit_insn (gen_vsx_extract_<VEC_F:mode> (operand0, vec, elt));
1404    DONE;
1405  })
1406