mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-25 12:41:01 +08:00
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:
parent
33abd7188e
commit
f87c904283
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user