diff options
author | Bin Cheng <bin.cheng@arm.com> | 2016-07-15 09:04:57 +0000 |
---|---|---|
committer | Bin Cheng <amker@gcc.gnu.org> | 2016-07-15 09:04:57 +0000 |
commit | 43aabfcfd4139e4c9e7b868199e09b97e66010bc (patch) | |
tree | bf2cd011c65849144b67a4d65d74e9dc61f556d8 /gcc/tree-ssa-loop-niter.c | |
parent | afc89e58498ef6a275d4e018d26b6fca3940ef1e (diff) | |
download | gcc-43aabfcfd4139e4c9e7b868199e09b97e66010bc.zip gcc-43aabfcfd4139e4c9e7b868199e09b97e66010bc.tar.gz gcc-43aabfcfd4139e4c9e7b868199e09b97e66010bc.tar.bz2 |
tree-scalar-evolution.c (simple_iv_with_niters): New funcion.
* tree-scalar-evolution.c (simple_iv_with_niters): New funcion.
(derive_simple_iv_with_niters): New function.
(simple_iv): Rewrite using simple_iv_with_niters.
* tree-scalar-evolution.h (simple_iv_with_niters): New decl.
* tree-ssa-loop-niter.c (number_of_iterations_exit_assumptions): New
function.
(number_of_iterations_exit): Rewrite using above function.
* tree-ssa-loop-niter.h (number_of_iterations_exit_assumptions): New
Decl.
gcc/testsuite
* gcc.dg/tree-ssa/loop-41.c: New test.
From-SVN: r238367
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 94 |
1 files changed, 47 insertions, 47 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 182753c..d96c03b 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -2176,20 +2176,17 @@ loop_only_exit_p (const struct loop *loop, const_edge exit) } /* Stores description of number of iterations of LOOP derived from - EXIT (an exit edge of the LOOP) in NITER. Returns true if some - useful information could be derived (and fields of NITER has - meaning described in comments at struct tree_niter_desc - declaration), false otherwise. If WARN is true and - -Wunsafe-loop-optimizations was given, warn if the optimizer is going to use - potentially unsafe assumptions. + EXIT (an exit edge of the LOOP) in NITER. Returns true if some useful + information could be derived (and fields of NITER have meaning described + in comments at struct tree_niter_desc declaration), false otherwise. When EVERY_ITERATION is true, only tests that are known to be executed - every iteration are considered (i.e. only test that alone bounds the loop). + every iteration are considered (i.e. only test that alone bounds the loop). */ bool -number_of_iterations_exit (struct loop *loop, edge exit, - struct tree_niter_desc *niter, - bool warn, bool every_iteration) +number_of_iterations_exit_assumptions (struct loop *loop, edge exit, + struct tree_niter_desc *niter, + bool every_iteration) { gimple *last; gcond *stmt; @@ -2241,9 +2238,16 @@ number_of_iterations_exit (struct loop *loop, edge exit, && !POINTER_TYPE_P (type)) return false; - if (!simple_iv (loop, loop_containing_stmt (stmt), op0, &iv0, false)) + tree iv0_niters = NULL_TREE; + if (!simple_iv_with_niters (loop, loop_containing_stmt (stmt), + op0, &iv0, &iv0_niters, false)) return false; - if (!simple_iv (loop, loop_containing_stmt (stmt), op1, &iv1, false)) + tree iv1_niters = NULL_TREE; + if (!simple_iv_with_niters (loop, loop_containing_stmt (stmt), + op1, &iv1, &iv1_niters, false)) + return false; + /* Give up on complicated case. */ + if (iv0_niters && iv1_niters) return false; /* We don't want to see undefined signed overflow warnings while @@ -2259,6 +2263,24 @@ number_of_iterations_exit (struct loop *loop, edge exit, return false; } + /* Incorporate additional assumption implied by control iv. */ + tree iv_niters = iv0_niters ? iv0_niters : iv1_niters; + if (iv_niters) + { + tree assumption = fold_build2 (LE_EXPR, boolean_type_node, niter->niter, + fold_convert (TREE_TYPE (niter->niter), + iv_niters)); + + if (!integer_nonzerop (assumption)) + niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, + niter->assumptions, assumption); + + /* Refine upper bound if possible. */ + if (TREE_CODE (iv_niters) == INTEGER_CST + && niter->max > wi::to_widest (iv_niters)) + niter->max = wi::to_widest (iv_niters); + } + if (optimize >= 3) { niter->assumptions = simplify_using_outer_evolutions (loop, @@ -2281,44 +2303,22 @@ number_of_iterations_exit (struct loop *loop, edge exit, if (TREE_CODE (niter->niter) == INTEGER_CST) niter->max = wi::to_widest (niter->niter); - if (integer_onep (niter->assumptions)) - return true; - - /* With -funsafe-loop-optimizations we assume that nothing bad can happen. - But if we can prove that there is overflow or some other source of weird - behavior, ignore the loop even with -funsafe-loop-optimizations. */ - if (integer_zerop (niter->assumptions) || !single_exit (loop)) - return false; - - if (flag_unsafe_loop_optimizations) - niter->assumptions = boolean_true_node; + return (!integer_zerop (niter->assumptions)); +} - if (warn) - { - const char *wording; - location_t loc = gimple_location (stmt); - - /* We can provide a more specific warning if one of the operator is - constant and the other advances by +1 or -1. */ - if (!integer_zerop (iv1.step) - ? (integer_zerop (iv0.step) - && (integer_onep (iv1.step) || integer_all_onesp (iv1.step))) - : (integer_onep (iv0.step) || integer_all_onesp (iv0.step))) - wording = - flag_unsafe_loop_optimizations - ? N_("assuming that the loop is not infinite") - : N_("cannot optimize possibly infinite loops"); - else - wording = - flag_unsafe_loop_optimizations - ? N_("assuming that the loop counter does not overflow") - : N_("cannot optimize loop, the loop counter may overflow"); +/* Like number_of_iterations_exit, but return TRUE only if the niter + information holds unconditionally. */ - warning_at ((LOCATION_LINE (loc) > 0) ? loc : input_location, - OPT_Wunsafe_loop_optimizations, "%s", gettext (wording)); - } +bool +number_of_iterations_exit (struct loop *loop, edge exit, + struct tree_niter_desc *niter, + bool, bool every_iteration) +{ + if (!number_of_iterations_exit_assumptions (loop, exit, niter, + every_iteration)) + return false; - return flag_unsafe_loop_optimizations; + return (integer_nonzerop (niter->assumptions)); } /* Try to determine the number of iterations of LOOP. If we succeed, |