diff options
author | dnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-03-26 10:33:36 +0000 |
---|---|---|
committer | dnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-03-26 10:33:36 +0000 |
commit | a63f89638edc7c3120e52faf6815bfe3e9b270e2 (patch) | |
tree | 61b7552b10852929b89f1cb93878fadffc1885c2 /gcc/tree-ssa-loop-niter.c | |
parent | 9402409a6bd0d7d1f7358793f768bda3ec8a9574 (diff) | |
parent | 087a99ba8749638f86c111f776ed326b3fbd97c0 (diff) | |
download | gcc-cxx-conversion.tar.gz |
Merged revisions 196607-196608,196611-196614,196625,196629-196634,196636,196639,196645-196647,196649-196650,196654-196659,196666,196669,196671-196675,196682-196683,196694-196695,196697-196698,196700-196701,196704-196706,196709,196721-196748,196750-196751,196753,196755-196758,196762,196764-196765,196767-196771,196773-196779,196781-196784,196788-196792,196795-196797,196799-196800,196804-196807,196810-196814,196821,196823-196825,196828-196829,196831-196832,196834,196841-196842,196847-196853,196855-196856,196858,196860-196861,196864-196866,196868,196870-196872,196874,196876,196878-196879,196882,196884-196890,196896-196897,196899-196902,196954,196956-196961,196964-196965,196970,196977-196978,196981-196983,196989,197002-197005,197007,197011-197012,197016-197019,197021,197023-197025,197029-197034,197036-197042 via svnmerge from cxx-conversion
svn+ssh://gcc.gnu.org/svn/gcc/trunk
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/cxx-conversion@197098 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index ba06b0c6936..bcd4317f390 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "diagnostic-core.h" #include "tree-inline.h" +#include "tree-pass.h" #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0) @@ -2525,6 +2526,40 @@ record_niter_bound (struct loop *loop, double_int i_bound, bool realistic, loop->nb_iterations_estimate = loop->nb_iterations_upper_bound; } +/* Emit a -Waggressive-loop-optimizations warning if needed. */ + +static void +do_warn_aggressive_loop_optimizations (struct loop *loop, + double_int i_bound, gimple stmt) +{ + /* Don't warn if the loop doesn't have known constant bound. */ + if (!loop->nb_iterations + || TREE_CODE (loop->nb_iterations) != INTEGER_CST + || !warn_aggressive_loop_optimizations + /* To avoid warning multiple times for the same loop, + only start warning when we preserve loops. */ + || (cfun->curr_properties & PROP_loops) == 0 + /* Only warn once per loop. */ + || loop->warned_aggressive_loop_optimizations + /* Only warn if undefined behavior gives us lower estimate than the + known constant bound. */ + || i_bound.ucmp (tree_to_double_int (loop->nb_iterations)) >= 0 + /* And undefined behavior happens unconditionally. */ + || !dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (stmt))) + return; + + edge e = single_exit (loop); + if (e == NULL) + return; + + gimple estmt = last_stmt (e->src); + warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations, + "iteration %E invokes undefined behavior", + double_int_to_tree (TREE_TYPE (loop->nb_iterations), i_bound)); + inform (gimple_location (estmt), "containing loop"); + loop->warned_aggressive_loop_optimizations = true; +} + /* Records that AT_STMT is executed at most BOUND + 1 times in LOOP. IS_EXIT is true if the loop is exited immediately after STMT, and this exit is taken at last when the STMT is executed BOUND + 1 times. @@ -2560,8 +2595,12 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, return; /* If we have a guaranteed upper bound, record it in the appropriate - list. */ - if (upper) + list, unless this is an !is_exit bound (i.e. undefined behavior in + at_stmt) in a loop with known constant number of iterations. */ + if (upper + && (is_exit + || loop->nb_iterations == NULL_TREE + || TREE_CODE (loop->nb_iterations) != INTEGER_CST)) { struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound (); @@ -2591,6 +2630,8 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, if (i_bound.ult (delta)) return; + if (upper && !is_exit) + do_warn_aggressive_loop_optimizations (loop, i_bound, at_stmt); record_niter_bound (loop, i_bound, realistic, upper); } @@ -3311,6 +3352,11 @@ estimate_numbers_of_iterations_loop (struct loop *loop) /* Force estimate compuation but leave any existing upper bound in place. */ loop->any_estimate = false; + /* Ensure that loop->nb_iterations is computed if possible. If it turns out + to be constant, we avoid undefined behavior implied bounds and instead + diagnose those loops with -Waggressive-loop-optimizations. */ + number_of_latch_executions (loop); + exits = get_loop_exit_edges (loop); likely_exit = single_likely_exit (loop); FOR_EACH_VEC_ELT (exits, i, ex) @@ -3345,6 +3391,17 @@ estimate_numbers_of_iterations_loop (struct loop *loop) bound = gcov_type_to_double_int (nit); record_niter_bound (loop, bound, true, false); } + + /* If we know the exact number of iterations of this loop, try to + not break code with undefined behavior by not recording smaller + maximum number of iterations. */ + if (loop->nb_iterations + && TREE_CODE (loop->nb_iterations) == INTEGER_CST) + { + loop->any_upper_bound = true; + loop->nb_iterations_upper_bound + = tree_to_double_int (loop->nb_iterations); + } } /* Sets NIT to the estimated number of executions of the latch of the |