aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2007-02-28 21:56:41 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2007-02-28 21:56:41 +0000
commita6d5f37cebac8c4c5e047d785d206c32d5be1fc9 (patch)
tree256bfe6ccb786147c33a51a1bcfea95906edd36a
parentcfac137674c84791371f8bf56d672891c02bcecf (diff)
downloadgcc-a6d5f37cebac8c4c5e047d785d206c32d5be1fc9.zip
gcc-a6d5f37cebac8c4c5e047d785d206c32d5be1fc9.tar.gz
gcc-a6d5f37cebac8c4c5e047d785d206c32d5be1fc9.tar.bz2
re PR middle-end/30364 (Wrong variable ranges due to constant folding)
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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/fold-const.c29
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr30364-1.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr30364-2.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr30364-3.c20
6 files changed, 96 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2974266..67d2386 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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):
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index f1f4c2c..c8e2f51 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 921cf14..f6a9766 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..09506c2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr30364-1.c
@@ -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
index 0000000..20450f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr30364-2.c
@@ -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
index 0000000..4365679
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr30364-3.c
@@ -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;
+}