From 567ec609c204d629c4327f4f469de61bb6ca9548 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Mon, 5 Mar 2007 13:15:25 +0000 Subject: [PATCH] backport: re PR middle-end/30364 (Wrong variable ranges due to constant folding) 2007-03-05 Richard Guenther Backport from mainline: 2007-02-28 Richard Guenther 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: r122548 --- gcc/ChangeLog | 9 +++++++ gcc/fold-const.c | 30 ++++++++++++++++++++---- gcc/testsuite/ChangeLog | 10 ++++++++ gcc/testsuite/gcc.dg/torture/pr30364-1.c | 19 +++++++++++++++ gcc/testsuite/gcc.dg/torture/pr30364-2.c | 19 +++++++++++++++ gcc/testsuite/gcc.dg/torture/pr30364-3.c | 20 ++++++++++++++++ 6 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr30364-1.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr30364-2.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr30364-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d0ed63192b6..f2e68eacdb90 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2007-03-05 Richard Guenther + + Backport from mainline: + 2007-02-28 Richard Guenther + + 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-03-04 Eric Botcazou PR ada/26797 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 6a328a42c4aa..30e463ac32a9 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8635,6 +8635,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, @@ -8645,12 +8646,33 @@ 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_UNSIGNED (type) || flag_wrapv))) + && 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 027c10356776..0579c00bd345 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2007-03-05 Richard Guenther + + Backport from mainline: + 2007-02-28 Richard Guenther + + 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-03-05 Tobias Burnus PR fortran/30968 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 000000000000..09506c21c1ce --- /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 000000000000..20450f55557a --- /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 000000000000..4365679a8e0a --- /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; +}