diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 42 |
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) |