Commit ca4c3169 by Zdenek Dvorak Committed by Zdenek Dvorak

re PR tree-optimization/18687 (>200% compile time regression compared to gcc-3.4)

	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.

From-SVN: r94787
parent 1bc83fd3
2005-02-09 Zdenek Dvorak <dvorakz@suse.cz>
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.
2005-02-09 Richard Henderson <rth@redhat.com> 2005-02-09 Richard Henderson <rth@redhat.com>
* builtins.c (DEF_BUILTIN): Add COND argument. * builtins.c (DEF_BUILTIN): Add COND argument.
......
...@@ -667,6 +667,7 @@ void number_of_iterations_cond (tree, tree, tree, enum tree_code, tree, tree, ...@@ -667,6 +667,7 @@ void number_of_iterations_cond (tree, tree, tree, enum tree_code, tree, tree,
struct tree_niter_desc *); struct tree_niter_desc *);
bool number_of_iterations_exit (struct loop *, edge, bool number_of_iterations_exit (struct loop *, edge,
struct tree_niter_desc *niter); struct tree_niter_desc *niter);
tree find_loop_niter (struct loop *, edge *);
tree loop_niter_by_eval (struct loop *, edge); tree loop_niter_by_eval (struct loop *, edge);
tree find_loop_niter_by_eval (struct loop *, edge *); tree find_loop_niter_by_eval (struct loop *, edge *);
void estimate_numbers_of_iterations (struct loops *); void estimate_numbers_of_iterations (struct loops *);
......
...@@ -220,12 +220,23 @@ canonicalize_loop_induction_variables (struct loops *loops, struct loop *loop, ...@@ -220,12 +220,23 @@ canonicalize_loop_induction_variables (struct loops *loops, struct loop *loop,
niter = fold (build2 (MINUS_EXPR, TREE_TYPE (niter), niter, niter = fold (build2 (MINUS_EXPR, TREE_TYPE (niter), niter,
build_int_cst (TREE_TYPE (niter), 1))); build_int_cst (TREE_TYPE (niter), 1)));
} }
else if (try_eval) else
niter = find_loop_niter_by_eval (loop, &exit); {
/* If the loop has more than one exit, try checking all of them
if (chrec_contains_undetermined (niter) for # of iterations determinable through scev. */
|| TREE_CODE (niter) != INTEGER_CST) if (!loop->single_exit)
return false; niter = find_loop_niter (loop, &exit);
/* Finally if everything else fails, try brute force evaluation. */
if (try_eval
&& (chrec_contains_undetermined (niter)
|| TREE_CODE (niter) != INTEGER_CST))
niter = find_loop_niter_by_eval (loop, &exit);
if (chrec_contains_undetermined (niter)
|| TREE_CODE (niter) != INTEGER_CST)
return false;
}
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
......
...@@ -80,44 +80,6 @@ nonzero_p (tree arg) ...@@ -80,44 +80,6 @@ nonzero_p (tree arg)
return (TREE_INT_CST_LOW (arg) != 0 || TREE_INT_CST_HIGH (arg) != 0); 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. */ /* Returns inverse of X modulo 2^s, where MASK = 2^s-1. */
static tree static tree
...@@ -823,6 +785,75 @@ number_of_iterations_exit (struct loop *loop, edge exit, ...@@ -823,6 +785,75 @@ number_of_iterations_exit (struct loop *loop, edge exit,
return integer_onep (niter->assumptions); 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. 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) ...@@ -1055,13 +1086,11 @@ find_loop_niter_by_eval (struct loop *loop, edge *exit)
continue; continue;
aniter = loop_niter_by_eval (loop, ex); aniter = loop_niter_by_eval (loop, ex);
if (chrec_contains_undetermined (aniter) if (chrec_contains_undetermined (aniter))
|| TREE_CODE (aniter) != INTEGER_CST)
continue; continue;
if (niter if (niter
&& !nonzero_p (fold (build2 (LT_EXPR, boolean_type_node, && !tree_int_cst_lt (aniter, niter))
aniter, niter))))
continue; continue;
niter = aniter; niter = aniter;
......
...@@ -6311,4 +6311,42 @@ operand_equal_for_phi_arg_p (tree arg0, tree arg1) ...@@ -6311,4 +6311,42 @@ operand_equal_for_phi_arg_p (tree arg0, tree arg1)
return operand_equal_p (arg0, arg1, 0); return operand_equal_p (arg0, arg1, 0);
} }
/* Returns number of zeros at the end of binary representation of X.
??? Use ffs if available? */
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);
}
#include "gt-tree.h" #include "gt-tree.h"
...@@ -3275,6 +3275,7 @@ extern int integer_nonzerop (tree); ...@@ -3275,6 +3275,7 @@ extern int integer_nonzerop (tree);
extern bool zero_p (tree); extern bool zero_p (tree);
extern bool cst_and_fits_in_hwi (tree); extern bool cst_and_fits_in_hwi (tree);
extern tree num_ending_zeros (tree);
/* staticp (tree x) is nonzero if X is a reference to data allocated /* staticp (tree x) is nonzero if X is a reference to data allocated
at a fixed address in memory. Returns the outermost data. */ at a fixed address in memory. Returns the outermost data. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment