From: Vladimir N. Makarov Date: Wed, 16 Aug 2023 13:13:54 +0000 (-0400) Subject: [LRA]: Spill pseudos assigned to fp when fp->sp elimination became impossible X-Git-Tag: basepoints/gcc-15~6890 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3452652236aa74995fa0f638d5ec3a3b53f8ad72;p=thirdparty%2Fgcc.git [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. --- diff --git a/gcc/lra-eliminations.cc b/gcc/lra-eliminations.cc index 1f4e3fec9e0e..3c58d4a38154 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, ®_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 < ®_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 633d9af80588..d0752c2ae505 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 fe58f162d050..7e1d35b5e4e8 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. */