This implements NEGATE_EXPR as 0 - X, re-using code we have for MINUS_EXPR.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2011-08-12 Richard Guenther <rguent...@suse.de> * tree-vrp.c (extract_range_from_unary_expr_1): Implement -X as 0 - X. Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 177671) +++ gcc/tree-vrp.c (working copy) @@ -2946,67 +2946,14 @@ extract_range_from_unary_expr_1 (value_r /* Apply the operation to each end of the range and see what we end up with. */ - if (code == NEGATE_EXPR - && !TYPE_UNSIGNED (type)) + if (code == NEGATE_EXPR) { - /* NEGATE_EXPR flips the range around. We need to treat - TYPE_MIN_VALUE specially. */ - if (is_positive_overflow_infinity (vr0.max)) - min = negative_overflow_infinity (type); - else if (is_negative_overflow_infinity (vr0.max)) - min = positive_overflow_infinity (type); - else if (!vrp_val_is_min (vr0.max)) - min = fold_unary_to_constant (code, type, vr0.max); - else if (needs_overflow_infinity (type)) - { - if (supports_overflow_infinity (type) - && !is_overflow_infinity (vr0.min) - && !vrp_val_is_min (vr0.min)) - min = positive_overflow_infinity (type); - else - { - set_value_range_to_varying (vr); - return; - } - } - else - min = TYPE_MIN_VALUE (type); - - if (is_positive_overflow_infinity (vr0.min)) - max = negative_overflow_infinity (type); - else if (is_negative_overflow_infinity (vr0.min)) - max = positive_overflow_infinity (type); - else if (!vrp_val_is_min (vr0.min)) - max = fold_unary_to_constant (code, type, vr0.min); - else if (needs_overflow_infinity (type)) - { - if (supports_overflow_infinity (type)) - max = positive_overflow_infinity (type); - else - { - set_value_range_to_varying (vr); - return; - } - } - else - max = TYPE_MIN_VALUE (type); - } - else if (code == NEGATE_EXPR - && TYPE_UNSIGNED (type)) - { - if (!range_includes_zero_p (&vr0)) - { - max = fold_unary_to_constant (code, type, vr0.min); - min = fold_unary_to_constant (code, type, vr0.max); - } - else - { - if (range_is_null (&vr0)) - set_value_range_to_null (vr, type); - else - set_value_range_to_varying (vr); - return; - } + /* -X is simply 0 - X, so re-use existing code that also handles + anti-ranges fine. */ + value_range_t zero = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }; + set_value_range_to_value (&zero, build_int_cst (type, 0), NULL); + extract_range_from_binary_expr_1 (vr, MINUS_EXPR, type, &zero, &vr0); + return; } else if (code == ABS_EXPR && !TYPE_UNSIGNED (type))