OSDN Git Service

2005-08-05 James A. Morrison <phython@gcc.gnu.org>
authorphython <phython@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 6 Aug 2005 05:35:31 +0000 (05:35 +0000)
committerphython <phython@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 6 Aug 2005 05:35:31 +0000 (05:35 +0000)
        PR tree-optimization/23128
        * tree-vrp.c (vrp_int_const_binop): Check if unsigned addition or
        subtraction wrap, and set TREE_OVERFLOW if they do.

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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/vrp-5.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/vrp-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/vrp21.c [new file with mode: 0644]
gcc/tree-vrp.c

index 3a9b189..db61463 100644 (file)
@@ -1,3 +1,9 @@
+2005-08-05  James A. Morrison  <phython@gcc.gnu.org>
+
+       PR tree-optimization/23128
+       * tree-vrp.c (vrp_int_const_binop): Check if unsigned addition or
+       subtraction wrap, and set TREE_OVERFLOW if they do.
+
 2005-08-05  Richard Henderson  <rth@redhat.com>
 
        PR 21728
index d0fb7f3..8b37d46 100644 (file)
@@ -1,5 +1,11 @@
 2005-08-05  James A. Morrison  <phython@gcc.gnu.org>
 
+       * gcc.c-torture/execute/vrp-5.c: New test.
+       * gcc.c-torture/execute/vrp-6.c: New test.
+       * gcc.dg/tree-ssa/vrp21.c: New test.
+
+2005-08-05  James A. Morrison  <phython@gcc.gnu.org>
+
        * g++.dg/parse/pr22514.C: New test.
 
 2005-08-05  J"orn Rennecke <joern.rennecke@st.com>
diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-5.c b/gcc/testsuite/gcc.c-torture/execute/vrp-5.c
new file mode 100644 (file)
index 0000000..8f3c725
--- /dev/null
@@ -0,0 +1,22 @@
+extern void exit (int);
+extern void abort ();
+
+void test(unsigned int a, unsigned int b)
+{
+  if (a < 5)
+    abort();
+  if (b < 5)
+    abort();
+  if (a + b != 0U)
+    abort();
+}
+
+int main(int argc, char *argv[])
+{
+  unsigned int x = 0x80000000;
+  test(x, x);
+  exit (0);
+}
+
+
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-6.c b/gcc/testsuite/gcc.c-torture/execute/vrp-6.c
new file mode 100644 (file)
index 0000000..7c6a175
--- /dev/null
@@ -0,0 +1,33 @@
+#include <limits.h>
+
+extern void exit (int);
+extern void abort ();
+
+void test01(unsigned int a, unsigned int b)
+{
+  if (a < 5)
+    abort();
+  if (b < 5)
+    abort();
+  if (a - b != 5)
+    abort();
+}
+
+void test02(unsigned int a, unsigned int b)
+{
+  if (a >= 12)
+    if (b > 15)
+      if (a - b < UINT_MAX - 15U)
+       abort ();
+}
+
+int main(int argc, char *argv[])
+{
+  unsigned x = 0x80000000;
+  test01(x + 5, x);
+  test02(14, 16);
+  exit (0);
+}
+
+
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp21.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp21.c
new file mode 100644 (file)
index 0000000..3cd817d
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp" } */
+
+extern void link_error ();
+
+void test01(unsigned int a, unsigned int b)
+{
+  unsigned int x = 0x80000000;
+  if (a < x)
+    if (b < x)
+      if (a > 5)
+        if (a + b == 0U)
+          link_error ();
+}
+
+void test02(unsigned int a, unsigned int b)
+{
+  unsigned int x = 0x80000000;
+  if (a > x)
+    if (b < x)
+      if (a - b == 1U)
+        link_error ();
+}
+
+/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
index 68bcb1e..a77be84 100644 (file)
@@ -915,12 +915,25 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
      on -INF and +INF.  */
   res = int_const_binop (code, val1, val2, 0);
 
+  if (TYPE_UNSIGNED (TREE_TYPE (val1)))
+    {
+      int checkz = compare_values (res, val1);
+
+      /* Ensure that res = val1 + val2 >= val1
+         or that res = val1 - val2 <= val1.  */
+      if ((code == PLUS_EXPR && !(checkz == 1 || checkz == 0))
+          || (code == MINUS_EXPR && !(checkz == 0 || checkz == -1)))
+       {
+         res = copy_node (res);
+         TREE_OVERFLOW (res) = 1;
+       }
+    }
   /* If the operation overflowed but neither VAL1 nor VAL2 are
      overflown, return -INF or +INF depending on the operation
      and the combination of signs of the operands.  */
-  if (TREE_OVERFLOW (res)
-      && !TREE_OVERFLOW (val1)
-      && !TREE_OVERFLOW (val2))
+  else if (TREE_OVERFLOW (res)
+          && !TREE_OVERFLOW (val1)
+          && !TREE_OVERFLOW (val2))
     {
       int sgn1 = tree_int_cst_sgn (val1);
       int sgn2 = tree_int_cst_sgn (val2);