re PR tree-optimization/27039 (Unable to determine # of iterations for a simple loop)
authorRichard Guenther <rguenther@suse.de>
Sun, 4 Jun 2006 12:59:40 +0000 (12:59 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sun, 4 Jun 2006 12:59:40 +0000 (12:59 +0000)
2006-06-04  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/27039
* fold-const.c (fold_comparison): Handle pointer comparison
again for all comparison codes.  Compare offsets in signed
size type.
(fold_binary): Move code from here.

* gcc.dg/tree-ssa/loop-17.c: New testcase.

From-SVN: r114357

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/loop-17.c [new file with mode: 0644]

index 977f32a79ede64258fa02a6bf31cc0b5b69da8ac..fd3d122112a03b9f69829280340b305a5f1e15ee 100644 (file)
@@ -1,3 +1,11 @@
+2006-06-04  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/27039
+       * fold-const.c (fold_comparison): Handle pointer comparison
+       again for all comparison codes.  Compare offsets in signed
+       size type.
+       (fold_binary): Move code from here.
+
 2006-06-03  Roger Sayle  <roger@eyesopen.com>
 
        PR target/26223
index 7930bb454d4ed5a611b52b354e9aba446ace3fad..3c8575e60e32252dc1d949a10e26146b82223ec7 100644 (file)
@@ -7764,6 +7764,41 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
        return fold_build2 (code, type, variable, lhs);
     }
 
+  /* If this is a comparison of two exprs that look like an ARRAY_REF of the
+     same object, then we can fold this to a comparison of the two offsets in
+     signed size type.  This is possible because pointer arithmetic is
+     restricted to retain within an object and overflow on pointer differences
+     is undefined as of 6.5.6/8 and /9 with respect to the signed ptrdiff_t.  */
+  if (POINTER_TYPE_P (TREE_TYPE (arg0))
+      && !flag_wrapv && !flag_trapv)
+    {
+      tree base0, offset0, base1, offset1;
+
+      if (extract_array_ref (arg0, &base0, &offset0)
+         && extract_array_ref (arg1, &base1, &offset1)
+         && operand_equal_p (base0, base1, 0))
+        {
+         tree signed_size_type_node;
+         signed_size_type_node = signed_type_for (size_type_node);
+
+         /* By converting to signed size type we cover middle-end pointer
+            arithmetic which operates on unsigned pointer types of size
+            type size and ARRAY_REF offsets which are properly sign or
+            zero extended from their type in case it is narrower than
+            size type.  */
+         if (offset0 == NULL_TREE)
+           offset0 = build_int_cst (signed_size_type_node, 0);
+         else
+           offset0 = fold_convert (signed_size_type_node, offset0);
+         if (offset1 == NULL_TREE)
+           offset1 = build_int_cst (signed_size_type_node, 0);
+         else
+           offset1 = fold_convert (signed_size_type_node, offset1);
+
+         return fold_build2 (code, type, offset0, offset1);
+       }
+    }
+
   if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
     {
       tree targ0 = strip_float_extensions (arg0);
@@ -10539,34 +10574,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                              tem, build_int_cst (TREE_TYPE (tem), 0));
        }
 
-      /* If this is a comparison of two exprs that look like an
-        ARRAY_REF of the same object, then we can fold this to a
-        comparison of the two offsets.  This is only safe for
-        EQ_EXPR and NE_EXPR because of overflow issues.  */
-      {
-       tree base0, offset0, base1, offset1;
-
-       if (extract_array_ref (arg0, &base0, &offset0)
-           && extract_array_ref (arg1, &base1, &offset1)
-           && operand_equal_p (base0, base1, 0))
-          {
-           /* Handle no offsets on both sides specially.  */
-           if (offset0 == NULL_TREE && offset1 == NULL_TREE)
-             return fold_build2 (code, type, integer_zero_node,
-                                 integer_zero_node);
-
-           if (!offset0 || !offset1
-               || TREE_TYPE (offset0) == TREE_TYPE (offset1))
-             {
-               if (offset0 == NULL_TREE)
-                 offset0 = build_int_cst (TREE_TYPE (offset1), 0);
-               if (offset1 == NULL_TREE)
-                 offset1 = build_int_cst (TREE_TYPE (offset0), 0);
-               return fold_build2 (code, type, offset0, offset1);
-             }
-         }
-      }
-
       if (integer_zerop (arg1)
          && tree_expr_nonzero_p (arg0))
         {
index 1553c98c6bfb28109f8af78bd056068eaeeb4d23..21fa2734273435cba91411d999a3c485a91fa45c 100644 (file)
@@ -1,3 +1,8 @@
+2006-06-04  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/27039
+       * gcc.dg/tree-ssa/loop-17.c: New testcase.
+
 2006-06-03  Roger Sayle  <roger@eyesopen.com>
 
        PR target/26223
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c
new file mode 100644 (file)
index 0000000..26e4986
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-sccp-details" } */
+
+/* To determine the number of iterations in this loop we need to fold
+   p_4 + 4B > p_4 + 8B to false.  This transformation has caused
+   troubles in the past due to overflow issues.  */
+
+int foo (int *p)
+{
+  int i = 0, *x;
+
+  for (x = p; x < p + 2; x++)
+    i++;
+
+  return i;
+}
+
+/* { dg-final { scan-tree-dump "set_nb_iterations_in_loop = 2" "sccp" } } */
+/* { dg-final { cleanup-tree-dump "sccp" } } */