]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[LRA]: Spill pseudos assigned to fp when fp->sp elimination became impossible
authorVladimir N. Makarov <vmakarov@redhat.com>
Wed, 16 Aug 2023 13:13:54 +0000 (09:13 -0400)
committerVladimir N. Makarov <vmakarov@redhat.com>
Wed, 16 Aug 2023 16:12:51 +0000 (12:12 -0400)
Porting LRA to AVR revealed that creating a stack slot can make fp->sp
elimination impossible.  The previous patches undoes fp assignment after
the stack slot creation but calculated wrongly live info after this.  This
resulted in wrong generation by deleting some still alive insns.  This
patch fixes this problem.

gcc/ChangeLog:

* lra-int.h (lra_update_fp2sp_elimination): Change the prototype.
* lra-eliminations.cc (spill_pseudos): Record spilled pseudos.
(lra_update_fp2sp_elimination): Ditto.
(update_reg_eliminate): Adjust spill_pseudos call.
* lra-spills.cc (lra_spill): Assign stack slots to pseudos spilled
in lra_update_fp2sp_elimination.

gcc/lra-eliminations.cc
gcc/lra-int.h
gcc/lra-spills.cc

index 1f4e3fec9e0ed7576fccaaa6ab2e34bf3df53a1b..3c58d4a3815414015feb8e2200a77107067c6a4c 100644 (file)
@@ -1086,18 +1086,18 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
   lra_update_insn_recog_data (insn);
 }
 
-/* Spill pseudos which are assigned to hard registers in SET.  Add
-   affected insns for processing in the subsequent constraint
-   pass.  */
-static void
-spill_pseudos (HARD_REG_SET set)
+/* Spill pseudos which are assigned to hard registers in SET, record them in
+   SPILLED_PSEUDOS unless it is null, and return the recorded pseudos number.
+   Add affected insns for processing in the subsequent constraint pass.  */
+static int
+spill_pseudos (HARD_REG_SET set, int *spilled_pseudos)
 {
-  int i;
+  int i, n;
   bitmap_head to_process;
   rtx_insn *insn;
 
   if (hard_reg_set_empty_p (set))
-    return;
+    return 0;
   if (lra_dump_file != NULL)
     {
       fprintf (lra_dump_file, "           Spilling non-eliminable hard regs:");
@@ -1107,6 +1107,7 @@ spill_pseudos (HARD_REG_SET set)
       fprintf (lra_dump_file, "\n");
     }
   bitmap_initialize (&to_process, &reg_obstack);
+  n = 0;
   for (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,
@@ -1116,6 +1117,8 @@ spill_pseudos (HARD_REG_SET set)
          fprintf (lra_dump_file, "      Spilling r%d(%d)\n",
                   i, reg_renumber[i]);
        reg_renumber[i] = -1;
+       if (spilled_pseudos != NULL)
+         spilled_pseudos[n++] = i;
        bitmap_ior_into (&to_process, &lra_reg_info[i].insn_bitmap);
       }
   lra_no_alloc_regs |= set;
@@ -1126,6 +1129,7 @@ spill_pseudos (HARD_REG_SET set)
        lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
       }
   bitmap_clear (&to_process);
+  return n;
 }
 
 /* Update all offsets and possibility for elimination on eliminable
@@ -1238,7 +1242,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
       }
   lra_no_alloc_regs |= temp_hard_reg_set;
   eliminable_regset &= ~temp_hard_reg_set;
-  spill_pseudos (temp_hard_reg_set);
+  spill_pseudos (temp_hard_reg_set, NULL);
   return result;
 }
 
@@ -1382,15 +1386,17 @@ process_insn_for_elimination (rtx_insn *insn, bool final_p, bool first_p)
 
 /* Update frame pointer to stack pointer elimination if we started with
    permitted frame pointer elimination and now target reports that we can not
-   do this elimination anymore.  */
-void
-lra_update_fp2sp_elimination (void)
+   do this elimination anymore.  Record spilled pseudos in SPILLED_PSEUDOS
+   unless it is null, and return the recorded pseudos number.  */
+int
+lra_update_fp2sp_elimination (int *spilled_pseudos)
 {
+  int n;
   HARD_REG_SET set;
   class lra_elim_table *ep;
 
   if (frame_pointer_needed || !targetm.frame_pointer_required ())
-    return;
+    return 0;
   gcc_assert (!elimination_fp2sp_occured_p);
   if (lra_dump_file != NULL)
     fprintf (lra_dump_file,
@@ -1398,10 +1404,11 @@ lra_update_fp2sp_elimination (void)
   frame_pointer_needed = true;
   CLEAR_HARD_REG_SET (set);
   add_to_hard_reg_set (&set, Pmode, HARD_FRAME_POINTER_REGNUM);
-  spill_pseudos (set);
+  n = spill_pseudos (set, spilled_pseudos);
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     if (ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
       setup_can_eliminate (ep, false);
+  return n;
 }
 
 /* Entry function to do final elimination if FINAL_P or to update
index 633d9af80588256a8d0a9fc49b677cf34b9117b0..d0752c2ae5052d2b6eea3abb6b5cb478797e823a 100644 (file)
@@ -414,7 +414,7 @@ extern int lra_get_elimination_hard_regno (int);
 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 void lra_update_fp2sp_elimination (void);
+extern int lra_update_fp2sp_elimination (int *spilled_pseudos);
 extern void lra_eliminate (bool, bool);
 
 extern poly_int64 lra_update_sp_offset (rtx, poly_int64);
index fe58f162d0502ff87e52df8a74130583dbb1ae74..7e1d35b5e4e8289a376b1ef4822fc91942da132b 100644 (file)
@@ -606,7 +606,7 @@ lra_need_for_spills_p (void)
 void
 lra_spill (void)
 {
-  int i, n, curr_regno;
+  int i, n, n2, curr_regno;
   int *pseudo_regnos;
 
   regs_num = max_reg_num ();
@@ -632,8 +632,14 @@ lra_spill (void)
   for (i = 0; i < n; i++)
     if (pseudo_slots[pseudo_regnos[i]].mem == NULL_RTX)
       assign_mem_slot (pseudo_regnos[i]);
-  lra_update_fp2sp_elimination ();
-  if (n > 0 && crtl->stack_alignment_needed)
+  if ((n2 = lra_update_fp2sp_elimination (pseudo_regnos)) > 0)
+    {
+      /* Assign stack slots to spilled pseudos assigned to fp.  */
+      for (i = 0; i < n2; i++)
+       if (pseudo_slots[pseudo_regnos[i]].mem == NULL_RTX)
+         assign_mem_slot (pseudo_regnos[i]);
+    }
+  if (n + n2 > 0 && crtl->stack_alignment_needed)
     /* If we have a stack frame, we must align it now.  The stack size
        may be a part of the offset computation for register
        elimination.  */