On 5/24/25 11:06 PM, Alexandre Oliva wrote:
In the added C++ testcase, a stack slot at a negative sp offset is
used to hold a value across a call.

There are a couple of causes that directly lead to this outcome:

- the -fstack-clash-protection and -fnon-call-exception options, that
cause arm_frame_pointer_required to flip from false to true when the
first pseudo gets spilled to memory;

- when the affected pseudo is spilled to memory, we fail to update lra
regno info, because the insns that reference it are already on the
lra_constraint_insn_stack;

There is another potentially-related issue:

- when we notice that the frame pointer can no longer be eliminated to
the stack pointer, we immediately clear can_eliminate, and also
prev_can_eliminate, but update_reg_eliminate relied on the latter to
tell that it needs to propagate a previous_offset to the
newly-selected elimination, or restore the original offsets.

This patch ensures that we update insn register info after spilling a
pseudo to memory, and enables update_reg_eliminate to recognize the
case in which a previously-preferred elimination is disabled
regardless of prev_can_eliminate.

Regstrapped on x86_64-linux-gnu, also tested with gcc-14 on arm-vx7r2,
and manually tested with trunk targeting arm-eabi and arm-linux-gnu.
Ok to install?

Yes, Alex.

This is a good explanation of the patch and the bug and the affected code seem very old (from the first commit of LRA). So thank you very much for working on and fixing this PR.


for  gcc/ChangeLog

        PR rtl-optimization/120424
        PR middle-end/118939?
        * lra-spills.cc (spill_pseudos): Update insn regno info.
        * lra-eliminations.cc (update_reg_eliminate): Recognize
        disabling of active elimination regardless of
        prev_can_eliminate.

for  gcc/testsuite/ChangeLog

        PR rtl-optimization/120424
        PR middle-end/118939?
        * g++.target/arm/pr120424.C: New.
        * gnat.dg/controlled9.adb: New.
        * gnat.dg/controlled9_pkg.ads: New.

Reply via email to