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
This commit is contained in:
Jan Hubicka 2009-04-27 01:35:27 +02:00 committed by Jan Hubicka
parent 33abd7188e
commit f87c904283
5 changed files with 73 additions and 14 deletions

View File

@ -1,3 +1,16 @@
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>
* tree-flow.h (tree_ann_common_d): Remove aux and value_handle

View File

@ -640,5 +640,6 @@ enum
extern void unroll_and_peel_loops (int);
extern void doloop_optimize_loops (void);
extern void move_loop_invariants (void);
extern bool finite_loop_p (struct loop *);
#endif /* GCC_CFGLOOP_H */

View File

@ -72,7 +72,8 @@ struct funct_state_d
/* See above. */
enum pure_const_state_e pure_const_state;
/* 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
lot of ways that this could be determined. We are pretty
@ -485,7 +486,8 @@ analyze_function (struct cgraph_node *fn, bool ipa)
l = XCNEW (struct funct_state_d);
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->can_throw = false;
@ -528,17 +530,17 @@ end:
if (TREE_READONLY (decl))
{
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))
l->looping = false;
l->looping = false, l->looping_previously_known = false;
}
if (DECL_PURE_P (decl))
{
if (l->pure_const_state != IPA_CONST)
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))
l->looping = false;
l->looping = false, l->looping_previously_known = false;
}
if (TREE_NOTHROW (decl))
l->can_throw = false;
@ -728,12 +730,11 @@ propagate (void)
enum pure_const_state_e this_state = pure_const_state;
bool this_looping = looping;
if (w_l->state_set_in_source != IPA_NEITHER)
{
if (this_state > w_l->state_set_in_source)
this_state = w_l->state_set_in_source;
this_looping = false;
}
if (w_l->state_previously_known != IPA_NEITHER
&& this_state > w_l->state_previously_known)
this_state = w_l->state_previously_known;
if (!w_l->looping_previously_known)
this_looping = false;
/* All nodes within a cycle share the same info. */
w_l->pure_const_state = this_state;

View File

@ -395,7 +395,6 @@ static bool
empty_loop_p (struct loop *loop)
{
edge exit;
struct tree_niter_desc niter;
basic_block *body;
gimple_stmt_iterator gsi;
unsigned i;
@ -408,7 +407,7 @@ empty_loop_p (struct loop *loop)
return false;
/* The loop must be finite. */
if (!number_of_iterations_exit (loop, exit, &niter, false))
if (!finite_loop_p (loop))
return false;
/* Values of all loop exit phi nodes must be invariants. */

View File

@ -1953,6 +1953,51 @@ find_loop_niter (struct loop *loop, edge *exit)
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.