lgtm
> From: "Robin Dapp"<[email protected]>
> Date:  Thu, Dec 18, 2025, 20:17
> Subject:  [PATCH] RISC-V: Fix overflow check in interleave pattern [PR122970].
> To: "gcc-patches"<[email protected]>
> Cc: <[email protected]>, <[email protected]>, <[email protected]>, 
> <[email protected]>, <[email protected]>
> 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<http://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<http://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<http://riscv-v.cc> 
> b/gcc/config/riscv/riscv-v.cc<http://riscv-v.cc> 
index 321b5172783..d64acff8e0f 100644 
> --- a/gcc/config/riscv/riscv-v.cc<http://riscv-v.cc> 
+++ b/gcc/config/riscv/riscv-v.cc<http://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

Reply via email to