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

commit r15-7932-ge355fe414aa3aaf215c7dd9dd789ce217a1b458c
Author: Vladimir N. Makarov <vmaka...@redhat.com>
Date:   Mon Mar 10 16:26:59 2025 -0400

    [PR114991][IRA]: Improve reg equiv invariant calculation
    
    In PR test case IRA preferred to allocate hard reg to a pseudo instead
    of its equivalence.  This resulted in allocating caller-saved hard reg
    and generating save/restore insns in the function prologue/epilogue.
    The equivalence is an invariant (stack pointer plus offset) and the
    pseudo is used mostly as memory address.  This happened as there was
    no simplification of insn after the invariant substitution.  The patch
    adds the necessary code.
    
    gcc/ChangeLog:
    
            PR target/114991
            * ira-costs.cc (equiv_can_be_consumed_p): Add new argument 
invariant_p.
            Add code for dealing with the invariant.
            (calculate_equiv_gains): Don't consider init insns.  Pass the new
            argument to equiv_can_be_consumed_p.  Don't treat invariant as
            memory.
    
    gcc/testsuite/ChangeLog:
    
            PR target/114991
            * gcc.target/aarch64/pr114991.c: New test.

Diff:
---
 gcc/ira-costs.cc                            | 38 +++++++++++++++++++++++++----
 gcc/testsuite/gcc.target/aarch64/pr114991.c | 15 ++++++++++++
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/gcc/ira-costs.cc b/gcc/ira-costs.cc
index a404e9f2690f..b568c7d03267 100644
--- a/gcc/ira-costs.cc
+++ b/gcc/ira-costs.cc
@@ -1788,11 +1788,27 @@ validate_autoinc_and_mem_addr_p (rtx x)
                                          MEM_ADDR_SPACE (x)));
 }
 
-/* Check that reg REGNO can be changed by TO in INSN.  Return true in case the
-   result insn would be valid one.  */
+/* Check that reg REGNO in INSN can be changed by TO (which is an invariant
+   equiv when INVARIANT_P is true).  Return true in case the result insn would
+   be valid one.  */
 static bool
-equiv_can_be_consumed_p (int regno, rtx to, rtx_insn *insn)
+equiv_can_be_consumed_p (int regno, rtx to, rtx_insn *insn, bool invariant_p)
 {
+  if (invariant_p)
+    {
+      /* We use more expensive code for the invariant because we need to
+        simplify the result insn as the invariant can be arithmetic rtx
+        inserted into another arithmetic rtx.  */
+      rtx pat = PATTERN (insn);
+      int code = INSN_CODE (insn);
+      PATTERN (insn) = copy_rtx (pat);
+      PATTERN (insn)
+       = simplify_replace_rtx (PATTERN (insn), regno_reg_rtx[regno], to);
+      bool res = !insn_invalid_p (insn, false);
+      PATTERN (insn) = pat;
+      INSN_CODE (insn) = code;
+      return res;
+    }
   validate_replace_src_group (regno_reg_rtx[regno], to, insn);
   /* We can change register to equivalent memory in autoinc rtl.  Some code
      including verify_changes assumes that autoinc contains only a register.
@@ -1910,6 +1926,14 @@ calculate_equiv_gains (void)
              || !get_equiv_regno (PATTERN (insn), regno, subreg)
              || !bitmap_bit_p (&equiv_pseudos, regno))
            continue;
+
+         rtx_insn_list *x;
+         for (x = ira_reg_equiv[regno].init_insns; x != NULL; x = x->next ())
+           if (insn == x->insn ())
+             break;
+         if (x != NULL)
+           continue; /* skip equiv init insn */
+
          rtx subst = ira_reg_equiv[regno].memory;
 
          if (subst == NULL)
@@ -1919,13 +1943,17 @@ calculate_equiv_gains (void)
          ira_assert (subst != NULL);
          mode = PSEUDO_REGNO_MODE (regno);
          ira_init_register_move_cost_if_necessary (mode);
-         bool consumed_p = equiv_can_be_consumed_p (regno, subst, insn);
+         bool consumed_p
+           = equiv_can_be_consumed_p (regno, subst, insn,
+                                      subst == ira_reg_equiv[regno].invariant);
 
          rclass = pref[COST_INDEX (regno)];
          if (MEM_P (subst)
              /* If it is a change of constant into double for example, the
                 result constant probably will be placed in memory.  */
-             || (subreg != NULL_RTX && !INTEGRAL_MODE_P (GET_MODE (subreg))))
+             || (ira_reg_equiv[regno].invariant == NULL
+                 && subreg != NULL_RTX
+                 && !INTEGRAL_MODE_P (GET_MODE (subreg))))
            cost = ira_memory_move_cost[mode][rclass][1] + (consumed_p ? 0 : 1);
          else if (consumed_p)
            continue;
diff --git a/gcc/testsuite/gcc.target/aarch64/pr114991.c 
b/gcc/testsuite/gcc.target/aarch64/pr114991.c
new file mode 100644
index 000000000000..d3c7bd131ddc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr114991.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-shrink-wrap" } */
+
+typedef struct { int arr[16]; } S;
+
+void g (S *);
+void h (S);
+void f(int x)
+{
+  S s;
+  g (&s);
+  h (s);
+}
+
+/* { dg-final { scan-assembler-not "\[ \t\]?str\[ \t\]x" } } */

Reply via email to