Hi,
In the pattern where we interpret and code-gen two interleaving series as if
they were represented in a larger type we check for overflow.
The overflow check is basically
if (base + (nelems - 1) * step >> inner_bits != 0)
overflow = true;
In the PR, base is negative and we interpret it as negative uint64
value. Thus, e.g. base + (nelems - 1) * step = -32 + 7 * 8 = 24.
24 fits uint8 and we wrongly assume that no overflow happens.
This patch reinterprets base as type of inner bit size which makes the
overflow check work.
Regtested on rv64gcv_zvl512b.
Regards
Robin
PR target/122970
gcc/ChangeLog:
* config/riscv/riscv-v.cc
(expand_const_vector_interleaved_stepped_npatterns):
Reinterpret base as smaller type.
gcc/testsuite/ChangeLog:
* lib/target-supports.exp: Add rvv_zvl128b_ok.
* gcc.target/riscv/rvv/autovec/pr122970.c: New test.
---
gcc/config/riscv/riscv-v.cc | 6 +-
.../gcc.target/riscv/rvv/autovec/pr122970.c | 71 +++++++++++++++++++
gcc/testsuite/lib/target-supports.exp | 18 +++++
3 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122970.c
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 321b5172783..d64acff8e0f 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1632,7 +1632,11 @@ expand_const_vector_interleaved_stepped_npatterns (rtx
target, rtx src,
{
int elem_count = XVECLEN (src, 0);
uint64_t step1_val = step1.to_constant ();
- uint64_t base1_val = base1_poly.to_constant ();
+ int64_t base1_signed = base1_poly.to_constant ();
+ /* Reinterpret as type of inner bits size so we can properly check
+ overflow. */
+ uint64_t base1_val
+ = base1_signed & ((1ULL << builder->inner_bits_size ()) - 1);
uint64_t elem_val = base1_val + (elem_count - 1) * step1_val;
if ((elem_val >> builder->inner_bits_size ()) != 0)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122970.c
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122970.c
new file mode 100644
index 00000000000..be2ac4a62ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122970.c
@@ -0,0 +1,71 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+/* { dg-require-effective-target rvv_zvl128b_ok } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl
-mrvv-max-lmul=m4" } */
+
+typedef unsigned char uint8_t;
+
+void
+f (uint8_t *restrict a, uint8_t *restrict c, uint8_t *restrict d, int n)
+{
+ for (int i = 0; i < n; ++i)
+ {
+ a[i * 8] = c[i * 8] + d[i * 8];
+ a[i * 8 + 1] = c[i * 8] + d[i * 8 + 1];
+ a[i * 8 + 2] = c[i * 8 + 2] + d[i * 8 + 2];
+ a[i * 8 + 3] = c[i * 8 + 2] + d[i * 8 + 3];
+ a[i * 8 + 4] = c[i * 8 + 4] + d[i * 8 + 4]; a[i * 8 + 5] = c[i * 8 + 4]
+ d[i * 8 + 5];
+ a[i * 8 + 6] = c[i * 8 + 6] + d[i * 8 + 6];
+ a[i * 8 + 7] = c[i * 8 + 6] + d[i * 8 + 7];
+ }
+}
+
+void __attribute__ ((noipa))
+f_golden (uint8_t *restrict a, uint8_t *restrict c, uint8_t *restrict d, int n)
+{
+#pragma GCC novector
+ for (int i = 0; i < n; ++i)
+ {
+ a[i * 8] = c[i * 8] + d[i * 8];
+ a[i * 8 + 1] = c[i * 8] + d[i * 8 + 1];
+ a[i * 8 + 2] = c[i * 8 + 2] + d[i * 8 + 2];
+ a[i * 8 + 3] = c[i * 8 + 2] + d[i * 8 + 3];
+ a[i * 8 + 4] = c[i * 8 + 4] + d[i * 8 + 4];
+ a[i * 8 + 5] = c[i * 8 + 4] + d[i * 8 + 5];
+ a[i * 8 + 6] = c[i * 8 + 6] + d[i * 8 + 6];
+ a[i * 8 + 7] = c[i * 8 + 6] + d[i * 8 + 7];
+ }
+}
+
+#define LIMIT 256
+#define NUM 32
+
+int
+main (void)
+{
+ uint8_t a[NUM * 8 + 8] = {0};
+ uint8_t a_golden[NUM * 8 + 8] = {0};
+ uint8_t c[NUM * 8 + 8] = {0};
+ uint8_t d[NUM * 8 + 8] = {0};
+
+ for (int i = 0; i < NUM * 8 + 8; i++)
+ {
+ if (i % NUM == 0)
+ c[i] = (i + NUM) % LIMIT;
+ else
+ c[i] = (i * 3) % LIMIT;
+ if (i % 2 == 0)
+ d[i] = i % LIMIT;
+ else
+ d[i] = (i * 7) % LIMIT;
+ }
+
+ f (a, c, d, NUM);
+ f_golden (a_golden, c, d, NUM);
+
+ if (a[241] != 103)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/lib/target-supports.exp
b/gcc/testsuite/lib/target-supports.exp
index 7f7e6ee2c60..ccd78f9f56f 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2127,6 +2127,24 @@ proc check_effective_target_riscv_v { } {
}]
}
+# Return 1 if the target runtime supports 128-bit vectors, 0 otherwise.
+# Cache the result.
+
+proc check_effective_target_rvv_zvl128b_ok { } {
+ # Check if the target has a VLENB of 16.
+ set gcc_march [riscv_get_arch]
+ return [check_runtime ${gcc_march}_exec {
+ int main()
+ {
+ int vlenb = 0;
+ asm ("csrr %0,vlenb" : "=r" (vlenb) : : );
+ if (vlenb == 16)
+ return 0;
+ return 1;
+ }
+ } "-march=${gcc_march}"]
+}
+
# Return 1 if the target runtime supports 256-bit vectors, 0 otherwise.
# Cache the result.
--
2.51.1