Home | History | Annotate | Line # | Download | only in rs6000
      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-2022 Free Software Foundation, Inc.
      7 ;; Contributed by Michael Meissner <meissner (a] 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 ;; 128-bit int modes
     30 (define_mode_iterator VEC_TI [V1TI TI])
     31 
     32 ;; Vector int modes for parity
     33 (define_mode_iterator VEC_IP [V8HI
     34 			      V4SI
     35 			      V2DI
     36 			      V1TI
     37 			      TI])
     38 
     39 ;; Vector float modes
     40 (define_mode_iterator VEC_F [V4SF V2DF])
     41 
     42 ;; Vector arithmetic modes
     43 (define_mode_iterator VEC_A [V16QI V8HI V4SI V2DI V4SF V2DF])
     44 
     45 ;; Vector modes that need alginment via permutes
     46 (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
     47 
     48 ;; Vector logical modes
     49 (define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI KF TF])
     50 
     51 ;; Vector modes for moves.  Don't do TImode or TFmode here, since their
     52 ;; moves are handled elsewhere.
     53 (define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI KF])
     54 
     55 ;; Vector modes for types that don't need a realignment under VSX
     56 (define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI KF TF])
     57 
     58 ;; Vector comparison modes
     59 (define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF V1TI])
     60 
     61 ;; Vector init/extract modes
     62 (define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF])
     63 
     64 ;; Vector modes for 64-bit base types
     65 (define_mode_iterator VEC_64 [V2DI V2DF])
     66 
     67 ;; Vector integer modes
     68 (define_mode_iterator VI [V4SI V8HI V16QI])
     69 
     70 ;; Base type from vector mode
     71 (define_mode_attr VEC_base [(V16QI "QI")
     72 			    (V8HI  "HI")
     73 			    (V4SI  "SI")
     74 			    (V2DI  "DI")
     75 			    (V4SF  "SF")
     76 			    (V2DF  "DF")
     77 			    (V1TI  "TI")
     78 			    (TI    "TI")])
     79 
     80 ;; As above, but in lower case
     81 (define_mode_attr VEC_base_l [(V16QI "qi")
     82 			      (V8HI  "hi")
     83 			      (V4SI  "si")
     84 			      (V2DI  "di")
     85 			      (V4SF  "sf")
     86 			      (V2DF  "df")
     87 			      (V1TI  "ti")
     88 			      (TI    "ti")])
     89 
     90 ;; Same size integer type for floating point data
     91 (define_mode_attr VEC_int [(V4SF  "v4si")
     92 			   (V2DF  "v2di")])
     93 
     94 (define_mode_attr VEC_INT [(V4SF  "V4SI")
     95 			   (V2DF  "V2DI")])
     96 
     97 ;; constants for unspec
     98 (define_c_enum "unspec" [UNSPEC_PREDICATE
     99 			 UNSPEC_REDUC
    100 			 UNSPEC_NEZ_P])
    101 
    102 ;; Vector reduction code iterators
    103 (define_code_iterator VEC_reduc [plus smin smax])
    104 
    105 (define_code_attr VEC_reduc_name [(plus "plus")
    106 				  (smin "smin")
    107 				  (smax "smax")])
    108 
    109 (define_code_attr VEC_reduc_rtx [(plus "add")
    110 				 (smin "smin")
    111 				 (smax "smax")])
    112 
    113 ;; code iterators and attributes for vector FP comparison operators:
    114 (define_code_iterator
    115   vector_fp_comparison_simple [lt le ne ungt unge unlt unle])
    116 (define_code_iterator
    117   vector_fp_comparison_complex [ltgt uneq unordered ordered])
    118 
    119 
    121 ;; Vector move instructions.  Little-endian VSX loads and stores require
    122 ;; special handling to circumvent "element endianness."
    123 (define_expand "mov<mode>"
    124   [(set (match_operand:VEC_M 0 "nonimmediate_operand")
    125 	(match_operand:VEC_M 1 "any_operand"))]
    126   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
    127 {
    128   if (can_create_pseudo_p ())
    129     {
    130       if (CONSTANT_P (operands[1]))
    131 	{
    132 	  if (FLOAT128_VECTOR_P (<MODE>mode))
    133 	    {
    134 	      if (!easy_fp_constant (operands[1], <MODE>mode))
    135 		operands[1] = force_const_mem (<MODE>mode, operands[1]);
    136 	    }
    137 	  else if (!easy_vector_constant (operands[1], <MODE>mode))
    138 	    operands[1] = force_const_mem (<MODE>mode, operands[1]);
    139 	}
    140 
    141       if (!vlogical_operand (operands[0], <MODE>mode)
    142 	  && !vlogical_operand (operands[1], <MODE>mode))
    143 	operands[1] = force_reg (<MODE>mode, operands[1]);
    144     }
    145   /* When generating load/store instructions to/from VSX registers on
    146      pre-power9 hardware in little endian mode, we need to emit register
    147      permute instructions to byte swap the contents, since the VSX load/store
    148      instructions do not include a byte swap as part of their operation.
    149      Altivec loads and stores have no such problem, so we skip them below.  */
    150   if (!BYTES_BIG_ENDIAN
    151       && VECTOR_MEM_VSX_P (<MODE>mode)
    152       && !TARGET_P9_VECTOR
    153       && !gpr_or_gpr_p (operands[0], operands[1])
    154       && ((memory_operand (operands[0], <MODE>mode)
    155 	   && !altivec_indexed_or_indirect_operand(operands[0], <MODE>mode))
    156 	  ^ (memory_operand (operands[1], <MODE>mode)
    157 	     && !altivec_indexed_or_indirect_operand(operands[1], <MODE>mode))))
    158     {
    159       rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
    160       DONE;
    161     }
    162 })
    163 
    164 ;; Generic vector floating point load/store instructions.  These will match
    165 ;; insns defined in vsx.md or altivec.md depending on the switches.
    166 (define_expand "vector_load_<mode>"
    167   [(set (match_operand:VEC_M 0 "vfloat_operand")
    168 	(match_operand:VEC_M 1 "memory_operand"))]
    169   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
    170   "")
    171 
    172 (define_expand "vector_store_<mode>"
    173   [(set (match_operand:VEC_M 0 "memory_operand")
    174 	(match_operand:VEC_M 1 "vfloat_operand"))]
    175   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
    176   "")
    177 
    178 ;; Splits if a GPR register was chosen for the move
    179 (define_split
    180   [(set (match_operand:VEC_L 0 "nonimmediate_operand")
    181         (match_operand:VEC_L 1 "input_operand"))]
    182   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
    183    && reload_completed
    184    && gpr_or_gpr_p (operands[0], operands[1])
    185    && !direct_move_p (operands[0], operands[1])
    186    && !quad_load_store_p (operands[0], operands[1])"
    187   [(pc)]
    188 {
    189   rs6000_split_multireg_move (operands[0], operands[1]);
    190   DONE;
    191 })
    192 
    193 
    195 ;; Generic floating point vector arithmetic support
    196 (define_expand "add<mode>3"
    197   [(set (match_operand:VEC_F 0 "vfloat_operand")
    198 	(plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
    199 		    (match_operand:VEC_F 2 "vfloat_operand")))]
    200   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    201   "")
    202 
    203 (define_expand "sub<mode>3"
    204   [(set (match_operand:VEC_F 0 "vfloat_operand")
    205 	(minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
    206 		     (match_operand:VEC_F 2 "vfloat_operand")))]
    207   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    208   "")
    209 
    210 (define_expand "mul<mode>3"
    211   [(set (match_operand:VEC_F 0 "vfloat_operand")
    212 	(mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
    213 		    (match_operand:VEC_F 2 "vfloat_operand")))]
    214   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    215 {
    216   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
    217     {
    218       emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2]));
    219       DONE;
    220     }
    221 })
    222 
    223 (define_expand "div<mode>3"
    224   [(set (match_operand:VEC_F 0 "vfloat_operand")
    225 	(div:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
    226 		   (match_operand:VEC_F 2 "vfloat_operand")))]
    227   "VECTOR_UNIT_VSX_P (<MODE>mode)"
    228 {
    229   if (RS6000_RECIP_AUTO_RE_P (<MODE>mode)
    230       && can_create_pseudo_p () && flag_finite_math_only
    231       && !flag_trapping_math && flag_reciprocal_math)
    232     {
    233       rs6000_emit_swdiv (operands[0], operands[1], operands[2], true);
    234       DONE;
    235     }
    236 })
    237 
    238 (define_expand "neg<mode>2"
    239   [(set (match_operand:VEC_F 0 "vfloat_operand")
    240 	(neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
    241   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    242 {
    243   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
    244     {
    245       emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1]));
    246       DONE;
    247     }
    248 })
    249 
    250 (define_expand "abs<mode>2"
    251   [(set (match_operand:VEC_F 0 "vfloat_operand")
    252 	(abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
    253   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    254 {
    255   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
    256     {
    257       emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1]));
    258       DONE;
    259     }
    260 })
    261 
    262 (define_expand "smin<mode>3"
    263   [(set (match_operand:VEC_F 0 "register_operand")
    264         (smin:VEC_F (match_operand:VEC_F 1 "register_operand")
    265 		    (match_operand:VEC_F 2 "register_operand")))]
    266   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    267   "")
    268 
    269 (define_expand "smax<mode>3"
    270   [(set (match_operand:VEC_F 0 "register_operand")
    271         (smax:VEC_F (match_operand:VEC_F 1 "register_operand")
    272 		    (match_operand:VEC_F 2 "register_operand")))]
    273   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    274   "")
    275 
    276 
    277 (define_expand "sqrt<mode>2"
    278   [(set (match_operand:VEC_F 0 "vfloat_operand")
    279 	(sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
    280   "VECTOR_UNIT_VSX_P (<MODE>mode)"
    281 {
    282   if (<MODE>mode == V4SFmode
    283       && !optimize_function_for_size_p (cfun)
    284       && flag_finite_math_only && !flag_trapping_math
    285       && flag_unsafe_math_optimizations)
    286     {
    287       rs6000_emit_swsqrt (operands[0], operands[1], 0);
    288       DONE;
    289     }
    290 })
    291 
    292 (define_expand "rsqrte<mode>2"
    293   [(set (match_operand:VEC_F 0 "vfloat_operand")
    294         (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")]
    295 		      UNSPEC_RSQRT))]
    296   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    297   "")
    298 
    299 (define_expand "re<mode>2"
    300   [(set (match_operand:VEC_F 0 "vfloat_operand")
    301 	(unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")]
    302 		      UNSPEC_FRES))]
    303   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    304   "")
    305 
    306 (define_expand "ftrunc<mode>2"
    307   [(set (match_operand:VEC_F 0 "vfloat_operand")
    308   	(fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
    309   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    310   "")
    311 
    312 (define_expand "vector_ceil<mode>2"
    313   [(set (match_operand:VEC_F 0 "vfloat_operand")
    314 	(unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")]
    315 		      UNSPEC_FRIP))]
    316   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    317   "")
    318 
    319 (define_expand "vector_floor<mode>2"
    320   [(set (match_operand:VEC_F 0 "vfloat_operand")
    321 	(unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")]
    322 		      UNSPEC_FRIM))]
    323   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    324   "")
    325 
    326 (define_expand "vector_btrunc<mode>2"
    327   [(set (match_operand:VEC_F 0 "vfloat_operand")
    328 	(fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))]
    329   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    330   "")
    331 
    332 (define_expand "vector_copysign<mode>3"
    333   [(set (match_operand:VEC_F 0 "vfloat_operand")
    334 	(unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")
    335 		       (match_operand:VEC_F 2 "vfloat_operand")] UNSPEC_COPYSIGN))]
    336   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    337 {
    338   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
    339     {
    340       emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1],
    341 					     operands[2]));
    342       DONE;
    343     }
    344 })
    345 
    346 
    348 ;; Vector comparisons
    349 (define_expand "vcond<mode><mode>"
    350   [(set (match_operand:VEC_F 0 "vfloat_operand")
    351 	(if_then_else:VEC_F
    352 	 (match_operator 3 "comparison_operator"
    353 			 [(match_operand:VEC_F 4 "vfloat_operand")
    354 			  (match_operand:VEC_F 5 "vfloat_operand")])
    355 	 (match_operand:VEC_F 1 "vfloat_operand")
    356 	 (match_operand:VEC_F 2 "vfloat_operand")))]
    357   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    358 {
    359   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    360 				    operands[3], operands[4], operands[5]))
    361     DONE;
    362   else
    363     gcc_unreachable ();
    364 })
    365 
    366 (define_expand "vcond<mode><mode>"
    367   [(set (match_operand:VEC_I 0 "vint_operand")
    368 	(if_then_else:VEC_I
    369 	 (match_operator 3 "comparison_operator"
    370 			 [(match_operand:VEC_I 4 "vint_operand")
    371 			  (match_operand:VEC_I 5 "vint_operand")])
    372 	 (match_operand:VEC_I 1 "vector_int_reg_or_same_bit")
    373 	 (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))]
    374   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    375 {
    376   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    377 				    operands[3], operands[4], operands[5]))
    378     DONE;
    379   else
    380     gcc_unreachable ();
    381 })
    382 
    383 (define_expand "vcondv4sfv4si"
    384   [(set (match_operand:V4SF 0 "vfloat_operand")
    385 	(if_then_else:V4SF
    386 	 (match_operator 3 "comparison_operator"
    387 			 [(match_operand:V4SI 4 "vint_operand")
    388 			  (match_operand:V4SI 5 "vint_operand")])
    389 	 (match_operand:V4SF 1 "vfloat_operand")
    390 	 (match_operand:V4SF 2 "vfloat_operand")))]
    391   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
    392    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
    393 {
    394   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    395 				    operands[3], operands[4], operands[5]))
    396     DONE;
    397   else
    398     gcc_unreachable ();
    399 })
    400 
    401 (define_expand "vcondv4siv4sf"
    402   [(set (match_operand:V4SI 0 "vint_operand")
    403 	(if_then_else:V4SI
    404 	 (match_operator 3 "comparison_operator"
    405 			 [(match_operand:V4SF 4 "vfloat_operand")
    406 			  (match_operand:V4SF 5 "vfloat_operand")])
    407 	 (match_operand:V4SI 1 "vint_operand")
    408 	 (match_operand:V4SI 2 "vint_operand")))]
    409   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
    410    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
    411 {
    412   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    413 				    operands[3], operands[4], operands[5]))
    414     DONE;
    415   else
    416     gcc_unreachable ();
    417 })
    418 
    419 (define_expand "vcondv2dfv2di"
    420   [(set (match_operand:V2DF 0 "vfloat_operand")
    421 	(if_then_else:V2DF
    422 	 (match_operator 3 "comparison_operator"
    423 			 [(match_operand:V2DI 4 "vint_operand")
    424 			  (match_operand:V2DI 5 "vint_operand")])
    425 	 (match_operand:V2DF 1 "vfloat_operand")
    426 	 (match_operand:V2DF 2 "vfloat_operand")))]
    427   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)
    428    && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)"
    429 {
    430   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    431 				    operands[3], operands[4], operands[5]))
    432     DONE;
    433   else
    434     gcc_unreachable ();
    435 })
    436 
    437 (define_expand "vcondv2div2df"
    438   [(set (match_operand:V2DI 0 "vint_operand")
    439 	(if_then_else:V2DI
    440 	 (match_operator 3 "comparison_operator"
    441 			 [(match_operand:V2DF 4 "vfloat_operand")
    442 			  (match_operand:V2DF 5 "vfloat_operand")])
    443 	 (match_operand:V2DI 1 "vint_operand")
    444 	 (match_operand:V2DI 2 "vint_operand")))]
    445   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)
    446    && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)"
    447 {
    448   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    449 				    operands[3], operands[4], operands[5]))
    450     DONE;
    451   else
    452     gcc_unreachable ();
    453 })
    454 
    455 (define_expand "vcondu<mode><mode>"
    456   [(set (match_operand:VEC_I 0 "vint_operand")
    457 	(if_then_else:VEC_I
    458 	 (match_operator 3 "comparison_operator"
    459 			 [(match_operand:VEC_I 4 "vint_operand")
    460 			  (match_operand:VEC_I 5 "vint_operand")])
    461 	 (match_operand:VEC_I 1 "vector_int_reg_or_same_bit")
    462 	 (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))]
    463   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    464 {
    465   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    466 				    operands[3], operands[4], operands[5]))
    467     DONE;
    468   else
    469     gcc_unreachable ();
    470 })
    471 
    472 (define_expand "vconduv4sfv4si"
    473   [(set (match_operand:V4SF 0 "vfloat_operand")
    474 	(if_then_else:V4SF
    475 	 (match_operator 3 "comparison_operator"
    476 			 [(match_operand:V4SI 4 "vint_operand")
    477 			  (match_operand:V4SI 5 "vint_operand")])
    478 	 (match_operand:V4SF 1 "vfloat_operand")
    479 	 (match_operand:V4SF 2 "vfloat_operand")))]
    480   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
    481    && VECTOR_UNIT_ALTIVEC_P (V4SImode)"
    482 {
    483   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    484 				    operands[3], operands[4], operands[5]))
    485     DONE;
    486   else
    487     gcc_unreachable ();
    488 })
    489 
    490 (define_expand "vconduv2dfv2di"
    491   [(set (match_operand:V2DF 0 "vfloat_operand")
    492 	(if_then_else:V2DF
    493 	 (match_operator 3 "comparison_operator"
    494 			 [(match_operand:V2DI 4 "vint_operand")
    495 			  (match_operand:V2DI 5 "vint_operand")])
    496 	 (match_operand:V2DF 1 "vfloat_operand")
    497 	 (match_operand:V2DF 2 "vfloat_operand")))]
    498   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)
    499    && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)"
    500 {
    501   if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
    502 				    operands[3], operands[4], operands[5]))
    503     DONE;
    504   else
    505     gcc_unreachable ();
    506 })
    507 
    508 ;; To support vector condition vectorization, define vcond_mask and vec_cmp.
    509 
    510 ;; Same mode for condition true/false values and predicate operand.
    511 (define_expand "vcond_mask_<mode><mode>"
    512   [(match_operand:VEC_I 0 "vint_operand")
    513    (match_operand:VEC_I 1 "vint_operand")
    514    (match_operand:VEC_I 2 "vint_operand")
    515    (match_operand:VEC_I 3 "vint_operand")]
    516   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    517 {
    518   emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1],
    519 				  operands[3]));
    520   DONE;
    521 })
    522 
    523 ;; Condition true/false values are float but predicate operand is of
    524 ;; type integer vector with same element size.
    525 (define_expand "vcond_mask_<mode><VEC_int>"
    526   [(match_operand:VEC_F 0 "vfloat_operand")
    527    (match_operand:VEC_F 1 "vfloat_operand")
    528    (match_operand:VEC_F 2 "vfloat_operand")
    529    (match_operand:<VEC_INT> 3 "vint_operand")]
    530   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    531 {
    532   emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1],
    533 				  gen_lowpart (<MODE>mode, operands[3])));
    534   DONE;
    535 })
    536 
    537 ;; For signed integer vectors comparison.
    538 (define_expand "vec_cmp<mode><mode>"
    539   [(set (match_operand:VEC_I 0 "vint_operand")
    540 	(match_operator 1 "signed_or_equality_comparison_operator"
    541 	  [(match_operand:VEC_I 2 "vint_operand")
    542 	   (match_operand:VEC_I 3 "vint_operand")]))]
    543   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    544 {
    545   enum rtx_code code = GET_CODE (operands[1]);
    546   rtx tmp = gen_reg_rtx (<MODE>mode);
    547   switch (code)
    548     {
    549     case NE:
    550       emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3]));
    551       emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0]));
    552       break;
    553     case EQ:
    554       emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3]));
    555       break;
    556     case GE:
    557       emit_insn (gen_vector_nlt<mode> (operands[0],operands[2], operands[3],
    558 				       tmp));
    559       break;
    560     case GT:
    561       emit_insn (gen_vector_gt<mode> (operands[0], operands[2], operands[3]));
    562       break;
    563     case LE:
    564       emit_insn (gen_vector_ngt<mode> (operands[0], operands[2], operands[3],
    565 				       tmp));
    566       break;
    567     case LT:
    568       emit_insn (gen_vector_gt<mode> (operands[0], operands[3], operands[2]));
    569       break;
    570     default:
    571       gcc_unreachable ();
    572       break;
    573     }
    574   DONE;
    575 })
    576 
    577 ;; For unsigned integer vectors comparison.
    578 (define_expand "vec_cmpu<mode><mode>"
    579   [(set (match_operand:VEC_I 0 "vint_operand")
    580 	(match_operator 1 "unsigned_or_equality_comparison_operator"
    581 	  [(match_operand:VEC_I 2 "vint_operand")
    582 	   (match_operand:VEC_I 3 "vint_operand")]))]
    583   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    584 {
    585   enum rtx_code code = GET_CODE (operands[1]);
    586   rtx tmp = gen_reg_rtx (<MODE>mode);
    587   switch (code)
    588     {
    589     case NE:
    590       emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3]));
    591       emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0]));
    592       break;
    593     case EQ:
    594       emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3]));
    595       break;
    596     case GEU:
    597       emit_insn (gen_vector_nltu<mode> (operands[0], operands[2], operands[3],
    598 					tmp));
    599       break;
    600     case GTU:
    601       emit_insn (gen_vector_gtu<mode> (operands[0], operands[2], operands[3]));
    602       break;
    603     case LEU:
    604       emit_insn (gen_vector_ngtu<mode> (operands[0], operands[2], operands[3],
    605 					tmp));
    606       break;
    607     case LTU:
    608       emit_insn (gen_vector_gtu<mode> (operands[0], operands[3], operands[2]));
    609       break;
    610     default:
    611       gcc_unreachable ();
    612       break;
    613     }
    614   DONE;
    615 })
    616 
    617 ;; For float point vectors comparison.
    618 (define_expand "vec_cmp<mode><VEC_int>"
    619   [(set (match_operand:<VEC_INT> 0 "vint_operand")
    620 	 (match_operator 1 "comparison_operator"
    621 	    [(match_operand:VEC_F 2 "vfloat_operand")
    622 	    (match_operand:VEC_F 3 "vfloat_operand")]))]
    623   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    624 {
    625   enum rtx_code code = GET_CODE (operands[1]);
    626   rtx res = gen_reg_rtx (<MODE>mode);
    627   switch (code)
    628     {
    629     case NE:
    630       emit_insn (gen_vector_ne<mode> (res, operands[2], operands[3]));
    631       break;
    632     case EQ:
    633       emit_insn (gen_vector_eq<mode> (res, operands[2], operands[3]));
    634       break;
    635     case GE:
    636       emit_insn (gen_vector_ge<mode> (res, operands[2], operands[3]));
    637       break;
    638     case GT:
    639       emit_insn (gen_vector_gt<mode> (res, operands[2], operands[3]));
    640       break;
    641     case LE:
    642       emit_insn (gen_vector_le<mode> (res, operands[2], operands[3]));
    643       break;
    644     case LT:
    645       emit_insn (gen_vector_lt<mode> (res, operands[2], operands[3]));
    646       break;
    647     case LTGT:
    648       emit_insn (gen_vector_ltgt<mode> (res, operands[2], operands[3]));
    649       break;
    650     case UNORDERED:
    651       emit_insn (gen_vector_unordered<mode> (res, operands[2], operands[3]));
    652       break;
    653     case ORDERED:
    654       emit_insn (gen_vector_ordered<mode> (res, operands[2], operands[3]));
    655       break;
    656     case UNEQ:
    657       emit_insn (gen_vector_uneq<mode> (res, operands[2], operands[3]));
    658       break;
    659     case UNGE:
    660       emit_insn (gen_vector_unge<mode> (res, operands[2], operands[3]));
    661       break;
    662     case UNGT:
    663       emit_insn (gen_vector_ungt<mode> (res, operands[2], operands[3]));
    664       break;
    665     case UNLE:
    666       emit_insn (gen_vector_unle<mode> (res, operands[2], operands[3]));
    667       break;
    668     case UNLT:
    669       emit_insn (gen_vector_unlt<mode> (res, operands[2], operands[3]));
    670       break;
    671 
    672     default:
    673       gcc_unreachable ();
    674     }
    675 
    676   emit_insn (gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res)));
    677   DONE;
    678 })
    679 
    680 (define_expand "vector_eq<mode>"
    681   [(set (match_operand:VEC_C 0 "vlogical_operand")
    682 	(eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand")
    683 		  (match_operand:VEC_C 2 "vlogical_operand")))]
    684   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    685   "")
    686 
    687 (define_expand "vector_gt<mode>"
    688   [(set (match_operand:VEC_C 0 "vlogical_operand")
    689 	(gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand")
    690 		  (match_operand:VEC_C 2 "vlogical_operand")))]
    691   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    692   "")
    693 
    694 ; >= for integer vectors: swap operands and apply not-greater-than
    695 (define_expand "vector_nlt<mode>"
    696   [(set (match_operand:VEC_I 3 "vlogical_operand")
    697 	(gt:VEC_I (match_operand:VEC_I 2 "vlogical_operand")
    698 		  (match_operand:VEC_I 1 "vlogical_operand")))
    699    (set (match_operand:VEC_I 0 "vlogical_operand")
    700         (not:VEC_I (match_dup 3)))]
    701   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    702 {
    703   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
    704 })
    705 
    706 (define_expand "vector_nltv1ti"
    707   [(set (match_operand:V1TI 3 "vlogical_operand")
    708 	(gt:V1TI (match_operand:V1TI 2 "vlogical_operand")
    709 		 (match_operand:V1TI 1 "vlogical_operand")))
    710    (set (match_operand:V1TI 0 "vlogical_operand")
    711         (not:V1TI (match_dup 3)))]
    712   "TARGET_POWER10"
    713 {
    714   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
    715 })
    716 
    717 (define_expand "vector_gtu<mode>"
    718   [(set (match_operand:VEC_I 0 "vint_operand")
    719 	(gtu:VEC_I (match_operand:VEC_I 1 "vint_operand")
    720 		   (match_operand:VEC_I 2 "vint_operand")))]
    721   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    722   "")
    723 
    724 (define_expand "vector_gtuv1ti"
    725   [(set (match_operand:V1TI 0 "altivec_register_operand")
    726 	(gtu:V1TI (match_operand:V1TI 1 "altivec_register_operand")
    727 		  (match_operand:V1TI 2 "altivec_register_operand")))]
    728   "TARGET_POWER10"
    729   "")
    730 
    731 ; >= for integer vectors: swap operands and apply not-greater-than
    732 (define_expand "vector_nltu<mode>"
    733   [(set (match_operand:VEC_I 3 "vlogical_operand")
    734 	(gtu:VEC_I (match_operand:VEC_I 2 "vlogical_operand")
    735 	 	   (match_operand:VEC_I 1 "vlogical_operand")))
    736    (set (match_operand:VEC_I 0 "vlogical_operand")
    737         (not:VEC_I (match_dup 3)))]
    738   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    739 {
    740   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
    741 })
    742 
    743 (define_expand "vector_nltuv1ti"
    744   [(set (match_operand:V1TI 3 "vlogical_operand")
    745 	(gtu:V1TI (match_operand:V1TI 2 "vlogical_operand")
    746 		  (match_operand:V1TI 1 "vlogical_operand")))
    747    (set (match_operand:V1TI 0 "vlogical_operand")
    748 	(not:V1TI (match_dup 3)))]
    749   "TARGET_POWER10"
    750 {
    751   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
    752 })
    753 
    754 (define_expand "vector_geu<mode>"
    755   [(set (match_operand:VEC_I 0 "vint_operand")
    756 	(geu:VEC_I (match_operand:VEC_I 1 "vint_operand")
    757 		   (match_operand:VEC_I 2 "vint_operand")))]
    758   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    759   "")
    760 
    761 ; <= for integer vectors: apply not-greater-than
    762 (define_expand "vector_ngt<mode>"
    763   [(set (match_operand:VEC_I 3 "vlogical_operand")
    764 	(gt:VEC_I (match_operand:VEC_I 1 "vlogical_operand")
    765 		  (match_operand:VEC_I 2 "vlogical_operand")))
    766    (set (match_operand:VEC_I 0 "vlogical_operand")
    767         (not:VEC_I (match_dup 3)))]
    768   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    769 {
    770   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
    771 })
    772 
    773 (define_expand "vector_ngtv1ti"
    774   [(set (match_operand:V1TI 3 "vlogical_operand")
    775 	(gt:V1TI (match_operand:V1TI 1 "vlogical_operand")
    776 		 (match_operand:V1TI 2 "vlogical_operand")))
    777    (set (match_operand:V1TI 0 "vlogical_operand")
    778         (not:V1TI (match_dup 3)))]
    779   "TARGET_POWER10"
    780 {
    781   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
    782 })
    783 
    784 (define_expand "vector_ngtu<mode>"
    785   [(set (match_operand:VEC_I 3 "vlogical_operand")
    786 	(gtu:VEC_I (match_operand:VEC_I 1 "vlogical_operand")
    787 	 	   (match_operand:VEC_I 2 "vlogical_operand")))
    788    (set (match_operand:VEC_I 0 "vlogical_operand")
    789         (not:VEC_I (match_dup 3)))]
    790   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    791 {
    792   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
    793 })
    794 
    795 (define_expand "vector_ngtuv1ti"
    796   [(set (match_operand:V1TI 3 "vlogical_operand")
    797 	(gtu:V1TI (match_operand:V1TI 1 "vlogical_operand")
    798 		  (match_operand:V1TI 2 "vlogical_operand")))
    799    (set (match_operand:V1TI 0 "vlogical_operand")
    800         (not:V1TI (match_dup 3)))]
    801   "TARGET_POWER10"
    802 {
    803   operands[3] = gen_reg_rtx_and_attrs (operands[0]);
    804 })
    805 
    806 ; There are 14 possible vector FP comparison operators, gt and eq of them have
    807 ; been expanded above, so just support 12 remaining operators here.
    808 
    809 ; For ge:
    810 (define_expand "vector_ge<mode>"
    811   [(set (match_operand:VEC_F 0 "vlogical_operand")
    812 	(ge:VEC_F (match_operand:VEC_F 1 "vlogical_operand")
    813 		  (match_operand:VEC_F 2 "vlogical_operand")))]
    814   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    815   "")
    816 
    817 ; For lt/le/ne/ungt/unge/unlt/unle:
    818 ; lt(a,b)   = gt(b,a)
    819 ; le(a,b)   = ge(b,a)
    820 ; unge(a,b) = ~lt(a,b)
    821 ; unle(a,b) = ~gt(a,b)
    822 ; ne(a,b)   = ~eq(a,b)
    823 ; ungt(a,b) = ~le(a,b)
    824 ; unlt(a,b) = ~ge(a,b)
    825 (define_insn_and_split "vector_<code><mode>"
    826   [(set (match_operand:VEC_F 0 "vfloat_operand")
    827 	(vector_fp_comparison_simple:VEC_F
    828 	   (match_operand:VEC_F 1 "vfloat_operand")
    829 	   (match_operand:VEC_F 2 "vfloat_operand")))]
    830   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()"
    831   "#"
    832   "&& can_create_pseudo_p ()"
    833   [(pc)]
    834 {
    835   enum rtx_code cond = <CODE>;
    836   bool need_invert = false;
    837 
    838   if (cond == UNLE || cond == UNLT || cond == NE || cond == UNGE
    839       || cond == UNGT)
    840     {
    841       cond = reverse_condition_maybe_unordered (cond);
    842       need_invert = true;
    843     }
    844 
    845   if (cond == LT || cond == LE)
    846     {
    847       cond = swap_condition (cond);
    848       std::swap (operands[1], operands[2]);
    849     }
    850 
    851   gcc_assert (cond == EQ || cond == GE || cond == GT);
    852 
    853   rtx comp = gen_rtx_fmt_ee (cond, <MODE>mode, operands[1], operands[2]);
    854 
    855   if (need_invert)
    856     {
    857       rtx res = gen_reg_rtx (<MODE>mode);
    858       emit_insn (gen_rtx_SET (res, comp));
    859       emit_insn (gen_one_cmpl<mode>2 (operands[0], res));
    860     }
    861   else
    862     emit_insn (gen_rtx_SET (operands[0], comp));
    863 
    864   DONE;
    865 })
    866 
    867 ; For ltgt/uneq/ordered/unordered:
    868 ; ltgt: gt(a,b) | gt(b,a)
    869 ; uneq: ~(gt(a,b) | gt(b,a))
    870 ; ordered: ge(a,b) | ge(b,a)
    871 ; unordered: ~(ge(a,b) | ge(b,a))
    872 (define_insn_and_split "vector_<code><mode>"
    873   [(set (match_operand:VEC_F 0 "vfloat_operand")
    874 	(vector_fp_comparison_complex:VEC_F
    875 	   (match_operand:VEC_F 1 "vfloat_operand")
    876 	   (match_operand:VEC_F 2 "vfloat_operand")))]
    877   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()"
    878   "#"
    879   "&& can_create_pseudo_p ()"
    880   [(pc)]
    881 {
    882   enum rtx_code cond = <CODE>;
    883   bool need_invert = false;
    884 
    885   if (cond == UNORDERED || cond == UNEQ)
    886     {
    887       cond = reverse_condition_maybe_unordered (cond);
    888       need_invert = true;
    889     }
    890 
    891   if (cond == LTGT)
    892     cond = GT;
    893   else if (cond == ORDERED)
    894     cond = GE;
    895   else
    896     gcc_unreachable ();
    897 
    898   rtx comp1 = gen_rtx_fmt_ee (cond, <MODE>mode, operands[1], operands[2]);
    899   rtx res1 = gen_reg_rtx (<MODE>mode);
    900   emit_insn (gen_rtx_SET (res1, comp1));
    901   rtx comp2 = gen_rtx_fmt_ee (cond, <MODE>mode, operands[2], operands[1]);
    902   rtx res2 = gen_reg_rtx (<MODE>mode);
    903   emit_insn (gen_rtx_SET (res2, comp2));
    904 
    905   if (need_invert)
    906     {
    907       rtx not1 = gen_rtx_fmt_e (NOT, <MODE>mode, res1);
    908       rtx not2 = gen_rtx_fmt_e (NOT, <MODE>mode, res2);
    909       rtx comp3 = gen_rtx_fmt_ee (AND, <MODE>mode, not1, not2);
    910       emit_insn (gen_rtx_SET (operands[0], comp3));
    911     }
    912   else
    913     emit_insn (gen_ior<mode>3 (operands[0], res1, res2));
    914 
    915   DONE;
    916 })
    917 
    918 ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
    919 ;; which is in the reverse order that we want
    920 (define_expand "vector_select_<mode>"
    921   [(set (match_operand:VEC_L 0 "vlogical_operand")
    922 	(ior:VEC_L
    923 	  (and:VEC_L (not:VEC_L (match_operand:VEC_L 3 "vlogical_operand"))
    924 		     (match_operand:VEC_L 1 "vlogical_operand"))
    925 	  (and:VEC_L (match_dup 3)
    926 		     (match_operand:VEC_L 2 "vlogical_operand"))))]
    927   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)")
    928 
    929 (define_expand "vector_select_<mode>_uns"
    930   [(set (match_operand:VEC_L 0 "vlogical_operand")
    931 	(ior:VEC_L
    932 	  (and:VEC_L (not:VEC_L (match_operand:VEC_L 3 "vlogical_operand"))
    933 		     (match_operand:VEC_L 1 "vlogical_operand"))
    934 	  (and:VEC_L (match_dup 3)
    935 		     (match_operand:VEC_L 2 "vlogical_operand"))))]
    936   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)")
    937 
    938 ;; Expansions that compare vectors producing a vector result and a predicate,
    939 ;; setting CR6 to indicate a combined status
    940 (define_expand "vector_eq_<mode>_p"
    941   [(parallel
    942     [(set (reg:CC CR6_REGNO)
    943 	  (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand")
    944 			     (match_operand:VEC_A 2 "vlogical_operand"))]
    945 		     UNSPEC_PREDICATE))
    946      (set (match_operand:VEC_A 0 "vlogical_operand")
    947 	  (eq:VEC_A (match_dup 1)
    948 		    (match_dup 2)))])]
    949   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
    950   "")
    951 
    952 (define_expand "vector_eq_v1ti_p"
    953   [(parallel
    954     [(set (reg:CC CR6_REGNO)
    955 	  (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand")
    956 			     (match_operand:V1TI 2 "altivec_register_operand"))]
    957 		     UNSPEC_PREDICATE))
    958      (set (match_operand:V1TI 0 "vlogical_operand")
    959 	  (eq:V1TI (match_dup 1)
    960 		   (match_dup 2)))])]
    961   "TARGET_POWER10"
    962   "")
    963 
    964 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
    965 ;; implementation of the vec_all_ne built-in functions on Power9.
    966 (define_expand "vector_ne_<mode>_p"
    967   [(parallel
    968     [(set (reg:CC CR6_REGNO)
    969 	  (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand")
    970 			     (match_operand:VI 2 "vlogical_operand"))]
    971 	   UNSPEC_PREDICATE))
    972      (set (match_dup 3)
    973 	  (ne:VI (match_dup 1)
    974 		 (match_dup 2)))])
    975    (set (match_operand:SI 0 "register_operand" "=r")
    976 	(lt:SI (reg:CC CR6_REGNO)
    977 	       (const_int 0)))]
    978   "TARGET_P9_VECTOR"
    979 {
    980   operands[3] = gen_reg_rtx (<MODE>mode);
    981 })
    982 
    983 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
    984 ;; implementation of the vec_any_eq built-in functions on Power9.
    985 (define_expand "vector_ae_<mode>_p"
    986   [(parallel
    987     [(set (reg:CC CR6_REGNO)
    988 	  (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand")
    989 			     (match_operand:VI 2 "vlogical_operand"))]
    990 	   UNSPEC_PREDICATE))
    991      (set (match_dup 3)
    992 	  (ne:VI (match_dup 1)
    993 		 (match_dup 2)))])
    994    (set (match_operand:SI 0 "register_operand" "=r")
    995 	(lt:SI (reg:CC CR6_REGNO)
    996 	       (const_int 0)))
    997    (set (match_dup 0)
    998 	(xor:SI (match_dup 0)
    999 		(const_int 1)))]
   1000   "TARGET_P9_VECTOR"
   1001 {
   1002   operands[3] = gen_reg_rtx (<MODE>mode);
   1003 })
   1004 
   1005 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the
   1006 ;; implementation of the vec_all_nez and vec_any_eqz built-in
   1007 ;; functions on Power9.
   1008 (define_expand "vector_nez_<mode>_p"
   1009   [(parallel
   1010     [(set (reg:CC CR6_REGNO)
   1011 	  (unspec:CC [(unspec:VI
   1012 		       [(match_operand:VI 1 "vlogical_operand")
   1013 			(match_operand:VI 2 "vlogical_operand")]
   1014 		       UNSPEC_NEZ_P)]
   1015 	   UNSPEC_PREDICATE))
   1016      (set (match_operand:VI 0 "vlogical_operand")
   1017 	  (unspec:VI [(match_dup 1)
   1018 		      (match_dup 2)]
   1019 	   UNSPEC_NEZ_P))])]
   1020   "TARGET_P9_VECTOR"
   1021   "")
   1022 
   1023 ;; This expansion handles the V2DI mode in the implementation of the
   1024 ;; vec_all_ne built-in function on Power9.
   1025 ;;
   1026 ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode,
   1027 ;; this expands into the same rtl that would be used for the Power8
   1028 ;; architecture.
   1029 (define_expand "vector_ne_v2di_p"
   1030   [(parallel
   1031     [(set (reg:CC CR6_REGNO)
   1032 	  (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand")
   1033 			     (match_operand:V2DI 2 "vlogical_operand"))]
   1034 		     UNSPEC_PREDICATE))
   1035      (set (match_dup 3)
   1036 	  (eq:V2DI (match_dup 1)
   1037 		   (match_dup 2)))])
   1038    (set (match_operand:SI 0 "register_operand" "=r")
   1039 	(eq:SI (reg:CC CR6_REGNO)
   1040 	       (const_int 0)))]
   1041   "TARGET_P9_VECTOR"
   1042 {
   1043   operands[3] = gen_reg_rtx (V2DImode);
   1044 })
   1045 
   1046 (define_expand "vector_ne_v1ti_p"
   1047   [(parallel
   1048     [(set (reg:CC CR6_REGNO)
   1049 	  (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand")
   1050 			     (match_operand:V1TI 2 "altivec_register_operand"))]
   1051 		     UNSPEC_PREDICATE))
   1052      (set (match_dup 3)
   1053 	  (eq:V1TI (match_dup 1)
   1054 		   (match_dup 2)))])
   1055    (set (match_operand:SI 0 "register_operand" "=r")
   1056 	(eq:SI (reg:CC CR6_REGNO)
   1057 	       (const_int 0)))]
   1058   "TARGET_POWER10"
   1059 {
   1060   operands[3] = gen_reg_rtx (V1TImode);
   1061 })
   1062 
   1063 ;; This expansion handles the V2DI mode in the implementation of the
   1064 ;; vec_any_eq built-in function on Power9.
   1065 ;;
   1066 ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode,
   1067 ;; this expands into the same rtl that would be used for the Power8
   1068 ;; architecture.
   1069 (define_expand "vector_ae_v2di_p"
   1070   [(parallel
   1071     [(set (reg:CC CR6_REGNO)
   1072 	  (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand")
   1073 			     (match_operand:V2DI 2 "vlogical_operand"))]
   1074 		     UNSPEC_PREDICATE))
   1075      (set (match_dup 3)
   1076 	  (eq:V2DI (match_dup 1)
   1077 		   (match_dup 2)))])
   1078    (set (match_operand:SI 0 "register_operand" "=r")
   1079 	(eq:SI (reg:CC CR6_REGNO)
   1080 	       (const_int 0)))
   1081    (set (match_dup 0)
   1082 	(xor:SI (match_dup 0)
   1083 		(const_int 1)))]
   1084   "TARGET_P9_VECTOR"
   1085 {
   1086   operands[3] = gen_reg_rtx (V2DImode);
   1087 })
   1088 
   1089 (define_expand "vector_ae_v1ti_p"
   1090   [(parallel
   1091     [(set (reg:CC CR6_REGNO)
   1092 	  (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand")
   1093 			     (match_operand:V1TI 2 "altivec_register_operand"))]
   1094 		     UNSPEC_PREDICATE))
   1095      (set (match_dup 3)
   1096 	  (eq:V1TI (match_dup 1)
   1097 		   (match_dup 2)))])
   1098    (set (match_operand:SI 0 "register_operand" "=r")
   1099 	(eq:SI (reg:CC CR6_REGNO)
   1100 	       (const_int 0)))
   1101    (set (match_dup 0)
   1102 	(xor:SI (match_dup 0)
   1103 		(const_int 1)))]
   1104   "TARGET_POWER10"
   1105 {
   1106   operands[3] = gen_reg_rtx (V1TImode);
   1107 })
   1108 
   1109 ;; This expansion handles the V4SF and V2DF modes in the Power9
   1110 ;; implementation of the vec_all_ne built-in functions.  Note that the
   1111 ;; expansions for this pattern with these modes makes no use of power9-
   1112 ;; specific instructions since there are no new power9 instructions
   1113 ;; for vector compare not equal with floating point arguments.
   1114 (define_expand "vector_ne_<mode>_p"
   1115   [(parallel
   1116     [(set (reg:CC CR6_REGNO)
   1117 	  (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand")
   1118 			     (match_operand:VEC_F 2 "vlogical_operand"))]
   1119 		     UNSPEC_PREDICATE))
   1120      (set (match_dup 3)
   1121 	  (eq:VEC_F (match_dup 1)
   1122 		    (match_dup 2)))])
   1123    (set (match_operand:SI 0 "register_operand" "=r")
   1124 	(eq:SI (reg:CC CR6_REGNO)
   1125 	       (const_int 0)))]
   1126   "TARGET_P9_VECTOR"
   1127 {
   1128   operands[3] = gen_reg_rtx (<MODE>mode);
   1129 })
   1130 
   1131 ;; This expansion handles the V4SF and V2DF modes in the Power9
   1132 ;; implementation of the vec_any_eq built-in functions.  Note that the
   1133 ;; expansions for this pattern with these modes makes no use of power9-
   1134 ;; specific instructions since there are no new power9 instructions
   1135 ;; for vector compare not equal with floating point arguments.
   1136 (define_expand "vector_ae_<mode>_p"
   1137   [(parallel
   1138     [(set (reg:CC CR6_REGNO)
   1139 	  (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand")
   1140 			     (match_operand:VEC_F 2 "vlogical_operand"))]
   1141 		     UNSPEC_PREDICATE))
   1142      (set (match_dup 3)
   1143 	  (eq:VEC_F (match_dup 1)
   1144 		    (match_dup 2)))])
   1145    (set (match_operand:SI 0 "register_operand" "=r")
   1146 	(eq:SI (reg:CC CR6_REGNO)
   1147 	       (const_int 0)))
   1148    (set (match_dup 0)
   1149 	(xor:SI (match_dup 0)
   1150 		(const_int 1)))]
   1151   "TARGET_P9_VECTOR"
   1152 {
   1153   operands[3] = gen_reg_rtx (<MODE>mode);
   1154 })
   1155 
   1156 (define_expand "vector_gt_<mode>_p"
   1157   [(parallel
   1158     [(set (reg:CC CR6_REGNO)
   1159 	  (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand")
   1160 			     (match_operand:VEC_A 2 "vlogical_operand"))]
   1161 		     UNSPEC_PREDICATE))
   1162      (set (match_operand:VEC_A 0 "vlogical_operand")
   1163 	  (gt:VEC_A (match_dup 1)
   1164 		    (match_dup 2)))])]
   1165   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1166   "")
   1167 
   1168 (define_expand "vector_gt_v1ti_p"
   1169   [(parallel
   1170     [(set (reg:CC CR6_REGNO)
   1171 	  (unspec:CC [(gt:CC (match_operand:V1TI 1 "vlogical_operand")
   1172 			     (match_operand:V1TI 2 "vlogical_operand"))]
   1173 		     UNSPEC_PREDICATE))
   1174      (set (match_operand:V1TI 0 "vlogical_operand")
   1175 	  (gt:V1TI (match_dup 1)
   1176 		   (match_dup 2)))])]
   1177   "TARGET_POWER10"
   1178   "")
   1179 
   1180 (define_expand "vector_ge_<mode>_p"
   1181   [(parallel
   1182     [(set (reg:CC CR6_REGNO)
   1183 	  (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand")
   1184 			     (match_operand:VEC_F 2 "vfloat_operand"))]
   1185 		     UNSPEC_PREDICATE))
   1186      (set (match_operand:VEC_F 0 "vfloat_operand")
   1187 	  (ge:VEC_F (match_dup 1)
   1188 		    (match_dup 2)))])]
   1189   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1190   "")
   1191 
   1192 (define_expand "vector_gtu_<mode>_p"
   1193   [(parallel
   1194     [(set (reg:CC CR6_REGNO)
   1195 	  (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand")
   1196 			      (match_operand:VEC_I 2 "vint_operand"))]
   1197 		     UNSPEC_PREDICATE))
   1198      (set (match_operand:VEC_I 0 "vlogical_operand")
   1199 	  (gtu:VEC_I (match_dup 1)
   1200 		     (match_dup 2)))])]
   1201   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1202   "")
   1203 
   1204 (define_expand "vector_gtu_v1ti_p"
   1205   [(parallel
   1206     [(set (reg:CC CR6_REGNO)
   1207 	  (unspec:CC [(gtu:CC (match_operand:V1TI 1 "altivec_register_operand")
   1208 			      (match_operand:V1TI 2 "altivec_register_operand"))]
   1209 		     UNSPEC_PREDICATE))
   1210      (set (match_operand:V1TI 0 "altivec_register_operand")
   1211 	  (gtu:V1TI (match_dup 1)
   1212 		    (match_dup 2)))])]
   1213   "TARGET_POWER10"
   1214   "")
   1215 
   1216 ;; AltiVec/VSX predicates.
   1217 
   1218 ;; This expansion is triggered during expansion of predicate built-in
   1219 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
   1220 ;; altivec_expand_predicate_builtin() function when the value of the
   1221 ;; integer constant first argument equals zero (aka __CR6_EQ in altivec.h).
   1222 (define_expand "cr6_test_for_zero"
   1223   [(set (match_operand:SI 0 "register_operand" "=r")
   1224 	(eq:SI (reg:CC CR6_REGNO)
   1225 	       (const_int 0)))]
   1226   "TARGET_ALTIVEC || TARGET_VSX"
   1227   "")
   1228 
   1229 ;; This expansion is triggered during expansion of predicate built-in
   1230 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
   1231 ;; altivec_expand_predicate_builtin() function when the value of the
   1232 ;; integer constant first argument equals one (aka __CR6_EQ_REV in altivec.h).
   1233 (define_expand "cr6_test_for_zero_reverse"
   1234   [(set (match_operand:SI 0 "register_operand" "=r")
   1235 	(eq:SI (reg:CC CR6_REGNO)
   1236 	       (const_int 0)))
   1237    (set (match_dup 0)
   1238 	(xor:SI (match_dup 0)
   1239 		(const_int 1)))]
   1240   "TARGET_ALTIVEC || TARGET_VSX"
   1241   "")
   1242 
   1243 ;; This expansion is triggered during expansion of predicate built-in
   1244 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
   1245 ;; altivec_expand_predicate_builtin() function when the value of the
   1246 ;; integer constant first argument equals two (aka __CR6_LT in altivec.h).
   1247 (define_expand "cr6_test_for_lt"
   1248   [(set (match_operand:SI 0 "register_operand" "=r")
   1249 	(lt:SI (reg:CC CR6_REGNO)
   1250 	       (const_int 0)))]
   1251   "TARGET_ALTIVEC || TARGET_VSX"
   1252   "")
   1253 
   1254 ;; This expansion is triggered during expansion of predicate built-in
   1255 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the
   1256 ;; altivec_expand_predicate_builtin() function when the value of the
   1257 ;; integer constant first argument equals three
   1258 ;; (aka __CR6_LT_REV in altivec.h).
   1259 (define_expand "cr6_test_for_lt_reverse"
   1260   [(set (match_operand:SI 0 "register_operand" "=r")
   1261 	(lt:SI (reg:CC CR6_REGNO)
   1262 	       (const_int 0)))
   1263    (set (match_dup 0)
   1264 	(xor:SI (match_dup 0)
   1265 		(const_int 1)))]
   1266   "TARGET_ALTIVEC || TARGET_VSX"
   1267   "")
   1268 
   1269 
   1271 ;; Vector count leading zeros
   1272 (define_expand "clz<mode>2"
   1273   [(set (match_operand:VEC_I 0 "register_operand")
   1274 	(clz:VEC_I (match_operand:VEC_I 1 "register_operand")))]
   1275   "TARGET_P8_VECTOR")
   1276 
   1277 ;; Vector count trailing zeros
   1278 (define_expand "ctz<mode>2"
   1279   [(set (match_operand:VEC_I 0 "register_operand")
   1280 	(ctz:VEC_I (match_operand:VEC_I 1 "register_operand")))]
   1281   "TARGET_P9_VECTOR")
   1282 
   1283 ;; Vector population count
   1284 (define_expand "popcount<mode>2"
   1285   [(set (match_operand:VEC_I 0 "register_operand")
   1286         (popcount:VEC_I (match_operand:VEC_I 1 "register_operand")))]
   1287   "TARGET_P8_VECTOR")
   1288 
   1289 ;; Vector parity
   1290 (define_expand "parity<mode>2"
   1291   [(set (match_operand:VEC_IP 0 "register_operand")
   1292 	(parity:VEC_IP (match_operand:VEC_IP 1 "register_operand")))]
   1293   "TARGET_P9_VECTOR"
   1294 {
   1295   rtx op1 = gen_lowpart (V16QImode, operands[1]);
   1296   rtx res = gen_reg_rtx (V16QImode);
   1297   emit_insn (gen_popcountv16qi2 (res, op1));
   1298   emit_insn (gen_rs6000_vprtyb<mode>2 (operands[0],
   1299 				       gen_lowpart (<MODE>mode, res)));
   1300 
   1301   DONE;
   1302 })
   1303 
   1304 
   1306 ;; Same size conversions
   1307 (define_expand "float<VEC_int><mode>2"
   1308   [(set (match_operand:VEC_F 0 "vfloat_operand")
   1309 	(float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))]
   1310   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1311 {
   1312   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
   1313     {
   1314       emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx));
   1315       DONE;
   1316     }
   1317 })
   1318 
   1319 (define_expand "floatuns<VEC_int><mode>2"
   1320   [(set (match_operand:VEC_F 0 "vfloat_operand")
   1321 	(unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))]
   1322   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1323 {
   1324   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
   1325     {
   1326       emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx));
   1327       DONE;
   1328     }
   1329 })
   1330 
   1331 (define_expand "fix_trunc<mode><VEC_int>2"
   1332   [(set (match_operand:<VEC_INT> 0 "vint_operand")
   1333 	(fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))]
   1334   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1335 {
   1336   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
   1337     {
   1338       emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx));
   1339       DONE;
   1340     }
   1341 })
   1342 
   1343 (define_expand "fixuns_trunc<mode><VEC_int>2"
   1344   [(set (match_operand:<VEC_INT> 0 "vint_operand")
   1345 	(unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))]
   1346   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1347 {
   1348   if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode))
   1349     {
   1350       emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx));
   1351       DONE;
   1352     }
   1353 })
   1354 
   1355 
   1357 ;; Vector initialization, set, extract
   1358 (define_expand "vec_init<mode><VEC_base_l>"
   1359   [(match_operand:VEC_E 0 "vlogical_operand")
   1360    (match_operand:VEC_E 1 "")]
   1361   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1362 {
   1363   rs6000_expand_vector_init (operands[0], operands[1]);
   1364   DONE;
   1365 })
   1366 
   1367 (define_expand "vec_set<mode>"
   1368   [(match_operand:VEC_E 0 "vlogical_operand")
   1369    (match_operand:<VEC_base> 1 "register_operand")
   1370    (match_operand 2 "vec_set_index_operand")]
   1371   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1372 {
   1373   rs6000_expand_vector_set (operands[0], operands[1], operands[2]);
   1374   DONE;
   1375 })
   1376 
   1377 (define_expand "vec_extract<mode><VEC_base_l>"
   1378   [(match_operand:<VEC_base> 0 "register_operand")
   1379    (match_operand:VEC_E 1 "vlogical_operand")
   1380    (match_operand 2 "const_int_operand")]
   1381   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1382 {
   1383   rs6000_expand_vector_extract (operands[0], operands[1], operands[2]);
   1384   DONE;
   1385 })
   1386 
   1388 ;; Convert double word types to single word types
   1389 (define_expand "vec_pack_trunc_v2df"
   1390   [(match_operand:V4SF 0 "vfloat_operand")
   1391    (match_operand:V2DF 1 "vfloat_operand")
   1392    (match_operand:V2DF 2 "vfloat_operand")]
   1393   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
   1394 {
   1395   rtx r1 = gen_reg_rtx (V4SFmode);
   1396   rtx r2 = gen_reg_rtx (V4SFmode);
   1397 
   1398   emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
   1399   emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
   1400   rs6000_expand_extract_even (operands[0], r1, r2);
   1401   DONE;
   1402 })
   1403 
   1404 (define_expand "vec_pack_sfix_trunc_v2df"
   1405   [(match_operand:V4SI 0 "vint_operand")
   1406    (match_operand:V2DF 1 "vfloat_operand")
   1407    (match_operand:V2DF 2 "vfloat_operand")]
   1408   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
   1409 {
   1410   rtx r1 = gen_reg_rtx (V4SImode);
   1411   rtx r2 = gen_reg_rtx (V4SImode);
   1412 
   1413   emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
   1414   emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
   1415   rs6000_expand_extract_even (operands[0], r1, r2);
   1416   DONE;
   1417 })
   1418 
   1419 (define_expand "vec_pack_ufix_trunc_v2df"
   1420   [(match_operand:V4SI 0 "vint_operand")
   1421    (match_operand:V2DF 1 "vfloat_operand")
   1422    (match_operand:V2DF 2 "vfloat_operand")]
   1423   "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
   1424 {
   1425   rtx r1 = gen_reg_rtx (V4SImode);
   1426   rtx r2 = gen_reg_rtx (V4SImode);
   1427 
   1428   emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
   1429   emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
   1430   rs6000_expand_extract_even (operands[0], r1, r2);
   1431   DONE;
   1432 })
   1433 
   1434 ;; Convert single word types to double word
   1435 (define_expand "vec_unpacks_hi_v4sf"
   1436   [(match_operand:V2DF 0 "vfloat_operand")
   1437    (match_operand:V4SF 1 "vfloat_operand")]
   1438   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
   1439 {
   1440   rtx reg = gen_reg_rtx (V4SFmode);
   1441 
   1442   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
   1443   emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
   1444   DONE;
   1445 })
   1446 
   1447 (define_expand "vec_unpacks_lo_v4sf"
   1448   [(match_operand:V2DF 0 "vfloat_operand")
   1449    (match_operand:V4SF 1 "vfloat_operand")]
   1450   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
   1451 {
   1452   rtx reg = gen_reg_rtx (V4SFmode);
   1453 
   1454   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
   1455   emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
   1456   DONE;
   1457 })
   1458 
   1459 (define_expand "vec_unpacks_float_hi_v4si"
   1460   [(match_operand:V2DF 0 "vfloat_operand")
   1461    (match_operand:V4SI 1 "vint_operand")]
   1462   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
   1463 {
   1464   rtx reg = gen_reg_rtx (V4SImode);
   1465 
   1466   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
   1467   emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
   1468   DONE;
   1469 })
   1470 
   1471 (define_expand "vec_unpacks_float_lo_v4si"
   1472   [(match_operand:V2DF 0 "vfloat_operand")
   1473    (match_operand:V4SI 1 "vint_operand")]
   1474   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
   1475 {
   1476   rtx reg = gen_reg_rtx (V4SImode);
   1477 
   1478   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
   1479   emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
   1480   DONE;
   1481 })
   1482 
   1483 (define_expand "vec_unpacku_float_hi_v4si"
   1484   [(match_operand:V2DF 0 "vfloat_operand")
   1485    (match_operand:V4SI 1 "vint_operand")]
   1486   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
   1487 {
   1488   rtx reg = gen_reg_rtx (V4SImode);
   1489 
   1490   rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
   1491   emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
   1492   DONE;
   1493 })
   1494 
   1495 (define_expand "vec_unpacku_float_lo_v4si"
   1496   [(match_operand:V2DF 0 "vfloat_operand")
   1497    (match_operand:V4SI 1 "vint_operand")]
   1498   "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
   1499 {
   1500   rtx reg = gen_reg_rtx (V4SImode);
   1501 
   1502   rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
   1503   emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
   1504   DONE;
   1505 })
   1506 
   1507 
   1509 ;; Align vector loads with a permute.
   1510 (define_expand "vec_realign_load_<mode>"
   1511   [(match_operand:VEC_K 0 "vlogical_operand")
   1512    (match_operand:VEC_K 1 "vlogical_operand")
   1513    (match_operand:VEC_K 2 "vlogical_operand")
   1514    (match_operand:V16QI 3 "vlogical_operand")]
   1515   "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1516 {
   1517   if (BYTES_BIG_ENDIAN)
   1518     emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
   1519     	      				 operands[2], operands[3]));
   1520   else
   1521     {
   1522       /* We have changed lvsr to lvsl, so to complete the transformation
   1523          of vperm for LE, we must swap the inputs.  */
   1524       rtx unspec = gen_rtx_UNSPEC (<MODE>mode,
   1525                                    gen_rtvec (3, operands[2],
   1526                                               operands[1], operands[3]),
   1527                                    UNSPEC_VPERM);
   1528       emit_move_insn (operands[0], unspec);
   1529     }
   1530   DONE;
   1531 })
   1532 
   1533 ;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned
   1534 ;; since the load already handles it.
   1535 (define_expand "movmisalign<mode>"
   1536  [(set (match_operand:VEC_N 0 "nonimmediate_operand")
   1537        (match_operand:VEC_N 1 "any_operand"))]
   1538  "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN"
   1539 {
   1540   rs6000_emit_move (operands[0], operands[1], <MODE>mode);
   1541   DONE;
   1542 })
   1543 
   1544 ;; Vector shift right in bits. Currently supported ony for shift
   1545 ;; amounts that can be expressed as byte shifts (divisible by 8).
   1546 ;; General shift amounts can be supported using vsro + vsr. We're
   1547 ;; not expecting to see these yet (the vectorizer currently
   1548 ;; generates only shifts by a whole number of vector elements).
   1549 ;; Note that the vec_shr operation is actually defined as 
   1550 ;; 'shift toward element 0' so is a shr for LE and shl for BE.
   1551 (define_expand "vec_shr_<mode>"
   1552   [(match_operand:VEC_L 0 "vlogical_operand")
   1553    (match_operand:VEC_L 1 "vlogical_operand")
   1554    (match_operand:QI 2 "reg_or_short_operand")]
   1555   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1556 {
   1557   rtx bitshift = operands[2];
   1558   rtx shift;
   1559   rtx insn;
   1560   rtx zero_reg, op1, op2;
   1561   HOST_WIDE_INT bitshift_val;
   1562   HOST_WIDE_INT byteshift_val;
   1563 
   1564   if (! CONSTANT_P (bitshift))
   1565     FAIL;
   1566   bitshift_val = INTVAL (bitshift);
   1567   if (bitshift_val & 0x7)
   1568     FAIL;
   1569   byteshift_val = (bitshift_val >> 3);
   1570   zero_reg = gen_reg_rtx (<MODE>mode);
   1571   emit_move_insn (zero_reg, CONST0_RTX (<MODE>mode));
   1572   if (!BYTES_BIG_ENDIAN)
   1573     {
   1574       /* Note, byteshift_val can be 0!  */
   1575       byteshift_val = -byteshift_val & 15;
   1576       op1 = zero_reg;
   1577       op2 = operands[1];
   1578     }
   1579   else
   1580     {
   1581       op1 = operands[1];
   1582       op2 = zero_reg;
   1583     }
   1584 
   1585   if (TARGET_VSX && (byteshift_val & 0x3) == 0)
   1586     {
   1587       shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2);
   1588       insn = gen_vsx_xxsldwi_<mode> (operands[0], op1, op2, shift);
   1589     }
   1590   else
   1591     {
   1592       shift = gen_rtx_CONST_INT (QImode, byteshift_val);
   1593       insn = gen_altivec_vsldoi_<mode> (operands[0], op1, op2, shift);
   1594     }
   1595 
   1596   emit_insn (insn);
   1597   DONE;
   1598 })
   1599 
   1600 ;; Expanders for rotate each element in a vector
   1601 (define_expand "vrotl<mode>3"
   1602   [(set (match_operand:VEC_I 0 "vint_operand")
   1603 	(rotate:VEC_I (match_operand:VEC_I 1 "vint_operand")
   1604 		      (match_operand:VEC_I 2 "vint_operand")))]
   1605   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1606   "")
   1607 
   1608 (define_expand "vrotlv1ti3"
   1609   [(set (match_operand:V1TI 0 "vsx_register_operand" "=v")
   1610         (rotate:V1TI (match_operand:V1TI 1 "vsx_register_operand" "v")
   1611                      (match_operand:V1TI 2 "vsx_register_operand" "v")))]
   1612   "TARGET_POWER10"
   1613 {
   1614   /* Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */
   1615   rtx tmp = gen_reg_rtx (V1TImode);
   1616 
   1617   emit_insn (gen_xxswapd_v1ti (tmp, operands[2]));
   1618   emit_insn (gen_altivec_vrlq (operands[0], operands[1], tmp));
   1619   DONE;
   1620 })
   1621 
   1622 ;; Expanders for rotatert to make use of vrotl
   1623 (define_expand "vrotr<mode>3"
   1624   [(set (match_operand:VEC_I 0 "vint_operand")
   1625 	(rotatert:VEC_I (match_operand:VEC_I 1 "vint_operand")
   1626 		(match_operand:VEC_I 2 "vint_operand")))]
   1627   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1628 {
   1629   rtx rot_count = gen_reg_rtx (<MODE>mode);
   1630   emit_insn (gen_neg<mode>2 (rot_count, operands[2]));
   1631   emit_insn (gen_vrotl<mode>3 (operands[0], operands[1], rot_count));
   1632   DONE;
   1633 })
   1634 
   1635 ;; Expanders for arithmetic shift left on each vector element
   1636 (define_expand "vashl<mode>3"
   1637   [(set (match_operand:VEC_I 0 "vint_operand")
   1638 	(ashift:VEC_I (match_operand:VEC_I 1 "vint_operand")
   1639 		      (match_operand:VEC_I 2 "vint_operand")))]
   1640   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1641   "")
   1642 
   1643 ;; No immediate version of this 128-bit instruction
   1644 (define_expand "vashl<mode>3"
   1645   [(set (match_operand:VEC_TI 0 "vsx_register_operand" "=v")
   1646 	(ashift:VEC_TI (match_operand:VEC_TI 1 "vsx_register_operand")
   1647 			 (match_operand:VEC_TI 2 "vsx_register_operand")))]
   1648   "TARGET_POWER10"
   1649 {
   1650   /* Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */
   1651   rtx tmp = gen_reg_rtx (<MODE>mode);
   1652 
   1653   emit_insn (gen_xxswapd_v1ti (tmp, operands[2]));
   1654   emit_insn(gen_altivec_vslq_<mode> (operands[0], operands[1], tmp));
   1655   DONE;
   1656 })
   1657 
   1658 ;; Expanders for logical shift right on each vector element
   1659 (define_expand "vlshr<mode>3"
   1660   [(set (match_operand:VEC_I 0 "vint_operand")
   1661 	(lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand")
   1662 			(match_operand:VEC_I 2 "vint_operand")))]
   1663   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1664   "")
   1665 
   1666 ;; No immediate version of this 128-bit instruction
   1667 (define_expand "vlshr<mode>3"
   1668   [(set (match_operand:VEC_TI 0 "vsx_register_operand" "=v")
   1669 	(lshiftrt:VEC_TI (match_operand:VEC_TI 1 "vsx_register_operand")
   1670 			   (match_operand:VEC_TI 2 "vsx_register_operand")))]
   1671   "TARGET_POWER10"
   1672 {
   1673   /* Shift amount in needs to be put into bits[57:63] of 128-bit operand2. */
   1674   rtx tmp = gen_reg_rtx (<MODE>mode);
   1675 
   1676   emit_insn (gen_xxswapd_v1ti (tmp, operands[2]));
   1677   emit_insn(gen_altivec_vsrq_<mode> (operands[0], operands[1], tmp));
   1678   DONE;
   1679 })
   1680 
   1681 ;; Expanders for arithmetic shift right on each vector element
   1682 (define_expand "vashr<mode>3"
   1683   [(set (match_operand:VEC_I 0 "vint_operand")
   1684 	(ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand")
   1685 			(match_operand:VEC_I 2 "vint_operand")))]
   1686   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   1687   "")
   1688 
   1689 ;; No immediate version of this 128-bit instruction
   1690 (define_expand "vashrv1ti3"
   1691   [(set (match_operand:V1TI 0 "vsx_register_operand" "=v")
   1692 	(ashiftrt:V1TI (match_operand:V1TI 1 "vsx_register_operand" "v")
   1693 		       (match_operand:V1TI 2 "vsx_register_operand" "v")))]
   1694   "TARGET_POWER10"
   1695 {
   1696   /* Shift amount in needs to be put into bits[57:63] of 128-bit operand2. */
   1697   rtx tmp = gen_reg_rtx (V1TImode);
   1698 
   1699   emit_insn (gen_xxswapd_v1ti (tmp, operands[2]));
   1700   emit_insn (gen_altivec_vsraq (operands[0], operands[1], tmp));
   1701   DONE;
   1702 })
   1703 
   1704 
   1706 ;; Vector reduction expanders for VSX
   1707 ; The (VEC_reduc:...
   1708 ;	(op1)
   1709 ;	(unspec:... [(const_int 0)] UNSPEC_REDUC))
   1710 ;
   1711 ; is to allow us to use a code iterator, but not completely list all of the
   1712 ; vector rotates, etc. to prevent canonicalization
   1713 
   1714 
   1715 (define_expand "reduc_<VEC_reduc:VEC_reduc_name>_scal_<VEC_F:mode>"
   1716   [(match_operand:<VEC_base> 0 "register_operand")
   1717    (VEC_reduc:VEC_F (match_operand:VEC_F 1 "vfloat_operand")
   1718 		    (unspec:VEC_F [(const_int 0)] UNSPEC_REDUC))]
   1719   "VECTOR_UNIT_VSX_P (<VEC_F:MODE>mode)"
   1720   {
   1721     rtx vec = gen_reg_rtx (<VEC_F:MODE>mode);
   1722     rtx elt = BYTES_BIG_ENDIAN
   1723 		? gen_int_mode (GET_MODE_NUNITS (<VEC_F:MODE>mode) - 1, QImode)
   1724 		: const0_rtx;
   1725     emit_insn (gen_vsx_reduc_<VEC_reduc:VEC_reduc_name>_<VEC_F:mode> (vec,
   1726 	operand1));
   1727     emit_insn (gen_vsx_extract_<VEC_F:mode> (operand0, vec, elt));
   1728     DONE;
   1729   })
   1730