https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122438
--- Comment #10 from Michael Matz <matz at gcc dot gnu.org> ---
A patch like the below makes reload correctly avoid the d1/d0 pair (and
chooses d2 for the scratch). But as this touches only the fairly late
hardreg selection anything earlier (cost estimation and such) is perhaps
off. It also probably doesn't touch all places that would need that:
Basically anything that goes off PSEUDO_REGNO_MODE or reg_renumber[pseudo]
directly is wrong in the presence of paradoxical subregs and would need
similar adjustments. And, of course, the use of reg_max_ref_mode[]
only works if a pseudo is used only in consistent paradoxical contexts,
not in multiple different ones that wouldn't lead to a consistent "maximal"
outer mode.
diff --git a/gcc/reload1.cc b/gcc/reload1.cc
index fe4fe58981c..261b8a37ce9 100644
--- a/gcc/reload1.cc
+++ b/gcc/reload1.cc
@@ -1692,6 +1692,30 @@ static int spill_add_cost[FIRST_PSEUDO_REGISTER];
reg. */
static int hard_regno_to_pseudo_regno[FIRST_PSEUDO_REGISTER];
+static int
+pseudo_to_hardreg (int pseudo, int *hardreg)
+{
+ machine_mode mode = PSEUDO_REGNO_MODE (pseudo);
+ machine_mode wider_mode;
+ int r = reg_renumber[pseudo];
+ int final_regno;
+ int nregs;
+
+ if (!reg_max_ref_mode)
+ wider_mode = mode;
+ else
+ wider_mode = wider_subreg_mode (mode, reg_max_ref_mode[pseudo]);
+
+ if (wider_mode != mode)
+ final_regno = simplify_subreg_regno (r, mode, 0, wider_mode);
+ else
+ final_regno = r;
+
+ nregs = hard_regno_nregs (final_regno, wider_mode);
+ *hardreg = final_regno;
+ return nregs;
+}
+
/* Update the spill cost arrays, considering that pseudo REG is live. */
static void
@@ -1713,8 +1737,8 @@ count_pseudo (int reg)
gcc_assert (r >= 0);
+ nregs = pseudo_to_hardreg (reg, &r);
spill_add_cost[r] += freq;
- nregs = hard_regno_nregs (r, PSEUDO_REGNO_MODE (reg));
while (nregs-- > 0)
{
hard_regno_to_pseudo_regno[r + nregs] = reg;
@@ -1791,7 +1815,7 @@ count_spilled_pseudo (int spilled, int spilled_nregs, int
reg)
gcc_assert (r >= 0);
- nregs = hard_regno_nregs (r, PSEUDO_REGNO_MODE (reg));
+ nregs = pseudo_to_hardreg (reg, &r);
if (REGNO_REG_SET_P (&spilled_pseudos, reg)
|| spilled + spilled_nregs <= r || r + nregs <= spilled)