aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2009-04-27 01:35:27 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2009-04-26 23:35:27 +0000
commitf87c904283c91ccb365e83a9fc1f7463265cdcf6 (patch)
treefa24152c68bb24d01ebfd5359eabb80b6d0be1a2 /gcc
parent33abd7188ed10fdc1a4b66a2208490fc58df041b (diff)
downloadgcc-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/ChangeLog13
-rw-r--r--gcc/cfgloop.h1
-rw-r--r--gcc/ipa-pure-const.c25
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c3
-rw-r--r--gcc/tree-ssa-loop-niter.c45
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.