As documented in PR116131, we might end up with the following
INSN for rv32i_xtheadmemidx after th_memidx_I_c is applied:

(insn 18 14 0 2 (set (mem:SI (plus:SI (reg/f:SI 141)
                (ashift:SI (subreg:SI (reg:DI 134 [ a.0_1 ]) 0)
                    (const_int 2 [0x2]))) [0  S4 A32])
        (reg:SI 143 [ b ])) "<source>":4:17 -1
     (nil))

This INSN is rejected by th_memidx_classify_address_index(),
because the first ASHIFT operand needs to satisfy REG_P().

For most other cases of subreg expressions, an extension/trunctation
will be created before the ASHIFT INSN.  However, this case is different
as we have a reg:DI and RV32, where no truncation is possible.
Therefore, this patch accepts this corner-case and allows this INSN.

        PR target/116131

gcc/ChangeLog:

        * config/riscv/thead.cc (th_memidx_classify_address_index):
        Allow (ashift (subreg:SI (reg:DI))) for RV32.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/pr116131.c: New test.

Reported-by: Patrick O'Neill <patr...@rivosinc.com>
Signed-off-by: Christoph Müllner <christoph.muell...@vrull.eu>
---
 gcc/config/riscv/thead.cc                 | 13 +++++++++++++
 gcc/testsuite/gcc.target/riscv/pr116131.c | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr116131.c

diff --git a/gcc/config/riscv/thead.cc b/gcc/config/riscv/thead.cc
index 6f5edeb7e0a..6cbbece3ec0 100644
--- a/gcc/config/riscv/thead.cc
+++ b/gcc/config/riscv/thead.cc
@@ -646,6 +646,19 @@ th_memidx_classify_address_index (struct 
riscv_address_info *info, rtx x,
       shift = INTVAL (XEXP (offset, 1));
       offset = XEXP (offset, 0);
     }
+  /* (ashift:SI (subreg:SI (reg:DI)) (const_int shift)) */
+  else if (GET_CODE (offset) == ASHIFT
+          && GET_MODE (offset) == SImode
+          && SUBREG_P (XEXP (offset, 0))
+          && GET_MODE (XEXP (offset, 0)) == SImode
+          && GET_MODE (XEXP (XEXP (offset, 0), 0)) == DImode
+          && CONST_INT_P (XEXP (offset, 1))
+          && IN_RANGE (INTVAL (XEXP (offset, 1)), 0, 3))
+    {
+      type = ADDRESS_REG_REG;
+      shift = INTVAL (XEXP (offset, 1));
+      offset = XEXP (XEXP (offset, 0), 0);
+    }
   /* (ashift:DI (zero_extend:DI (reg:SI)) (const_int shift)) */
   else if (GET_CODE (offset) == ASHIFT
           && GET_MODE (offset) == DImode
diff --git a/gcc/testsuite/gcc.target/riscv/pr116131.c 
b/gcc/testsuite/gcc.target/riscv/pr116131.c
new file mode 100644
index 00000000000..4d644c37cde
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr116131.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" "-O0" "-Og" "-Os" "-Oz" } } */
+/* { dg-options "-march=rv64gc_xtheadmemidx" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xtheadmemidx" { target { rv32 } } } */
+
+volatile long long a;
+int b;
+int c[1];
+
+void d()
+{
+  c[a] = b;
+}
+
+/* { dg-final { scan-assembler "th.srw\t" } } */
-- 
2.45.2

Reply via email to