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