diff options
author | Richard Guenther <rguenther@suse.de> | 2012-07-13 11:21:39 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2012-07-13 11:21:39 +0000 |
commit | e8f808b30e83bb6bfa8ff0984fb13b136b3bd4a1 (patch) | |
tree | bb828fb1d805b42eb14a3c239b82bce7717d3d6e /gcc/tree-vrp.c | |
parent | c3e7ee4191ea60b02af9fff0ccc15d060961fde4 (diff) | |
download | gcc-e8f808b30e83bb6bfa8ff0984fb13b136b3bd4a1.zip gcc-e8f808b30e83bb6bfa8ff0984fb13b136b3bd4a1.tar.gz gcc-e8f808b30e83bb6bfa8ff0984fb13b136b3bd4a1.tar.bz2 |
re PR tree-optimization/53922 (VRP: semantic conflict between range_includes_zero_p and value_inside_range)
2012-07-13 Richard Guenther <rguenther@suse.de>
PR tree-optimization/53922
* tree-vrp.c (value_inside_range): Change prototype to take
min/max instead of value-range.
(range_includes_zero_p): Likewise. Return the result from
value_inside_range.
(extract_range_from_binary_expr_1): Adjust to handle dont-know
return value from range_includes_zero_p.
(extract_range_from_unary_expr_1): Likewise.
(compare_range_with_value): Likewise.
(vrp_meet_1): Likewise.
* gcc.dg/torture/pr53922.c: New testcase.
From-SVN: r189461
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 78 |
1 files changed, 26 insertions, 52 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 32c5afa..0ce9a74 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1339,41 +1339,25 @@ compare_values (tree val1, tree val2) } -/* Return 1 if VAL is inside value range VR (VR->MIN <= VAL <= VR->MAX), - 0 if VAL is not inside VR, +/* Return 1 if VAL is inside value range MIN <= VAL <= MAX, + 0 if VAL is not inside [MIN, MAX], -2 if we cannot tell either way. - FIXME, the current semantics of this functions are a bit quirky - when taken in the context of VRP. In here we do not care - about VR's type. If VR is the anti-range ~[3, 5] the call - value_inside_range (4, VR) will return 1. - - This is counter-intuitive in a strict sense, but the callers - currently expect this. They are calling the function - merely to determine whether VR->MIN <= VAL <= VR->MAX. The - callers are applying the VR_RANGE/VR_ANTI_RANGE semantics - themselves. - - This also applies to value_ranges_intersect_p and - range_includes_zero_p. The semantics of VR_RANGE and - VR_ANTI_RANGE should be encoded here, but that also means - adapting the users of these functions to the new semantics. - Benchmark compile/20001226-1.c compilation time after changing this function. */ static inline int -value_inside_range (tree val, value_range_t * vr) +value_inside_range (tree val, tree min, tree max) { int cmp1, cmp2; - cmp1 = operand_less_p (val, vr->min); + cmp1 = operand_less_p (val, min); if (cmp1 == -2) return -2; if (cmp1 == 1) return 0; - cmp2 = operand_less_p (vr->max, val); + cmp2 = operand_less_p (max, val); if (cmp2 == -2) return -2; @@ -1402,23 +1386,14 @@ value_ranges_intersect_p (value_range_t *vr0, value_range_t *vr1) } -/* Return true if VR includes the value zero, false otherwise. FIXME, - currently this will return false for an anti-range like ~[-4, 3]. - This will be wrong when the semantics of value_inside_range are - modified (currently the users of this function expect these - semantics). */ +/* Return 1 if [MIN, MAX] includes the value zero, 0 if it does not + include the value zero, -2 if we cannot tell. */ -static inline bool -range_includes_zero_p (value_range_t *vr) +static inline int +range_includes_zero_p (tree min, tree max) { - tree zero; - - gcc_assert (vr->type != VR_UNDEFINED - && vr->type != VR_VARYING - && !symbolic_range_p (vr)); - - zero = build_int_cst (TREE_TYPE (vr->min), 0); - return (value_inside_range (zero, vr) == 1); + tree zero = build_int_cst (TREE_TYPE (min), 0); + return value_inside_range (zero, min, max); } /* Return true if *VR is know to only contain nonnegative values. */ @@ -2641,7 +2616,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, gives [min / 4, max / 4] range. */ if (vr1.type == VR_RANGE && !symbolic_range_p (&vr1) - && !range_includes_zero_p (&vr1)) + && range_includes_zero_p (vr1.min, vr1.max) == 0) { vr0.type = type = VR_RANGE; vr0.min = vrp_val_min (expr_type); @@ -2658,8 +2633,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, not eliminate a division by zero. */ if (cfun->can_throw_non_call_exceptions && (vr1.type != VR_RANGE - || symbolic_range_p (&vr1) - || range_includes_zero_p (&vr1))) + || range_includes_zero_p (vr1.min, vr1.max) != 0)) { set_value_range_to_varying (vr); return; @@ -2670,8 +2644,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, include 0. */ if (vr0.type == VR_RANGE && (vr1.type != VR_RANGE - || symbolic_range_p (&vr1) - || range_includes_zero_p (&vr1))) + || range_includes_zero_p (vr1.min, vr1.max) != 0)) { tree zero = build_int_cst (TREE_TYPE (vr0.min), 0); int cmp; @@ -2723,8 +2696,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, else if (code == TRUNC_MOD_EXPR) { if (vr1.type != VR_RANGE - || symbolic_range_p (&vr1) - || range_includes_zero_p (&vr1) + || range_includes_zero_p (vr1.min, vr1.max) != 0 || vrp_val_is_min (vr1.min)) { set_value_range_to_varying (vr); @@ -3159,7 +3131,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr, ~[-INF, min(MIN, MAX)]. */ if (vr0.type == VR_ANTI_RANGE) { - if (range_includes_zero_p (&vr0)) + if (range_includes_zero_p (vr0.min, vr0.max) == 1) { /* Take the lower of the two values. */ if (cmp != 1) @@ -3210,7 +3182,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr, /* 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)) + else if (range_includes_zero_p (vr0.min, vr0.max) == 1) { if (cmp == 1) max = min; @@ -3812,7 +3784,7 @@ compare_range_with_value (enum tree_code comp, value_range_t *vr, tree val, return NULL_TREE; /* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2. */ - if (value_inside_range (val, vr) == 1) + if (value_inside_range (val, vr->min, vr->max) == 1) return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node; return NULL_TREE; @@ -7548,12 +7520,14 @@ vrp_meet_1 (value_range_t *vr0, value_range_t *vr1) anti-range. FIXME, all this nonsense about distinguishing anti-ranges from ranges is necessary because of the odd semantics of range_includes_zero_p and friends. */ - if (!symbolic_range_p (&saved) - && ((saved.type == VR_RANGE && !range_includes_zero_p (&saved)) - || (saved.type == VR_ANTI_RANGE && range_includes_zero_p (&saved))) - && !symbolic_range_p (vr1) - && ((vr1->type == VR_RANGE && !range_includes_zero_p (vr1)) - || (vr1->type == VR_ANTI_RANGE && range_includes_zero_p (vr1)))) + if (((saved.type == VR_RANGE + && range_includes_zero_p (saved.min, saved.max) == 0) + || (saved.type == VR_ANTI_RANGE + && range_includes_zero_p (saved.min, saved.max) == 1)) + && ((vr1->type == VR_RANGE + && range_includes_zero_p (vr1->min, vr1->max) == 0) + || (vr1->type == VR_ANTI_RANGE + && range_includes_zero_p (vr1->min, vr1->max) == 1))) { set_value_range_to_nonnull (vr0, TREE_TYPE (saved.min)); |