diff mbox series

RISC-V: xtheadmemidx: Fix RV32 ICE because of unexpected subreg

Message ID 20240730161707.853999-1-christoph.muellner@vrull.eu
State New
Headers show
Series RISC-V: xtheadmemidx: Fix RV32 ICE because of unexpected subreg | expand

Commit Message

Christoph Müllner July 30, 2024, 4:17 p.m. UTC
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 <patrick@rivosinc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@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

Comments

Jeff Law July 30, 2024, 7:19 p.m. UTC | #1
On 7/30/24 10:17 AM, Christoph Müllner wrote:
> 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.
But why do we have the ashift form here at all?   Canonicalization rules 
say this is invalid RTL.   So while this patch fixes the ICE it does not 
address the canonicalization problem in this RTL.

Specifically in a memory address we should be using mult rather than 
ashift.   And for associative ops, we chain left.  So the proper form of 
the address (inside a MEM) is:

(plus (mult (op1) (const_int 4) (op2))

That needs to be fixed.

jeff
diff mbox series

Patch

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" } } */