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 <[email protected]>
Signed-off-by: Christoph Müllner <[email protected]>
---
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