> -----Original Message-----
> From: Dominic P <[email protected]>
> Sent: 29 September 2026 18:35
> To: [email protected]
> Cc: Richard Biener <[email protected]>; Richard Sandiford
> <[email protected]>; Tamar Christina
> <[email protected]>; Robin Dapp <[email protected]>
> Subject: [PATCH v2 1/2] vect: Account for peeling by masking in strided gather
> offsets
> 
> vect_truncate_gather_scatter_offset bounds the offsets { 0, X, X*2, ... }
> by the latch iteration count, but peeling for alignment by masking
> shifts the active lanes up by the number of skipped iterations.  With
> -msve-vector-bits=256 the new tests access lane 7 through the 32-bit
> offset 7 * 650000000, which wraps.  Do not lower the bound when peeling
> for alignment, since whether a mask will do the peeling is not yet known.
> GCC 11 onwards have the same wrong code.
> 
> Bootstrapped and regression tested on x86_64-pc-linux-gnu; regression
> tested on aarch64-linux-gnu (qemu, default and SVE-256 boards).
> 
> Assisted-by: Claude Opus 5 (Anthropic)
> 
> gcc/ChangeLog:
> 
>       * tree-vect-stmts.cc (vect_truncate_gather_scatter_offset): Do not
>       lower the element count to the latch iteration count when peeling
>       for alignment.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.target/aarch64/sve/strided_load_9.c: New test.
>       * gcc.target/aarch64/sve/strided_store_8.c: New test.
> 
> Signed-off-by: Dominic P <[email protected]>
> ---
>  .../gcc.target/aarch64/sve/strided_load_9.c      | 16 ++++++++++++++++
>  .../gcc.target/aarch64/sve/strided_store_8.c     | 16 ++++++++++++++++
>  gcc/tree-vect-stmts.cc                           |  6 ++++--
>  3 files changed, 36 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/strided_load_9.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/strided_store_8.c
> 
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/strided_load_9.c
> b/gcc/testsuite/gcc.target/aarch64/sve/strided_load_9.c
> new file mode 100644
> index 00000000000..b5e793f4394
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/strided_load_9.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile { target lp64 } } */
> +/* { dg-options "-O3 -fno-vect-cost-model -msve-vector-bits=256 -
> mautovec-preference=sve-only" } */
> +
> +int x[8] __attribute__ ((aligned (64)));
> +
> +void
> +foo (int *restrict b, unsigned int n)
> +{
> +  for (unsigned int i = 1; i < n; ++i)
> +    x[i] = b[i * 650000000L];
> +}
> +
> +/* Peeling for alignment by masking makes lane 7 active; 7 * 650000000
> +   does not fit in 32 bits.  */
> +/* { dg-final { scan-assembler-not {\tld1w\tz[0-9]+\.s, p[0-7]/z, \[x[0-9]+,
> z[0-9]+\.s, [su]xtw} } } */
> +/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d, p[0-7]/z, 
> \[x[0-9]+,
> z[0-9]+\.d\]} 2 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/strided_store_8.c
> b/gcc/testsuite/gcc.target/aarch64/sve/strided_store_8.c
> new file mode 100644
> index 00000000000..6e6602eb923
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/strided_store_8.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile { target lp64 } } */
> +/* { dg-options "-O3 -fno-vect-cost-model -msve-vector-bits=256 -
> mautovec-preference=sve-only" } */
> +
> +int x[8] __attribute__ ((aligned (64)));
> +
> +void
> +bar (int *restrict b, unsigned int n)
> +{
> +  for (unsigned int i = 1; i < n; ++i)
> +    b[i * 650000000L] = x[i];
> +}
> +
> +/* Peeling for alignment by masking makes lane 7 active; 7 * 650000000
> +   does not fit in 32 bits.  */
> +/* { dg-final { scan-assembler-not {\tst1w\tz[0-9]+\.s, p[0-7], \[x[0-9]+, 
> z[0-
> 9]+\.s, [su]xtw} } } */
> +/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.d, p[0-7], \[x[0-9]+,
> z[0-9]+\.d\]} 2 } } */
> diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
> index 244f319d0e4..1db6786078e 100644
> --- a/gcc/tree-vect-stmts.cc
> +++ b/gcc/tree-vect-stmts.cc
> @@ -1653,10 +1653,12 @@ vect_truncate_gather_scatter_offset
> (stmt_vec_info stmt_info, tree vectype,
>       Start with the maximum vectorization factor.  */
>    unsigned HOST_WIDE_INT count = vect_max_vf (loop_vinfo) - 1;
> 
> -  /* Try lowering COUNT to the number of scalar latch iterations.  */
> +  /* Try lowering COUNT to the number of scalar latch iterations.
> +     Peeling for alignment by masking shifts the active lanes up.  */
>    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
>    widest_int max_iters;
> -  if (max_loop_iterations (loop, &max_iters)
> +  if (!LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)

That's a bit too broad as it'll apply for unmasked targets as well which
ofcourse can't use peeling using masks.  Unfortunately this is very early
so we haven't even determined the peeling method yet.

But at the very least, this needs to be restricted to only masked targets.

So

! (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)
       && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo))

Patch is OK with that change.

Thanks,
Tamar

> +      && max_loop_iterations (loop, &max_iters)
>        && max_iters < count)
>      count = max_iters.to_shwi ();
> 
> --
> 2.55.0

Reply via email to