Commit f87c9042 by Jan Hubicka Committed by Jan Hubicka

ipa-pure-const.c (struct funct_state_d): New fields state_previously_known,…

ipa-pure-const.c (struct funct_state_d): New fields state_previously_known, looping_previously_known...

	* ipa-pure-const.c (struct funct_state_d): New fields
	state_previously_known, looping_previously_known; remove
	state_set_in_source.
	(analyze_function): Use new fields.
	(propagate): Avoid assumption that state_set_in_source imply
	nonlooping.

	* tree-ssa-loop-niter.c (finite_loop_p): New function.
	* tree-ssa-loop-ivcanon.c (empty_loop_p): Use it.
	* cfgloop.h (finite_loop_p): Declare.

From-SVN: r146821
parent 33abd718
2009-04-27 Jan Hubicka <jh@suse.cz>
* ipa-pure-const.c (struct funct_state_d): New fields
state_previously_known, looping_previously_known; remove
state_set_in_source.
(analyze_function): Use new fields.
(propagate): Avoid assumption that state_set_in_source imply
nonlooping.
* tree-ssa-loop-niter.c (finite_loop_p): New function.
* tree-ssa-loop-ivcanon.c (empty_loop_p): Use it.
* cfgloop.h (finite_loop_p): Declare.
2009-04-26 Michael Matz <matz@suse.de> 2009-04-26 Michael Matz <matz@suse.de>
* tree-flow.h (tree_ann_common_d): Remove aux and value_handle * tree-flow.h (tree_ann_common_d): Remove aux and value_handle
......
...@@ -640,5 +640,6 @@ enum ...@@ -640,5 +640,6 @@ enum
extern void unroll_and_peel_loops (int); extern void unroll_and_peel_loops (int);
extern void doloop_optimize_loops (void); extern void doloop_optimize_loops (void);
extern void move_loop_invariants (void); extern void move_loop_invariants (void);
extern bool finite_loop_p (struct loop *);
#endif /* GCC_CFGLOOP_H */ #endif /* GCC_CFGLOOP_H */
...@@ -72,7 +72,8 @@ struct funct_state_d ...@@ -72,7 +72,8 @@ struct funct_state_d
/* See above. */ /* See above. */
enum pure_const_state_e pure_const_state; enum pure_const_state_e pure_const_state;
/* What user set here; we can be always sure about this. */ /* What user set here; we can be always sure about this. */
enum pure_const_state_e state_set_in_source; enum pure_const_state_e state_previously_known;
bool looping_previously_known;
/* True if the function could possibly infinite loop. There are a /* True if the function could possibly infinite loop. There are a
lot of ways that this could be determined. We are pretty lot of ways that this could be determined. We are pretty
...@@ -485,7 +486,8 @@ analyze_function (struct cgraph_node *fn, bool ipa) ...@@ -485,7 +486,8 @@ analyze_function (struct cgraph_node *fn, bool ipa)
l = XCNEW (struct funct_state_d); l = XCNEW (struct funct_state_d);
l->pure_const_state = IPA_CONST; l->pure_const_state = IPA_CONST;
l->state_set_in_source = IPA_NEITHER; l->state_previously_known = IPA_NEITHER;
l->looping_previously_known = true;
l->looping = false; l->looping = false;
l->can_throw = false; l->can_throw = false;
...@@ -528,17 +530,17 @@ end: ...@@ -528,17 +530,17 @@ end:
if (TREE_READONLY (decl)) if (TREE_READONLY (decl))
{ {
l->pure_const_state = IPA_CONST; l->pure_const_state = IPA_CONST;
l->state_set_in_source = IPA_CONST; l->state_previously_known = IPA_CONST;
if (!DECL_LOOPING_CONST_OR_PURE_P (decl)) if (!DECL_LOOPING_CONST_OR_PURE_P (decl))
l->looping = false; l->looping = false, l->looping_previously_known = false;
} }
if (DECL_PURE_P (decl)) if (DECL_PURE_P (decl))
{ {
if (l->pure_const_state != IPA_CONST) if (l->pure_const_state != IPA_CONST)
l->pure_const_state = IPA_PURE; l->pure_const_state = IPA_PURE;
l->state_set_in_source = IPA_PURE; l->state_previously_known = IPA_PURE;
if (!DECL_LOOPING_CONST_OR_PURE_P (decl)) if (!DECL_LOOPING_CONST_OR_PURE_P (decl))
l->looping = false; l->looping = false, l->looping_previously_known = false;
} }
if (TREE_NOTHROW (decl)) if (TREE_NOTHROW (decl))
l->can_throw = false; l->can_throw = false;
...@@ -728,12 +730,11 @@ propagate (void) ...@@ -728,12 +730,11 @@ propagate (void)
enum pure_const_state_e this_state = pure_const_state; enum pure_const_state_e this_state = pure_const_state;
bool this_looping = looping; bool this_looping = looping;
if (w_l->state_set_in_source != IPA_NEITHER) if (w_l->state_previously_known != IPA_NEITHER
{ && this_state > w_l->state_previously_known)
if (this_state > w_l->state_set_in_source) this_state = w_l->state_previously_known;
this_state = w_l->state_set_in_source; if (!w_l->looping_previously_known)
this_looping = false; this_looping = false;
}
/* All nodes within a cycle share the same info. */ /* All nodes within a cycle share the same info. */
w_l->pure_const_state = this_state; w_l->pure_const_state = this_state;
......
...@@ -395,7 +395,6 @@ static bool ...@@ -395,7 +395,6 @@ static bool
empty_loop_p (struct loop *loop) empty_loop_p (struct loop *loop)
{ {
edge exit; edge exit;
struct tree_niter_desc niter;
basic_block *body; basic_block *body;
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
unsigned i; unsigned i;
...@@ -408,7 +407,7 @@ empty_loop_p (struct loop *loop) ...@@ -408,7 +407,7 @@ empty_loop_p (struct loop *loop)
return false; return false;
/* The loop must be finite. */ /* The loop must be finite. */
if (!number_of_iterations_exit (loop, exit, &niter, false)) if (!finite_loop_p (loop))
return false; return false;
/* Values of all loop exit phi nodes must be invariants. */ /* Values of all loop exit phi nodes must be invariants. */
......
...@@ -1953,6 +1953,51 @@ find_loop_niter (struct loop *loop, edge *exit) ...@@ -1953,6 +1953,51 @@ find_loop_niter (struct loop *loop, edge *exit)
return niter ? niter : chrec_dont_know; return niter ? niter : chrec_dont_know;
} }
/* Return true if loop is known to have bounded number of iterations. */
bool
finite_loop_p (struct loop *loop)
{
unsigned i;
VEC (edge, heap) *exits = get_loop_exit_edges (loop);
edge ex;
struct tree_niter_desc desc;
bool finite = false;
if (flag_unsafe_loop_optimizations)
return true;
if ((TREE_READONLY (current_function_decl)
|| DECL_PURE_P (current_function_decl))
&& !DECL_LOOPING_CONST_OR_PURE_P (current_function_decl))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Found loop %i to be finite: it is within pure or const function.\n",
loop->num);
return true;
}
exits = get_loop_exit_edges (loop);
for (i = 0; VEC_iterate (edge, exits, i, ex); i++)
{
if (!just_once_each_iteration_p (loop, ex->src))
continue;
if (number_of_iterations_exit (loop, ex, &desc, false))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Found loop %i to be finite: iterating ", loop->num);
print_generic_expr (dump_file, desc.niter, TDF_SLIM);
fprintf (dump_file, " times\n");
}
finite = true;
break;
}
}
VEC_free (edge, heap, exits);
return finite;
}
/* /*
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.
......
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