[power7-meissner, committed] Make vector unsigned builtins type correct

Michael Meissner meissner@linux.vnet.ibm.com
Thu Apr 30 20:59:00 GMT 2009


I spent some fixing up the builtin functions so that the internal tree is type
correct, and survives the gimple type checking that was just enabled.  It
doesn't fix all of the bugs that type checking has found, but this patch
reduces the vectorization failures by about 20 cases.

Because this patch depends on all of the infrastructure I've developed for the
power7, it will not apply at all to the mainline.  The power7 stuff is ready
for submission, so I will not be back porting these changes to the mainline,
unless it appears it will take awhile to get the total power7 patches approved
(for example if a condition of the slush being lifted is that the power
regressions go away).

I will be putting a call for other powerpc users to try my branch to make sure
I haven't broken things in parts of the compiler I don't test on the gcc
mailing list shortly.

-- 
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
meissner@linux.vnet.ibm.com
-------------- next part --------------
[gcc]
2009-04-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/vector.md (vector_select_<mode>): Rename from
	vector_vsel_<mode>.  Use mode of CCmode on the NE operator.
	(vector_select_<mode>_uns): Clone vector_select_<mode> for
	unsigned types.

	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Map both of
	the A and M types of multiply/add builtins to the internal name
	without either A/M, since the compiler will pick the appropriate
	instruction based on the registers allocated.

	* config/rs6000/rs6000.c (builtin_mode_to_type): Add support for
	unsigned types.
	(struct builtin_hash_struct): Ditto.
	(rs6000_init_builtins): Ditto.
	(builtin_hash_function): Ditto.
	(builtin_hash_eq): Ditto.
	(builtin_function_type): Add an argument for the builtin function
	code.  For functions that take or produce unsigned types, use an
	unsigned type instead of a signed types to make things type
	correct.  Change callers.
	(rs6000_builtin_vec_perm): Add support for unsigned vector permute
	functions.
	(bdesc_3arg): Ditto.
	(rs6000_emit_vector_cond): Ditto.

	* config/rs6000/vsx.md (vsx_xxsel<mode>): Make NE operator have
	CCmode mode.
	(vsx_xxsel<mode>_uns): Clone vsx_xxsel<mode> to make unsigned
	varients.

	* config/rs6000/rs6000.h (ALTIVEC_BUILTIN_VSEL*): Add unsigned
	variants.
	(ALTIVEC_BUILTIN_VPERM*): Ditto.
	(VSX_BUILTIN_XXSEL*): Ditto.
	(VSX_BUILTIN_VPERM*): Ditto.

	* config/rs6000/altivec.md (UNSPEC_VPERM_UNS): New unspec constant.
	(altivec_vsel<mode>): Use CCmode for NE mode.
	(altivec_vsel<mode>_uns): Clone from altivec_vsel<mode> for
	unsigned types.
	(altivec_vperm<mode>_uns): New insn for vperm on unsigned types.

[gcc/testsuite]
2009-04-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/vsx-builtin-3.c (do_perm): Fixup calls to the
	vperm builtin to always use a vector of unsigned char for the mask.

Index: gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c	(revision 146915)
+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c	(working copy)
@@ -82,11 +82,11 @@ int do_perm(void)
 {
   int i = 0;
 
-  si[i][0] = __builtin_vsx_vperm_4si (si[i][1], si[i][2], sc[i][3]); i++;
-  ss[i][0] = __builtin_vsx_vperm_8hi (ss[i][1], ss[i][2], sc[i][3]); i++;
-  sc[i][0] = __builtin_vsx_vperm_16qi (sc[i][1], sc[i][2], sc[i][3]); i++;
-  f[i][0] = __builtin_vsx_vperm_4sf (f[i][1], f[i][2], sc[i][3]); i++;
-  d[i][0] = __builtin_vsx_vperm_2df (d[i][1], d[i][2], sc[i][3]); i++;
+  si[i][0] = __builtin_vsx_vperm_4si (si[i][1], si[i][2], uc[i][3]); i++;
+  ss[i][0] = __builtin_vsx_vperm_8hi (ss[i][1], ss[i][2], uc[i][3]); i++;
+  sc[i][0] = __builtin_vsx_vperm_16qi (sc[i][1], sc[i][2], uc[i][3]); i++;
+  f[i][0] = __builtin_vsx_vperm_4sf (f[i][1], f[i][2], uc[i][3]); i++;
+  d[i][0] = __builtin_vsx_vperm_2df (d[i][1], d[i][2], uc[i][3]); i++;
 
   si[i][0] = __builtin_vsx_vperm (si[i][1], si[i][2], uc[i][3]); i++;
   ss[i][0] = __builtin_vsx_vperm (ss[i][1], ss[i][2], uc[i][3]); i++;
Index: gcc/config/rs6000/vector.md
===================================================================
--- gcc/config/rs6000/vector.md	(revision 146915)
+++ gcc/config/rs6000/vector.md	(working copy)
@@ -357,12 +357,23 @@
 
 ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
 ;; which is in the reverse order that we want
-(define_expand "vector_vsel<mode>"
+(define_expand "vector_select_<mode>"
   [(set (match_operand:VEC_L 0 "vlogical_operand" "")
-	(if_then_else:VEC_L (ne (match_operand:VEC_L 3 "vlogical_operand" "")
-				(const_int 0))
-			    (match_operand:VEC_L 2 "vlogical_operand" "")
-			    (match_operand:VEC_L 1 "vlogical_operand" "")))]
+	(if_then_else:VEC_L
+	 (ne:CC (match_operand:VEC_L 3 "vlogical_operand" "")
+		(const_int 0))
+	 (match_operand:VEC_L 2 "vlogical_operand" "")
+	 (match_operand:VEC_L 1 "vlogical_operand" "")))]
+  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
+  "")
+
+(define_expand "vector_select_<mode>_uns"
+  [(set (match_operand:VEC_L 0 "vlogical_operand" "")
+	(if_then_else:VEC_L
+	 (ne:CCUNS (match_operand:VEC_L 3 "vlogical_operand" "")
+		   (const_int 0))
+	 (match_operand:VEC_L 2 "vlogical_operand" "")
+	 (match_operand:VEC_L 1 "vlogical_operand" "")))]
   "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
   "")
 
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 146916)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -349,6 +349,25 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
       builtin_define ("__builtin_vsx_xxlxor=__builtin_vec_xor");
       builtin_define ("__builtin_vsx_xxsel=__builtin_vec_sel");
       builtin_define ("__builtin_vsx_vperm=__builtin_vec_perm");
+
+      /* Also map the a and m versions of the multiply/add instructions to the
+	 builtin for people blindly going off the instruction manual.  */
+      builtin_define ("__builtin_vsx_xvmaddadp=__builtin_vsx_xvmadddp");
+      builtin_define ("__builtin_vsx_xvmaddmdp=__builtin_vsx_xvmadddp");
+      builtin_define ("__builtin_vsx_xvmaddasp=__builtin_vsx_xvmaddsp");
+      builtin_define ("__builtin_vsx_xvmaddmsp=__builtin_vsx_xvmaddsp");
+      builtin_define ("__builtin_vsx_xvmsubadp=__builtin_vsx_xvmsubdp");
+      builtin_define ("__builtin_vsx_xvmsubmdp=__builtin_vsx_xvmsubdp");
+      builtin_define ("__builtin_vsx_xvmsubasp=__builtin_vsx_xvmsubsp");
+      builtin_define ("__builtin_vsx_xvmsubmsp=__builtin_vsx_xvmsubsp");
+      builtin_define ("__builtin_vsx_xvnmaddadp=__builtin_vsx_xvnmadddp");
+      builtin_define ("__builtin_vsx_xvnmaddmdp=__builtin_vsx_xvnmadddp");
+      builtin_define ("__builtin_vsx_xvnmaddasp=__builtin_vsx_xvnmaddsp");
+      builtin_define ("__builtin_vsx_xvnmaddmsp=__builtin_vsx_xvnmaddsp");
+      builtin_define ("__builtin_vsx_xvnmsubadp=__builtin_vsx_xvnmsubdp");
+      builtin_define ("__builtin_vsx_xvnmsubmdp=__builtin_vsx_xvnmsubdp");
+      builtin_define ("__builtin_vsx_xvnmsubasp=__builtin_vsx_xvnmsubsp");
+      builtin_define ("__builtin_vsx_xvnmsubmsp=__builtin_vsx_xvnmsubsp");
     }
 
   /* May be overridden by target configuration.  */
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 146916)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -311,7 +311,7 @@ int rs6000_vector_align[NUM_MACHINE_MODE
 enum reg_class rs6000_vsx_reg_class = NO_REGS;
 
 /* Map selected modes to types for builtins.  */
-static tree builtin_mode_to_type[MAX_MACHINE_MODE];
+static tree builtin_mode_to_type[MAX_MACHINE_MODE][2];
 
 /* Target cpu costs.  */
 
@@ -925,7 +925,7 @@ static unsigned builtin_hash_function (c
 static int builtin_hash_eq (const void *, const void *);
 static tree builtin_function_type (enum machine_mode, enum machine_mode,
 				   enum machine_mode, enum machine_mode,
-				   const char *name);
+				   enum rs6000_builtins, const char *name);
 static void rs6000_common_init_builtins (void);
 static void rs6000_init_libfuncs (void);
 
@@ -1047,7 +1047,8 @@ static GTY ((param_is (struct toc_hash_s
 struct GTY(()) builtin_hash_struct
 {
   tree type;
-  enum machine_mode mode[4];	/* return value + 3 arguments */
+  enum machine_mode mode[4];	/* return value + 3 arguments.  */
+  unsigned char uns_p[4];	/* and whether the types are unsigned.  */
 };
 
 static GTY ((param_is (struct builtin_hash_struct))) htab_t builtin_hash_table;
@@ -2742,6 +2743,8 @@ rs6000_vector_alignment_reachable (const
 tree
 rs6000_builtin_vec_perm (tree type, tree *mask_element_type)
 {
+  tree inner_type = TREE_TYPE (type);
+  bool uns_p = TYPE_UNSIGNED (inner_type);
   tree d;
 
   *mask_element_type = unsigned_char_type_node;
@@ -2749,15 +2752,21 @@ rs6000_builtin_vec_perm (tree type, tree
   switch (TYPE_MODE (type))
     {
     case V16QImode:
-      d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI];
+      d = (uns_p
+	   ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI_UNS]
+	   : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI]);
       break;
 
     case V8HImode:
-      d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI];
+      d = (uns_p
+	   ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI_UNS]
+	   : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI]);
       break;
 
     case V4SImode:
-      d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI];
+      d = (uns_p
+	   ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI_UNS]
+	   : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI]);
       break;
 
     case V4SFmode:
@@ -2769,7 +2778,9 @@ rs6000_builtin_vec_perm (tree type, tree
       break;
 
     case V2DImode:
-      d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI];
+      d = (uns_p
+	   ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI_UNS]
+	   : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI]);
       break;
 
     default:
@@ -7973,17 +7984,26 @@ static const struct builtin_description 
   { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhs, "__builtin_altivec_vmsumuhs", ALTIVEC_BUILTIN_VMSUMUHS },
   { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshs, "__builtin_altivec_vmsumshs", ALTIVEC_BUILTIN_VMSUMSHS },
   { MASK_ALTIVEC, CODE_FOR_altivec_vnmsubfp, "__builtin_altivec_vnmsubfp", ALTIVEC_BUILTIN_VNMSUBFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2df, "__builtin_altivec_vperm_2df", ALTIVEC_BUILTIN_VPERM_2DF },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di, "__builtin_altivec_vperm_2di", ALTIVEC_BUILTIN_VPERM_2DI },
   { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4sf, "__builtin_altivec_vperm_4sf", ALTIVEC_BUILTIN_VPERM_4SF },
   { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
   { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
-  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
-  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2df, "__builtin_altivec_vperm_2df", ALTIVEC_BUILTIN_VPERM_2DF },
-  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di, "__builtin_altivec_vperm_2di", ALTIVEC_BUILTIN_VPERM_2DI },
-  { MASK_ALTIVEC, CODE_FOR_vector_vselv4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
-  { MASK_ALTIVEC, CODE_FOR_vector_vselv4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
-  { MASK_ALTIVEC, CODE_FOR_vector_vselv8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
-  { MASK_ALTIVEC, CODE_FOR_vector_vselv16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
-  { MASK_ALTIVEC, CODE_FOR_vector_vselv2df, "__builtin_altivec_vsel_2df", ALTIVEC_BUILTIN_VSEL_2DF },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di_uns, "__builtin_altivec_vperm_2di_uns", ALTIVEC_BUILTIN_VPERM_2DI_UNS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si_uns, "__builtin_altivec_vperm_4si_uns", ALTIVEC_BUILTIN_VPERM_4SI_UNS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi_uns, "__builtin_altivec_vperm_8hi_uns", ALTIVEC_BUILTIN_VPERM_8HI_UNS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_altivec_vperm_16qi_uns", ALTIVEC_BUILTIN_VPERM_16QI_UNS },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v2df, "__builtin_altivec_vsel_2df", ALTIVEC_BUILTIN_VSEL_2DF },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v2di, "__builtin_altivec_vsel_2di", ALTIVEC_BUILTIN_VSEL_2DI },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v4si_uns, "__builtin_altivec_vsel_4si_uns", ALTIVEC_BUILTIN_VSEL_4SI_UNS },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v8hi_uns, "__builtin_altivec_vsel_8hi_uns", ALTIVEC_BUILTIN_VSEL_8HI_UNS },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v16qi_uns, "__builtin_altivec_vsel_16qi_uns", ALTIVEC_BUILTIN_VSEL_16QI_UNS },
+  { MASK_ALTIVEC, CODE_FOR_vector_select_v2di_uns, "__builtin_altivec_vsel_2di_uns", ALTIVEC_BUILTIN_VSEL_2DI_UNS },
   { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
   { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
   { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
@@ -8015,12 +8035,16 @@ static const struct builtin_description 
   { MASK_VSX, CODE_FOR_vsx_fnmaddv4sf4, "__builtin_vsx_xvnmaddsp", VSX_BUILTIN_XVNMADDSP },
   { MASK_VSX, CODE_FOR_vsx_fnmsubv4sf4, "__builtin_vsx_xvnmsubsp", VSX_BUILTIN_XVNMSUBSP },
 
-  { MASK_VSX, CODE_FOR_vector_vselv2di, "__builtin_vsx_xxsel_2di", VSX_BUILTIN_XXSEL_2DI },
-  { MASK_VSX, CODE_FOR_vector_vselv2df, "__builtin_vsx_xxsel_2df", VSX_BUILTIN_XXSEL_2DF },
-  { MASK_VSX, CODE_FOR_vector_vselv4sf, "__builtin_vsx_xxsel_4sf", VSX_BUILTIN_XXSEL_4SF },
-  { MASK_VSX, CODE_FOR_vector_vselv4si, "__builtin_vsx_xxsel_4si", VSX_BUILTIN_XXSEL_4SI },
-  { MASK_VSX, CODE_FOR_vector_vselv8hi, "__builtin_vsx_xxsel_8hi", VSX_BUILTIN_XXSEL_8HI },
-  { MASK_VSX, CODE_FOR_vector_vselv16qi, "__builtin_vsx_xxsel_16qi", VSX_BUILTIN_XXSEL_16QI },
+  { MASK_VSX, CODE_FOR_vector_select_v2di, "__builtin_vsx_xxsel_2di", VSX_BUILTIN_XXSEL_2DI },
+  { MASK_VSX, CODE_FOR_vector_select_v2df, "__builtin_vsx_xxsel_2df", VSX_BUILTIN_XXSEL_2DF },
+  { MASK_VSX, CODE_FOR_vector_select_v4sf, "__builtin_vsx_xxsel_4sf", VSX_BUILTIN_XXSEL_4SF },
+  { MASK_VSX, CODE_FOR_vector_select_v4si, "__builtin_vsx_xxsel_4si", VSX_BUILTIN_XXSEL_4SI },
+  { MASK_VSX, CODE_FOR_vector_select_v8hi, "__builtin_vsx_xxsel_8hi", VSX_BUILTIN_XXSEL_8HI },
+  { MASK_VSX, CODE_FOR_vector_select_v16qi, "__builtin_vsx_xxsel_16qi", VSX_BUILTIN_XXSEL_16QI },
+  { MASK_VSX, CODE_FOR_vector_select_v2di_uns, "__builtin_vsx_xxsel_2di_uns", VSX_BUILTIN_XXSEL_2DI_UNS },
+  { MASK_VSX, CODE_FOR_vector_select_v4si_uns, "__builtin_vsx_xxsel_4si_uns", VSX_BUILTIN_XXSEL_4SI_UNS },
+  { MASK_VSX, CODE_FOR_vector_select_v8hi_uns, "__builtin_vsx_xxsel_8hi_uns", VSX_BUILTIN_XXSEL_8HI_UNS },
+  { MASK_VSX, CODE_FOR_vector_select_v16qi_uns, "__builtin_vsx_xxsel_16qi_uns", VSX_BUILTIN_XXSEL_16QI_UNS },
 
   { MASK_VSX, CODE_FOR_altivec_vperm_v2di, "__builtin_vsx_vperm_2di", VSX_BUILTIN_VPERM_2DI },
   { MASK_VSX, CODE_FOR_altivec_vperm_v2df, "__builtin_vsx_vperm_2df", VSX_BUILTIN_VPERM_2DF },
@@ -8028,6 +8052,10 @@ static const struct builtin_description 
   { MASK_VSX, CODE_FOR_altivec_vperm_v4si, "__builtin_vsx_vperm_4si", VSX_BUILTIN_VPERM_4SI },
   { MASK_VSX, CODE_FOR_altivec_vperm_v8hi, "__builtin_vsx_vperm_8hi", VSX_BUILTIN_VPERM_8HI },
   { MASK_VSX, CODE_FOR_altivec_vperm_v16qi, "__builtin_vsx_vperm_16qi", VSX_BUILTIN_VPERM_16QI },
+  { MASK_VSX, CODE_FOR_altivec_vperm_v2di_uns, "__builtin_vsx_vperm_2di_uns", VSX_BUILTIN_VPERM_2DI_UNS },
+  { MASK_VSX, CODE_FOR_altivec_vperm_v4si_uns, "__builtin_vsx_vperm_4si_uns", VSX_BUILTIN_VPERM_4SI_UNS },
+  { MASK_VSX, CODE_FOR_altivec_vperm_v8hi_uns, "__builtin_vsx_vperm_8hi_uns", VSX_BUILTIN_VPERM_8HI_UNS },
+  { MASK_VSX, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_vsx_vperm_16qi_uns", VSX_BUILTIN_VPERM_16QI_UNS },
 
   { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2df, "__builtin_vsx_xxpermdi_2df", VSX_BUILTIN_XXPERMDI_2DF },
   { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2di, "__builtin_vsx_xxpermdi_2di", VSX_BUILTIN_XXPERMDI_2DI },
@@ -10414,21 +10442,27 @@ rs6000_init_builtins (void)
 
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
-  builtin_mode_to_type[QImode] = integer_type_node;
-  builtin_mode_to_type[HImode] = integer_type_node;
-  builtin_mode_to_type[SImode] = intSI_type_node;
-  builtin_mode_to_type[DImode] = intDI_type_node;
-  builtin_mode_to_type[SFmode] = float_type_node;
-  builtin_mode_to_type[DFmode] = double_type_node;
-  builtin_mode_to_type[V2SImode] = V2SI_type_node;
-  builtin_mode_to_type[V2SFmode] = V2SF_type_node;
-  builtin_mode_to_type[V2DImode] = V2DI_type_node;
-  builtin_mode_to_type[V2DFmode] = V2DF_type_node;
-  builtin_mode_to_type[V4HImode] = V4HI_type_node;
-  builtin_mode_to_type[V4SImode] = V4SI_type_node;
-  builtin_mode_to_type[V4SFmode] = V4SF_type_node;
-  builtin_mode_to_type[V8HImode] = V8HI_type_node;
-  builtin_mode_to_type[V16QImode] = V16QI_type_node;
+  builtin_mode_to_type[QImode][0] = integer_type_node;
+  builtin_mode_to_type[HImode][0] = integer_type_node;
+  builtin_mode_to_type[SImode][0] = intSI_type_node;
+  builtin_mode_to_type[SImode][1] = unsigned_intSI_type_node;
+  builtin_mode_to_type[DImode][0] = intDI_type_node;
+  builtin_mode_to_type[DImode][1] = unsigned_intDI_type_node;
+  builtin_mode_to_type[SFmode][0] = float_type_node;
+  builtin_mode_to_type[DFmode][0] = double_type_node;
+  builtin_mode_to_type[V2SImode][0] = V2SI_type_node;
+  builtin_mode_to_type[V2SFmode][0] = V2SF_type_node;
+  builtin_mode_to_type[V2DImode][0] = V2DI_type_node;
+  builtin_mode_to_type[V2DImode][1] = unsigned_V2DI_type_node;
+  builtin_mode_to_type[V2DFmode][0] = V2DF_type_node;
+  builtin_mode_to_type[V4HImode][0] = V4HI_type_node;
+  builtin_mode_to_type[V4SImode][0] = V4SI_type_node;
+  builtin_mode_to_type[V4SImode][1] = unsigned_V4SI_type_node;
+  builtin_mode_to_type[V4SFmode][0] = V4SF_type_node;
+  builtin_mode_to_type[V8HImode][0] = V8HI_type_node;
+  builtin_mode_to_type[V8HImode][1] = unsigned_V8HI_type_node;
+  builtin_mode_to_type[V16QImode][0] = V16QI_type_node;
+  builtin_mode_to_type[V16QImode][1] = unsigned_V16QI_type_node;
 
   tdecl = build_decl (TYPE_DECL, get_identifier ("__bool char"),
 		      bool_char_type_node);
@@ -10535,11 +10569,13 @@ rs6000_init_builtins (void)
   if (TARGET_PPC_GFXOPT)
     {
       tree ftype = builtin_function_type (SFmode, SFmode, SFmode, VOIDmode,
+					  RS6000_BUILTIN_RECIPF,
 					  "__builtin_recipdivf");
       def_builtin (MASK_PPC_GFXOPT, "__builtin_recipdivf", ftype,
 		   RS6000_BUILTIN_RECIPF);
 
       ftype = builtin_function_type (SFmode, SFmode, VOIDmode, VOIDmode,
+				     RS6000_BUILTIN_RSQRTF,
 				     "__builtin_rsqrtf");
       def_builtin (MASK_PPC_GFXOPT, "__builtin_rsqrtf", ftype,
 		   RS6000_BUILTIN_RSQRTF);
@@ -10547,6 +10583,7 @@ rs6000_init_builtins (void)
   if (TARGET_POPCNTB)
     {
       tree ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode,
+					  RS6000_BUILTIN_RECIP,
 					  "__builtin_recipdiv");
       def_builtin (MASK_POPCNTB, "__builtin_recipdiv", ftype,
 		   RS6000_BUILTIN_RECIP);
@@ -10556,6 +10593,7 @@ rs6000_init_builtins (void)
     {
       enum machine_mode mode = (TARGET_64BIT) ? DImode : SImode;
       tree ftype = builtin_function_type (mode, mode, mode, VOIDmode,
+					  POWER7_BUILTIN_BPERMD,
 					  "__builtin_bpermd");
       def_builtin (MASK_POPCNTD, "__builtin_bpermd", ftype,
 		   POWER7_BUILTIN_BPERMD);
@@ -11325,7 +11363,10 @@ builtin_hash_function (const void *hash_
     (const struct builtin_hash_struct *) hash_entry;
 
   for (i = 0; i < 4; i++)
-    ret = (ret * (unsigned)MAX_MACHINE_MODE) + ((unsigned)bh->mode[i]);
+    {
+      ret = (ret * (unsigned)MAX_MACHINE_MODE) + ((unsigned)bh->mode[i]);
+      ret = (ret * 2) + bh->uns_p[i];
+    }
 
   return ret;
 }
@@ -11340,7 +11381,11 @@ builtin_hash_eq (const void *h1, const v
   return ((p1->mode[0] == p2->mode[0])
 	  && (p1->mode[1] == p2->mode[1])
 	  && (p1->mode[2] == p2->mode[2])
-	  && (p1->mode[3] == p2->mode[3]));
+	  && (p1->mode[3] == p2->mode[3])
+	  && (p1->uns_p[0] == p2->uns_p[0])
+	  && (p1->uns_p[1] == p2->uns_p[1])
+	  && (p1->uns_p[2] == p2->uns_p[2])
+	  && (p1->uns_p[3] == p2->uns_p[3]));
 }
 
 /* Map types for builtin functions with an explicit return type and up to 3
@@ -11349,13 +11394,15 @@ builtin_hash_eq (const void *h1, const v
 static tree
 builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
 		       enum machine_mode mode_arg1, enum machine_mode mode_arg2,
-		       const char *name)
+		       enum rs6000_builtins builtin, const char *name)
 {
   struct builtin_hash_struct h;
   struct builtin_hash_struct *h2;
   void **found;
   int num_args = 3;
   int i;
+  tree ret_type = NULL_TREE;
+  tree arg_type[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
 
   /* Create builtin_hash_table.  */
   if (builtin_hash_table == NULL)
@@ -11367,6 +11414,184 @@ builtin_function_type (enum machine_mode
   h.mode[1] = mode_arg0;
   h.mode[2] = mode_arg1;
   h.mode[3] = mode_arg2;
+  h.uns_p[0] = 0;
+  h.uns_p[1] = 0;
+  h.uns_p[2] = 0;
+  h.uns_p[3] = 0;
+
+  /* If the builtin is a type that produces unsigned results, change to use
+     unsigned types instead of signed types.  All of the types below are
+     probably overkill for now.  It is important that the decls that are used
+     in the vectorizer such as the widening multiplies have the correct signed
+     or unsigned type, so that the gimple type verifier doesn't complain about
+     the wrong types being used.  */
+  switch (builtin)
+    {
+    case ALTIVEC_BUILTIN_VADDUBM:
+    case ALTIVEC_BUILTIN_VADDUHM:
+    case ALTIVEC_BUILTIN_VADDUWM:
+    case ALTIVEC_BUILTIN_VADDCUW:
+    case ALTIVEC_BUILTIN_VADDUBS:
+    case ALTIVEC_BUILTIN_VADDUHS:
+    case ALTIVEC_BUILTIN_VADDUWS:
+    case ALTIVEC_BUILTIN_VAVGUB:
+    case ALTIVEC_BUILTIN_VAVGUH:
+    case ALTIVEC_BUILTIN_VAVGUW:
+    case ALTIVEC_BUILTIN_VCMPEQUB:
+    case ALTIVEC_BUILTIN_VCMPEQUH:
+    case ALTIVEC_BUILTIN_VCMPEQUW:
+    case ALTIVEC_BUILTIN_VCMPGTUB:
+    case ALTIVEC_BUILTIN_VCMPGTUH:
+    case ALTIVEC_BUILTIN_VCMPGTUW:
+    case ALTIVEC_BUILTIN_VMAXUB:
+    case ALTIVEC_BUILTIN_VMAXUH:
+    case ALTIVEC_BUILTIN_VMAXUW:
+    case ALTIVEC_BUILTIN_VMSUMUBM:
+    case ALTIVEC_BUILTIN_VMSUMUHM:
+    case ALTIVEC_BUILTIN_VMSUMUHS:
+    case ALTIVEC_BUILTIN_VMSUMSHS:
+    case ALTIVEC_BUILTIN_VMINUB:
+    case ALTIVEC_BUILTIN_VMINUH:
+    case ALTIVEC_BUILTIN_VMINUW:
+    case ALTIVEC_BUILTIN_VMULEUB:
+    case ALTIVEC_BUILTIN_VMULEUH:
+    case ALTIVEC_BUILTIN_VMULOUB:
+    case ALTIVEC_BUILTIN_VMULOUH:
+    case ALTIVEC_BUILTIN_VPKUHUM:
+    case ALTIVEC_BUILTIN_VPKUWUM:
+    case ALTIVEC_BUILTIN_VPKUHUS:
+    case ALTIVEC_BUILTIN_VPKUWUS:
+    case ALTIVEC_BUILTIN_VSUBUBM:
+    case ALTIVEC_BUILTIN_VSUBUHM:
+    case ALTIVEC_BUILTIN_VSUBUWM:
+    case ALTIVEC_BUILTIN_VSUBCUW:
+    case ALTIVEC_BUILTIN_VSUBUBS:
+    case ALTIVEC_BUILTIN_VSUBUHS:
+    case ALTIVEC_BUILTIN_VSUBUWS:
+    case ALTIVEC_BUILTIN_VSUM4UBS:
+    case ALTIVEC_BUILTIN_VCMPEQUB_P:
+    case ALTIVEC_BUILTIN_VCMPEQUH_P:
+    case ALTIVEC_BUILTIN_VCMPEQUW_P:
+    case ALTIVEC_BUILTIN_VCMPGTUB_P:
+    case ALTIVEC_BUILTIN_VCMPGTUH_P:
+    case ALTIVEC_BUILTIN_VCMPGTUW_P:
+    case ALTIVEC_BUILTIN_VEC_VADDUBM:
+    case ALTIVEC_BUILTIN_VEC_VADDUBS:
+    case ALTIVEC_BUILTIN_VEC_VADDUHM:
+    case ALTIVEC_BUILTIN_VEC_VADDUHS:
+    case ALTIVEC_BUILTIN_VEC_VADDUWM:
+    case ALTIVEC_BUILTIN_VEC_VADDUWS:
+    case ALTIVEC_BUILTIN_VEC_VAVGUB:
+    case ALTIVEC_BUILTIN_VEC_VAVGUH:
+    case ALTIVEC_BUILTIN_VEC_VAVGUW:
+    case ALTIVEC_BUILTIN_VEC_VCMPEQUB:
+    case ALTIVEC_BUILTIN_VEC_VCMPEQUH:
+    case ALTIVEC_BUILTIN_VEC_VCMPGTUB:
+    case ALTIVEC_BUILTIN_VEC_VCMPGTUH:
+    case ALTIVEC_BUILTIN_VEC_VCMPGTUW:
+    case ALTIVEC_BUILTIN_VEC_VMAXUB:
+    case ALTIVEC_BUILTIN_VEC_VMAXUH:
+    case ALTIVEC_BUILTIN_VEC_VMAXUW:
+    case ALTIVEC_BUILTIN_VEC_VMINUB:
+    case ALTIVEC_BUILTIN_VEC_VMINUH:
+    case ALTIVEC_BUILTIN_VEC_VMINUW:
+    case ALTIVEC_BUILTIN_VEC_VMSUMMBM:
+    case ALTIVEC_BUILTIN_VEC_VMSUMUBM:
+    case ALTIVEC_BUILTIN_VEC_VMSUMUHM:
+    case ALTIVEC_BUILTIN_VEC_VMSUMUHS:
+    case ALTIVEC_BUILTIN_VEC_VMULESB:
+    case ALTIVEC_BUILTIN_VEC_VMULESH:
+    case ALTIVEC_BUILTIN_VEC_VMULEUB:
+    case ALTIVEC_BUILTIN_VEC_VMULEUH:
+    case ALTIVEC_BUILTIN_VEC_VMULOUB:
+    case ALTIVEC_BUILTIN_VEC_VMULOUH:
+    case ALTIVEC_BUILTIN_VEC_VPKUHUM:
+    case ALTIVEC_BUILTIN_VEC_VPKUHUS:
+    case ALTIVEC_BUILTIN_VEC_VPKUWUM:
+    case ALTIVEC_BUILTIN_VEC_VPKUWUS:
+    case ALTIVEC_BUILTIN_VEC_VSUBUBM:
+    case ALTIVEC_BUILTIN_VEC_VSUBUBS:
+    case ALTIVEC_BUILTIN_VEC_VSUBUHM:
+    case ALTIVEC_BUILTIN_VEC_VSUBUHS:
+    case ALTIVEC_BUILTIN_VEC_VSUBUWM:
+    case ALTIVEC_BUILTIN_VEC_VSUBUWS:
+    case ALTIVEC_BUILTIN_VEC_VSUM4UBS:
+      h.uns_p[0] = 1;
+      h.uns_p[1] = 1;
+      h.uns_p[2] = 1;
+      break;
+
+      /* unsigned 3 argument functions.  */
+    case ALTIVEC_BUILTIN_VPERM_16QI_UNS:
+    case ALTIVEC_BUILTIN_VPERM_8HI_UNS:
+    case ALTIVEC_BUILTIN_VPERM_4SI_UNS:
+    case ALTIVEC_BUILTIN_VPERM_2DI_UNS:
+    case ALTIVEC_BUILTIN_VSEL_16QI_UNS:
+    case ALTIVEC_BUILTIN_VSEL_8HI_UNS:
+    case ALTIVEC_BUILTIN_VSEL_4SI_UNS:
+    case ALTIVEC_BUILTIN_VSEL_2DI_UNS:
+    case VSX_BUILTIN_VPERM_16QI_UNS:
+    case VSX_BUILTIN_VPERM_8HI_UNS:
+    case VSX_BUILTIN_VPERM_4SI_UNS:
+    case VSX_BUILTIN_VPERM_2DI_UNS:
+    case VSX_BUILTIN_XXSEL_16QI_UNS:
+    case VSX_BUILTIN_XXSEL_8HI_UNS:
+    case VSX_BUILTIN_XXSEL_4SI_UNS:
+    case VSX_BUILTIN_XXSEL_2DI_UNS:
+      h.uns_p[0] = 1;
+      h.uns_p[1] = 1;
+      h.uns_p[2] = 1;
+      h.uns_p[3] = 1;
+      break;
+
+      /* signed permute functions with unsigned char mask.  */
+    case ALTIVEC_BUILTIN_VPERM_16QI:
+    case ALTIVEC_BUILTIN_VPERM_8HI:
+    case ALTIVEC_BUILTIN_VPERM_4SI:
+    case ALTIVEC_BUILTIN_VPERM_4SF:
+    case ALTIVEC_BUILTIN_VPERM_2DI:
+    case ALTIVEC_BUILTIN_VPERM_2DF:
+    case VSX_BUILTIN_VPERM_16QI:
+    case VSX_BUILTIN_VPERM_8HI:
+    case VSX_BUILTIN_VPERM_4SI:
+    case VSX_BUILTIN_VPERM_4SF:
+    case VSX_BUILTIN_VPERM_2DI:
+    case VSX_BUILTIN_VPERM_2DF:
+      h.uns_p[3] = 1;
+      break;
+
+      /* unsigned args, signed return.  */
+    case ALTIVEC_BUILTIN_VCFUX:
+    case ALTIVEC_BUILTIN_VPKUHSS:
+    case ALTIVEC_BUILTIN_VPKUWSS:
+    case VSX_BUILTIN_XSCVUXDDP:
+    case VSX_BUILTIN_XVCVUXDDP:
+    case VSX_BUILTIN_XVCVUXDSP:
+    case VSX_BUILTIN_XVCVUXWDP:
+    case VSX_BUILTIN_XVCVUXWSP:
+    case VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF:
+      h.uns_p[1] = 1;
+      break;
+
+      /* signed args, unsigned return.  */
+    case ALTIVEC_BUILTIN_VCTUXS:
+    case ALTIVEC_BUILTIN_VPKSHUS:
+    case ALTIVEC_BUILTIN_VPKSWUS:
+    case ALTIVEC_BUILTIN_VEC_VPKSHUS:
+    case ALTIVEC_BUILTIN_VEC_VPKSWUS:
+    case VSX_BUILTIN_XSCVDPUXDS:
+    case VSX_BUILTIN_XSCVDPUXWS:
+    case VSX_BUILTIN_XVCVDPUXDS:
+    case VSX_BUILTIN_XVCVDPUXWS:
+    case VSX_BUILTIN_XVCVSPUXDS:
+    case VSX_BUILTIN_XVCVSPUXWS:
+    case VECTOR_BUILTIN_FIXUNS_V4SF_V4SI:
+      h.uns_p[0] = 1;
+      break;
+
+    default:
+      break;
+    }
 
   /* Figure out how many args are present.  */
   while (num_args > 0 && h.mode[num_args] == VOIDmode)
@@ -11375,15 +11600,28 @@ builtin_function_type (enum machine_mode
   if (num_args == 0)
     fatal_error ("internal error: builtin function %s had no type", name);
 
-  if (!builtin_mode_to_type[h.mode[0]])
+  ret_type = builtin_mode_to_type[h.mode[0]][h.uns_p[0]];
+  if (!ret_type && h.uns_p[0])
+    ret_type = builtin_mode_to_type[h.mode[0]][0];
+
+  if (!ret_type)
     fatal_error ("internal error: builtin function %s had an unexpected "
 		 "return type %s", name, GET_MODE_NAME (h.mode[0]));
 
   for (i = 0; i < num_args; i++)
-    if (!builtin_mode_to_type[h.mode[i+1]])
-      fatal_error ("internal error: builtin function %s, argument %d "
-		   "had unexpected argument type %s", name, i,
-		   GET_MODE_NAME (h.mode[i+1]));
+    {
+      int m = (int) h.mode[i+1];
+      int uns_p = h.uns_p[i+1];
+
+      arg_type[i] = builtin_mode_to_type[m][uns_p];
+      if (!arg_type[i] && uns_p)
+	arg_type[i] = builtin_mode_to_type[m][0];
+
+      if (!arg_type[i])
+	fatal_error ("internal error: builtin function %s, argument %d "
+		     "had unexpected argument type %s", name, i,
+		     GET_MODE_NAME (m));
+    }
 
   found = htab_find_slot (builtin_hash_table, &h, INSERT);
   if (*found == NULL)
@@ -11395,23 +11633,18 @@ builtin_function_type (enum machine_mode
       switch (num_args)
 	{
 	case 1:
-	  h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
-					       builtin_mode_to_type[mode_arg0],
+	  h2->type = build_function_type_list (ret_type, arg_type[0],
 					       NULL_TREE);
 	  break;
 
 	case 2:
-	  h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
-					       builtin_mode_to_type[mode_arg0],
-					       builtin_mode_to_type[mode_arg1],
-					       NULL_TREE);
+	  h2->type = build_function_type_list (ret_type, arg_type[0],
+					       arg_type[1], NULL_TREE);
 	  break;
 
 	case 3:
-	  h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
-					       builtin_mode_to_type[mode_arg0],
-					       builtin_mode_to_type[mode_arg1],
-					       builtin_mode_to_type[mode_arg2],
+	  h2->type = build_function_type_list (ret_type, arg_type[0],
+					       arg_type[1], arg_type[2],
 					       NULL_TREE);
 	  break;
 
@@ -11438,8 +11671,8 @@ rs6000_common_init_builtins (void)
 
   if (!TARGET_PAIRED_FLOAT)
     {
-      builtin_mode_to_type[V2SImode] = opaque_V2SI_type_node;
-      builtin_mode_to_type[V2SFmode] = opaque_V2SF_type_node;
+      builtin_mode_to_type[V2SImode][0] = opaque_V2SI_type_node;
+      builtin_mode_to_type[V2SFmode][0] = opaque_V2SF_type_node;
     }
 
   /* Add the ternary operators.  */
@@ -11476,7 +11709,7 @@ rs6000_common_init_builtins (void)
 					insn_data[icode].operand[1].mode,
 					insn_data[icode].operand[2].mode,
 					insn_data[icode].operand[3].mode,
-					d->name);
+					d->code, d->name);
 	}
 
       def_builtin (d->mask, d->name, type, d->code);
@@ -11539,7 +11772,7 @@ rs6000_common_init_builtins (void)
 
 	  else
 	    type = builtin_function_type (mode0, mode1, mode2, VOIDmode,
-					  d->name);
+					  d->code, d->name);
 	}
 
       def_builtin (d->mask, d->name, type, d->code);
@@ -11588,7 +11821,7 @@ rs6000_common_init_builtins (void)
 
 	  else
 	    type = builtin_function_type (mode0, mode1, VOIDmode, VOIDmode,
-					  d->name);
+					  d->code, d->name);
 	}
 
       def_builtin (d->mask, d->name, type, d->code);
@@ -14799,8 +15032,7 @@ rs6000_emit_vector_compare_vsx (enum rtx
     case GE:
       emit_insn (gen_rtx_SET (VOIDmode,
 			      mask,
-			      gen_rtx_fmt_ee (code, GET_MODE (mask),
-					      op0,
+			      gen_rtx_fmt_ee (code, GET_MODE (op0), op0,
 					      op1)));
       return mask;
     }
@@ -14830,9 +15062,7 @@ rs6000_emit_vector_compare_altivec (enum
     case GTU:
       emit_insn (gen_rtx_SET (VOIDmode,
 			      mask,
-			      gen_rtx_fmt_ee (code, GET_MODE (mask),
-					      op0,
-					      op1)));
+			      gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1)));
       return mask;
     }
 
@@ -14988,19 +15218,39 @@ rs6000_emit_vector_cond_expr (rtx dest, 
 {
   enum machine_mode dest_mode = GET_MODE (dest);
   enum rtx_code rcode = GET_CODE (cond);
+  enum machine_mode cc_mode = unsigned_condition (rcode) ? CCmode : CCUNSmode;
   rtx mask;
   rtx cond2;
+  rtx tmp;
 
   if (VECTOR_UNIT_NONE_P (dest_mode))
     return 0;
 
+  /* Swap operands rather than doing a NOR operation to invert the test.  */
+  switch (rcode)
+    {
+    case NE:
+    case UNLE:
+    case UNLT:
+    case UNGE:
+    case UNGT:
+      tmp = op1;
+      op1 = op2;
+      op2 = tmp;
+      rcode = reverse_condition (rcode);
+      break;
+
+    default:
+      break;
+    }
+
   /* Get the vector mask for the given relational operations.  */
   mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
 
   if (!mask)
     return 0;
 
-  cond2 = gen_rtx_fmt_ee (NE, VOIDmode, mask, const0_rtx);
+  cond2 = gen_rtx_fmt_ee (NE, cc_mode, mask, const0_rtx);
   emit_insn (gen_rtx_SET (VOIDmode,
 			  dest,
 			  gen_rtx_IF_THEN_ELSE (dest_mode,
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md	(revision 146915)
+++ gcc/config/rs6000/vsx.md	(working copy)
@@ -820,12 +820,24 @@
   [(set_attr "type" "veccmp")])
 
 ;; Vector select
-(define_insn "*vsx_vsel<mode>"
+(define_insn "*vsx_xxsel<mode>"
   [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
-	(if_then_else:VSX_L (ne (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
-				(const_int 0))
-			    (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
-			    (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
+	(if_then_else:VSX_L
+	 (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
+		(const_int 0))
+	 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
+	 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
+  "VECTOR_MEM_VSX_P (<MODE>mode)"
+  "xxsel %x0,%x3,%x2,%x1"
+  [(set_attr "type" "vecperm")])
+
+(define_insn "*vsx_xxsel<mode>_uns"
+  [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
+	(if_then_else:VSX_L
+	 (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
+		   (const_int 0))
+	 (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
+	 (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
   "VECTOR_MEM_VSX_P (<MODE>mode)"
   "xxsel %x0,%x3,%x2,%x1"
   [(set_attr "type" "vecperm")])
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 146916)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -2598,18 +2598,26 @@ enum rs6000_builtins
   ALTIVEC_BUILTIN_VNMSUBFP,
   ALTIVEC_BUILTIN_VNOR,
   ALTIVEC_BUILTIN_VOR,
+  ALTIVEC_BUILTIN_VSEL_2DF,		/* needed for VSX */
+  ALTIVEC_BUILTIN_VSEL_2DI,		/* needed for VSX */
   ALTIVEC_BUILTIN_VSEL_4SI,
   ALTIVEC_BUILTIN_VSEL_4SF,
   ALTIVEC_BUILTIN_VSEL_8HI,
   ALTIVEC_BUILTIN_VSEL_16QI,
-  ALTIVEC_BUILTIN_VSEL_2DF,		/* needed for VSX */
-  ALTIVEC_BUILTIN_VSEL_2DI,		/* needed for VSX */
+  ALTIVEC_BUILTIN_VSEL_2DI_UNS,
+  ALTIVEC_BUILTIN_VSEL_4SI_UNS,
+  ALTIVEC_BUILTIN_VSEL_8HI_UNS,
+  ALTIVEC_BUILTIN_VSEL_16QI_UNS,
+  ALTIVEC_BUILTIN_VPERM_2DF,		/* needed for VSX */
+  ALTIVEC_BUILTIN_VPERM_2DI,		/* needed for VSX */
   ALTIVEC_BUILTIN_VPERM_4SI,
   ALTIVEC_BUILTIN_VPERM_4SF,
   ALTIVEC_BUILTIN_VPERM_8HI,
   ALTIVEC_BUILTIN_VPERM_16QI,
-  ALTIVEC_BUILTIN_VPERM_2DF,		/* needed for VSX */
-  ALTIVEC_BUILTIN_VPERM_2DI,		/* needed for VSX */
+  ALTIVEC_BUILTIN_VPERM_2DI_UNS,
+  ALTIVEC_BUILTIN_VPERM_4SI_UNS,
+  ALTIVEC_BUILTIN_VPERM_8HI_UNS,
+  ALTIVEC_BUILTIN_VPERM_16QI_UNS,
   ALTIVEC_BUILTIN_VPKUHUM,
   ALTIVEC_BUILTIN_VPKUWUM,
   ALTIVEC_BUILTIN_VPKPX,
@@ -3374,12 +3382,20 @@ enum rs6000_builtins
   VSX_BUILTIN_XXSEL_4SF,
   VSX_BUILTIN_XXSEL_8HI,
   VSX_BUILTIN_XXSEL_16QI,
+  VSX_BUILTIN_XXSEL_2DI_UNS,
+  VSX_BUILTIN_XXSEL_4SI_UNS,
+  VSX_BUILTIN_XXSEL_8HI_UNS,
+  VSX_BUILTIN_XXSEL_16QI_UNS,
   VSX_BUILTIN_VPERM_2DI,
   VSX_BUILTIN_VPERM_2DF,
   VSX_BUILTIN_VPERM_4SI,
   VSX_BUILTIN_VPERM_4SF,
   VSX_BUILTIN_VPERM_8HI,
   VSX_BUILTIN_VPERM_16QI,
+  VSX_BUILTIN_VPERM_2DI_UNS,
+  VSX_BUILTIN_VPERM_4SI_UNS,
+  VSX_BUILTIN_VPERM_8HI_UNS,
+  VSX_BUILTIN_VPERM_16QI_UNS,
   VSX_BUILTIN_XXPERMDI_2DF,
   VSX_BUILTIN_XXPERMDI_2DI,
   VSX_BUILTIN_CONCAT_2DF,
Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 146915)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -65,6 +65,7 @@
    (UNSPEC_VSUM2SWS     134)
    (UNSPEC_VSUMSWS      135)
    (UNSPEC_VPERM        144)
+   (UNSPEC_VPERM_UNS    145)
    (UNSPEC_VRFIP        148)
    (UNSPEC_VRFIN        149)
    (UNSPEC_VRFIM        150)
@@ -464,10 +465,22 @@
 
 (define_insn "*altivec_vsel<mode>"
   [(set (match_operand:VM 0 "altivec_register_operand" "=v")
-	(if_then_else:VM (ne (match_operand:VM 1 "altivec_register_operand" "v")
-			     (const_int 0))
-			 (match_operand:VM 2 "altivec_register_operand" "v")
-			 (match_operand:VM 3 "altivec_register_operand" "v")))]
+	(if_then_else:VM
+	 (ne:CC (match_operand:VM 1 "altivec_register_operand" "v")
+		(const_int 0))
+	 (match_operand:VM 2 "altivec_register_operand" "v")
+	 (match_operand:VM 3 "altivec_register_operand" "v")))]
+  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
+  "vsel %0,%3,%2,%1"
+  [(set_attr "type" "vecperm")])
+
+(define_insn "*altivec_vsel<mode>_uns"
+  [(set (match_operand:VM 0 "altivec_register_operand" "=v")
+	(if_then_else:VM
+	 (ne:CCUNS (match_operand:VM 1 "altivec_register_operand" "v")
+		   (const_int 0))
+	 (match_operand:VM 2 "altivec_register_operand" "v")
+	 (match_operand:VM 3 "altivec_register_operand" "v")))]
   "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
   "vsel %0,%3,%2,%1"
   [(set_attr "type" "vecperm")])
@@ -1315,6 +1328,16 @@
   "vperm %0,%1,%2,%3"
   [(set_attr "type" "vecperm")])
 
+(define_insn "altivec_vperm_<mode>_uns"
+  [(set (match_operand:VM 0 "register_operand" "=v")
+	(unspec:VM [(match_operand:VM 1 "register_operand" "v")
+		    (match_operand:VM 2 "register_operand" "v")
+		    (match_operand:V16QI 3 "register_operand" "v")]
+		   UNSPEC_VPERM_UNS))]
+  "TARGET_ALTIVEC"
+  "vperm %0,%1,%2,%3"
+  [(set_attr "type" "vecperm")])
+
 (define_insn "altivec_vrfip"
   [(set (match_operand:V4SF 0 "register_operand" "=v")
         (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]


More information about the Gcc-patches mailing list