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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146821
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
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 */
/* 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
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;
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;
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;
empty_loop_p (struct loop *loop)
{
edge exit;
- struct tree_niter_desc niter;
basic_block *body;
gimple_stmt_iterator gsi;
unsigned i;
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. */
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.