https://gcc.gnu.org/g:0383e6c398a0636c54209ce5822fd4fd43e9a99f
commit r16-7762-g0383e6c398a0636c54209ce5822fd4fd43e9a99f Author: Tamar Christina <[email protected]> Date: Fri Feb 27 14:21:36 2026 +0000 vect: enforce trapping math checks when early breaks [PR124142] 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. 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: --- gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s332.c | 2 +- gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s481.c | 2 +- gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s482.c | 2 +- .../gcc.dg/vect/vect-early-break_143-pr124142.c | 16 +++++++++ gcc/testsuite/gcc.dg/vect/vect-early-break_61.c | 1 + .../aarch64/vect-early-break-cbranch_3.c | 2 +- gcc/tree-vect-data-refs.cc | 38 ++++++++++++++++++++-- 7 files changed, 57 insertions(+), 6 deletions(-) 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 21a9c5a6b2b6..04727388fc9c 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 e4433385d668..24ac2fbedd2d 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 146df409ecc6..38426845a3d1 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 000000000000..b9141e3f15a9 --- /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 c789ec01f32c..0cd20549cdc6 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 8980b9f04f9a..b252b80ef291 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 4977e425e81b..25eb2b07c600 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
