diff options
author | Jan Hubicka <jh@suse.cz> | 2009-04-27 01:35:27 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2009-04-26 23:35:27 +0000 |
commit | f87c904283c91ccb365e83a9fc1f7463265cdcf6 (patch) | |
tree | fa24152c68bb24d01ebfd5359eabb80b6d0be1a2 /gcc | |
parent | 33abd7188ed10fdc1a4b66a2208490fc58df041b (diff) | |
download | gcc-f87c904283c91ccb365e83a9fc1f7463265cdcf6.zip gcc-f87c904283c91ccb365e83a9fc1f7463265cdcf6.tar.gz gcc-f87c904283c91ccb365e83a9fc1f7463265cdcf6.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cfgloop.h | 1 | ||||
-rw-r--r-- | gcc/ipa-pure-const.c | 25 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivcanon.c | 3 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 45 |
5 files changed, 73 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ed101c0..1231e59 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index d95e50d..fe0120e 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -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 */ diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index c938b0d..9575468 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -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; diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 5c2f6af..2101073 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -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. */ diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 6547382..3892a43 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -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. |