diff options
author | Andrew Stubbs <ams@codesourcery.com> | 2014-11-20 20:22:54 +0000 |
---|---|---|
committer | Andrew Stubbs <ams@gcc.gnu.org> | 2014-11-20 20:22:54 +0000 |
commit | 480677242917f34fa2f72ef5e02e6b43689d0ae5 (patch) | |
tree | 431f77de5d4b389b2cbcd785e96ac89bb1d9fa29 /gcc/tree-ssa-loop-niter.c | |
parent | ea6a433c6cc3875e03f0aa2bdfe7afdcb7a90083 (diff) | |
download | gcc-480677242917f34fa2f72ef5e02e6b43689d0ae5.zip gcc-480677242917f34fa2f72ef5e02e6b43689d0ae5.tar.gz gcc-480677242917f34fa2f72ef5e02e6b43689d0ae5.tar.bz2 |
Warn on undefined loop exit.
2014-11-20 Andrew Stubbs <ams@codesourcery.com>
gcc/
* tree-ssa-loop-niter.c (maybe_lower_iteration_bound): Warn if a loop
condition would be removed due to undefined behaviour.
gcc/testsuite/
* gcc.dg/undefined-loop-1.c: New file.
* gcc.dg/undefined-loop-2.c: New file.
From-SVN: r217891
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index fd4d5bf..8ba365c 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -3294,6 +3294,7 @@ maybe_lower_iteration_bound (struct loop *loop) struct nb_iter_bound *elt; bool found_exit = false; vec<basic_block> queue = vNULL; + vec<gimple> problem_stmts = vNULL; bitmap visited; /* Collect all statements with interesting (i.e. lower than @@ -3339,6 +3340,7 @@ maybe_lower_iteration_bound (struct loop *loop) if (not_executed_last_iteration->contains (stmt)) { stmt_found = true; + problem_stmts.safe_push (stmt); break; } if (gimple_has_side_effects (stmt)) @@ -3382,9 +3384,53 @@ maybe_lower_iteration_bound (struct loop *loop) "undefined statement must be executed at the last iteration.\n"); record_niter_bound (loop, loop->nb_iterations_upper_bound - 1, false, true); + + if (warn_aggressive_loop_optimizations) + { + bool exit_warned = false; + for (elt = loop->bounds; elt; elt = elt->next) + { + if (elt->is_exit + && wi::gtu_p (elt->bound, loop->nb_iterations_upper_bound)) + { + basic_block bb = gimple_bb (elt->stmt); + edge exit_edge = EDGE_SUCC (bb, 0); + struct tree_niter_desc niter; + + if (!loop_exit_edge_p (loop, exit_edge)) + exit_edge = EDGE_SUCC (bb, 1); + + if(number_of_iterations_exit (loop, exit_edge, + &niter, false, false) + && integer_onep (niter.assumptions) + && integer_zerop (niter.may_be_zero) + && niter.niter + && TREE_CODE (niter.niter) == INTEGER_CST + && wi::ltu_p (loop->nb_iterations_upper_bound, + wi::to_widest (niter.niter))) + { + if (warning_at (gimple_location (elt->stmt), + OPT_Waggressive_loop_optimizations, + "loop exit may only be reached after undefined behavior")) + exit_warned = true; + } + } + } + + if (exit_warned && !problem_stmts.empty ()) + { + gimple stmt; + int index; + FOR_EACH_VEC_ELT (problem_stmts, index, stmt) + inform (gimple_location (stmt), + "possible undefined statement is here"); + } + } } + BITMAP_FREE (visited); queue.release (); + problem_stmts.release (); delete not_executed_last_iteration; } |