]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/30364 (Wrong variable ranges due to constant folding)
authorRichard Guenther <rguenther@suse.de>
Wed, 28 Feb 2007 21:56:41 +0000 (21:56 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 28 Feb 2007 21:56:41 +0000 (21:56 +0000)
2007-02-28  Richard Guenther  <rguenther@suse.de>

PR middle-end/30364
* fold-const.c (fold_binary): Do not associate expressions
with more than one variable for integer types that do not wrap.

* gcc.dg/torture/pr30364-1.c: New testcase.
* gcc.dg/torture/pr30364-2.c: Likewise.
* gcc.dg/torture/pr30364-3.c: Likewise.

From-SVN: r122414

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr30364-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr30364-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr30364-3.c [new file with mode: 0644]

index 2974266dc25bdfef5a2437287aadf78f1c86e16d..67d23869fd14a38a728db02dbb3f8c066674b13f 100644 (file)
@@ -1,3 +1,9 @@
+2007-02-28  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/30364
+       * fold-const.c (fold_binary): Do not associate expressions
+       with more than one variable for integer types that do not wrap.
+
 2007-02-28  Sandra Loosemore  <sandra@codesourcery.com>
 
        * builtins.c (fold_builtin_call_list, fold_builtin_call_valist):
index f1f4c2cb296a1a58167d81acd18e41a9274a64fe..c8e2f514c7181e754a079be899ed29e24f5c30b9 100644 (file)
@@ -9424,6 +9424,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        {
          tree var0, con0, lit0, minus_lit0;
          tree var1, con1, lit1, minus_lit1;
+         bool ok = true;
 
          /* Split both trees into variables, constants, and literals.  Then
             associate each group together, the constants with literals,
@@ -9434,12 +9435,32 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
                             code == MINUS_EXPR);
 
+         /* With undefined overflow we can only associate constants
+            with one variable.  */
+         if ((POINTER_TYPE_P (type)
+              || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
+             && var0 && var1)
+           {
+             tree tmp0 = var0;
+             tree tmp1 = var1;
+
+             if (TREE_CODE (tmp0) == NEGATE_EXPR)
+               tmp0 = TREE_OPERAND (tmp0, 0);
+             if (TREE_CODE (tmp1) == NEGATE_EXPR)
+               tmp1 = TREE_OPERAND (tmp1, 0);
+             /* The only case we can still associate with two variables
+                is if they are the same, modulo negation.  */
+             if (!operand_equal_p (tmp0, tmp1, 0))
+               ok = false;
+           }
+
          /* Only do something if we found more than two objects.  Otherwise,
             nothing has changed and we risk infinite recursion.  */
-         if (2 < ((var0 != 0) + (var1 != 0)
-                  + (con0 != 0) + (con1 != 0)
-                  + (lit0 != 0) + (lit1 != 0)
-                  + (minus_lit0 != 0) + (minus_lit1 != 0)))
+         if (ok
+             && (2 < ((var0 != 0) + (var1 != 0)
+                      + (con0 != 0) + (con1 != 0)
+                      + (lit0 != 0) + (lit1 != 0)
+                      + (minus_lit0 != 0) + (minus_lit1 != 0))))
            {
              /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
              if (code == MINUS_EXPR)
index 921cf1493e717cae66de02dfcbf2983321316f41..f6a9766d11ea9cb0c97ebb3e6a187e2f0b558e33 100644 (file)
@@ -1,3 +1,10 @@
+2007-02-28  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/30364
+       * gcc.dg/torture/pr30364-1.c: New testcase.
+       * gcc.dg/torture/pr30364-2.c: Likewise.
+       * gcc.dg/torture/pr30364-3.c: Likewise.
+
 2007-02-28  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gcc.dg/torture/builtin-frexp-1.c: On mips*-*-irix6* and
diff --git a/gcc/testsuite/gcc.dg/torture/pr30364-1.c b/gcc/testsuite/gcc.dg/torture/pr30364-1.c
new file mode 100644 (file)
index 0000000..09506c2
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int f(int a, int b)
+{
+  if (a > 0x7FFFFFF0) return 0;
+  if (b > 0x7FFFFFF0) return 0;
+
+  int c = (a - 20) + (b - 20);
+  return c > 0x7FFFFFF0;
+}
+
+int main()
+{
+  if (f (0x7FFFFFF0, 41) != 1)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr30364-2.c b/gcc/testsuite/gcc.dg/torture/pr30364-2.c
new file mode 100644 (file)
index 0000000..20450f5
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int f(unsigned int a, unsigned int b)
+{
+  if (a > 0x7FFFFFF0) return 0;
+  if (b > 0x7FFFFFF0) return 0;
+
+  int c = (a - 20) + (b - 20);
+  return c > 0x7FFFFFF0;
+}
+
+int main()
+{
+  if (f (0x7FFFFFF0, 41) != 1)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr30364-3.c b/gcc/testsuite/gcc.dg/torture/pr30364-3.c
new file mode 100644 (file)
index 0000000..4365679
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-fwrapv" } */
+
+extern void abort (void);
+
+int f(int a, int b)
+{
+  if (a > 0x7FFFFFF0) return 0;
+  if (b > 0x7FFFFFF0) return 0;
+
+  int c = (a - 20) + (b - 20);
+  return c > 0x7FFFFFF0;
+}
+
+int main()
+{
+  if (f (0x7FFFFFF0, 41) != 1)
+    abort ();
+  return 0;
+}