On Jun 13, 2025, Vladimir Makarov <vmaka...@redhat.com> wrote:

>> * lra-eliminations.cc (lra_update_fp2sp_elimination):
>> Inactivate the unused fp2sp elimination right away.

Alas, this seems to cause trouble on arm-linux-gnueabihf bootstraps.

Here's an alternate approach that builds on it to solves the earlier
problem without making for a new one.


Deactivating the fp2sp elimination in lra_update_fp2sp_elimination
prevents update_reg_eliminate from propagating the fp2sp elimination
offset to the next chosen elimination, so it may retain -1 as the
prev_offset, and prev_offset will be taken as an already-applied
offset that needs to be compensated in the next round of spilling and
reloading.  This affects, for example, crtbegin.o's
__do_global_dtors_aux on arm-linux-gnueabihf in a {BOOT_C,T}FLAGS='-O2
-g -fnon-call-exceptions -fstack-clash-protection' bootstrap.

Alas, just retaining that elimination causes spills to use the fp2sp
elimination, including applying sp offsets, which breaks e.g. an
x86_64-linux-gnu native bootstrap with ix86_frame_pointer_required
modified to return true on nonzero frame size.

The middle-ground solution is to keep the elimination active, so that
its offsets are applied and propagated on to the subsequent fp
elimination, but without introducing sp offsets, so that
e.g. pr103973-18.c on the modified x86_64-linux-gnu doesn't get
adjacent argument pushes of two adjacent on-stack temporaries ending
up pushing the same temporary because of undesired adjustments.

Regstrapped on x86_64-linux-gnu, bootstrapped on arm-linux-gnueabihf
(arm and thumb modes), also tested with gcc-14 on arm-vx7r2 and
arm-linux-gnueabihf.  Ok to install?


for  gcc/ChangeLog

        PR rtl-optimization/120424
        * lra-elimination.cc (lra_update_fp2sp_elimination):
        Avoid sp offsets in further fp2sp eliminations...
        (update_reg_eliminate): ... and restore to_rtx before assert
        checking.
---
 gcc/lra-eliminations.cc |   18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/gcc/lra-eliminations.cc b/gcc/lra-eliminations.cc
index 6663d1c37e8ba..0a702a43a5a17 100644
--- a/gcc/lra-eliminations.cc
+++ b/gcc/lra-eliminations.cc
@@ -1172,7 +1172,16 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
       /* If it is a currently used elimination: update the previous
         offset.  */
       if (elimination_map[ep->from] == ep)
-       ep->previous_offset = ep->offset;
+       {
+         ep->previous_offset = ep->offset;
+         /* Restore the stack_pointer_rtx into to_rtx, that
+            lra_update_fp2sp_elimination set to from_rtx, so that the assert
+            below still checks what it was supposed to check.  */
+         if (ep->from_rtx == ep->to_rtx
+             && ep->from != ep->to
+             && ep->from == FRAME_POINTER_REGNUM)
+           ep->to_rtx = stack_pointer_rtx;
+       }
 
       prev = ep->prev_can_eliminate;
       setup_can_eliminate (ep, targetm.can_eliminate (ep->from, ep->to));
@@ -1418,7 +1427,12 @@ lra_update_fp2sp_elimination (int *spilled_pseudos)
   ep = elimination_map[FRAME_POINTER_REGNUM];
   if (ep->to == STACK_POINTER_REGNUM)
     {
-      elimination_map[FRAME_POINTER_REGNUM] = NULL;
+      /* Prevent any further uses of fp, say in spill addresses, from being
+        eliminated to sp and affected by sp offsets.  Alas, deactivating the
+        elimination altogether causes the next chosen fp elimination to miss
+        the offset propagation, so it may keep -1 as its prev_offset, and that
+        will make subsequent offsets incorrect.  */
+      ep->to_rtx = ep->from_rtx;
       setup_can_eliminate (ep, false);
     }
   else


-- 
Alexandre Oliva, happy hacker            https://blog.lx.oliva.nom.br/
Free Software Activist     FSFLA co-founder     GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity.
Excluding neuro-others for not behaving ""normal"" is *not* inclusive!

Reply via email to