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 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; +} -- 2.36.3