Bootstrapped regtested and on x86_64-pc-linux-gnu.
2021-02-22 Joern Rennecke <joern.renne...@embecosm.com>
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: */