diff options
author | Michael Meissner <meissner@linux.vnet.ibm.com> | 2016-10-27 20:52:07 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 2016-10-27 20:52:07 +0000 |
commit | 787c7a65f6ec2876337e6c50a26a1da0fadcb5bf (patch) | |
tree | 6fef9d9f4d0a61bd0a82f599ed70624bc18e9835 /gcc/config/rs6000/rs6000.c | |
parent | 6f21288f8c3579ec7ae47615e76ba1e6ad25551f (diff) | |
download | gcc-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.c | 120 |
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 |