]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/25985 (with optimization integer math fails)
authorZdenek Dvorak <dvorakz@suse.cz>
Wed, 29 Mar 2006 01:41:27 +0000 (03:41 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Wed, 29 Mar 2006 01:41:27 +0000 (01:41 +0000)
PR tree-optimization/25985
* tree-ssa-loop-niter.c (number_of_iterations_le,
number_of_iterations_ne): Make comments more precise.
(number_of_iterations_cond): Add only_exit argument.  Use the
fact that signed variables do not overflow only when only_exit
is true.
(loop_only_exit_p): New.
(number_of_iterations_exit): Pass result of loop_only_exit_p to
number_of_iterations_cond.

From-SVN: r112484

gcc/ChangeLog
gcc/tree-ssa-loop-niter.c

index c6646319fde0c1ca50ccffbc4e82e3264a0a03bd..c9be20c4a451326a5b24b5b040c93a80f9bbc32d 100644 (file)
@@ -1,3 +1,15 @@
+2006-03-28  Zdenek Dvorak <dvorakz@suse.cz>
+
+       PR tree-optimization/25985
+       * tree-ssa-loop-niter.c (number_of_iterations_le,
+       number_of_iterations_ne): Make comments more precise.
+       (number_of_iterations_cond): Add only_exit argument.  Use the
+       fact that signed variables do not overflow only when only_exit
+       is true.
+       (loop_only_exit_p): New.
+       (number_of_iterations_exit): Pass result of loop_only_exit_p to
+       number_of_iterations_cond.
+
 2006-03-28  Zdenek Dvorak <dvorakz@suse.cz>
 
        PR tree-optimization/26643
index cda02dd778328300d9f76340e5671a839fffda82..f7319b2a425e2a6fac3b59cdeacd7b5ec0e6e4c0 100644 (file)
@@ -129,9 +129,9 @@ inverse (tree x, tree mask)
 /* Determines number of iterations of loop whose ending condition
    is IV <> FINAL.  TYPE is the type of the iv.  The number of
    iterations is stored to NITER.  NEVER_INFINITE is true if
-   we know that the loop cannot be infinite (we derived this
-   earlier, and possibly set NITER->assumptions to make sure this
-   is the case.  */
+   we know that the exit must be taken eventually, i.e., that the IV
+   ever reaches the value FINAL (we derived this earlier, and possibly set
+   NITER->assumptions to make sure this is the case).  */
 
 static bool
 number_of_iterations_ne (tree type, affine_iv *iv, tree final,
@@ -492,9 +492,9 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
 /* Determines number of iterations of loop whose ending condition
    is IV0 <= IV1.  TYPE is the type of the iv.  The number of
    iterations is stored to NITER.  NEVER_INFINITE is true if
-   we know that the loop cannot be infinite (we derived this
+   we know that this condition must eventually become false (we derived this
    earlier, and possibly set NITER->assumptions to make sure this
-   is the case.  */
+   is the case).  */
 
 static bool
 number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
@@ -538,6 +538,11 @@ number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
    is IV0, the right-hand side is IV1.  Both induction variables must have
    type TYPE, which must be an integer or pointer type.  The steps of the
    ivs must be constants (or NULL_TREE, which is interpreted as constant zero).
+
+   ONLY_EXIT is true if we are sure this is the only way the loop could be
+   exited (including possibly non-returning function calls, exceptions, etc.)
+   -- in this case we can use the information whether the control induction
+   variables can overflow or not in a more efficient way.
    
    The results (number of iterations and assumptions as described in
    comments at struct tree_niter_desc in tree-flow.h) are stored to NITER.
@@ -546,7 +551,8 @@ number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
 
 static bool
 number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code,
-                          affine_iv *iv1, struct tree_niter_desc *niter)
+                          affine_iv *iv1, struct tree_niter_desc *niter,
+                          bool only_exit)
 {
   bool never_infinite;
 
@@ -572,13 +578,30 @@ number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code,
       code = swap_tree_comparison (code);
     }
 
+  if (!only_exit)
+    {
+      /* If this is not the only possible exit from the loop, the information
+        that the induction variables cannot overflow as derived from
+        signedness analysis cannot be relied upon.  We use them e.g. in the
+        following way:  given loop for (i = 0; i <= n; i++), if i is
+        signed, it cannot overflow, thus this loop is equivalent to
+        for (i = 0; i < n + 1; i++);  however, if n == MAX, but the loop
+        is exited in some other way before i overflows, this transformation
+        is incorrect (the new loop exits immediately).  */
+      iv0->no_overflow = false;
+      iv1->no_overflow = false;
+    }
+
   if (POINTER_TYPE_P (type))
     {
       /* Comparison of pointers is undefined unless both iv0 and iv1 point
         to the same object.  If they do, the control variable cannot wrap
         (as wrap around the bounds of memory will never return a pointer
         that would be guaranteed to point to the same object, even if we
-        avoid undefined behavior by casting to size_t and back).  */
+        avoid undefined behavior by casting to size_t and back).  The
+        restrictions on pointer arithmetics and comparisons of pointers
+        ensure that using the no-overflow assumptions is correct in this
+        case even if ONLY_EXIT is false.  */
       iv0->no_overflow = true;
       iv1->no_overflow = true;
     }
@@ -963,6 +986,37 @@ simplify_using_outer_evolutions (struct loop *loop, tree expr)
   return expr;
 }
 
+/* Returns true if EXIT is the only possible exit from LOOP.  */
+
+static bool
+loop_only_exit_p (struct loop *loop, edge exit)
+{
+  basic_block *body;
+  block_stmt_iterator bsi;
+  unsigned i;
+  tree call;
+
+  if (exit != loop->single_exit)
+    return false;
+
+  body = get_loop_body (loop);
+  for (i = 0; i < loop->num_nodes; i++)
+    {
+      for (bsi = bsi_start (body[0]); !bsi_end_p (bsi); bsi_next (&bsi))
+       {
+         call = get_call_expr_in (bsi_stmt (bsi));
+         if (call && TREE_SIDE_EFFECTS (call))
+           {
+             free (body);
+             return false;
+           }
+       }
+    }
+
+  free (body);
+  return true;
+}
+
 /* Stores description of number of iterations of LOOP derived from
    EXIT (an exit edge of the LOOP) in NITER.  Returns true if some
    useful information could be derived (and fields of NITER has
@@ -1023,7 +1077,8 @@ number_of_iterations_exit (struct loop *loop, edge exit,
 
   iv0.base = expand_simple_operations (iv0.base);
   iv1.base = expand_simple_operations (iv1.base);
-  if (!number_of_iterations_cond (type, &iv0, code, &iv1, niter))
+  if (!number_of_iterations_cond (type, &iv0, code, &iv1, niter,
+                                 loop_only_exit_p (loop, exit)))
     return false;
 
   if (optimize >= 3)