diff options
author | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-10 00:32:47 +0000 |
---|---|---|
committer | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-10 00:32:47 +0000 |
commit | b091dc59bfbdb8a9414f2e64f95b1284f991acf5 (patch) | |
tree | 97fb019298ce16faec345a7102ee459f0b806cce /gcc/tree-ssa-loop-niter.c | |
parent | 65b78b4ffced866cff85b63c222943c746c69c9e (diff) | |
download | gcc-b091dc59bfbdb8a9414f2e64f95b1284f991acf5.tar.gz |
PR tree-optimization/18687
* tree-flow.h (find_loop_niter): Declare.
* tree-ssa-loop-ivcanon.c (canonicalize_loop_induction_variables):
Try using scev even for loops with more than one exit.
* tree-ssa-loop-ivopts.c (struct loop_data): Removed niter field.
(struct ivopts_data): Added niters field.
(struct nfe_cache_elt): New.
(nfe_hash, nfe_eq, niter_for_exit, niter_for_single_dom_exit): New
functions.
(tree_ssa_iv_optimize_init): Initialize niters cache.
(determine_number_of_iterations): Removed.
(find_induction_variables): Do not call determine_number_of_iterations.
Access niters for single exit through niter_for_single_dom_exit.
(add_iv_outer_candidates): Access niters for single exit through
niter_for_single_dom_exit.
(may_eliminate_iv): Take data argument. Use niter_for_exit. Do not use
number_of_iterations_cond.
(iv_period): New function.
(determine_use_iv_cost_condition): Pass data to may_eliminate_iv.
(may_replace_final_value): Take data argument. Use
niter_for_single_dom_exit.
(determine_use_iv_cost_outer): Pass data to may_replace_final_value.
(rewrite_use_compare): Pass data to may_eliminate_iv.
(rewrite_use_outer): Pass data to may_replace_final_value.
(free_loop_data): Clean up the niters cache.
(tree_ssa_iv_optimize_finalize): Free the niters cache.
(tree_ssa_iv_optimize_loop): Do not call loop_commit_inserts.
* tree-ssa-loop-niter.c (find_loop_niter): New function.
(find_loop_niter_by_eval): Use tree_int_cst_lt.
(num_ending_zeros): Moved to tree.c.
* tree.h (num_ending_zeros): Declare.
* tree.c (num_ending_zeros): Moved from tree.c.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94787 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 113 |
1 files changed, 71 insertions, 42 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 6a429b73cac..dbbc52d2573 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -80,44 +80,6 @@ nonzero_p (tree arg) return (TREE_INT_CST_LOW (arg) != 0 || TREE_INT_CST_HIGH (arg) != 0); } -/* Returns number of zeros at the end of binary representation of X. - - ??? Use ffs if available? */ - -static tree -num_ending_zeros (tree x) -{ - unsigned HOST_WIDE_INT fr, nfr; - unsigned num, abits; - tree type = TREE_TYPE (x); - - if (TREE_INT_CST_LOW (x) == 0) - { - num = HOST_BITS_PER_WIDE_INT; - fr = TREE_INT_CST_HIGH (x); - } - else - { - num = 0; - fr = TREE_INT_CST_LOW (x); - } - - for (abits = HOST_BITS_PER_WIDE_INT / 2; abits; abits /= 2) - { - nfr = fr >> abits; - if (nfr << abits == fr) - { - num += abits; - fr = nfr; - } - } - - if (num > TYPE_PRECISION (type)) - num = TYPE_PRECISION (type); - - return build_int_cst_type (type, num); -} - /* Returns inverse of X modulo 2^s, where MASK = 2^s-1. */ static tree @@ -823,6 +785,75 @@ number_of_iterations_exit (struct loop *loop, edge exit, return integer_onep (niter->assumptions); } +/* Try to determine the number of iterations of LOOP. If we succeed, + expression giving number of iterations is returned and *EXIT is + set to the edge from that the information is obtained. Otherwise + chrec_dont_know is returned. */ + +tree +find_loop_niter (struct loop *loop, edge *exit) +{ + unsigned n_exits, i; + edge *exits = get_loop_exit_edges (loop, &n_exits); + edge ex; + tree niter = NULL_TREE, aniter; + struct tree_niter_desc desc; + + *exit = NULL; + for (i = 0; i < n_exits; i++) + { + ex = exits[i]; + if (!just_once_each_iteration_p (loop, ex->src)) + continue; + + if (!number_of_iterations_exit (loop, ex, &desc)) + continue; + + if (nonzero_p (desc.may_be_zero)) + { + /* We exit in the first iteration through this exit. + We won't find anything better. */ + niter = build_int_cst_type (unsigned_type_node, 0); + *exit = ex; + break; + } + + if (!zero_p (desc.may_be_zero)) + continue; + + aniter = desc.niter; + + if (!niter) + { + /* Nothing recorded yet. */ + niter = aniter; + *exit = ex; + continue; + } + + /* Prefer constants, the lower the better. */ + if (TREE_CODE (aniter) != INTEGER_CST) + continue; + + if (TREE_CODE (niter) != INTEGER_CST) + { + niter = aniter; + *exit = ex; + continue; + } + + if (tree_int_cst_lt (aniter, niter)) + { + niter = aniter; + *exit = ex; + continue; + } + } + free (exits); + + return niter ? niter : chrec_dont_know; +} + /* Analysis of a number of iterations of a loop by a brute-force evaluation. @@ -1055,13 +1086,11 @@ find_loop_niter_by_eval (struct loop *loop, edge *exit) continue; aniter = loop_niter_by_eval (loop, ex); - if (chrec_contains_undetermined (aniter) - || TREE_CODE (aniter) != INTEGER_CST) + if (chrec_contains_undetermined (aniter)) continue; if (niter - && !nonzero_p (fold (build2 (LT_EXPR, boolean_type_node, - aniter, niter)))) + && !tree_int_cst_lt (aniter, niter)) continue; niter = aniter; |