When we walk stmts to find always executed stmts with UB in the last iteration to be able to reduce the iteration count by one we fail to consider infinite subloops in the last iteration that would make such stmt not execute. The following adds this.
Third try - bootstrapped and tested on x86_64-unknown-linux-gnu. I'm reasonably happy with this and will push tomorrow unless I hear otherwise. Richard. PR tree-optimization/114052 * tree-ssa-loop-niter.cc (maybe_lower_iteration_bound): Check for infinite subloops we might not exit. * gcc.dg/pr114052-1.c: New testcase. --- gcc/testsuite/gcc.dg/pr114052-1.c | 41 +++++++++++++++++++++++++++++++ gcc/tree-ssa-loop-niter.cc | 9 ++++++- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr114052-1.c diff --git a/gcc/testsuite/gcc.dg/pr114052-1.c b/gcc/testsuite/gcc.dg/pr114052-1.c new file mode 100644 index 00000000000..98e93bf670d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114052-1.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ +/* { dg-require-effective-target signal } */ +/* { dg-require-effective-target alarm } */ +/* { dg-options "-O2" } */ + +#include <stdint.h> +#include <unistd.h> +#include <signal.h> +#include <stdlib.h> + +volatile int y; +void __attribute__((noipa)) put(int x) +{ + if (y) + __builtin_printf ("%i\n", x); +} + +void __attribute__((noipa)) f(void) +{ + int counter = 0; + while (1) { + if (counter >= 2) continue; + put (counter++); + } +} + +void do_exit (int i) +{ + exit (0); +} + +int main() +{ + struct sigaction s; + sigemptyset (&s.sa_mask); + s.sa_handler = do_exit; + s.sa_flags = 0; + sigaction (SIGALRM, &s, NULL); + alarm (1); + f(); +} diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc index de8d5ae6233..7743970bf3d 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -4757,7 +4757,14 @@ maybe_lower_iteration_bound (class loop *loop) FOR_EACH_EDGE (e, ei, bb->succs) { if (loop_exit_edge_p (loop, e) - || e == loop_latch_edge (loop)) + || e == loop_latch_edge (loop) + /* When exiting an inner loop, verify it is finite. */ + || (!flow_bb_inside_loop_p (bb->loop_father, e->dest) + && !finite_loop_p (bb->loop_father)) + /* When we enter an irreducible region and the entry + does not contain a bounding stmt assume it might be + infinite. */ + || (bb->flags & BB_IRREDUCIBLE_LOOP)) { found_exit = true; break; -- 2.43.0