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

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


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

Reply via email to