Bootstrapped regtested and on x86_64-pc-linux-gnu.
2021-02-22 Joern Rennecke <[email protected]>
lra fix to reduce fatal spill failures.
* lra-constraints.c (split_reg): No longer static.
* lra-int.h (split_reg): Declare.
* lra-assigns.c (lra_split_hard_reg_for): Add strategy to split a
longer range pseudo to accomodate a short range pseudo in a
likely-spilled reg.
diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index c6a941fe663..4f765bbd8de 100644
--- a/gcc/lra-assigns.c
+++ b/gcc/lra-assigns.c
@@ -1799,6 +1799,35 @@ lra_split_hard_reg_for (void)
bitmap_clear (&failed_reload_pseudos);
return true;
}
+ /* For a likely spilled class, a pseudo hogging a hard register
+ and a hard reg use are pretty much interchangable.
+ If the use is for adjacent insns, we can win by splitting
+ a conflicting pseudo that has a larger range. */
+ if (next_nonnote_insn (first) == last
+ && targetm.class_likely_spilled_p (rclass))
+ {
+ int j;
+ rtx_insn *j_first, *j_last;
+ for (j = lra_constraint_new_regno_start; j < max_regno; j++)
+ if (reg_renumber[j] >= 0
+ && REGNO_REG_CLASS (reg_renumber[j]) == rclass
+ && (hard_regno_nregs (reg_renumber[j],
+ GET_MODE (regno_reg_rtx[j]))
+ >= hard_regno_nregs (reg_renumber[j],
+ GET_MODE (regno_reg_rtx[i])))
+ && find_reload_regno_insns (j, j_first, j_last)
+ && j_first != j_last && j_last != last)
+ {
+ for (insn = NEXT_INSN (j_first); insn != j_last;
+ insn = NEXT_INSN (insn))
+ if (insn == first
+ && split_reg (TRUE, j, first, NULL, last))
+ {
+ bitmap_clear (&failed_reload_pseudos);
+ return true;
+ }
+ }
+ }
bitmap_set_bit (&failed_reload_pseudos, i);
}
bitmap_clear (&non_reload_pseudos);
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index a766f1fd7e8..a13d02a9028 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -5774,7 +5774,7 @@ lra_copy_reg_equiv (unsigned int new_regno, unsigned int
original_regno)
register and s is a new split pseudo. The save is put before INSN
if BEFORE_P is true. Return true if we succeed in such
transformation. */
-static bool
+bool
split_reg (bool before_p, int original_regno, rtx_insn *insn,
rtx next_usage_insns, rtx_insn *to)
{
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 4dadccc79f4..eece250eafb 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -346,6 +346,9 @@ extern void lra_constraints_finish (void);
extern bool spill_hard_reg_in_range (int, enum reg_class, rtx_insn *, rtx_insn
*);
extern void lra_inheritance (void);
extern bool lra_undo_inheritance (void);
+extern bool split_reg (bool before_p, int original_regno, rtx_insn *insn,
+ rtx next_usage_insns, rtx_insn *to);
+
/* lra-lives.c: */