[BUG,FIX] RISC-V: Disallow COSNT_VECTOR for DI on RV32

Message ID 20231121100209.315304-1-juzhe.zhong@rivai.ai
State Unresolved
Headers
Series [BUG,FIX] RISC-V: Disallow COSNT_VECTOR for DI on RV32 |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

juzhe.zhong@rivai.ai Nov. 21, 2023, 10:02 a.m. UTC
  This bug is exposed when testing on zvl512b RV32 system.

The rootcause is RA reload DI CONST_VECTOR into vmv.v.x then it ICE.

So disallow DI CONST_VECTOR on RV32.

	PR target/112598

gcc/ChangeLog:

	* config/riscv/riscv.cc (riscv_const_insns): Disallow DI CONST_VECTOR on RV32.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/pr112598-1.c: New test.

---
 gcc/config/riscv/riscv.cc                     |  8 +++
 .../gcc.target/riscv/rvv/autovec/pr112598-1.c | 56 +++++++++++++++++++
 2 files changed, 64 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-1.c
  

Patch

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3701f41b1b3..60d3f617395 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1598,6 +1598,14 @@  riscv_const_insns (rtx x)
 	    rtx elt;
 	    if (const_vec_duplicate_p (x, &elt))
 	      {
+		/* We don't allow CONST_VECTOR for DI vector on RV32
+		   system since the ELT constant value can not held
+		   within a single register to disable reload a DI
+		   register vec_duplicate into vmv.v.x.  */
+		scalar_mode smode = GET_MODE_INNER (GET_MODE (x));
+		if (maybe_gt (GET_MODE_SIZE (smode), UNITS_PER_WORD)
+		    && !immediate_operand (elt, Pmode))
+		  return 0;
 		/* Constants from -16 to 15 can be loaded with vmv.v.i.
 		   The Wc0, Wc1 constraints are already covered by the
 		   vi constraint so we do not need to check them here
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-1.c
new file mode 100644
index 00000000000..a1d7e5bf17b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-1.c
@@ -0,0 +1,56 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv_zvfh_zfh_zvl512b -mabi=ilp32d -O3 --param=riscv-autovec-lmul=m8 -O3 -fno-vect-cost-model -ffast-math" } */
+
+#include <stdint-gcc.h>
+#define TEST_UNARY_CALL_CVT(TYPE_IN, TYPE_OUT, CALL) \
+  void test_##TYPE_IN##_##TYPE_OUT##_##CALL (        \
+    TYPE_OUT *out, TYPE_IN *in, unsigned count)      \
+  {                                                  \
+    for (unsigned i = 0; i < count; i++)             \
+      out[i] = CALL (in[i]);                         \
+  }
+#define TEST_ASSERT(TYPE)                                         \
+  void test_##TYPE##_assert (TYPE *out, TYPE *ref, unsigned size) \
+  {                                                               \
+    for (unsigned i = 0; i < size; i++)                           \
+      {                                                           \
+	if (out[i] != ref[i])                                     \
+	  __builtin_abort ();                                     \
+      }                                                           \
+  }
+#define TEST_INIT_CVT(TYPE_IN, VAL_IN, TYPE_REF, VAL_REF, NUM) \
+  void test_##TYPE_IN##_##TYPE_REF##_init_##NUM (              \
+    TYPE_IN *in, TYPE_REF *ref, unsigned size)                 \
+  {                                                            \
+    for (unsigned i = 0; i < size; i++)                        \
+      {                                                        \
+	in[i] = VAL_IN;                                        \
+	ref[i] = VAL_REF;                                      \
+      }                                                        \
+  }
+#define RUN_TEST_CVT(TYPE_IN, TYPE_OUT, NUM, CALL, IN, OUT, REF, SIZE) \
+  test_##TYPE_IN##_##TYPE_OUT##_init_##NUM (IN, REF, SIZE);            \
+  test_##TYPE_IN##_##TYPE_OUT##_##CALL (OUT, IN, SIZE);                \
+  test_##TYPE_OUT##_assert (OUT, REF, SIZE);
+
+#define ARRAY_SIZE 128
+
+float in[ARRAY_SIZE];
+int64_t out[ARRAY_SIZE];
+int64_t ref[ARRAY_SIZE];
+
+TEST_UNARY_CALL_CVT (float, int64_t, __builtin_llceilf)
+
+TEST_ASSERT (int64_t)
+
+
+TEST_INIT_CVT (float, 9223372036854775808.0, int64_t, 0x7fffffffffffffff, 26)
+TEST_INIT_CVT (float, __builtin_inf (), int64_t, __builtin_llceilf (__builtin_inf ()), 29)
+
+int64_t
+main ()
+{
+  RUN_TEST_CVT (float, int64_t, 26, __builtin_llceilf, in, out, ref, ARRAY_SIZE);
+  RUN_TEST_CVT (float, int64_t, 29, __builtin_llceilf, in, out, ref, ARRAY_SIZE);
+  return 0;
+}