OSDN Git Service

* ipa-pure-const.c (struct funct_state_d): New fields
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 26 Apr 2009 23:35:27 +0000 (23:35 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 26 Apr 2009 23:35:27 +0000 (23:35 +0000)
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

gcc/ChangeLog
gcc/cfgloop.h
gcc/ipa-pure-const.c
gcc/tree-ssa-loop-ivcanon.c
gcc/tree-ssa-loop-niter.c

index ed101c0..1231e59 100644 (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
 2009-04-26  Michael Matz  <matz@suse.de>
 
        * tree-flow.h (tree_ann_common_d): Remove aux and value_handle
index d95e50d..fe0120e 100644 (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 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 */
 
 #endif /* GCC_CFGLOOP_H */
index c938b0d..9575468 100644 (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.  */
   /* 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
 
   /* 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 = 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;
 
   l->looping = false;
   l->can_throw = false;
 
@@ -528,17 +530,17 @@ end:
   if (TREE_READONLY (decl))
     {
       l->pure_const_state = IPA_CONST;
   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))
       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;
     }
   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))
       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;
     }
   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;
 
          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;
 
          /* All nodes within a cycle share the same info.  */
          w_l->pure_const_state = this_state;
index 5c2f6af..2101073 100644 (file)
@@ -395,7 +395,6 @@ static bool
 empty_loop_p (struct loop *loop)
 {
   edge exit;
 empty_loop_p (struct loop *loop)
 {
   edge exit;
-  struct tree_niter_desc niter;
   basic_block *body;
   gimple_stmt_iterator gsi;
   unsigned i;
   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.  */
     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 false;
 
   /* Values of all loop exit phi nodes must be invariants.  */
index 6547382..3892a43 100644 (file)
@@ -1953,6 +1953,51 @@ find_loop_niter (struct loop *loop, edge *exit)
   return niter ? niter : chrec_dont_know;
 }
 
   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.
 /*
 
    Analysis of a number of iterations of a loop by a brute-force evaluation.