PR 21959
authordnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 28 Jun 2005 00:52:35 +0000 (00:52 +0000)
committerdnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 28 Jun 2005 00:52:35 +0000 (00:52 +0000)
* tree-ssa-loop-niter.c (scev_probably_wraps_p): Handle type
casts between unsigned and signed types with different size
or precision.

testsuite/ChangeLog

PR 21959
* gcc.dg/tree-ssa/pr21959.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101365 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr21959.c [new file with mode: 0644]
gcc/tree-ssa-loop-niter.c

index bdbbe42..d8fdb6d 100644 (file)
@@ -1,3 +1,10 @@
+2005-06-27  Diego Novillo  <dnovillo@redhat.com>
+
+       PR 21959
+       * tree-ssa-loop-niter.c (scev_probably_wraps_p): Handle type
+       casts between unsigned and signed types with different size
+       or precision.
+
 2005-06-28  Jan Hubicka  <jh@suse.cz>
 
        * tree-optimize.c (exercute_free_datastructures):
index 31444a4..1fab590 100644 (file)
@@ -1,3 +1,8 @@
+2005-06-27  Diego Novillo  <dnovillo@redhat.com>
+
+       PR 21959
+       * gcc.dg/tree-ssa/pr21959.c: New test.
+
 2005-06-27  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.c-torture/execute/builtins/lib/main.c (abort): Add prototype.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21959.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21959.c
new file mode 100644 (file)
index 0000000..7b83b03
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+unsigned char c[0xFF];
+void f(void)
+{
+  unsigned char i;
+  c[128] = 128;
+  i = 0;
+  while (1)
+  {
+    /* This predicate should not be folded out.  */
+    if (((signed char) i) < 0) break;
+    c[i] = ' ';
+    i++;
+  }
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate " 0 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
index 83c291d..c99aa38 100644 (file)
@@ -1649,6 +1649,41 @@ scev_probably_wraps_p (tree type, tree base, tree step,
       return true;
     }
 
+  /* If AT_STMT represents a cast operation, we may not be able to
+     take advantage of the undefinedness of signed type evolutions.
+     See PR 21959 for a test case.  Essentially, given a cast
+     operation
+               unsigned char i;
+               signed char i.0;
+               ...
+               i.0_6 = (signed char) i_2;
+               if (i.0_6 < 0)
+                 ...
+
+     where i_2 and i.0_6 have the scev {0, +, 1}, we would consider
+     i_2 to wrap around, but not i.0_6, because it is of a signed
+     type.  This causes VRP to erroneously fold the predicate above
+     because it thinks that i.0_6 cannot be negative.  */
+  if (TREE_CODE (at_stmt) == MODIFY_EXPR)
+    {
+      tree rhs = TREE_OPERAND (at_stmt, 1);
+      tree outer_t = TREE_TYPE (rhs);
+
+      if (!TYPE_UNSIGNED (outer_t)
+         && (TREE_CODE (rhs) == NOP_EXPR || TREE_CODE (rhs) == CONVERT_EXPR))
+       {
+         tree inner_t = TREE_TYPE (TREE_OPERAND (rhs, 0));
+
+         /* If the inner type is unsigned and its size and/or
+            precision are smaller to that of the outer type, then the
+            expression may wrap around.  */
+         if (TYPE_UNSIGNED (inner_t)
+             && (TYPE_SIZE (inner_t) <= TYPE_SIZE (outer_t)
+                 || TYPE_PRECISION (inner_t) <= TYPE_PRECISION (outer_t)))
+           return true;
+       }
+    }
+
   /* After having set INIT_IS_MAX, we can return false: when not using
      wrapping arithmetic, signed types don't wrap.  */
   if (!flag_wrapv && !TYPE_UNSIGNED (type))