https://gcc.gnu.org/g:87076bd7820274ece9f78a2baf11bf94040083f9
commit 87076bd7820274ece9f78a2baf11bf94040083f9 Author: Alexandre Oliva <ol...@adacore.com> Date: Sun Jun 22 17:34:54 2025 -0300 [lra] catch all to-sp eliminations An x86_64-linux-gnu native with ix86_frame_pointer_required modified to return true for nonzero frames, to exercize lra_update_fp2sp_elimination, reveals in stage1 testing that wrong code is generated for gcc.c-torture/execute/ieee/fp-cmp-8l.c: argp-to-sp eliminations are used for one_test to pass its arguments on to *pos, and the sp offsets survive the disabling of that elimination. We didn't really have to disable that elimination, but the backend disables eliminations to sp if frame_pointer_needed. The workaround for this scenario is to compile with -maccumulate-outgoing-args. This change extends the catching of fp2sp eliminations to all (?) eliminations to sp, since none of them can be properly reversed and would silently lead to wrong code. This is probably too strict. for gcc/ChangeLog PR rtl-optimization/120424 * lra-eliminations.cc (elimination_2sp_occurred_p): Rename from... (elimination_fp2sp_occured_p): ... this. Adjust all uses. (lra_eliminate_regs_1): Don't require a from-frame-pointer elimination to set it. (update_reg_eliminate): Likewise to test it. Diff: --- gcc/lra-eliminations.cc | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gcc/lra-eliminations.cc b/gcc/lra-eliminations.cc index 9cdd0c5ff53a..f6ee33aa70a5 100644 --- a/gcc/lra-eliminations.cc +++ b/gcc/lra-eliminations.cc @@ -309,8 +309,9 @@ move_plus_up (rtx x) return x; } -/* Flag that we already did frame pointer to stack pointer elimination. */ -static bool elimination_fp2sp_occured_p = false; +/* Flag that we already applied stack pointer elimination offset; sp + updates cannot be undone. */ +static bool elimination_2sp_occurred_p = false; /* Scan X and replace any eliminable registers (such as fp) with a replacement (such as sp) if SUBST_P, plus an offset. The offset is @@ -369,8 +370,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, { rtx to = subst_p ? ep->to_rtx : ep->from_rtx; - if (ep->to_rtx == stack_pointer_rtx && ep->from == FRAME_POINTER_REGNUM) - elimination_fp2sp_occured_p = true; + if (ep->to_rtx == stack_pointer_rtx) + elimination_2sp_occurred_p = true; if (maybe_ne (update_sp_offset, 0)) { @@ -402,8 +403,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, poly_int64 offset, curr_offset; rtx to = subst_p ? ep->to_rtx : ep->from_rtx; - if (ep->to_rtx == stack_pointer_rtx && ep->from == FRAME_POINTER_REGNUM) - elimination_fp2sp_occured_p = true; + if (ep->to_rtx == stack_pointer_rtx) + elimination_2sp_occurred_p = true; if (! update_p && ! full_p) return simplify_gen_binary (PLUS, Pmode, to, XEXP (x, 1)); @@ -465,8 +466,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, { rtx to = subst_p ? ep->to_rtx : ep->from_rtx; - if (ep->to_rtx == stack_pointer_rtx && ep->from == FRAME_POINTER_REGNUM) - elimination_fp2sp_occured_p = true; + if (ep->to_rtx == stack_pointer_rtx) + elimination_2sp_occurred_p = true; if (maybe_ne (update_sp_offset, 0)) { @@ -1213,8 +1214,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets) pointer elimination the condition is a bit relaxed and we just require that actual elimination has not been done yet. */ gcc_assert (ep->to_rtx != stack_pointer_rtx - || (ep->from == FRAME_POINTER_REGNUM - && !elimination_fp2sp_occured_p) + || !elimination_2sp_occurred_p || (ep->from < FIRST_PSEUDO_REGISTER && fixed_regs [ep->from])); @@ -1429,7 +1429,7 @@ lra_update_fp2sp_elimination (int *spilled_pseudos) if (frame_pointer_needed || !targetm.frame_pointer_required ()) return 0; - gcc_assert (!elimination_fp2sp_occured_p); + gcc_assert (!elimination_2sp_occurred_p); ep = elimination_map[FRAME_POINTER_REGNUM]; if (ep->to == STACK_POINTER_REGNUM) { @@ -1499,7 +1499,7 @@ lra_eliminate (bool final_p, bool first_p) if (first_p) { - elimination_fp2sp_occured_p = false; + elimination_2sp_occurred_p = false; init_elimination (); }