aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/rs6000/rs6000.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/rs6000/rs6000.c')
-rw-r--r--gcc-4.9/gcc/config/rs6000/rs6000.c149
1 files changed, 97 insertions, 52 deletions
diff --git a/gcc-4.9/gcc/config/rs6000/rs6000.c b/gcc-4.9/gcc/config/rs6000/rs6000.c
index d7cbc6cde..28ccf86df 100644
--- a/gcc-4.9/gcc/config/rs6000/rs6000.c
+++ b/gcc-4.9/gcc/config/rs6000/rs6000.c
@@ -388,6 +388,7 @@ struct rs6000_reg_addr {
enum insn_code reload_gpr_vsx; /* INSN to move from GPR to VSX. */
enum insn_code reload_vsx_gpr; /* INSN to move from VSX to GPR. */
addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks. */
+ bool scalar_in_vmx_p; /* Scalar value can go in VMX. */
};
static struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
@@ -1221,7 +1222,12 @@ char rs6000_reg_names[][8] =
/* Soft frame pointer. */
"sfp",
/* HTM SPR registers. */
- "tfhar", "tfiar", "texasr"
+ "tfhar", "tfiar", "texasr",
+ /* SPE High registers. */
+ "0", "1", "2", "3", "4", "5", "6", "7",
+ "8", "9", "10", "11", "12", "13", "14", "15",
+ "16", "17", "18", "19", "20", "21", "22", "23",
+ "24", "25", "26", "27", "28", "29", "30", "31"
};
#ifdef TARGET_REGNAMES
@@ -1249,7 +1255,12 @@ static const char alt_reg_names[][8] =
/* Soft frame pointer. */
"sfp",
/* HTM SPR registers. */
- "tfhar", "tfiar", "texasr"
+ "tfhar", "tfiar", "texasr",
+ /* SPE High registers. */
+ "%rh0", "%rh1", "%rh2", "%rh3", "%rh4", "%rh5", "%rh6", "%rh7",
+ "%rh8", "%rh9", "%rh10", "%r11", "%rh12", "%rh13", "%rh14", "%rh15",
+ "%rh16", "%rh17", "%rh18", "%rh19", "%rh20", "%rh21", "%rh22", "%rh23",
+ "%rh24", "%rh25", "%rh26", "%rh27", "%rh28", "%rh29", "%rh30", "%rh31"
};
#endif
@@ -1723,8 +1734,7 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
asked for it. */
if (TARGET_VSX && VSX_REGNO_P (regno)
&& (VECTOR_MEM_VSX_P (mode)
- || (TARGET_VSX_SCALAR_FLOAT && mode == SFmode)
- || (TARGET_VSX_SCALAR_DOUBLE && (mode == DFmode || mode == DImode))
+ || reg_addr[mode].scalar_in_vmx_p
|| (TARGET_VSX_TIMODE && mode == TImode)
|| (TARGET_VADDUQM && mode == V1TImode)))
{
@@ -1733,10 +1743,7 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
if (ALTIVEC_REGNO_P (regno))
{
- if (mode == SFmode && !TARGET_UPPER_REGS_SF)
- return 0;
-
- if ((mode == DFmode || mode == DImode) && !TARGET_UPPER_REGS_DF)
+ if (GET_MODE_SIZE (mode) != 16 && !reg_addr[mode].scalar_in_vmx_p)
return 0;
return ALTIVEC_REGNO_P (last_regno);
@@ -1916,14 +1923,16 @@ rs6000_debug_print_mode (ssize_t m)
if (rs6000_vector_unit[m] != VECTOR_NONE
|| rs6000_vector_mem[m] != VECTOR_NONE
|| (reg_addr[m].reload_store != CODE_FOR_nothing)
- || (reg_addr[m].reload_load != CODE_FOR_nothing))
+ || (reg_addr[m].reload_load != CODE_FOR_nothing)
+ || reg_addr[m].scalar_in_vmx_p)
{
fprintf (stderr,
- " Vector-arith=%-10s Vector-mem=%-10s Reload=%c%c",
+ " Vector-arith=%-10s Vector-mem=%-10s Reload=%c%c Upper=%c",
rs6000_debug_vector_unit (rs6000_vector_unit[m]),
rs6000_debug_vector_unit (rs6000_vector_mem[m]),
(reg_addr[m].reload_store != CODE_FOR_nothing) ? 's' : '*',
- (reg_addr[m].reload_load != CODE_FOR_nothing) ? 'l' : '*');
+ (reg_addr[m].reload_load != CODE_FOR_nothing) ? 'l' : '*',
+ (reg_addr[m].scalar_in_vmx_p) ? 'y' : 'n');
}
fputs ("\n", stderr);
@@ -2040,6 +2049,10 @@ rs6000_debug_reg_global (void)
"wd reg_class = %s\n"
"wf reg_class = %s\n"
"wg reg_class = %s\n"
+ "wh reg_class = %s\n"
+ "wi reg_class = %s\n"
+ "wj reg_class = %s\n"
+ "wk reg_class = %s\n"
"wl reg_class = %s\n"
"wm reg_class = %s\n"
"wr reg_class = %s\n"
@@ -2059,6 +2072,10 @@ rs6000_debug_reg_global (void)
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wd]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wf]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wg]],
+ 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]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wm]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]],
@@ -2347,6 +2364,8 @@ rs6000_setup_reg_addr_masks (void)
for (m = 0; m < NUM_MACHINE_MODES; ++m)
{
+ enum machine_mode m2 = (enum machine_mode)m;
+
/* SDmode is special in that we want to access it only via REG+REG
addressing on power7 and above, since we want to use the LFIWZX and
STFIWZX instructions to load it. */
@@ -2381,13 +2400,12 @@ rs6000_setup_reg_addr_masks (void)
if (TARGET_UPDATE
&& (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR)
- && GET_MODE_SIZE (m) <= 8
- && !VECTOR_MODE_P (m)
- && !COMPLEX_MODE_P (m)
+ && GET_MODE_SIZE (m2) <= 8
+ && !VECTOR_MODE_P (m2)
+ && !COMPLEX_MODE_P (m2)
&& !indexed_only_p
- && !(TARGET_E500_DOUBLE && GET_MODE_SIZE (m) == 8)
- && !(m == DFmode && TARGET_UPPER_REGS_DF)
- && !(m == SFmode && TARGET_UPPER_REGS_SF))
+ && !(TARGET_E500_DOUBLE && GET_MODE_SIZE (m2) == 8)
+ && !reg_addr[m2].scalar_in_vmx_p)
{
addr_mask |= RELOAD_REG_PRE_INCDEC;
@@ -2618,37 +2636,44 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
f - Register class to use with traditional SFmode instructions.
v - Altivec register.
wa - Any VSX register.
+ wc - Reserved to represent individual CR bits (used in LLVM).
wd - Preferred register class for V2DFmode.
wf - Preferred register class for V4SFmode.
wg - Float register for power6x move insns.
+ wh - FP register for direct move instructions.
+ wi - FP or VSX register to hold 64-bit integers for VSX insns.
+ wj - FP or VSX register to hold 64-bit integers for direct moves.
+ wk - FP or VSX register to hold 64-bit doubles for direct moves.
wl - Float register if we can do 32-bit signed int loads.
wm - VSX register for ISA 2.07 direct move operations.
+ wn - always NO_REGS.
wr - GPR if 64-bit mode is permitted.
ws - Register class to do ISA 2.06 DF operations.
+ wt - VSX register for TImode in VSX registers.
wu - Altivec register for ISA 2.07 VSX SF/SI load/stores.
wv - Altivec register for ISA 2.06 VSX DF/DI load/stores.
- wt - VSX register for TImode in VSX registers.
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. */
if (TARGET_HARD_FLOAT && TARGET_FPRS)
- rs6000_constraints[RS6000_CONSTRAINT_f] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_f] = FLOAT_REGS; /* SFmode */
if (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
- rs6000_constraints[RS6000_CONSTRAINT_d] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_d] = FLOAT_REGS; /* DFmode */
if (TARGET_VSX)
{
rs6000_constraints[RS6000_CONSTRAINT_wa] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wd] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wd] = VSX_REGS; /* V2DFmode */
+ rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS; /* V4SFmode */
+ rs6000_constraints[RS6000_CONSTRAINT_wi] = FLOAT_REGS; /* DImode */
if (TARGET_VSX_TIMODE)
- rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS; /* TImode */
- if (TARGET_UPPER_REGS_DF)
+ if (TARGET_UPPER_REGS_DF) /* DFmode */
{
rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS;
rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
@@ -2662,19 +2687,26 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_ALTIVEC)
rs6000_constraints[RS6000_CONSTRAINT_v] = ALTIVEC_REGS;
- if (TARGET_MFPGPR)
+ if (TARGET_MFPGPR) /* DFmode */
rs6000_constraints[RS6000_CONSTRAINT_wg] = FLOAT_REGS;
if (TARGET_LFIWAX)
- rs6000_constraints[RS6000_CONSTRAINT_wl] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wl] = FLOAT_REGS; /* DImode */
if (TARGET_DIRECT_MOVE)
- rs6000_constraints[RS6000_CONSTRAINT_wm] = VSX_REGS;
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_wh] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wj] /* DImode */
+ = rs6000_constraints[RS6000_CONSTRAINT_wi];
+ rs6000_constraints[RS6000_CONSTRAINT_wk] /* DFmode */
+ = rs6000_constraints[RS6000_CONSTRAINT_ws];
+ rs6000_constraints[RS6000_CONSTRAINT_wm] = VSX_REGS;
+ }
if (TARGET_POWERPC64)
rs6000_constraints[RS6000_CONSTRAINT_wr] = GENERAL_REGS;
- if (TARGET_P8_VECTOR && TARGET_UPPER_REGS_SF)
+ if (TARGET_P8_VECTOR && TARGET_UPPER_REGS_SF) /* SFmode */
{
rs6000_constraints[RS6000_CONSTRAINT_wu] = ALTIVEC_REGS;
rs6000_constraints[RS6000_CONSTRAINT_wy] = VSX_REGS;
@@ -2689,10 +2721,10 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS;
if (TARGET_STFIWX)
- rs6000_constraints[RS6000_CONSTRAINT_wx] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wx] = FLOAT_REGS; /* DImode */
if (TARGET_LFIWZX)
- rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS; /* DImode */
/* Set up the reload helper and direct move functions. */
if (TARGET_VSX || TARGET_ALTIVEC)
@@ -2715,10 +2747,11 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[V2DFmode].reload_load = CODE_FOR_reload_v2df_di_load;
if (TARGET_VSX && TARGET_UPPER_REGS_DF)
{
- reg_addr[DFmode].reload_store = CODE_FOR_reload_df_di_store;
- reg_addr[DFmode].reload_load = CODE_FOR_reload_df_di_load;
- reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_di_store;
- reg_addr[DDmode].reload_load = CODE_FOR_reload_dd_di_load;
+ reg_addr[DFmode].reload_store = CODE_FOR_reload_df_di_store;
+ reg_addr[DFmode].reload_load = CODE_FOR_reload_df_di_load;
+ reg_addr[DFmode].scalar_in_vmx_p = true;
+ reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_di_store;
+ reg_addr[DDmode].reload_load = CODE_FOR_reload_dd_di_load;
}
if (TARGET_P8_VECTOR)
{
@@ -2726,6 +2759,8 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[SFmode].reload_load = CODE_FOR_reload_sf_di_load;
reg_addr[SDmode].reload_store = CODE_FOR_reload_sd_di_store;
reg_addr[SDmode].reload_load = CODE_FOR_reload_sd_di_load;
+ if (TARGET_UPPER_REGS_SF)
+ reg_addr[SFmode].scalar_in_vmx_p = true;
}
if (TARGET_VSX_TIMODE)
{
@@ -2782,10 +2817,11 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[V2DFmode].reload_load = CODE_FOR_reload_v2df_si_load;
if (TARGET_VSX && TARGET_UPPER_REGS_DF)
{
- reg_addr[DFmode].reload_store = CODE_FOR_reload_df_si_store;
- reg_addr[DFmode].reload_load = CODE_FOR_reload_df_si_load;
- reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_si_store;
- reg_addr[DDmode].reload_load = CODE_FOR_reload_dd_si_load;
+ reg_addr[DFmode].reload_store = CODE_FOR_reload_df_si_store;
+ reg_addr[DFmode].reload_load = CODE_FOR_reload_df_si_load;
+ reg_addr[DFmode].scalar_in_vmx_p = true;
+ reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_si_store;
+ reg_addr[DDmode].reload_load = CODE_FOR_reload_dd_si_load;
}
if (TARGET_P8_VECTOR)
{
@@ -2793,6 +2829,8 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[SFmode].reload_load = CODE_FOR_reload_sf_si_load;
reg_addr[SDmode].reload_store = CODE_FOR_reload_sd_si_store;
reg_addr[SDmode].reload_load = CODE_FOR_reload_sd_si_load;
+ if (TARGET_UPPER_REGS_SF)
+ reg_addr[SFmode].scalar_in_vmx_p = true;
}
if (TARGET_VSX_TIMODE)
{
@@ -2833,6 +2871,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
for (m = 0; m < NUM_MACHINE_MODES; ++m)
{
+ enum machine_mode m2 = (enum machine_mode)m;
int reg_size2 = reg_size;
/* TFmode/TDmode always takes 2 registers, even in VSX. */
@@ -2841,7 +2880,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_size2 = UNITS_PER_FP_WORD;
rs6000_class_max_nregs[m][c]
- = (GET_MODE_SIZE (m) + reg_size2 - 1) / reg_size2;
+ = (GET_MODE_SIZE (m2) + reg_size2 - 1) / reg_size2;
}
}
@@ -17167,7 +17206,14 @@ rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
prefer Altivec loads.. */
if (rclass == VSX_REGS)
{
- if (GET_MODE_SIZE (mode) <= 8)
+ if (MEM_P (x) && reg_addr[mode].scalar_in_vmx_p)
+ {
+ rtx addr = XEXP (x, 0);
+ if (rs6000_legitimate_offset_address_p (mode, addr, false, true)
+ || legitimate_lo_sum_address_p (mode, addr, false))
+ return FLOAT_REGS;
+ }
+ else if (GET_MODE_SIZE (mode) <= 8 && !reg_addr[mode].scalar_in_vmx_p)
return FLOAT_REGS;
if (VECTOR_UNIT_ALTIVEC_P (mode) || VECTOR_MEM_ALTIVEC_P (mode)
@@ -31171,13 +31217,13 @@ rs6000_dwarf_register_span (rtx reg)
{
if (BYTES_BIG_ENDIAN)
{
- parts[2 * i] = gen_rtx_REG (SImode, regno + 1200);
+ parts[2 * i] = gen_rtx_REG (SImode, regno + FIRST_SPE_HIGH_REGNO);
parts[2 * i + 1] = gen_rtx_REG (SImode, regno);
}
else
{
parts[2 * i] = gen_rtx_REG (SImode, regno);
- parts[2 * i + 1] = gen_rtx_REG (SImode, regno + 1200);
+ parts[2 * i + 1] = gen_rtx_REG (SImode, regno + FIRST_SPE_HIGH_REGNO);
}
}
@@ -31197,11 +31243,11 @@ rs6000_init_dwarf_reg_sizes_extra (tree address)
rtx mem = gen_rtx_MEM (BLKmode, addr);
rtx value = gen_int_mode (4, mode);
- for (i = 1201; i < 1232; i++)
+ for (i = FIRST_SPE_HIGH_REGNO; i < LAST_SPE_HIGH_REGNO+1; i++)
{
- int column = DWARF_REG_TO_UNWIND_COLUMN (i);
- HOST_WIDE_INT offset
- = DWARF_FRAME_REGNUM (column) * GET_MODE_SIZE (mode);
+ int column = DWARF_REG_TO_UNWIND_COLUMN
+ (DWARF2_FRAME_REG_OUT (DWARF_FRAME_REGNUM (i), true));
+ HOST_WIDE_INT offset = column * GET_MODE_SIZE (mode);
emit_move_insn (adjust_address (mem, mode, offset), value);
}
@@ -31220,9 +31266,9 @@ rs6000_init_dwarf_reg_sizes_extra (tree address)
for (i = FIRST_ALTIVEC_REGNO; i < LAST_ALTIVEC_REGNO+1; i++)
{
- int column = DWARF_REG_TO_UNWIND_COLUMN (i);
- HOST_WIDE_INT offset
- = DWARF_FRAME_REGNUM (column) * GET_MODE_SIZE (mode);
+ int column = DWARF_REG_TO_UNWIND_COLUMN
+ (DWARF2_FRAME_REG_OUT (DWARF_FRAME_REGNUM (i), true));
+ HOST_WIDE_INT offset = column * GET_MODE_SIZE (mode);
emit_move_insn (adjust_address (mem, mode, offset), value);
}
@@ -31254,9 +31300,8 @@ rs6000_dbx_register_number (unsigned int regno)
return 99;
if (regno == SPEFSCR_REGNO)
return 612;
- /* SPE high reg number. We get these values of regno from
- rs6000_dwarf_register_span. */
- gcc_assert (regno >= 1200 && regno < 1232);
+ if (SPE_HIGH_REGNO_P (regno))
+ return regno - FIRST_SPE_HIGH_REGNO + 1200;
return regno;
}