On Fri, 27 Feb 2026, Tamar Christina wrote:

> The loop
> 
> void
> __attribute__((noipa))
> bug (int f, int *w, int l)
> {
>   int i;
>   for (i = 0; i < l; ++i)
>     while (f % w[i]) w[i]--;
> }
> 
> is an uncounted loop which performs a trapping operation during vectorization.
> Normally the vectorizer doesn't stop vectorization if the operation can't be
> masked (though ifcvt does).
> 
> For Early breaks however this is unsafe as we are introducing a trap where the
> original scalar code may not have.
> 
> Some tests now fail to vectorize (including some tsvc ones) which I could have
> xfail'ed but instead decided to add -fno-trapping-math just to get the
> additional coverage they provide.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and 1 test failure on -m32 that I'm
> looking at but seems unrelated/latent.
> 
> This reduced example:
> 
> long long a[1024];
> float b[1024];
> float c;
> void abort();
> int main() {
>   int d;
>   volatile float e;
>   volatile double h, i, f, g = 1.0f;
>   for (; c == e;)
>     for (; (i = f) == g;)
>       ;
>   for (d = 0; d < 4; d++)
>     if (d == 0)
>       b[d] = h;

so at least b[0] is random (h is uninitialized), as a[] isn't written to
and neither the rest of b is I think this is just UB?

>   for (d = 0; d < 1024; d++)
>     if (a[d] != (__typeof(0))b[d])
>       abort();
> }
> 
> works with -fno-tree-vectorize, but is broken
> with -ftree-vectorize and we reject the loop
> during analysis.  I've checked that just
> unconditionally returning opt_result::failure_at
> also triggers this so is unrelated to the patch.
> 
> Something goes wrong during cleanup.
> 
> Any objections? I won't commit till fixing the other
> bug.

OK.

Thanks,
Richard.

> Thanks,
> Tamar
> 
> gcc/ChangeLog:
> 
>       PR tree-optimization/124142
>       * tree-vect-data-refs.cc (vect_analyze_early_break_dependences):
>       For early break require masking when operation can trap.
> 
> gcc/testsuite/ChangeLog:
> 
>       PR tree-optimization/124142
>       * gcc.dg/vect/tsvc/vect-tsvc-s481.c: Add -fno-trapping-math.
>       * gcc.dg/vect/tsvc/vect-tsvc-s332.c: Likewise.
>       * gcc.dg/vect/tsvc/vect-tsvc-s482.c: Likewise.
>       * gcc.dg/vect/vect-early-break_61.c: Likewise.
>       * gcc.target/aarch64/vect-early-break-cbranch_3.c: Likewise.
>       * gcc.dg/vect/vect-early-break_143-pr124142.c: New test
> 
> ---
> diff --git a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s332.c 
> b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s332.c
> index 
> 21a9c5a6b2b6a81762977d6caaeaca06b67d29fb..04727388fc9c648981454c2fa4a38afa96b01126
>  100644
> --- a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s332.c
> +++ b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s332.c
> @@ -1,7 +1,7 @@
>  /*  This file is distributed under the University of Illinois Open Source
>      License. See license.txt for details.  */
>  
> -/* { dg-additional-options "--param vect-epilogues-nomask=0" } */
> +/* { dg-additional-options "--param vect-epilogues-nomask=0 
> -fno-trapping-math" } */
>  /* { dg-require-effective-target vect_float } */
>  /* { dg-require-effective-target vect_early_break_hw } */
>  /* { dg-add-options vect_early_break } */
> diff --git a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s481.c 
> b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s481.c
> index 
> e4433385d6686806a75fffe22f90e3bfb603564c..24ac2fbedd2d64a6c98de922b058e4d5f7a93ef5
>  100644
> --- a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s481.c
> +++ b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s481.c
> @@ -1,7 +1,7 @@
>  /*  This file is distributed under the University of Illinois Open Source
>      License. See license.txt for details.  */
>  
> -/* { dg-additional-options "--param vect-epilogues-nomask=0" } */
> +/* { dg-additional-options "--param vect-epilogues-nomask=0 
> -fno-trapping-math" } */
>  /* { dg-require-effective-target vect_float } */
>  /* { dg-require-effective-target vect_early_break_hw } */
>  /* { dg-add-options vect_early_break } */
> diff --git a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s482.c 
> b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s482.c
> index 
> 146df409ecc64e9535583c0d0083469d7aa24031..38426845a3d115432bfc68d9e1e7539fe10e27e2
>  100644
> --- a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s482.c
> +++ b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s482.c
> @@ -1,7 +1,7 @@
>  /*  This file is distributed under the University of Illinois Open Source
>      License. See license.txt for details.  */
>  
> -/* { dg-additional-options "--param vect-epilogues-nomask=0" } */
> +/* { dg-additional-options "--param vect-epilogues-nomask=0 
> -fno-trapping-math" } */
>  /* { dg-require-effective-target vect_float } */
>  /* { dg-require-effective-target vect_early_break_hw } */
>  /* { dg-add-options vect_early_break } */
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_143-pr124142.c 
> b/gcc/testsuite/gcc.dg/vect/vect-early-break_143-pr124142.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..b9141e3f15a9d152118c2d8e84fc45d5e83066cb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_143-pr124142.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-add-options vect_early_break } */
> +/* { dg-require-effective-target vect_early_break } */
> +/* { dg-require-effective-target vect_int } */
> +
> +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */
> +
> +void
> +__attribute__((noipa))
> +bug (int f, int *w, int l)
> +{
> +  int i;
> +  for (i = 0; i < l; ++i)
> +    while (f % w[i]) w[i]--;
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_61.c 
> b/gcc/testsuite/gcc.dg/vect/vect-early-break_61.c
> index 
> c789ec01f32c6b958c6a3663531a7b7517b94477..0cd20549cdc656baad2b5561e39ca999bca98bb0
>  100644
> --- a/gcc/testsuite/gcc.dg/vect/vect-early-break_61.c
> +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_61.c
> @@ -2,6 +2,7 @@
>  /* { dg-do compile } */
>  /* { dg-require-effective-target vect_early_break } */
>  /* { dg-require-effective-target vect_float } */
> +/* { dg-additional-options "-fno-trapping-math" } */
>  
>  typedef float real_t;
>  __attribute__((aligned(64))) real_t a[32000], b[32000], c[32000];
> diff --git a/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c 
> b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c
> index 
> 8980b9f04f9a15ded9e90954e25b2c0578681761..b252b80ef291efd4f6fc98224a44ef7fadc68d6c
>  100644
> --- a/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c
> +++ b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c
> @@ -1,5 +1,5 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks 
> -fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
> +/* { dg-options "-O3 -fno-trapping-math -fno-schedule-insns 
> -fno-reorder-blocks -fno-schedule-insns2 --param 
> aarch64-autovec-preference=asimd-only" } */
>  /* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
>  
>  #pragma GCC target "+sve"
> diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
> index 
> 4977e425e81b23f4f449ae41ceb3f95f51bb7cb9..25eb2b07c600e3f2e0dec47182ab502a95fd3ddf
>  100644
> --- a/gcc/tree-vect-data-refs.cc
> +++ b/gcc/tree-vect-data-refs.cc
> @@ -732,11 +732,45 @@ vect_analyze_early_break_dependences (loop_vec_info 
> loop_vinfo)
>         if (is_gimple_debug (stmt))
>           continue;
>  
> +       stmt_vec_info orig_stmt_vinfo = loop_vinfo->lookup_stmt (stmt);
>         stmt_vec_info stmt_vinfo
> -         = vect_stmt_to_vectorize (loop_vinfo->lookup_stmt (stmt));
> +         = vect_stmt_to_vectorize (orig_stmt_vinfo);
>         auto dr_ref = STMT_VINFO_DATA_REF (stmt_vinfo);
>         if (!dr_ref)
> -         continue;
> +         {
> +           /* Trapping statements after the last early exit are fine.  */
> +           if (check_deps)
> +             {
> +               bool could_trap_p = false;
> +               gimple *cur_stmt = STMT_VINFO_STMT (stmt_vinfo);
> +               could_trap_p = gimple_could_trap_p (cur_stmt);
> +               if (STMT_VINFO_IN_PATTERN_P (orig_stmt_vinfo))
> +                 {
> +                   gimple_stmt_iterator gsi2;
> +                   auto stmt_seq
> +                     = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_vinfo);
> +                   for (gsi2 = gsi_start (stmt_seq);
> +                        !could_trap_p && !gsi_end_p (gsi2); gsi_next (&gsi2))
> +                     {
> +                       cur_stmt = gsi_stmt (gsi2);
> +                       could_trap_p = gimple_could_trap_p (cur_stmt);
> +                     }
> +                 }
> +
> +               if (could_trap_p)
> +                 {
> +                   if (dump_enabled_p ())
> +                     dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
> +                          "cannot vectorize as operation may trap.\n");
> +                   return opt_result::failure_at (cur_stmt,
> +                          "can't safely apply code motion to dependencies"
> +                          " to vectorize the early exit. %G may trap.\n",
> +                          cur_stmt);
> +                 }
> +             }
> +
> +           continue;
> +         }
>  
>         /* We know everything below dest_bb is safe since we know we
>            had a full vector iteration when reaching it.  Either by
> 
> 
> 

-- 
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