aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir N. Makarov <vmakarov@redhat.com>2023-08-16 09:13:54 -0400
committerVladimir N. Makarov <vmakarov@redhat.com>2023-08-16 12:12:51 -0400
commit3452652236aa74995fa0f638d5ec3a3b53f8ad72 (patch)
treef51814cb733ec32f6b3993c53e9d47104d040db7
parent083b7f2833d71dd940abcf9cfba99782cb7c07fd (diff)
downloadgcc-3452652236aa74995fa0f638d5ec3a3b53f8ad72.zip
gcc-3452652236aa74995fa0f638d5ec3a3b53f8ad72.tar.gz
gcc-3452652236aa74995fa0f638d5ec3a3b53f8ad72.tar.bz2
[LRA]: Spill pseudos assigned to fp when fp->sp elimination became impossible
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.
-rw-r--r--gcc/lra-eliminations.cc33
-rw-r--r--gcc/lra-int.h2
-rw-r--r--gcc/lra-spills.cc12
3 files changed, 30 insertions, 17 deletions
diff --git a/gcc/lra-eliminations.cc b/gcc/lra-eliminations.cc
index 1f4e3fe..3c58d4a 100644
--- a/gcc/lra-eliminations.cc
+++ b/gcc/lra-eliminations.cc
@@ -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
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 633d9af8..d0752c2 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -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);
diff --git a/gcc/lra-spills.cc b/gcc/lra-spills.cc
index fe58f16..7e1d35b 100644
--- a/gcc/lra-spills.cc
+++ b/gcc/lra-spills.cc
@@ -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. */