https://gcc.gnu.org/g:09ea2b042881a6fad24e9b96029b62b93eda4fea
commit r17-1614-g09ea2b042881a6fad24e9b96029b62b93eda4fea Author: Tamar Christina <[email protected]> Date: Wed Jun 17 12:09:22 2026 +0100 vect: Fix early break in PEELED cases [PR125804] When a loop is LOOP_VINFO_EARLY_BREAKS_VECT_PEELED && ! LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG then we still need the epilog loop for the main latch edge. The early exits themselves when LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG don't need to go to scalar code. Allowing bound_epilog to still be set to VF when LOOP_VINFO_EARLY_BREAKS_VECT_PEELED we get to the desired effect that the early exits do not require an epilog when !LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG but the main edge still does if LOOP_VINFO_EARLY_BREAKS_VECT_PEELED. gcc/ChangeLog: PR tree-optimization/125804 * tree-vect-loop-manip.cc (vect_do_peeling): Have LOOP_VINFO_EARLY_BREAKS_VECT_PEELED require epilog. gcc/testsuite/ChangeLog: PR tree-optimization/125804 * gcc.dg/vect/vect-early-break_144-pr125804.c: New test. Diff: --- .../gcc.dg/vect/vect-early-break_144-pr125804.c | 51 ++++++++++++++++++++++ gcc/tree-vect-loop-manip.cc | 3 +- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_144-pr125804.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_144-pr125804.c new file mode 100644 index 000000000000..f8974023ee6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_144-pr125804.c @@ -0,0 +1,51 @@ +/* { dg-add-options vect_early_break } */ +/* { dg-do run } */ +/* { dg-require-effective-target vect_early_break_hw } */ +/* { dg-require-effective-target vect_long } */ + +/* { dg-additional-options "-mavx512f" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-require-effective-target avx512f_runtime { target i?86-*-* x86_64-*-* } } */ + +#include "tree-vect.h" + +typedef struct { + unsigned b; + long long bits[2]; +} c; +typedef struct { + c *d; +} e, *bitmap; +e f; +int g; + +__attribute__((noipa)) +int h(bitmap i) { + c j = *i->d; + unsigned k, l = j.b < 4; + for (; l < 2; l++) { + long long m = j.bits[l]; + for (; k < 64; k++) { + long long n = (long long)1LL << k; + if (m & n) + goto o; + } + k = 0; + } + return 0; +o: + return 1; +} + +int main() { + + check_vect (); + + c a; + a.bits[0] = 1ull << 63; + f.d = &a; + g = h(&f); + return g == 0; +} + +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 1 "vect" { target { ! arm*-*-* } } } } */ +/* { dg-final { scan-tree-dump "early break does not require epilog" "vect" { target { ! arm*-*-* } } } } */ diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index d2c854e16d44..a64a79d3299f 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -3320,7 +3320,8 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1, /* For early breaks the scalar loop needs to execute at most VF times to find the element that caused the break. */ if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo) - && LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG (loop_vinfo)) + && (LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG (loop_vinfo) + || LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo))) bound_epilog = vf; bool epilog_peeling = maybe_ne (bound_epilog, 0U);
