https://gcc.gnu.org/g:d4e6fc510f90b0e6895841febfa9da8858653cfe
commit r16-6299-gd4e6fc510f90b0e6895841febfa9da8858653cfe Author: Robin Dapp <[email protected]> Date: Thu Dec 18 11:19:57 2025 +0100 RISC-V: Fix overflow check in interleave pattern [PR122970]. 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. 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. Diff: --- 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(-) diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index 321b5172783d..d64acff8e0f8 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 000000000000..be2ac4a62aeb --- /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 27759094d852..4d2d1e939d25 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.
