A full-width bit-field store can use force_subreg to reinterpret a DImode
function address as V2SImode.  validate_subreg accepts the resulting
SUBREG of a SYMBOL_REF, although it is not a general_operand, causing an
ICE during vregs.

Reject symbolic SUBREGs when either mode has multiple units.  This makes
force_subreg materialize the address in a register first, while preserving
scalar and single-unit vector forms.

        PR target/127060

gcc/ChangeLog:

        * emit-rtl.cc (validate_subreg): Reject symbolic constants when either
        mode has multiple units.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/base/pr127060.c: New test.

Reported-by: XChy <[email protected]>
Signed-off-by: Jin Ma <[email protected]>
---
 gcc/emit-rtl.cc                                    | 10 ++++++++++
 gcc/testsuite/gcc.target/riscv/rvv/base/pr127060.c | 14 ++++++++++++++
 2 files changed, 24 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/pr127060.c

diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
index 4a23eaefe02..b1205e80a38 100644
--- a/gcc/emit-rtl.cc
+++ b/gcc/emit-rtl.cc
@@ -924,6 +924,16 @@ validate_subreg (machine_mode omode, machine_mode imode,
   if (maybe_ge (offset, isize))
     return false;
 
+  /* Symbolic constants have no meaningful SUBREG interpretation when either
+     mode has multiple units.  */
+  if (reg
+      && (GET_CODE (reg) == CONST
+         || SYMBOL_REF_P (reg)
+         || LABEL_REF_P (reg))
+      && (maybe_ne (GET_MODE_NUNITS (omode), 1)
+         || maybe_ne (GET_MODE_NUNITS (imode), 1)))
+    return false;
+
   poly_uint64 regsize = REGMODE_NATURAL_SIZE (imode);
 
   /* ??? This should not be here.  Temporarily continue to allow word_mode
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr127060.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/pr127060.c
new file mode 100644
index 00000000000..43fe619f8d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr127060.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O1" } */
+/* PR target/127060 */
+
+typedef int v2si __attribute__ ((vector_size (8)));
+
+int
+f (unsigned long i)
+{
+  v2si v;
+  int (*p) (unsigned long) = f;
+  __builtin_memcpy (&v, &p, sizeof (p));
+  return v[i & 1];
+}
-- 
2.52.0

Reply via email to