On Tue, 10 Feb 2026, Victor Do Nascimento wrote:

> For the vectorization of non-contiguous memory accesses such as the
> vectorization of loads from a particular struct member, specifically
> when vectorizing with unknown bounds (thus using a pointer and not an
> array) it is observed that inadequate alignment checking allows for
> the crossing of a page boundary within a single vectorized loop
> iteration. This leads to potential segmentation faults in the
> resulting binaries.
> 
> For example, for the given datatype:
> 
>     typedef struct {
>       uint64_t a;
>       uint64_t b;
>       uint32_t flag;
>       uint32_t pad;
>     } Data;
> 
> and a loop such as:
> 
> int
> foo (Data *ptr) {
>   if (ptr == NULL)
>     return -1;
> 
>   int cnt;
>   for (cnt = 0; cnt < MAX; cnt++) {
>     if (ptr->flag == 0)
>       break;
>     ptr++;
>   }
>   return cnt;
> }
> 
> the vectorizer yields the following loop logic on armhf:
> 
> <bb 1>:
> _41 = ptr_4(D) + 16;
> <bb 2>:
> _44 = MEM[(unsigned int *)ivtmp_42];
> ivtmp_45 = ivtmp_42 + 24;
> _46 = MEM[(unsigned int *)ivtmp_45];
> ivtmp_47 = ivtmp_45 + 24;
> _48 = MEM[(unsigned int *)ivtmp_47];
> ivtmp_49 = ivtmp_47 + 24;
> _50 = MEM[(unsigned int *)ivtmp_49];
> vect_cst__51 = {_44, _46, _48, _50};
> mask_patt_6.17_52 = vect_cst__51 == { 0, 0, 0, 0 };
> if (mask_patt_6.17_52 != { 0, 0, 0, 0 })
>   goto <bb 4>;
> else
>   ivtmp_43 = ivtmp_42 + 96;
>   goto <bb 2>;
> <bb4>
> ...
> 
> without any proper address alignment checks on the starting address
> or on whether alignment is preserved across iterations.
> 
> Reject the vectorization of such cases.

Why is peeling for alignment not applied?  This is not a
STMT_VINFO_STRIDED_P access and VMAT_ELEMENTWISE is only a fallback
for the access, it should not disable the peeling for alignment
requirement here?

Richard.

> 
> gcc/ChangeLog:
> 
>       PR tree-optimization/124037
>       * tree-vect-stmts.cc (get_load_store_type): Add check for use
>       context of VMAT_ELEMENTWISE loads.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.dg/vect/pr123588.c: New.
> ---
>  gcc/testsuite/gcc.dg/vect/pr124037.c | 57 ++++++++++++++++++++++++++++
>  gcc/tree-vect-stmts.cc               | 13 +++++++
>  2 files changed, 70 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/vect/pr124037.c
> 
> diff --git a/gcc/testsuite/gcc.dg/vect/pr124037.c 
> b/gcc/testsuite/gcc.dg/vect/pr124037.c
> new file mode 100644
> index 00000000000..3121380454b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/pr124037.c
> @@ -0,0 +1,57 @@
> +/* PR tree-optimization/124037 */
> +/* { dg-options "-O3" } */
> +/* { dg-require-effective-target mmap } */
> +/* { dg-require-effective-target vect_early_break } */
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <sys/mman.h>
> +#include <unistd.h>
> +
> +#define MAX 65536
> +
> +typedef struct {
> +  uint64_t a;
> +  uint64_t b;
> +  uint32_t flag;
> +  uint32_t pad;
> +} Data;
> +
> +int __attribute__ ((noinline))
> +foo (Data *ptr) {
> +  if (ptr == NULL)
> +    return -1;
> +
> +  int cnt;
> +  for (cnt = 0; cnt < MAX; cnt++) {
> +    if (ptr->flag == 0)
> +      break;
> +    ptr++;
> +  }
> +  return cnt;
> +}
> +
> +int main() {
> +  long pgsz = sysconf (_SC_PAGESIZE);
> +  if (pgsz == -1) {
> +    fprintf (stderr, "sysconf failed\n");
> +    return 0;
> +  }
> +
> +  /* Allocate 2 consecutive pages.  */
> +  void *mem = mmap (NULL, pgsz * 2, PROT_READ | PROT_WRITE,
> +                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> +  if (mem == MAP_FAILED) {
> +    fprintf (stderr, "mmap failed\n");
> +    return 0;
> +  }
> +
> +  memset (mem, 1, pgsz);
> +  uint8_t *ptr = (uint8_t*) mem + pgsz;
> +  memset (ptr - 16, 0, 16);
> +
> +  mprotect (ptr, pgsz, PROT_NONE);
> +  Data *data = (Data *) (ptr - 80);
> +  __builtin_printf("%d\n", foo(data));
> +}
> +
> diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
> index ee98e72d1e5..7434d934463 100644
> --- a/gcc/tree-vect-stmts.cc
> +++ b/gcc/tree-vect-stmts.cc
> @@ -2581,6 +2581,19 @@ get_load_store_type (vec_info  *vinfo, stmt_vec_info 
> stmt_info,
>       return false;
>      }
>  
> +  if (loop_vinfo
> +      && !inbounds
> +      && dr_safe_speculative_read_required (stmt_info)
> +      && *memory_access_type == VMAT_ELEMENTWISE
> +      && !STMT_VINFO_GATHER_SCATTER_P (stmt_info))
> +    {
> +      if (dump_enabled_p ())
> +     dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
> +                      "unsafe use of elementwise access for buffer with"
> +                      "unknown bounds\n");
> +      return false;
> +    }
> +
>    /* If this DR needs alignment for correctness, we must ensure the target
>       alignment is a constant power-of-two multiple of the amount read per
>       vector iteration or force masking.  */
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to