This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[power7-meissner] Fix secondary register classes
- From: Michael Meissner <meissner at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 26 Feb 2009 18:19:23 -0500
- Subject: [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