RISC-V: Fix natural regsize for fixed-vlmax of -march=rv64gc_zve32f

Message ID 20231218032013.99095-1-juzhe.zhong@rivai.ai
State Unresolved
Headers
Series RISC-V: Fix natural regsize for fixed-vlmax of -march=rv64gc_zve32f |

Checks

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

Commit Message

juzhe.zhong@rivai.ai Dec. 18, 2023, 3:20 a.m. UTC
  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

Robin Dapp Dec. 18, 2023, 9:20 a.m. UTC | #1
LGTM.

Regards
 Robin
  

Patch

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3fef1ab1514..8ae65760b6e 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -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;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-4.c
new file mode 100644
index 00000000000..c860e92dc3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-4.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-5.c
new file mode 100644
index 00000000000..df16fb28c49
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-5.c
@@ -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();
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-6.c
new file mode 100644
index 00000000000..975c4816a28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/bug-6.c
@@ -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);
+}