https://gcc.gnu.org/g:3c67a0fa1dd39a3378deb854a7fef0ff7fe38004

commit r15-2810-g3c67a0fa1dd39a3378deb854a7fef0ff7fe38004
Author: Surya Kumari Jangala <jskum...@linux.ibm.com>
Date:   Thu Dec 7 22:42:43 2023 -0600

    lra: emit caller-save register spills before call insn [PR116028]
    
    LRA emits insns to save caller-save registers in the
    inheritance/splitting pass. In this pass, LRA builds EBBs (Extended
    Basic Block) and traverses the insns in the EBBs in reverse order from
    the last insn to the first insn. When LRA sees a write to a pseudo (that
    has been assigned a caller-save register), and there is a read following
    the write, with an intervening call insn between the write and read,
    then LRA generates a spill immediately after the write and a restore
    immediately before the read. The spill is needed because the call insn
    will clobber the caller-save register.
    
    If there is a write insn and a call insn in two separate BBs but
    belonging to the same EBB, the spill insn gets generated in the BB
    containing the write insn. If the write insn is in the entry BB, then
    the spill insn that is generated in the entry BB prevents shrink wrap
    from happening. This is because the spill insn references the stack
    pointer and hence the prolog gets generated in the entry BB itself.
    
    This patch ensures the the spill insn is generated before the call insn
    instead of after the write. This also ensures that the spill occurs
    only in the path containing the call.
    
    2024-08-01  Surya Kumari Jangala  <jskum...@linux.ibm.com>
    
    gcc:
            PR rtl-optimization/116028
            * lra-constraints.cc (split_reg): Spill register before call
            insn.
            (latest_call_insn): New variable.
            (inherit_in_ebb): Track the latest call insn.
    
    gcc/testsuite:
            PR rtl-optimization/116028
            * gcc.dg/ira-shrinkwrap-prep-1.c: Remove xfail for powerpc.
            * gcc.dg/pr10474.c: Remove xfail for powerpc.

Diff:
---
 gcc/lra-constraints.cc                       | 28 ++++++++++++++++++++++++----
 gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c |  2 +-
 gcc/testsuite/gcc.dg/pr10474.c               |  2 +-
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 92b343fa99a0..28c1a877c003 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -152,6 +152,9 @@ static machine_mode curr_operand_mode[MAX_RECOG_OPERANDS];
    (e.g. constant) and whose subreg is given operand of the current
    insn.  VOIDmode in all other cases.  */
 static machine_mode original_subreg_reg_mode[MAX_RECOG_OPERANDS];
+/* The nearest call insn for an insn on which split transformation
+   will be done. The call insn is in the same EBB as the insn.  */
+static rtx_insn *latest_call_insn;
 
 
 
@@ -6286,10 +6289,25 @@ split_reg (bool before_p, int original_regno, rtx_insn 
*insn,
                         after_p ? restore : NULL,
                         call_save_p
                         ?  "Add reg<-save" : "Add reg<-split");
-  lra_process_new_insns (insn, before_p ? save : NULL,
-                        before_p ? NULL : save,
-                        call_save_p
-                        ?  "Add save<-reg" : "Add split<-reg");
+  if (call_save_p && latest_call_insn != NULL)
+    /* PR116028: If original_regno is a pseudo that has been assigned a
+       call-save hard register, then emit the spill insn before the call
+       insn 'latest_call_insn' instead of adjacent to 'insn'. If 'insn'
+       and 'latest_call_insn' belong to the same EBB but to two separate
+       BBs, and if 'insn' is present in the entry BB, then generating the
+       spill insn in the entry BB can prevent shrink wrap from happening.
+       This is because the spill insn references the stack pointer and
+       hence the prolog gets generated in the entry BB itself. It is
+       also more efficient to generate the spill before
+       'latest_call_insn' as the spill now occurs only in the path
+       containing the call.  */
+    lra_process_new_insns (PREV_INSN (latest_call_insn), NULL, save,
+                          "Add save<-reg");
+  else
+    lra_process_new_insns (insn, before_p ? save : NULL,
+                          before_p ? NULL : save,
+                          call_save_p
+                          ?  "Add save<-reg" : "Add split<-reg");
   if (nregs > 1 || original_regno < FIRST_PSEUDO_REGISTER)
     /* If we are trying to split multi-register.  We should check
        conflicts on the next assignment sub-pass.  IRA can allocate on
@@ -6773,6 +6791,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
   last_processed_bb = NULL;
   CLEAR_HARD_REG_SET (potential_reload_hard_regs);
   live_hard_regs = eliminable_regset | lra_no_alloc_regs;
+  latest_call_insn = NULL;
   /* We don't process new insns generated in the loop. */
   for (curr_insn = tail; curr_insn != PREV_INSN (head); curr_insn = prev_insn)
     {
@@ -6985,6 +7004,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
              last_call_for_abi[callee_abi.id ()] = calls_num;
              full_and_partial_call_clobbers
                |= callee_abi.full_and_partial_reg_clobbers ();
+             latest_call_insn = curr_insn;
              if ((cheap = find_reg_note (curr_insn,
                                          REG_RETURNED, NULL_RTX)) != NULL_RTX
                  && ((cheap = XEXP (cheap, 0)), true)
diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c 
b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
index a95637abbe54..8c150972f952 100644
--- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
+++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
@@ -26,4 +26,4 @@ bar (long a)
 
 /* { dg-final { scan-rtl-dump "Will split live ranges of parameters" "ira" } } 
*/
 /* { dg-final { scan-rtl-dump "Split live-range of register" "ira" { xfail { ! 
aarch64*-*-* } } } } */
-/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" 
{ xfail powerpc*-*-* } } } */
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" 
} } */
diff --git a/gcc/testsuite/gcc.dg/pr10474.c b/gcc/testsuite/gcc.dg/pr10474.c
index a4af536ec284..b5393d5b6e3e 100644
--- a/gcc/testsuite/gcc.dg/pr10474.c
+++ b/gcc/testsuite/gcc.dg/pr10474.c
@@ -13,4 +13,4 @@ void f(int *i)
 }
 
 /* XFAIL due to PR70681.  */ 
-/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue"  
{ xfail arm*-*-* powerpc*-*-* } } } */
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue"  
{ xfail arm*-*-* } } } */

Reply via email to