aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.c
diff options
context:
space:
mode:
authorMichael Meissner <meissner@linux.vnet.ibm.com>2016-10-27 20:52:07 +0000
committerMichael Meissner <meissner@gcc.gnu.org>2016-10-27 20:52:07 +0000
commit787c7a65f6ec2876337e6c50a26a1da0fadcb5bf (patch)
tree6fef9d9f4d0a61bd0a82f599ed70624bc18e9835 /gcc/config/rs6000/rs6000.c
parent6f21288f8c3579ec7ae47615e76ba1e6ad25551f (diff)
downloadgcc-787c7a65f6ec2876337e6c50a26a1da0fadcb5bf.zip
gcc-787c7a65f6ec2876337e6c50a26a1da0fadcb5bf.tar.gz
gcc-787c7a65f6ec2876337e6c50a26a1da0fadcb5bf.tar.bz2
constraints.md (wH constraint): Add new constraints for allowing 32-bit integers (and eventually 8/16-bit...
[gcc] 2016-10-27 Michael Meissner <meissner@linux.vnet.ibm.com> * config/rs6000/constraints.md (wH constraint): Add new constraints for allowing 32-bit integers (and eventually 8/16-bit integers) into the vector registers. (wI constraint): Likewise. (wJ constraint): Likewise. (wK constraint): Likewise. * config/rs6000/rs6000-cpus.def (ISA_2_7_MASKS_SERVER): Add -mvsx-small-integer as a default option for ISA 2.07 (i.e. power8). (POWERPC_MASKS): Likewise. * config/rs6000/rs6000.opt (-mvsx-small-integer): Add new debug switch to turn off small integer support in vector registers. * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Eliminate test for -mupper-regs-di, since it is already done with the reg_add[mode].scalar_in_vsx_p. Add support for the switch -mvsx-small-integer. (rs6000_debug_reg_global): Add support for wH, wI, wJ, and wK constraints. (rs6000_setup_reg_addr_masks): Likewise. (rs6000_init_hard_regno_mode_ok): Likewise. (rs6000_option_override_internal): Add consistency checks for -mvsx-small-integer. (rs6000_secondary_reload_simple_move): SImode is a simple move if -mvsx-small-integer. (rs6000_secondary_reload): Use std::swap. (rs6000_preferred_reload_class): Don't prefer FLOAT_REGS over VSX_REGS for small integers in vector registers, since there is no D-FORM address mode for such types. (rs6000_register_move_cost): Use FIRST_FPR_REGNO instead of 32. (rs6000_opt_masks): Add -mvsx-small-integer. * config/rs6000/vsx.md (VSINT_84): Add SImode for small integer support. (VSX_EXTRACT_I2): Clone VSX_EXTRACT_I, but drop V4SI since SImode extracts can be done on ISA 2.07. (vsx_extract_<mode>): Add support for small integers in vsx registers. (vsx_extract_<mode>_p9): Use 'v' instead of VSX_EX, since we no longer support V4SImode in this pattern. (vsx_extract_si): New insn to support extraction of SImode in ISA 2.07 using either xxextractuw or vspltw. (vsx_extract_<mode>_p8): Use 'v' instead of VSX_EX, since we no longer support V4SImode in this pattern. * config/rs6000/rs6000.h (enum rs6000_reg_class_enum): Add wH, wI, wJ, and wK constraints. * config/rs6000/rs6000.md (f32_sv): Use correct instruction for storing SDmode with VSX instructions. (zero_extendsi<mode>2): Reorder pattern, so RLDICL comes after the GPR load and before the FPR and VSX loads. Remove ??, ! from the constraints. Add MFVSRWZ and XXEXTRACTUW instructions to support small integers in vector registers. (extendsi<mode>2): Reorder pattern, so EXTSW comes after the GPR load and before the FPR and VSX loads. Remove ??, ! from the constraints. Add VEXTSW2D support for small integers in vector registers. (lfiwax): Remove ! constraint. Add VEXTSW2D support for small integers in vector registers. (floatsi<mode>2_lfiwax): If -mvsx-small-integer issue a normal move instead of using an UNSPEC. (lfiwzx): Remove ! constraint. Add XXEXTRACTUW support for small integers in vector registers. (floatunssi<mode>2_lfiwzx): If -mvsx-small-integer issue a normal move instead of using an UNSPEC. (movsi_internal1): Add support for -mvsx-small-integer. Align columns so that it is more readable. (SImode splitter for ISA 3.0 constants): Add splitter for -128..127 constants that can easily be constructed on ISA 3.0. * doc/md.texi (PowerPC Constraints): Document wH, wI, wJ, and wK constraints. [gcc/testsuite] 2016-10-27 Michael Meissner <meissner@linux.vnet.ibm.com> * gcc.target/powerpc/vsx-simode.c: New test. * gcc.target/powerpc/vsx-simode2.c: Likewise. * gcc.target/powerpc/vsx-simode3.c: Likewise. From-SVN: r241631
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r--gcc/config/rs6000/rs6000.c120
1 files changed, 93 insertions, 27 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 5e35e33..f9e4739 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1980,8 +1980,7 @@ rs6000_hard_regno_mode_ok (int regno, machine_mode mode)
|| FLOAT128_VECTOR_P (mode)
|| reg_addr[mode].scalar_in_vmx_p
|| (TARGET_VSX_TIMODE && mode == TImode)
- || (TARGET_VADDUQM && mode == V1TImode)
- || (TARGET_UPPER_REGS_DI && mode == DImode)))
+ || (TARGET_VADDUQM && mode == V1TImode)))
{
if (FP_REGNO_P (regno))
return FP_REGNO_P (last_regno);
@@ -2012,9 +2011,14 @@ rs6000_hard_regno_mode_ok (int regno, machine_mode mode)
&& FP_REGNO_P (last_regno))
return 1;
- if (GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
- return 1;
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ if(GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
+ return 1;
+
+ if (TARGET_VSX_SMALL_INTEGER && mode == SImode)
+ return 1;
+ }
if (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
&& PAIRED_VECTOR_MODE (mode))
@@ -2447,6 +2451,10 @@ rs6000_debug_reg_global (void)
"wx reg_class = %s\n"
"wy reg_class = %s\n"
"wz reg_class = %s\n"
+ "wH reg_class = %s\n"
+ "wI reg_class = %s\n"
+ "wJ reg_class = %s\n"
+ "wK reg_class = %s\n"
"\n",
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_d]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_f]],
@@ -2474,7 +2482,11 @@ rs6000_debug_reg_global (void)
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ww]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wy]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wz]]);
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wz]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wH]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wI]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wJ]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wK]]);
nl = "\n";
for (m = 0; m < NUM_MACHINE_MODES; ++m)
@@ -2770,6 +2782,7 @@ rs6000_setup_reg_addr_masks (void)
{
machine_mode m2 = (machine_mode) m;
bool complex_p = false;
+ bool small_int_p = (m2 == QImode || m2 == HImode || m2 == SImode);
size_t msize;
if (COMPLEX_MODE_P (m2))
@@ -2794,13 +2807,20 @@ rs6000_setup_reg_addr_masks (void)
/* Can mode values go in the GPR/FPR/Altivec registers? */
if (reg >= 0 && rs6000_hard_regno_mode_ok_p[m][reg])
{
+ bool small_int_vsx_p = (small_int_p
+ && (rc == RELOAD_REG_FPR
+ || rc == RELOAD_REG_VMX));
+
nregs = rs6000_hard_regno_nregs[m][reg];
addr_mask |= RELOAD_REG_VALID;
/* Indicate if the mode takes more than 1 physical register. If
it takes a single register, indicate it can do REG+REG
- addressing. */
- if (nregs > 1 || m == BLKmode || complex_p)
+ addressing. Small integers in VSX registers can only do
+ REG+REG addressing. */
+ if (small_int_vsx_p)
+ addr_mask |= RELOAD_REG_INDEXED;
+ else if (nregs > 1 || m == BLKmode || complex_p)
addr_mask |= RELOAD_REG_MULTIPLE;
else
addr_mask |= RELOAD_REG_INDEXED;
@@ -2817,6 +2837,7 @@ rs6000_setup_reg_addr_masks (void)
&& !VECTOR_MODE_P (m2)
&& !FLOAT128_VECTOR_P (m2)
&& !complex_p
+ && !small_int_vsx_p
&& (m2 != DFmode || !TARGET_UPPER_REGS_DF)
&& (m2 != SFmode || !TARGET_UPPER_REGS_SF)
&& !(TARGET_E500_DOUBLE && msize == 8))
@@ -3115,7 +3136,11 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
ww - Register class to do SF conversions in with VSX operations.
wx - Float register if we can do 32-bit int stores.
wy - Register class to do ISA 2.07 SF operations.
- wz - Float register if we can do 32-bit unsigned int loads. */
+ wz - Float register if we can do 32-bit unsigned int loads.
+ wH - Altivec register if SImode is allowed in VSX registers.
+ wI - VSX register if SImode is allowed in VSX registers.
+ wJ - VSX register if QImode/HImode are allowed in VSX registers.
+ wK - Altivec register if QImode/HImode are allowed in VSX registers. */
if (TARGET_HARD_FLOAT && TARGET_FPRS)
rs6000_constraints[RS6000_CONSTRAINT_f] = FLOAT_REGS; /* SFmode */
@@ -3209,6 +3234,18 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_DIRECT_MOVE_128)
rs6000_constraints[RS6000_CONSTRAINT_we] = VSX_REGS;
+ /* Support small integers in VSX registers. */
+ if (TARGET_VSX_SMALL_INTEGER)
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_wH] = ALTIVEC_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wI] = FLOAT_REGS;
+ if (TARGET_P9_VECTOR)
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_wJ] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wK] = ALTIVEC_REGS;
+ }
+ }
+
/* Set up the reload helper and direct move functions. */
if (TARGET_VSX || TARGET_ALTIVEC)
{
@@ -3361,6 +3398,9 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_UPPER_REGS_SF)
reg_addr[SFmode].scalar_in_vmx_p = true;
+
+ if (TARGET_VSX_SMALL_INTEGER)
+ reg_addr[SImode].scalar_in_vmx_p = true;
}
/* Setup the fusion operations. */
@@ -4433,6 +4473,20 @@ rs6000_option_override_internal (bool global_init_p)
}
}
+ /* Check whether we should allow small integers into VSX registers. We
+ require direct move to prevent the register allocator from having to move
+ variables through memory to do moves. SImode can be used on ISA 2.07,
+ while HImode and QImode require ISA 3.0. */
+ if (TARGET_VSX_SMALL_INTEGER
+ && (!TARGET_DIRECT_MOVE || !TARGET_P8_VECTOR || !TARGET_UPPER_REGS_DI))
+ {
+ if (rs6000_isa_flags_explicit & OPTION_MASK_VSX_SMALL_INTEGER)
+ error ("-mvsx-small-integer requires -mpower8-vector, "
+ "-mupper-regs-di, and -mdirect-move");
+
+ rs6000_isa_flags &= ~OPTION_MASK_VSX_SMALL_INTEGER;
+ }
+
/* Set long double size before the IEEE 128-bit tests. */
if (!global_options_set.x_rs6000_long_double_type_size)
{
@@ -20485,32 +20539,46 @@ rs6000_secondary_reload_simple_move (enum rs6000_reg_type to_type,
enum rs6000_reg_type from_type,
machine_mode mode)
{
- int size;
+ int size = GET_MODE_SIZE (mode);
/* Add support for various direct moves available. In this function, we only
look at cases where we don't need any extra registers, and one or more
- simple move insns are issued. At present, 32-bit integers are not allowed
+ simple move insns are issued. Originally small integers are not allowed
in FPR/VSX registers. Single precision binary floating is not a simple
move because we need to convert to the single precision memory layout.
The 4-byte SDmode can be moved. TDmode values are disallowed since they
need special direct move handling, which we do not support yet. */
- size = GET_MODE_SIZE (mode);
if (TARGET_DIRECT_MOVE
- && ((mode == SDmode) || (TARGET_POWERPC64 && size == 8))
&& ((to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE)
|| (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE)))
- return true;
+ {
+ if (TARGET_POWERPC64)
+ {
+ /* ISA 2.07: MTVSRD or MVFVSRD. */
+ if (size == 8)
+ return true;
- else if (TARGET_DIRECT_MOVE_128 && size == 16 && mode != TDmode
- && ((to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE)
- || (to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE)))
- return true;
+ /* ISA 3.0: MTVSRDD or MFVSRD + MFVSRLD. */
+ if (size == 16 && TARGET_P9_VECTOR && mode != TDmode)
+ return true;
+ }
+
+ /* ISA 2.07: MTVSRWZ or MFVSRWZ. */
+ if (TARGET_VSX_SMALL_INTEGER && mode == SImode)
+ return true;
+
+ /* ISA 2.07: MTVSRWZ or MFVSRWZ. */
+ if (mode == SDmode)
+ return true;
+ }
+ /* Power6+: MFTGPR or MFFGPR. */
else if (TARGET_MFPGPR && TARGET_POWERPC64 && size == 8
- && ((to_type == GPR_REG_TYPE && from_type == FPR_REG_TYPE)
- || (to_type == FPR_REG_TYPE && from_type == GPR_REG_TYPE)))
+ && ((to_type == GPR_REG_TYPE && from_type == FPR_REG_TYPE)
+ || (to_type == FPR_REG_TYPE && from_type == GPR_REG_TYPE)))
return true;
+ /* Move to/from SPR. */
else if ((size == 4 || (TARGET_POWERPC64 && size == 8))
&& ((to_type == GPR_REG_TYPE && from_type == SPR_REG_TYPE)
|| (to_type == SPR_REG_TYPE && from_type == GPR_REG_TYPE)))
@@ -20686,11 +20754,7 @@ rs6000_secondary_reload (bool in_p,
enum rs6000_reg_type from_type = register_to_reg_type (x, &altivec_p);
if (!in_p)
- {
- enum rs6000_reg_type exchange = to_type;
- to_type = from_type;
- from_type = exchange;
- }
+ std::swap (to_type, from_type);
/* Can we do a direct move of some sort? */
if (rs6000_secondary_reload_move (to_type, from_type, mode, sri,
@@ -21318,7 +21382,8 @@ rs6000_preferred_reload_class (rtx x, enum reg_class 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)
+ if (rclass == VSX_REGS
+ && (mode == SFmode || GET_MODE_SIZE (mode) == 8))
return FLOAT_REGS;
/* Prefer the Altivec registers if Altivec is handling the vector
@@ -35898,7 +35963,7 @@ rs6000_register_move_cost (machine_mode mode,
else if (VECTOR_MEM_VSX_P (mode)
&& reg_classes_intersect_p (to, VSX_REGS)
&& reg_classes_intersect_p (from, VSX_REGS))
- ret = 2 * hard_regno_nregs[32][mode];
+ ret = 2 * hard_regno_nregs[FIRST_FPR_REGNO][mode];
/* Moving between two similar registers is just one instruction. */
else if (reg_classes_intersect_p (to, from))
@@ -37504,6 +37569,7 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "upper-regs-df", OPTION_MASK_UPPER_REGS_DF, false, true },
{ "upper-regs-sf", OPTION_MASK_UPPER_REGS_SF, false, true },
{ "vsx", OPTION_MASK_VSX, false, true },
+ { "vsx-small-integer", OPTION_MASK_VSX_SMALL_INTEGER, false, true },
{ "vsx-timode", OPTION_MASK_VSX_TIMODE, false, true },
#ifdef OPTION_MASK_64BIT
#if TARGET_AIX_OS