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