diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce53bb296270..79f68e9ca44d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2006-06-09 Richard Guenther + + PR tree-optimization/26998 + * tree-vrp.c (extract_range_from_unary_expr): For NEGATE_EXPR + of signed types, only TYPE_MIN_VALUE is special, but for both, + minimum and maximum value. Likewise VR_ANTI_RANGE is special + in this case, as is -fwrapv. + 2006-06-08 Mike Stump PR target/26427 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 267c08c28fa1..f187c313572c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2006-06-09 Richard Guenther + + PR tree-optimization/26998 + * gcc.dg/torture/pr26998.c: New testcase. + * gcc.dg/tree-ssa/vrp29.c: New testcase. + 2006-06-08 Mike Stump * gcc.dg/pr27095.c: Account for stubs. diff --git a/gcc/testsuite/gcc.dg/torture/pr26998.c b/gcc/testsuite/gcc.dg/torture/pr26998.c new file mode 100644 index 000000000000..d50c344734e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr26998.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ + +int decCompareOp (int result) +{ + if (result != (int)0x80000000) + { + result = -result; + return (result > 0); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c new file mode 100644 index 000000000000..bace4ffcadfe --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort(void); + +void decCompareOp (int result) +{ + if (result != (int)0x80000000) + { + result = -result; + if (result != (int)0x80000001) + abort (); + } +} + +int main() +{ + decCompareOp (0x7fffffff); + return 0; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 3ac01fb70f36..9eac7e9b67de 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1795,14 +1795,21 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr) if (code == NEGATE_EXPR && !TYPE_UNSIGNED (TREE_TYPE (expr))) { - /* NEGATE_EXPR flips the range around. */ - min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr)) && !flag_wrapv) - ? TYPE_MIN_VALUE (TREE_TYPE (expr)) - : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max); + /* NEGATE_EXPR flips the range around. We need to treat + TYPE_MIN_VALUE specially dependent on wrapping, range type + and if it was used as minimum or maximum value: + -~[MIN, MIN] == ~[MIN, MIN] + -[MIN, 0] == [0, MAX] for -fno-wrapv + -[MIN, 0] == [0, MIN] for -fwrapv (will be set to varying later) */ + min = vr0.max == TYPE_MIN_VALUE (TREE_TYPE (expr)) + ? TYPE_MIN_VALUE (TREE_TYPE (expr)) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max); - max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)) && !flag_wrapv) - ? TYPE_MAX_VALUE (TREE_TYPE (expr)) - : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min); + max = vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)) + ? (vr0.type == VR_ANTI_RANGE || flag_wrapv + ? TYPE_MIN_VALUE (TREE_TYPE (expr)) + : TYPE_MAX_VALUE (TREE_TYPE (expr))) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min); } else if (code == NEGATE_EXPR