diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 299d20642a65..b0d7bff72885 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2005-07-27 James A. Morrison + + PR tree-optimization/22493 + * tree-vrp.c (extract_range_from_unary_expr): Deal with -fwrapv and + VR_ANTI_RANGEs properly for NEGATE_EXPRs and ABS_EXPRs. + 2005-07-27 Aldy Hernandez * config/frv/frv.opt (moptimize-membar): New. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a98dd06ee7d8..d2861aade39c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2005-07-27 James A. Morrison + + PR rtl-optimization/22493 + * gcc.c-torture/execute/pr22493-1.c: New test. + * gcc.c-torture/execute/pr22493-1.x: New. + * gcc.c-torture/execute/vrp-1.c: New test. + * gcc.c-torture/execute/vrp-2.c: New test. + * gcc.c-torture/execute/vrp-2.c: New test. + 2005-07-27 Aldy Hernandez * gcc.target/frv/all-builtin-read8.c: Delete. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr22493-1.c b/gcc/testsuite/gcc.c-torture/execute/pr22493-1.c new file mode 100644 index 000000000000..bc0ff785ae3c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr22493-1.c @@ -0,0 +1,18 @@ +#include +extern void abort (); +extern void exit (int); +void f(int i) +{ + if (i>0) + abort(); + i = -i; + if (i<0) + return; + abort (); +} + +int main(int argc, char *argv[]) +{ + f(INT_MIN); + exit (0); +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr22493-1.x b/gcc/testsuite/gcc.c-torture/execute/pr22493-1.x new file mode 100644 index 000000000000..36a58395004c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr22493-1.x @@ -0,0 +1,2 @@ +set additional_flags "-fwrapv" +return 0 diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-1.c b/gcc/testsuite/gcc.c-torture/execute/vrp-1.c new file mode 100644 index 000000000000..ac42e6c37dc4 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/vrp-1.c @@ -0,0 +1,20 @@ + +extern void abort (); +extern void exit (int); + +int f (int a) { + if (a != 2) { + a = -a; + if (a == 2) + return 0; + return 1; + } + return 1; +} + +int main (int argc, char *argv[]) { + if (f (-2)) + abort (); + exit (0); +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-2.c b/gcc/testsuite/gcc.c-torture/execute/vrp-2.c new file mode 100644 index 000000000000..69ed3e702810 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/vrp-2.c @@ -0,0 +1,19 @@ +extern void abort (); +extern void exit (int); + +int f (int a) { + if (a != 2) { + a = a > 0 ? a : -a; + if (a == 2) + return 0; + return 1; + } + return 1; +} + +int main (int argc, char *argv[]) { + if (f (-2)) + abort (); + exit (0); +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-3.c b/gcc/testsuite/gcc.c-torture/execute/vrp-3.c new file mode 100644 index 000000000000..bc0e490dc57f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/vrp-3.c @@ -0,0 +1,21 @@ +extern void abort (); +extern void exit (int); + +int f (int a) { + if (a < 12) { + if (a > -15) { + a = a > 0 ? a : -a; + if (a == 2) + return 0; + return 1; + } + } + return 1; +} + +int main (int argc, char *argv[]) { + if (f (-2)) + abort (); + exit (0); +} + diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 58fb7ef017fb..af79ba48906f 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1353,27 +1353,31 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr) if (code == NEGATE_EXPR && !TYPE_UNSIGNED (TREE_TYPE (expr))) { - /* Negating an anti-range doesn't really do anything to it. The - new range will also not take on the same range of values - excluded by the original anti-range. */ - if (vr0.type == VR_ANTI_RANGE) - { - copy_value_range (vr, &vr0); - return; - } - /* NEGATE_EXPR flips the range around. */ - min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr))) - ? TYPE_MIN_VALUE (TREE_TYPE (expr)) - : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max); + 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); - max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr))) - ? 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)) && !flag_wrapv) + ? TYPE_MAX_VALUE (TREE_TYPE (expr)) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min); } else if (code == ABS_EXPR && !TYPE_UNSIGNED (TREE_TYPE (expr))) { + /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a + useful range. */ + if (flag_wrapv + && ((vr0.type == VR_RANGE + && vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr))) + || (vr0.type == VR_ANTI_RANGE + && vr0.min != TYPE_MIN_VALUE (TREE_TYPE (expr)) + && !range_includes_zero_p (&vr0)))) + { + set_value_range_to_varying (vr); + return; + } + /* ABS_EXPR may flip the range around, if the original range included negative values. */ min = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr))) @@ -1382,12 +1386,58 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr) max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max); - /* If the range was reversed, swap MIN and MAX. */ - if (compare_values (min, max) == 1) + cmp = compare_values (min, max); + + /* If a VR_ANTI_RANGEs contains zero, then we have + ~[-INF, min(MIN, MAX)]. */ + if (vr0.type == VR_ANTI_RANGE) + { + if (range_includes_zero_p (&vr0)) + { + tree type_min_value = TYPE_MIN_VALUE (TREE_TYPE (expr)); + + /* Take the lower of the two values. */ + if (cmp != 1) + max = min; + + /* Create ~[-INF, min (abs(MIN), abs(MAX))] + or ~[-INF + 1, min (abs(MIN), abs(MAX))] when + flag_wrapv is set and the original anti-range doesn't include + TYPE_MIN_VALUE, remember -TYPE_MIN_VALUE = TYPE_MIN_VALUE. */ + min = (flag_wrapv && vr0.min != type_min_value + ? int_const_binop (PLUS_EXPR, + type_min_value, + integer_one_node, 0) + : type_min_value); + } + else + { + /* All else has failed, so create the range [0, INF], even for + flag_wrapv since TYPE_MIN_VALUE is in the original + anti-range. */ + vr0.type = VR_RANGE; + min = build_int_cst (TREE_TYPE (expr), 0); + max = TYPE_MAX_VALUE (TREE_TYPE (expr)); + } + } + + /* If the range contains zero then we know that the minimum value in the + range will be zero. */ + else if (range_includes_zero_p (&vr0)) { - tree t = min; - min = max; - max = t; + if (cmp == 1) + max = min; + min = build_int_cst (TREE_TYPE (expr), 0); + } + else + { + /* If the range was reversed, swap MIN and MAX. */ + if (cmp == 1) + { + tree t = min; + min = max; + max = t; + } } } else