summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-niter.c
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-10 00:32:47 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-10 00:32:47 +0000
commitb091dc59bfbdb8a9414f2e64f95b1284f991acf5 (patch)
tree97fb019298ce16faec345a7102ee459f0b806cce /gcc/tree-ssa-loop-niter.c
parent65b78b4ffced866cff85b63c222943c746c69c9e (diff)
downloadgcc-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.c113
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;