From 480677242917f34fa2f72ef5e02e6b43689d0ae5 Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Thu, 20 Nov 2014 20:22:54 +0000 Subject: [PATCH] Warn on undefined loop exit. 2014-11-20 Andrew Stubbs 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 --- gcc/ChangeLog | 5 +++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/undefined-loop-1.c | 18 ++++++++++ gcc/testsuite/gcc.dg/undefined-loop-2.c | 22 ++++++++++++ gcc/tree-ssa-loop-niter.c | 46 +++++++++++++++++++++++++ 5 files changed, 96 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/undefined-loop-1.c create mode 100644 gcc/testsuite/gcc.dg/undefined-loop-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 537fa882631..7153d67ad3a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2014-11-20 Andrew Stubbs + + * tree-ssa-loop-niter.c (maybe_lower_iteration_bound): Warn if a loop + condition would be removed due to undefined behaviour. + 2014-11-20 Andrew Pinski PR ipa/63981 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 61f8a495a42..4aba5fb9e86 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-11-20 Andrew Stubbs + + * gcc.dg/undefined-loop-1.c: New file. + * gcc.dg/undefined-loop-2.c: New file. + 2014-11-20 Tejas Belagod * gcc.target/aarch64/symbol-range.c: New. diff --git a/gcc/testsuite/gcc.dg/undefined-loop-1.c b/gcc/testsuite/gcc.dg/undefined-loop-1.c new file mode 100644 index 00000000000..80260cc8b01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/undefined-loop-1.c @@ -0,0 +1,18 @@ +/* Check that loops whose final iteration is undefined are detected. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Waggressive-loop-optimizations" } */ + +void doSomething(char); + +char array[5]; + +void +foo (void) +{ + int i; + for (i = 0; + array[i] /* { dg-message "note: possible undefined statement is here" } */ + && i < 5; /* { dg-warning "loop exit may only be reached after undefined behavior" } */ + i++) + doSomething(array[i]); +} diff --git a/gcc/testsuite/gcc.dg/undefined-loop-2.c b/gcc/testsuite/gcc.dg/undefined-loop-2.c new file mode 100644 index 00000000000..dbea62cf20b --- /dev/null +++ b/gcc/testsuite/gcc.dg/undefined-loop-2.c @@ -0,0 +1,22 @@ +/* Check that loops whose final iteration is undefined are detected. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Waggressive-loop-optimizations" } */ + +void doSomething(char); + +char array1[5]; +char array2[5]; + +void +foo (int p) +{ + int i; + for (i=0; + (p + ? array1[i] /* { dg-message "note: possible undefined statement is here" } */ + : array2[i]) /* { dg-message "note: possible undefined statement is here" } */ + && i < 5 /* { dg-warning "loop exit may only be reached after undefined behavior" } */ + && i < 100; /* { dg-warning "loop exit may only be reached after undefined behavior" } */ + i++) + doSomething(array1[i]); +} diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index fd4d5bf7b5e..8ba365c4f34 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 queue = vNULL; + vec 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; } -- 2.30.2