The following patch is a better solution for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116778
The patch was successfully tested and bootstrapped on x86-64, aarch64, ppc64le.
commit fca0ab08cd936464b152e9b45356f625eba27575 Author: Vladimir N. Makarov <vmaka...@redhat.com> Date: Wed Dec 11 15:36:21 2024 -0500 [PR116778][LRA]: Check pseudos assigned to FP after rematerialization to build live ranges This is a better fix of the PR permitting to avoid building live ranges after rematerialization. It checks that FP can not be eliminated now and that pseudos assigned to FP will be spilled. In this case we need to build live ranges after rematerialization for correct assignments of stack slots to spilled pseudos involved in rematerialization. gcc/ChangeLog: PR rtl-optimization/116778 * ira-int.h (x_ira_class_hard_reg_index): Fix comment typo. * lra-eliminations.cc (lra_fp_pseudo_p): New function. * lra-int.h (lra_fp_pseudo_p): External declaration. * lra-spills.cc (lra_need_for_spills_p): Fix formatting. * lra.cc (lra): Use lra_fp_pseudo_p in lra_create_live_range after lra_remat. diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 8c3c5941de5..5ce930b6d22 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -868,7 +868,7 @@ public: /* Index (in ira_class_hard_regs; for given register class and hard register (in general case a hard register can belong to several - register classes;. The index is negative for hard registers + register classes). The index is negative for hard registers unavailable for the allocation. */ short x_ira_class_hard_reg_index[N_REG_CLASSES][FIRST_PSEUDO_REGISTER]; diff --git a/gcc/lra-eliminations.cc b/gcc/lra-eliminations.cc index 96772f2904a..5343d8c5102 100644 --- a/gcc/lra-eliminations.cc +++ b/gcc/lra-eliminations.cc @@ -1428,6 +1428,25 @@ lra_update_fp2sp_elimination (int *spilled_pseudos) return n; } +/* Return true if we have a pseudo assigned to hard frame pointer. */ +bool +lra_fp_pseudo_p (void) +{ + HARD_REG_SET set; + + if (frame_pointer_needed) + /* At this stage it means we have no pseudos assigned to FP: */ + return false; + CLEAR_HARD_REG_SET (set); + add_to_hard_reg_set (&set, Pmode, HARD_FRAME_POINTER_REGNUM); + for (int i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++) + if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0 + && overlaps_hard_reg_set_p (set, PSEUDO_REGNO_MODE (i), + reg_renumber[i])) + return true; + return false; +} + /* Entry function to do final elimination if FINAL_P or to update elimination register offsets (FIRST_P if we are doing it the first time). */ diff --git a/gcc/lra-int.h b/gcc/lra-int.h index 5f605c3ae41..abee008e642 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -419,6 +419,7 @@ extern rtx lra_eliminate_regs_1 (rtx_insn *, rtx, machine_mode, bool, bool, poly_int64, bool); extern void eliminate_regs_in_insn (rtx_insn *insn, bool, bool, poly_int64); extern int lra_update_fp2sp_elimination (int *spilled_pseudos); +extern bool lra_fp_pseudo_p (void); extern void lra_eliminate (bool, bool); extern poly_int64 lra_update_sp_offset (rtx, poly_int64); diff --git a/gcc/lra-spills.cc b/gcc/lra-spills.cc index 3f5c8d2bcb0..6e9a8c3e34e 100644 --- a/gcc/lra-spills.cc +++ b/gcc/lra-spills.cc @@ -594,8 +594,9 @@ lra_need_for_scratch_reg_p (void) bool lra_need_for_spills_p (void) { - int i; max_regno = max_reg_num (); + int i; + max_regno = max_reg_num (); for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0 && ! ira_former_scratch_p (i)) diff --git a/gcc/lra.cc b/gcc/lra.cc index 6b740ed2325..55737deba3f 100644 --- a/gcc/lra.cc +++ b/gcc/lra.cc @@ -2555,8 +2555,11 @@ lra (FILE *f, int verbose) rematerialize them first. */ if (lra_remat ()) { - /* We need full live info -- see the comment above. */ - lra_create_live_ranges (true, true); + /* We need full live info -- see the comment above. We also might + need live info if we have a pseudo assigned to hard frame pointer + reg and will need FP for usual purposes. */ + lra_create_live_ranges (lra_reg_spill_p || lra_fp_pseudo_p (), + true); live_p = true; if (! lra_need_for_spills_p ()) {