diff options
author | Richard Guenther <rguenther@suse.de> | 2007-02-28 21:56:41 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2007-02-28 21:56:41 +0000 |
commit | a6d5f37cebac8c4c5e047d785d206c32d5be1fc9 (patch) | |
tree | 256bfe6ccb786147c33a51a1bcfea95906edd36a /gcc/fold-const.c | |
parent | cfac137674c84791371f8bf56d672891c02bcecf (diff) | |
download | gcc-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
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 29 |
1 files changed, 25 insertions, 4 deletions
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) |