This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[power7-meissner] Fix secondary register classes


This patch fixes up the nagging problems with reload failing on some when
building spec 2006.  All of spec 2006 now builds and validates when using
-mcpu=power7, as does bootstrapping the compiler.

I also flipped the defaults so that if -mvsx, the vsx memory reference/logical
instructions are used, and to do V4SF floating point in VSX.

Next up, adding the Power7/VSX conversion operations, reciprocal square
root/division, and maybe flipping the default for scalar double so it can use
the VSX instructions.

2009-02-26  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/constraints.md ("wd" constraint):  Change the
	variable that holds the register class to use.
	("wf" constraint): Ditto.
	("ws" constraint): Ditto.
	("wa" constraint): Ditto.

	* config/rs6000/rs6000.opt (-mvsx-vector-memory): Make this on by
	default.
	(-mvsx-vector-float): Ditto.

	* config/rs6000/rs6000.c (rs6000_vector_reg_class): New global to
	hold the register classes for the vector modes.
	(rs6000_vsx_v4sf_regclass): Delete, move into
	rs6000_vector_reg_class.
	(rs6000_vsx_v2df_regclass): Ditto.
	(rs6000_vsx_df_regclass): Ditto.
	(rs6000_vsx_reg_class): Rename from rs6000_vsx_any_regclass.
	(rs6000_hard_regno_mode_ok): Rework VSX, Altivec registers.
	(rs6000_init_hard_regno_mode_ok): Setup rs6000_vector_reg_class.
	Drop rs6000_vsx_*_regclass.  By default, use all 64 registers for
	V4SF and V2DF.  Use VSX_REG_CLASS_P macro instead of separate
	tests.  Update -mdebug=reg printout.
	(rs6000_preferred_reload_class): If VSX, prefer FLOAT_REGS for
	scalar floating point and ALTIVEC_REGS for the types that have
	altivec instructions.
	(rs6000_secondary_memory_needed): If VSX, we can copy between FPR
	and Altivec registers without needed memory.
	(rs6000_secondary_reload_class): Delete ATTRIBUTE_UNUSED from an
	argument that is used.  If VSX, we can copy between FPR and
	Altivec registers directly.

	* config/rs6000/rs6000.h (VSX_MOVE_MODE): Add in the Altivec
	types.
	(rs6000_vsx_v4sf_regclass): Delete.
	(rs6000_vsx_v2df_regclass): Ditto.
	(rs6000_vsx_df_regclass): Ditto.
	(rs6000_vsx_reg_class): Rename from rs6000_vsx_any_reg_class.
	(rs6000_vector_reg_class): New global to map machine mode to the
	preferred register class to use for that mode.
	(VSX_REG_CLASS_P): New macro to return true for all of the
	register classes VSX items can be in.

Index: gcc/config/rs6000/constraints.md
===================================================================
--- gcc/config/rs6000/constraints.md	(revision 144438)
+++ gcc/config/rs6000/constraints.md	(working copy)
@@ -54,19 +54,19 @@
 
 ;; Use w as a prefix to add VSX modes
 ;; vector double (V2DF)
-(define_register_constraint "wd" "rs6000_vsx_v2df_regclass"
+(define_register_constraint "wd" "rs6000_vector_reg_class[V2DFmode]"
   "@internal")
 
 ;; vector float (V4SF)
-(define_register_constraint "wf" "rs6000_vsx_v4sf_regclass"
+(define_register_constraint "wf" "rs6000_vector_reg_class[V4SFmode]"
   "@internal")
 
 ;; scalar double (DF)
-(define_register_constraint "ws" "rs6000_vsx_df_regclass"
+(define_register_constraint "ws" "rs6000_vector_reg_class[DFmode]"
   "@internal")
 
 ;; any VSX register
-(define_register_constraint "wa" "rs6000_vsx_any_regclass"
+(define_register_constraint "wa" "rs6000_vsx_reg_class"
   "@internal")
 
 ;; Integer constraints
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 144438)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -120,11 +120,11 @@ Target Report Mask(VSX)
 Use vector/scalar (VSX) instructions.
 
 mvsx-vector-memory
-Target Report Var(TARGET_VSX_VECTOR_MEMORY)
+Target Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1)
 If -mvsx, use VSX vector load/store instructions instead of Altivec instructions
 
 mvsx-vector-float
-Target Report Var(TARGET_VSX_VECTOR_FLOAT)
+Target Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1)
 If -mvsx, use VSX arithmetic instructions for float vectors
 
 mvsx-vector-double
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 144438)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -297,15 +297,13 @@ struct builtin_description
 /* Describe the vector unit used for modes.  */
 enum rs6000_vector rs6000_vector_unit[NUM_MACHINE_MODES];
 enum rs6000_vector rs6000_vector_mem[NUM_MACHINE_MODES];
+enum reg_class rs6000_vector_reg_class[NUM_MACHINE_MODES];
 
 /* Describe the alignment of a vector.  */
 int rs6000_vector_align[NUM_MACHINE_MODES];
 
 /* Describe the register classes used by VSX instructions.  */
-enum reg_class rs6000_vsx_v4sf_regclass		= NO_REGS;
-enum reg_class rs6000_vsx_v2df_regclass		= NO_REGS;
-enum reg_class rs6000_vsx_df_regclass		= NO_REGS;
-enum reg_class rs6000_vsx_any_regclass		= NO_REGS;
+enum reg_class rs6000_vsx_reg_class = NO_REGS;
 
 
 /* Target cpu costs.  */
@@ -1395,11 +1393,14 @@ rs6000_hard_regno_mode_ok (int regno, en
      and an Altivec register.  */
   if (VECTOR_UNIT_VSX_P (mode))
     {
+      enum reg_class rclass = rs6000_vector_reg_class[mode];
       if (FP_REGNO_P (regno))
-	return FP_REGNO_P (last_regno);
+	return ((rclass == FLOAT_REGS || rclass == VSX_REGS)
+		&& FP_REGNO_P (last_regno));
 
       if (ALTIVEC_REGNO_P (regno))
-	return ALTIVEC_REGNO_P (last_regno);
+	return ((rclass == ALTIVEC_REGS || rclass == VSX_REGS)
+		&& ALTIVEC_REGNO_P (last_regno));
     }
 
   /* The GPRs can hold any mode, but values bigger than one register
@@ -1437,7 +1438,7 @@ rs6000_hard_regno_mode_ok (int regno, en
 
   /* AltiVec only in AldyVec registers.  */
   if (ALTIVEC_REGNO_P (regno))
-    return VECTOR_UNIT_ALTIVEC_P (mode);
+    return VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode);
 
   /* ...but GPRs can hold SIMD data on the SPE in one register.  */
   if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
@@ -1527,7 +1528,10 @@ rs6000_init_hard_regno_mode_ok (void)
   /* Precalculate vector information, this must be set up before the
      rs6000_hard_regno_nregs_internal below.  */
   for (m = 0; m < NUM_MACHINE_MODES; ++m)
-    rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
+    {
+      rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
+      rs6000_vector_reg_class[m] = NO_REGS;
+    }
 
   if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_DOUBLE)
     {
@@ -1585,24 +1589,31 @@ rs6000_init_hard_regno_mode_ok (void)
   /* TODO, add SPE and paired floating point vector support.  */
 
   /* Set the VSX register classes.  */
-  rs6000_vsx_v4sf_regclass
+  rs6000_vector_reg_class[V4SFmode]
     = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode))
-       ? ALTIVEC_REGS /* vsx_rc */
+       ? vsx_rc
        : (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
 	  ? ALTIVEC_REGS
 	  : NO_REGS));
 
-  rs6000_vsx_v2df_regclass
+  rs6000_vector_reg_class[V2DFmode]
     = (VECTOR_UNIT_VSX_P (V2DFmode) ? vsx_rc : NO_REGS);
 
-  rs6000_vsx_df_regclass
+  rs6000_vector_reg_class[DFmode]
     = (!float_p
        ? NO_REGS
        : ((VECTOR_UNIT_VSX_P (DFmode) && TARGET_VSX_VECTOR_MEMORY > 0)
 	  ? vsx_rc
 	  : FLOAT_REGS));
 
-  rs6000_vsx_any_regclass = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS;
+  if (TARGET_ALTIVEC)
+    {
+      rs6000_vector_reg_class[V16QImode] = ALTIVEC_REGS;
+      rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS;
+      rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS;
+    }
+
+  rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS;
 
   /* Precalculate HARD_REGNO_NREGS.  */
   for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
@@ -1620,8 +1631,7 @@ rs6000_init_hard_regno_mode_ok (void)
     {
       int reg_size;
 
-      if (TARGET_VSX
-	  && (c == FLOAT_REGS || c == ALTIVEC_REGS || c == VSX_REGS))
+      if (TARGET_VSX && VSX_REG_CLASS_P (c))
 	reg_size = UNITS_PER_VSX_WORD;
 
       else if (c == ALTIVEC_REGS)
@@ -1657,14 +1667,22 @@ rs6000_init_hard_regno_mode_ok (void)
 
       fprintf (stderr,
 	       "\n"
-	       "rs6000_vsx_v4sf_regclass    = %s\n"
-	       "rs6000_vsx_v2df_regclass    = %s\n"
-	       "rs6000_vsx_df_regclass      = %s\n"
-	       "rs6000_vsx_any_regclass     = %s\n\n",
-	       reg_class_names[rs6000_vsx_v4sf_regclass],
-	       reg_class_names[rs6000_vsx_v2df_regclass],
-	       reg_class_names[rs6000_vsx_df_regclass],
-	       reg_class_names[rs6000_vsx_any_regclass]);
+	       "V16QI reg_class = %s\n"
+	       "V8HI  reg_class = %s\n"
+	       "V4SI  reg_class = %s\n"
+	       "V2DI  reg_class = %s\n"
+	       "V4SF  reg_class = %s\n"
+	       "V2DF  reg_class = %s\n"
+	       "DF    reg_class = %s\n"
+	       "vsx   reg_class = %s\n\n",
+	       reg_class_names[rs6000_vector_reg_class[V16QImode]],
+	       reg_class_names[rs6000_vector_reg_class[V8HImode]],
+	       reg_class_names[rs6000_vector_reg_class[V4SImode]],
+	       reg_class_names[rs6000_vector_reg_class[V2DImode]],
+	       reg_class_names[rs6000_vector_reg_class[V4SFmode]],
+	       reg_class_names[rs6000_vector_reg_class[V2DFmode]],
+	       reg_class_names[rs6000_vector_reg_class[DFmode]],
+	       reg_class_names[rs6000_vsx_reg_class]);
 
       for (m = 0; m < NUM_MACHINE_MODES; ++m)
 	if (rs6000_vector_unit[m] || rs6000_vector_mem[m])
@@ -12042,8 +12060,7 @@ rs6000_preferred_reload_class (rtx x, en
   enum machine_mode mode = GET_MODE (x);
 
   if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode)
-      && (rclass == FLOAT_REGS || rclass == VSX_REGS
-	  || rclass == ALTIVEC_REGS))
+      && VSX_REG_CLASS_P (rclass))
     return rclass;
 
   if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) && rclass == ALTIVEC_REGS
@@ -12056,13 +12073,24 @@ rs6000_preferred_reload_class (rtx x, en
   if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
     return GENERAL_REGS;
 
+  /* For VSX, prefer the traditional registers.  */
+  if (rclass == VSX_REGS)
+    {
+      if (mode == DFmode)
+	return FLOAT_REGS;
+
+      if (ALTIVEC_VECTOR_MODE (mode))
+	return ALTIVEC_REGS;
+    }
+
   return rclass;
 }
 
-/* If we are copying between FP or AltiVec registers and anything
-   else, we need a memory location.  The exception is when we are
-   targeting ppc64 and the move to/from fpr to gpr instructions
-   are available.*/
+/* If we are copying between FP or AltiVec registers and anything else, we need
+   a memory location.  The exception is when we are targeting ppc64 and the
+   move to/from fpr to gpr instructions are available.  Also, under VSX, you
+   can copy vector registers from the FP register set to the Altivec register
+   set and vice versa.  */
 
 bool
 rs6000_secondary_memory_needed (enum reg_class class1,
@@ -12072,6 +12100,10 @@ rs6000_secondary_memory_needed (enum reg
   if (class1 == class2)
     return false;
 
+  if (TARGET_VSX && VSX_MOVE_MODE (mode) && VSX_REG_CLASS_P (class1)
+      && VSX_REG_CLASS_P (class2))
+    return false;
+
   if (class1 == FLOAT_REGS
        && (!TARGET_MFPGPR || !TARGET_POWERPC64
 	   || ((mode != DFmode)
@@ -12098,7 +12130,7 @@ rs6000_secondary_memory_needed (enum reg
 
 enum reg_class
 rs6000_secondary_reload_class (enum reg_class rclass,
-			       enum machine_mode mode ATTRIBUTE_UNUSED,
+			       enum machine_mode mode,
 			       rtx in)
 {
   int regno;
@@ -12154,6 +12186,13 @@ rs6000_secondary_reload_class (enum reg_
       && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
     return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
 
+  /* Memory, and FP/altivec registers can go into fp/altivec registers under
+     VSX.  */
+  if (TARGET_VSX
+      && (regno == -1 || VSX_REGNO_P (regno))
+      && VSX_REG_CLASS_P (rclass))
+    return NO_REGS;
+
   /* Memory, and AltiVec registers can go into AltiVec registers.  */
   if ((regno == -1 || ALTIVEC_REGNO_P (regno))
       && rclass == ALTIVEC_REGS)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 144438)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1019,7 +1019,11 @@ extern int rs6000_vector_align[];
 
 #define VSX_MOVE_MODE(MODE)		\
 	(VSX_VECTOR_MOVE_MODE (MODE)	\
-	 || VSX_SCALAR_MODE(MODE))
+	 || VSX_SCALAR_MODE(MODE)	\
+	 || (MODE) == V16QImode		\
+	 || (MODE) == V8HImode		\
+	 || (MODE) == V4SImode		\
+	 || (MODE) == V2DImode)
 
 #define ALTIVEC_VECTOR_MODE(MODE)	\
 	 ((MODE) == V16QImode		\
@@ -1303,15 +1307,17 @@ enum reg_class
   : NO_REGS)
 
 /* VSX register classes.  */
-extern enum reg_class rs6000_vsx_v4sf_regclass;
-extern enum reg_class rs6000_vsx_v2df_regclass;
-extern enum reg_class rs6000_vsx_df_regclass;
-extern enum reg_class rs6000_vsx_any_regclass;
+extern enum reg_class rs6000_vector_reg_class[];
+extern enum reg_class rs6000_vsx_reg_class;
 
 /* The class value for index registers, and the one for base regs.  */
 #define INDEX_REG_CLASS GENERAL_REGS
 #define BASE_REG_CLASS BASE_REGS
 
+/* Return whether a given register class can hold VSX objects.  */
+#define VSX_REG_CLASS_P(CLASS)			\
+  ((CLASS) == VSX_REGS || (CLASS) == FLOAT_REGS || (CLASS) == ALTIVEC_REGS)
+
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
    In general this is just CLASS; but on some machines

-- 
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
meissner@linux.vnet.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]