https://gcc.gnu.org/g:b4101b15255fe09fc3dccd36f9cb0b4e1978e94c

commit b4101b15255fe09fc3dccd36f9cb0b4e1978e94c
Author: Alexandre Oliva <ol...@adacore.com>
Date:   Wed Jun 18 04:13:19 2025 -0300

    [genoutput] mark scratch outputs as eliminable [PR120424]
    
    acats' fdd2a00.read is miscompiled on arm-linux-gnu with -O2
    -fstack-clash-protection -march=armv7-a -marm: a clobbered scratch
    register in a *iorsi3_compare0_scratch pattern gets initially assigned
    to the frame pointer register, but at some point during lra the frame
    size grows to nonzero, arm_frame_pointer_required flips to true, and
    the fp2sp elimination has to be disabled, so the scratch register gets
    spilled to a stack slot.
    
    It needs to get the sfp elimination at that point, because later
    rounds of elimination will assume the previous round's offset has
    already been applied.  But since scratch matches are not regarded as
    eliminable by genoutput, we don't attempt elimination in the clobbered
    stack slot MEM rtx.
    
    Later on, lra issues a reload for that slot, using a new pseudo
    allocated to a hardware register, that gets stored in the stack slot
    after the original insn.  Elimination in that reload store insn
    eventually updates the elimination offset, but it's an incremental
    update, assuming that the offset so far has already been applied.
    
    Without applying the initial offset, the store ends up overlapping
    with the function's register save area, corrupting a caller's
    call-saved register.
    
    AFAICT the old reload's elimination wouldn't be harmed by allowing
    elimination in scratch operands, so I'm enabling eliminable for them
    regardless.  Should it be found to make a difference, we could
    presumably set a different bit in eliminable to enable reload and lra
    to tell them apart and behave accordingly.
    
    
    for  gcc/ChangeLog
    
            PR rtl-optimization/120424
            * genoutput.cc (scan_operands): Make MATCH_SCRATCHes eliminable.

Diff:
---
 gcc/genoutput.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/genoutput.cc b/gcc/genoutput.cc
index dd4e7b80c2a9..25d0b8b86467 100644
--- a/gcc/genoutput.cc
+++ b/gcc/genoutput.cc
@@ -478,7 +478,7 @@ scan_operands (class data *d, rtx part, int this_address_p,
       d->operand[opno].n_alternatives
        = n_occurrences (',', d->operand[opno].constraint) + 1;
       d->operand[opno].address_p = 0;
-      d->operand[opno].eliminable = 0;
+      d->operand[opno].eliminable = 1;
       return;
 
     case MATCH_OPERATOR:

Reply via email to