https://gcc.gnu.org/g:2548121b626ef79434bf71e9040ae3969e7c98d9
commit 2548121b626ef79434bf71e9040ae3969e7c98d9 Author: Surya Kumari Jangala <[email protected]> Date: Tue Jul 7 09:33:54 2026 -0500 [rs6000] Changes required to make the register allocators DMR register aware This patch makes changes in the various rs6000 specific register allocation callbacks. Diff: --- gcc/config/rs6000/rs6000.cc | 91 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 12 deletions(-) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 515507e6ee55..8b479fc29d3e 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -1868,6 +1868,10 @@ rs6000_hard_regno_mode_ok_uncached (int regno, machine_mode mode) if (COMPLEX_MODE_P (mode)) mode = GET_MODE_INNER (mode); + /* No other types other than XOmode or TDOmode can go in DMRs. */ + if (DMR_REGNO_P (regno) && !(mode ==XOmode || mode == TDOmode)) + return 0; + if (mode == TDOmode) { if (TARGET_DMF) @@ -1889,10 +1893,6 @@ rs6000_hard_regno_mode_ok_uncached (int regno, machine_mode mode) return ((TARGET_DMF && DMR_REGNO_P (regno)) || (TARGET_MMA && FP_REGNO_P (regno) && (regno & 3) == 0)); - /* No other types other than XOmode or TDOmode can go in DMRs. */ - if (DMR_REGNO_P (regno)) - return 0; - /* PTImode can only go in GPRs. Quad word memory operations require even/odd register combinations, and use PTImode where we need to deal with quad word memory operations. Don't allow quad words in the argument or frame @@ -12408,9 +12408,6 @@ rs6000_secondary_reload_memory (rtx addr, const char *type = NULL; const char *fail_msg = NULL; - if (rclass == DMR_REGS) - return 2; - if (GPR_REG_CLASS_P (rclass)) addr_mask = reg_addr[mode].addr_mask[RELOAD_REG_GPR]; @@ -12425,6 +12422,14 @@ rs6000_secondary_reload_memory (rtx addr, addr_mask = (reg_addr[mode].addr_mask[RELOAD_REG_VMX] & ~RELOAD_REG_AND_M16); + /* DMR registers have no load/store instructions; memory access goes + through an intermediate VSX stage handled by the TDO reload insn. + Use the DMR addr_mask so the address-code checks below can determine + whether a scratch GPR is needed to simplify the address before the + TDO reload insn is invoked. */ + else if (rclass == DMR_REGS) + addr_mask = reg_addr[mode].addr_mask[RELOAD_REG_DMR]; + /* If the register allocator hasn't made up its mind yet on the register class to use, settle on defaults to use. */ else if (rclass == NO_REGS) @@ -13452,6 +13457,7 @@ rs6000_preferred_reload_class (rtx x, enum reg_class rclass) machine_mode mode = GET_MODE (x); bool is_constant = CONSTANT_P (x); + /* Values cannot be loaded into DMR registers. */ if (rclass == DMR_REGS) return NO_REGS; @@ -13551,7 +13557,10 @@ rs6000_preferred_reload_class (rtx x, enum reg_class rclass) return VSX_REGS; if (mode == XOmode) - return FLOAT_REGS; + return (TARGET_DMF ? VSX_REGS : FLOAT_REGS); + + if (mode == TDOmode) + return VSX_REGS; if (GET_MODE_CLASS (mode) == MODE_INT) return GENERAL_REGS; @@ -13715,6 +13724,26 @@ rs6000_secondary_reload_class (enum reg_class rclass, machine_mode mode, && regno >= 0 && CR_REGNO_P (regno)) return NO_REGS; + /* DMR registers can only be moved to/from VSX registers. + - DMR -> VSX or VSX -> DMR: direct, no scratch register needed. + - DMR -> memory or memory -> DMR: must route through VSX; request + VSX_REGS as the intermediate scratch class. + - DMR -> DMR: direct move, no scratch needed. */ + if (rclass == DMR_REGS) + { + /* VSX register or another DMR register: direct move, no scratch. */ + if (regno >= 0 && (VSX_REGNO_P (regno) || DMR_REGNO_P (regno))) + return NO_REGS; + + /* Memory (regno == -1) or unresolved pseudo: need a VSX intermediate. */ + return VSX_REGS; + } + + /* Copying into a VSX register from a DMR register: direct. */ + if ((rclass == VSX_REGS || rclass == FLOAT_REGS || rclass == ALTIVEC_REGS) + && regno >= 0 && DMR_REGNO_P (regno)) + return NO_REGS; + /* Otherwise, we need GENERAL_REGS. */ return GENERAL_REGS; } @@ -22853,6 +22882,31 @@ rs6000_debug_address_cost (rtx x, machine_mode mode, } +static int +rs6000_dmr_register_move_cost (machine_mode mode, reg_class_t rclass) +{ + const int move_cost = 2; + HARD_REG_SET vsx_set = (reg_class_contents[rclass] + & reg_class_contents[VSX_REGS]); + + if (TARGET_DMF && !hard_reg_set_empty_p (vsx_set)) + { + /* XOmode can be copied in 1 instruction. */ + if (mode == XOmode) + return move_cost; + + /* TDOmode can be copied in 2 instructions. */ + else if (mode == TDOmode) + return move_cost * 2; + + else + return move_cost * 2 * hard_regno_nregs (FIRST_DMR_REGNO, mode); + } + + return 1000 * 2 * hard_regno_nregs (FIRST_DMR_REGNO, mode); +} + + /* A C expression returning the cost of moving data from a register of class CLASS1 to one of CLASS2. */ @@ -22873,10 +22927,20 @@ rs6000_register_move_cost (machine_mode mode, HARD_REG_SET to_vsx, from_vsx; to_vsx = reg_class_contents[to] & reg_class_contents[VSX_REGS]; from_vsx = reg_class_contents[from] & reg_class_contents[VSX_REGS]; - if (!hard_reg_set_empty_p (to_vsx) - && !hard_reg_set_empty_p (from_vsx) - && (TARGET_VSX - || hard_reg_set_intersect_p (to_vsx, from_vsx))) + + if ((mode == TDOmode || mode==XOmode) && from == DMR_REGS && to == DMR_REGS) + ret = 2 * hard_regno_nregs (FIRST_DMR_REGNO, mode); + + else if (from == DMR_REGS) + ret = rs6000_dmr_register_move_cost (mode, to); + + else if (to == DMR_REGS) + ret = rs6000_dmr_register_move_cost (mode, from); + + else if (!hard_reg_set_empty_p (to_vsx) + && !hard_reg_set_empty_p (from_vsx) + && (TARGET_VSX + || hard_reg_set_intersect_p (to_vsx, from_vsx))) { int reg = FIRST_FPR_REGNO; if (TARGET_VSX @@ -22972,6 +23036,9 @@ rs6000_memory_move_cost (machine_mode mode, reg_class_t rclass, ret = 4 * hard_regno_nregs (32, mode); else if (reg_classes_intersect_p (rclass, ALTIVEC_REGS)) ret = 4 * hard_regno_nregs (FIRST_ALTIVEC_REGNO, mode); + else if (reg_classes_intersect_p (rclass, DMR_REGS)) + ret = (rs6000_dmr_register_move_cost (mode, VSX_REGS) + + rs6000_memory_move_cost (mode, VSX_REGS, false)); else ret = 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS);
