RISC-V: Fix natural regsize for fixed-vlmax of -march=rv64gc_zve32f
Checks
Commit Message
This patch fixes 12 ICEs of "full coverage" testing:
Running target riscv-sim/-march=rv64gc_zve32f/-mabi=lp64d/-mcmodel=medlow/--param=riscv-autovec-lmul=dynamic/--param=riscv-autovec-preference=fixed-vlmax
FAIL: gcc.dg/torture/pr96513.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (internal compiler error: Segmentation fault)
FAIL: gcc.dg/torture/pr96513.c -O3 -g (internal compiler error: Segmentation fault)
Running target riscv-sim/-march=rv64gc_zve32f/-mabi=lp64d/-mcmodel=medlow/--param=riscv-autovec-lmul=m4/--param=riscv-autovec-preference=fixed-vlmax
FAIL: gcc.dg/torture/pr111048.c -O2 (internal compiler error: Segmentation fault)
FAIL: gcc.dg/torture/pr111048.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (internal compiler error: Segmentation fault)
FAIL: gcc.dg/torture/pr111048.c -O3 -g (internal compiler error: Segmentation fault)
FAIL: gcc.dg/torture/pr96513.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (internal compiler error: Segmentation fault)
FAIL: gcc.dg/torture/pr96513.c -O3 -g (internal compiler error: Segmentation fault)
Running target riscv-sim/-march=rv64gc_zve32f/-mabi=lp64d/-mcmodel=medlow/--param=riscv-autovec-lmul=m8/--param=riscv-autovec-preference=fixed-vlmax
FAIL: gcc.dg/torture/pr96513.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (internal compiler error: Segmentation fault)
FAIL: gcc.dg/torture/pr96513.c -O3 -g (internal compiler error: Segmentation fault)
Running target riscv-sim/-march=rv64gc_zve32f/-mabi=lp64d/-mcmodel=medlow/--param=riscv-autovec-preference=fixed-vlmax
FAIL: gcc.c-torture/execute/20000801-1.c -O2 (internal compiler error: Segmentation fault)
FAIL: gcc.c-torture/execute/20000801-1.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (internal compiler error: Segmentation fault)
FAIL: gcc.c-torture/execute/20000801-1.c -O3 -g (internal compiler error: Segmentation fault)
The root cause of those ICEs is vector register size = 32bits, wheras scalar register size = 64bit.
That is, vector regsize < scalar regsize on -march=rv64gc_zve32f FIXED-VLMAX.
So the original natural regsize using scalar register size is incorrect. Instead, we should return minimum regsize between vector regsize and scalar regsize.
gcc/ChangeLog:
* config/riscv/riscv.cc (riscv_regmode_natural_size): Fix ICE for FIXED-VLMAX of -march=rv32gc_zve32f.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/rvv/autovec/bug-4.c: New test.
* gcc.target/riscv/rvv/autovec/bug-5.c: New test.
* gcc.target/riscv/rvv/autovec/bug-6.c: New test.
---
gcc/config/riscv/riscv.cc | 12 ++++--
.../gcc.target/riscv/rvv/autovec/bug-4.c | 27 ++++++++++++
.../gcc.target/riscv/rvv/autovec/bug-5.c | 24 +++++++++++
.../gcc.target/riscv/rvv/autovec/bug-6.c | 42 +++++++++++++++++++
4 files changed, 102 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-6.c
Comments
@@ -9621,10 +9621,10 @@ riscv_regmode_natural_size (machine_mode mode)
if (riscv_v_ext_mode_p (mode))
{
+ poly_uint64 size = GET_MODE_SIZE (mode);
if (riscv_v_ext_tuple_mode_p (mode))
{
- poly_uint64 size
- = GET_MODE_SIZE (riscv_vector::get_subpart_mode (mode));
+ size = GET_MODE_SIZE (riscv_vector::get_subpart_mode (mode));
if (known_lt (size, BYTES_PER_RISCV_VECTOR))
return size;
}
@@ -9634,8 +9634,14 @@ riscv_regmode_natural_size (machine_mode mode)
if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
return BYTES_PER_RISCV_VECTOR;
}
- if (!GET_MODE_SIZE (mode).is_constant ())
+ if (!size.is_constant ())
return BYTES_PER_RISCV_VECTOR;
+ else if (!riscv_v_ext_vls_mode_p (mode))
+ /* For -march=rv64gc_zve32f, the natural vector register size
+ is 32bits which is smaller than scalar register size, so we
+ return minimum size between vector register size and scalar
+ register size. */
+ return MIN (size.to_constant (), UNITS_PER_WORD);
}
return UNITS_PER_WORD;
}
new file mode 100644
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zve32f -mabi=lp64d -O3 --param=riscv-autovec-lmul=m8 --param=riscv-autovec-preference=fixed-vlmax" } */
+
+typedef struct {
+ short a;
+ short b;
+} c;
+c *d;
+int e, f, i, j, k, l, m, n, o, p;
+c g, h;
+void q() {
+ do {
+ if (o) {
+ (*d).a = (*d).b = d[e].a = d[e].a * 3 + 1 >> 15;
+ d[e].b = d[e].b * 3 + 1 >> 15;
+ }
+ n = -(d[e].b * g.b) >> 5;
+ m = d[e].b * g.a + 1 >> 5;
+ l = d[f].a * -d[f].b * h.b + 1 >> 5;
+ k = d[f].a * h.b + d[f].b * h.a + 1 >> 5;
+ j = n + l;
+ i = m - k;
+ (*d).a += j;
+ d[e].a -= i;
+ ++d;
+ } while (--p);
+}
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zve32f -mabi=lp64d -O2 --param=riscv-autovec-lmul=m4 --param=riscv-autovec-preference=fixed-vlmax" } */
+
+typedef unsigned char u8;
+
+__attribute__((noipa))
+static void check(const u8 * v) {
+ if (*v != 15) __builtin_trap();
+}
+
+__attribute__((noipa))
+static void bug(void) {
+ u8 in_lanes[32];
+ for (unsigned i = 0; i < 32; i += 2) {
+ in_lanes[i + 0] = 0;
+ in_lanes[i + 1] = ((u8)0xff) >> (i & 7);
+ }
+
+ check(&in_lanes[13]);
+ }
+
+int main() {
+ bug();
+}
new file mode 100644
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zve32f -mabi=lp64d -O2 --param=riscv-autovec-preference=fixed-vlmax" } */
+
+extern void abort(void);
+extern void exit(int);
+
+void
+foo (char *bp, unsigned n)
+{
+ register char c;
+ register char *ep = bp + n;
+ register char *sp;
+
+ while (bp < ep)
+ {
+ sp = bp + 3;
+ c = *sp;
+ *sp = *bp;
+ *bp++ = c;
+ sp = bp + 1;
+ c = *sp;
+ *sp = *bp;
+ *bp++ = c;
+ bp += 2;
+ }
+}
+
+int main(void)
+{
+ int one = 1;
+
+ if (sizeof(int) != 4 * sizeof(char))
+ exit(0);
+
+ foo((char *)&one, sizeof(one));
+ foo((char *)&one, sizeof(one));
+
+ if (one != 1)
+ abort();
+
+ exit(0);
+}