aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r--gcc/config/rs6000/rs6000.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 31e9301..ba00b61 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -409,6 +409,13 @@ mode_supports_pre_modify_p (machine_mode mode)
!= 0);
}
+/* Return true if we have D-form addressing in altivec registers. */
+static inline bool
+mode_supports_vmx_dform (machine_mode mode)
+{
+ return ((reg_addr[mode].addr_mask[RELOAD_REG_VMX] & RELOAD_REG_OFFSET) != 0);
+}
+
/* Target cpu costs. */
@@ -2263,7 +2270,9 @@ rs6000_debug_reg_global (void)
"f reg_class = %s\n"
"v reg_class = %s\n"
"wa reg_class = %s\n"
+ "wb reg_class = %s\n"
"wd reg_class = %s\n"
+ "we reg_class = %s\n"
"wf reg_class = %s\n"
"wg reg_class = %s\n"
"wh reg_class = %s\n"
@@ -2288,7 +2297,9 @@ rs6000_debug_reg_global (void)
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_f]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_v]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wa]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wb]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wd]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_we]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wf]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wg]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wh]],
@@ -2669,9 +2680,15 @@ rs6000_setup_reg_addr_masks (void)
}
/* GPR and FPR registers can do REG+OFFSET addressing, except
- possibly for SDmode. */
+ possibly for SDmode. ISA 3.0 (i.e. power9) adds D-form
+ addressing for scalars to altivec registers. */
if ((addr_mask != 0) && !indexed_only_p
- && (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR))
+ && msize <= 8
+ && (rc == RELOAD_REG_GPR
+ || rc == RELOAD_REG_FPR
+ || (rc == RELOAD_REG_VMX
+ && TARGET_P9_DFORM
+ && (m2 == DFmode || m2 == SFmode))))
addr_mask |= RELOAD_REG_OFFSET;
/* VMX registers can do (REG & -16) and ((REG+REG) & -16)
@@ -2995,6 +3012,10 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS; /* TFmode */
}
+ /* Support for new D-form instructions. */
+ if (TARGET_P9_DFORM)
+ rs6000_constraints[RS6000_CONSTRAINT_wb] = ALTIVEC_REGS;
+
/* Support for new direct moves. */
if (TARGET_DIRECT_MOVE_128)
rs6000_constraints[RS6000_CONSTRAINT_we] = VSX_REGS;
@@ -18260,8 +18281,10 @@ rs6000_secondary_reload (bool in_p,
/* If this is a scalar floating point value and we want to load it into the
traditional Altivec registers, do it via a move via a traditional floating
- point register. Also make sure that non-zero constants use a FPR. */
+ point register, unless we have D-form addressing. Also make sure that
+ non-zero constants use a FPR. */
if (!done_p && reg_addr[mode].scalar_in_vmx_p
+ && !mode_supports_vmx_dform (mode)
&& (rclass == VSX_REGS || rclass == ALTIVEC_REGS)
&& (memory_p || (GET_CODE (x) == CONST_DOUBLE)))
{
@@ -18825,10 +18848,14 @@ rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
return NO_REGS;
}
- /* If this is a scalar floating point value, prefer the traditional
- floating point registers so that we can use D-form (register+offset)
- addressing. */
- if (GET_MODE_SIZE (mode) < 16)
+ /* D-form addressing can easily reload the value. */
+ if (mode_supports_vmx_dform (mode))
+ return rclass;
+
+ /* If this is a scalar floating point value and we don't have D-form
+ addressing, prefer the traditional floating point registers so that we
+ can use D-form (register+offset) addressing. */
+ if (GET_MODE_SIZE (mode) < 16 && rclass == VSX_REGS)
return FLOAT_REGS;
/* Prefer the Altivec registers if Altivec is handling the vector
@@ -18977,6 +19004,7 @@ rs6000_secondary_reload_class (enum reg_class rclass, machine_mode mode,
instead of reloading the secondary memory address for Altivec moves. */
if (TARGET_VSX
&& GET_MODE_SIZE (mode) < 16
+ && !mode_supports_vmx_dform (mode)
&& (((rclass == GENERAL_REGS || rclass == BASE_REGS)
&& (regno >= 0 && ALTIVEC_REGNO_P (regno)))
|| ((rclass == VSX_REGS || rclass == ALTIVEC_REGS)