[gcc r17-2428] [PATCH v1] RISC-V: Share bases for scaled indexed addresses

Jeff Law via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:2887d4857aaaed75f6c7aa6843c5b3cd58954124

commit r17-2428-g2887d4857aaaed75f6c7aa6843c5b3cd58954124
Author: wangjue <[email protected]>
Date:   Wed Jul 15 15:11:22 2026 -0600

    [PATCH v1] RISC-V: Share bases for scaled indexed addresses
    
    riscv_legitimize_address handled scaled indexed addresses only when
    the constant offset fit an I-type immediate.  Large offsets fell back to
    generic legalization and could materialize the same base at each
    reference.
    
    Use riscv_add_offset for all offsets before adding the scaled index.
    This preserves small-offset code generation and exposes large bases to
    CSE.
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.cc (riscv_legitimize_address): Use
            riscv_add_offset for scaled indexed addresses.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/large-frame-indexed-base.c: New test.
            * gcc.target/riscv/small-frame-indexed-base.c: New test.

Diff:
---
 gcc/config/riscv/riscv.cc                          | 11 ++++---
 .../gcc.target/riscv/large-frame-indexed-base.c    | 37 ++++++++++++++++++++++
 .../gcc.target/riscv/small-frame-indexed-base.c    | 35 ++++++++++++++++++++
 3 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 873defc5a5b5..6eeaa11caab2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3464,9 +3464,11 @@ 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))
+			    (stack_base)) (C)).
+	 Form STACK_BASE + 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 +3481,9 @@ 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 reg1 = force_reg (Pmode, riscv_add_offset (NULL, fp, offset));
 	      rtx reg2 = gen_reg_rtx (Pmode);
 	      rtx reg3 = gen_reg_rtx (Pmode);
-	      riscv_emit_binary (PLUS, reg1, fp, GEN_INT (offset));
 	      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.c b/gcc/testsuite/gcc.target/riscv/large-frame-indexed-base.c
new file mode 100644
index 000000000000..98549996cfa8
--- /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_loop (long *indices, struct item **values, long count)
+{
+  struct item *perm[4096];
+
+  init (perm);
+  for (long i = 0; i < count; ++i)
+    update (&indices[i], perm, values[i], i);
+}
+
+/* { dg-final { scan-assembler-times {\tli\t[^\n]+,-32768} 1 } } */
+/* { dg-final { scan-assembler-times {\tli\t[^\n]+,32768} 1 } } */
+/* { dg-final { scan-assembler {\tsh3add\t} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/small-frame-indexed-base.c b/gcc/testsuite/gcc.target/riscv/small-frame-indexed-base.c
new file mode 100644
index 000000000000..9ed0ecdd03e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/small-frame-indexed-base.c
@@ -0,0 +1,35 @@
+/* { 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
+small_frame_indexed_access (long *index, struct item *value, long x)
+{
+  struct item *perm[64];
+
+  init (perm);
+  update (index, perm, value, x);
+}
+
+/* { dg-final { scan-assembler-not {\tli\t} } } */
+/* { dg-final { scan-assembler-times {\tsh3add\t} 3 } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.