From: "wangjue.wangjue" <[email protected]>

riscv_legitimize_address handles scaled indexed frame addresses specially
when the constant offset fits an I-type immediate.  With a large offset,
generic address legalization can materialize the same frame base at each
reference.

Form the frame base before adding the scaled index for both small and large
offsets.  Keeping a large frame base in a pseudo makes it available to CSE
and avoids repeated materialization.

gcc/ChangeLog:

        * config/riscv/riscv.cc (riscv_legitimize_address): Handle large
        constant offsets in scaled indexed frame addresses.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/large-frame-indexed-base.c: New test.
        * gcc.target/riscv/large-frame-indexed-base-2.c: New test.
---
 gcc/config/riscv/riscv.cc                     | 22 ++++---
 .../riscv/large-frame-indexed-base-2.c        | 59 +++++++++++++++++++
 .../riscv/large-frame-indexed-base.c          | 37 ++++++++++++
 3 files changed, 111 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/large-frame-indexed-base-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/large-frame-indexed-base.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 873defc5a5b..9607ee6389d 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3464,9 +3464,10 @@ riscv_legitimize_address (rtx x, rtx oldx 
ATTRIBUTE_UNUSED,
       rtx base = XEXP (x, 0);
       HOST_WIDE_INT offset = INTVAL (XEXP (x, 1));
 
-      /* Handle (plus (plus (mult (a) (mem_shadd_constant)) (fp)) (C)) case.  
*/
-      if (GET_CODE (base) == PLUS && mem_shadd_or_shadd_rtx_p (XEXP (base, 0))
-         && SMALL_OPERAND (offset))
+      /* Handle (plus (plus (mult (a) (mem_shadd_constant)) (fp)) (C)).
+        Form FP + C before adding the scaled index, so that CSE can share
+        the base when C is a large frame offset.  */
+      if (GET_CODE (base) == PLUS && mem_shadd_or_shadd_rtx_p (XEXP (base, 0)))
        {
          rtx index = XEXP (base, 0);
          rtx fp = XEXP (base, 1);
@@ -3479,10 +3480,17 @@ riscv_legitimize_address (rtx x, rtx oldx 
ATTRIBUTE_UNUSED,
              if (GET_CODE (index) == MULT)
                shift_val = exact_log2 (shift_val);
 
-             rtx reg1 = gen_reg_rtx (Pmode);
-             rtx reg2 = gen_reg_rtx (Pmode);
-             rtx reg3 = gen_reg_rtx (Pmode);
-             riscv_emit_binary (PLUS, reg1, fp, GEN_INT (offset));
+             rtx reg1, reg2, reg3;
+             if (SMALL_OPERAND (offset))
+               {
+                 reg1 = gen_reg_rtx (Pmode);
+                 riscv_emit_binary (PLUS, reg1, fp, GEN_INT (offset));
+               }
+             else
+               /* Expose FP + OFFSET as a CSE candidate.  */
+               reg1 = force_reg (Pmode, riscv_add_offset (NULL, fp, offset));
+             reg2 = gen_reg_rtx (Pmode);
+             reg3 = gen_reg_rtx (Pmode);
              riscv_emit_binary (ASHIFT, reg2, XEXP (index, 0), GEN_INT 
(shift_val));
              riscv_emit_binary (PLUS, reg3, reg2, reg1);
 
diff --git a/gcc/testsuite/gcc.target/riscv/large-frame-indexed-base-2.c 
b/gcc/testsuite/gcc.target/riscv/large-frame-indexed-base-2.c
new file mode 100644
index 00000000000..4aea87b708c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/large-frame-indexed-base-2.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-stack-protector -march=rv64gc_zba -mabi=lp64d" } */
+
+struct item
+{
+  struct item *a;
+  long b;
+  long c;
+};
+
+extern void init (struct item **);
+
+static __attribute__ ((always_inline)) inline void
+update1 (long *index, struct item **perm, struct item *value, long x)
+{
+  ++*index;
+  perm[*index]->a = value;
+  perm[*index]->b = x;
+  perm[*index]->c = x + 1;
+}
+
+static __attribute__ ((always_inline)) inline void
+update2 (long *index, struct item **perm, struct item *value, long x)
+{
+  ++*index;
+  perm[*index]->a = value;
+  perm[*index]->b = x + 2;
+  perm[*index]->c = x + 3;
+}
+
+static __attribute__ ((always_inline)) inline void
+update3 (long *index, struct item **perm, struct item *value, long x)
+{
+  ++*index;
+  perm[*index]->a = value;
+  perm[*index]->b = x + 4;
+  perm[*index]->c = x + 5;
+}
+
+__attribute__ ((noinline, noclone))
+void
+three_branch_materializations (long *index, struct item *value, long x,
+                              int selector)
+{
+  struct item *perm[4096];
+
+  init (perm);
+  if (selector == 1)
+    update1 (index, perm, value, x);
+  else if (selector == 2)
+    update2 (index, perm, value, x);
+  else
+    update3 (index, perm, value, x);
+}
+
+/* The 32 KiB constants should only be used to adjust the stack pointer.  */
+/* { dg-final { scan-assembler-times {\tli\t[^\n]+,-32768} 1 } } */
+/* { dg-final { scan-assembler-times {\tli\t[^\n]+,32768} 1 } } */
+/* { dg-final { scan-assembler-times {\tsh3add\t} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/large-frame-indexed-base.c 
b/gcc/testsuite/gcc.target/riscv/large-frame-indexed-base.c
new file mode 100644
index 00000000000..6c69d3bf75e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/large-frame-indexed-base.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-stack-protector -march=rv64gc_zba -mabi=lp64d" } */
+
+struct item
+{
+  struct item *a;
+  long b;
+  long c;
+  long d;
+};
+
+extern void init (struct item **);
+
+static __attribute__ ((always_inline)) inline void
+update (long *index, struct item **perm, struct item *value, long x)
+{
+  ++*index;
+  perm[*index]->a = value;
+  perm[*index]->b = x;
+  perm[*index]->c = x < 0 ? -x : x;
+  perm[*index]->d = 0;
+}
+
+__attribute__ ((noinline, noclone))
+void
+large_frame_indexed_access (long *index, struct item *value, long x)
+{
+  struct item *perm[4096];
+
+  init (perm);
+  update (index, perm, value, x);
+}
+
+/* The 32 KiB constants should only be used to adjust the stack pointer.  */
+/* { dg-final { scan-assembler-times {\tli\t[^\n]+,-32768} 1 } } */
+/* { dg-final { scan-assembler-times {\tli\t[^\n]+,32768} 1 } } */
+/* { dg-final { scan-assembler-times {\tsh3add\t} 3 } } */
-- 
2.34.1

Reply via email to