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 ())
 	    {

Reply via email to