From 933a2c39fd3778d46305894d55fca0dd584acefa Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 25 Jul 2012 20:26:12 +0200 Subject: [PATCH] re PR tree-optimization/30318 (VRP does not create ANTI_RANGEs on overflow) 2012-07-25 Marc Glisse PR tree-optimization/30318 * tree-vrp.c (extract_range_from_binary_expr_1) [PLUS_EXPR]: Handle __int128. [MINUS_EXPR]: Merge with PLUS_EXPR. From-SVN: r189861 --- gcc/ChangeLog | 7 +++ gcc/tree-vrp.c | 125 ++++++++++++++++++++++++++++--------------------- 2 files changed, 78 insertions(+), 54 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a61a37c7fffc..1e12fb689ecd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2012-07-25 Marc Glisse + + PR tree-optimization/30318 + * tree-vrp.c (extract_range_from_binary_expr_1) [PLUS_EXPR]: + Handle __int128. + [MINUS_EXPR]: Merge with PLUS_EXPR. + 2012-07-25 Sandra Loosemore Paul Brook diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 68c449e0acca..2d1628dee3d4 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2352,15 +2352,14 @@ extract_range_from_binary_expr_1 (value_range_t *vr, /* For integer ranges, apply the operation to each end of the range and see what we end up with. */ - if (code == PLUS_EXPR) + if (code == PLUS_EXPR || code == MINUS_EXPR) { /* If we have a PLUS_EXPR with two VR_RANGE integer constant ranges compute the precise range for such case if possible. */ if (range_int_cst_p (&vr0) && range_int_cst_p (&vr1) - /* We attempt to do infinite precision signed integer arithmetic, - thus we need two more bits than the possibly unsigned inputs. */ - && TYPE_PRECISION (expr_type) < HOST_BITS_PER_DOUBLE_INT - 1) + /* We need as many bits as the possibly unsigned inputs. */ + && TYPE_PRECISION (expr_type) <= HOST_BITS_PER_DOUBLE_INT) { double_int min0 = tree_to_double_int (vr0.min); double_int max0 = tree_to_double_int (vr0.max); @@ -2372,9 +2371,60 @@ extract_range_from_binary_expr_1 (value_range_t *vr, double_int type_max = double_int_max_value (TYPE_PRECISION (expr_type), uns); double_int dmin, dmax; + int min_ovf = 0; + int max_ovf = 0; - dmin = double_int_add (min0, min1); - dmax = double_int_add (max0, max1); + if (code == PLUS_EXPR) + { + dmin = double_int_add (min0, min1); + dmax = double_int_add (max0, max1); + + /* Check for overflow in double_int. */ + if (double_int_cmp (min1, double_int_zero, uns) + != double_int_cmp (dmin, min0, uns)) + min_ovf = double_int_cmp (min0, dmin, uns); + if (double_int_cmp (max1, double_int_zero, uns) + != double_int_cmp (dmax, max0, uns)) + max_ovf = double_int_cmp (max0, dmax, uns); + } + else /* if (code == MINUS_EXPR) */ + { + dmin = double_int_sub (min0, max1); + dmax = double_int_sub (max0, min1); + + if (double_int_cmp (double_int_zero, max1, uns) + != double_int_cmp (dmin, min0, uns)) + min_ovf = double_int_cmp (min0, max1, uns); + if (double_int_cmp (double_int_zero, min1, uns) + != double_int_cmp (dmax, max0, uns)) + max_ovf = double_int_cmp (max0, min1, uns); + } + + /* For non-wrapping arithmetic look at possibly smaller + value-ranges of the type. */ + if (!TYPE_OVERFLOW_WRAPS (expr_type)) + { + if (vrp_val_min (expr_type)) + type_min = tree_to_double_int (vrp_val_min (expr_type)); + if (vrp_val_max (expr_type)) + type_max = tree_to_double_int (vrp_val_max (expr_type)); + } + + /* Check for type overflow. */ + if (min_ovf == 0) + { + if (double_int_cmp (dmin, type_min, uns) == -1) + min_ovf = -1; + else if (double_int_cmp (dmin, type_max, uns) == 1) + min_ovf = 1; + } + if (max_ovf == 0) + { + if (double_int_cmp (dmax, type_min, uns) == -1) + max_ovf = -1; + else if (double_int_cmp (dmax, type_max, uns) == 1) + max_ovf = 1; + } if (TYPE_OVERFLOW_WRAPS (expr_type)) { @@ -2384,21 +2434,15 @@ extract_range_from_binary_expr_1 (value_range_t *vr, = double_int_ext (dmin, TYPE_PRECISION (expr_type), uns); double_int tmax = double_int_ext (dmax, TYPE_PRECISION (expr_type), uns); - gcc_assert (double_int_scmp (dmin, dmax) <= 0); - if ((double_int_scmp (dmin, type_min) == -1 - && double_int_scmp (dmax, type_min) == -1) - || (double_int_scmp (dmin, type_max) == 1 - && double_int_scmp (dmax, type_max) == 1) - || (double_int_scmp (type_min, dmin) <= 0 - && double_int_scmp (dmax, type_max) <= 0)) + if (min_ovf == max_ovf) { /* No overflow or both overflow or underflow. The range kind stays VR_RANGE. */ min = double_int_to_tree (expr_type, tmin); max = double_int_to_tree (expr_type, tmax); } - else if (double_int_scmp (dmin, type_min) == -1 - && double_int_scmp (dmax, type_max) == 1) + else if (min_ovf == -1 + && max_ovf == 1) { /* Underflow and overflow, drop to VR_VARYING. */ set_value_range_to_varying (vr); @@ -2409,12 +2453,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr, /* Min underflow or max overflow. The range kind changes to VR_ANTI_RANGE. */ double_int tem = tmin; - gcc_assert ((double_int_scmp (dmin, type_min) == -1 - && double_int_scmp (dmax, type_min) >= 0 - && double_int_scmp (dmax, type_max) <= 0) - || (double_int_scmp (dmax, type_max) == 1 - && double_int_scmp (dmin, type_min) >= 0 - && double_int_scmp (dmin, type_max) <= 0)); + gcc_assert ((min_ovf == -1 && max_ovf == 0) + || (max_ovf == 1 && min_ovf == 0)); type = VR_ANTI_RANGE; tmin = double_int_add (tmax, double_int_one); tmax = double_int_add (tem, double_int_minus_one); @@ -2434,16 +2474,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr, } else { - /* For non-wrapping arithmetic look at possibly smaller - value-ranges of the type. */ - if (vrp_val_min (expr_type)) - type_min = tree_to_double_int (vrp_val_min (expr_type)); - if (vrp_val_max (expr_type)) - type_max = tree_to_double_int (vrp_val_max (expr_type)); - /* If overflow does not wrap, saturate to the types min/max value. */ - if (double_int_scmp (dmin, type_min) == -1) + if (min_ovf == -1) { if (needs_overflow_infinity (expr_type) && supports_overflow_infinity (expr_type)) @@ -2451,7 +2484,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, else min = double_int_to_tree (expr_type, type_min); } - else if (double_int_scmp (dmin, type_max) == 1) + else if (min_ovf == 1) { if (needs_overflow_infinity (expr_type) && supports_overflow_infinity (expr_type)) @@ -2462,7 +2495,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, else min = double_int_to_tree (expr_type, dmin); - if (double_int_scmp (dmax, type_min) == -1) + if (max_ovf == -1) { if (needs_overflow_infinity (expr_type) && supports_overflow_infinity (expr_type)) @@ -2470,7 +2503,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, else max = double_int_to_tree (expr_type, type_min); } - else if (double_int_scmp (dmax, type_max) == 1) + else if (max_ovf == 1) { if (needs_overflow_infinity (expr_type) && supports_overflow_infinity (expr_type)) @@ -2485,10 +2518,14 @@ extract_range_from_binary_expr_1 (value_range_t *vr, && supports_overflow_infinity (expr_type)) { if (is_negative_overflow_infinity (vr0.min) - || is_negative_overflow_infinity (vr1.min)) + || (code == PLUS_EXPR + ? is_negative_overflow_infinity (vr1.min) + : is_positive_overflow_infinity (vr1.max))) min = negative_overflow_infinity (expr_type); if (is_positive_overflow_infinity (vr0.max) - || is_positive_overflow_infinity (vr1.max)) + || (code == PLUS_EXPR + ? is_positive_overflow_infinity (vr1.max) + : is_negative_overflow_infinity (vr1.min))) max = positive_overflow_infinity (expr_type); } } @@ -2717,26 +2754,6 @@ extract_range_from_binary_expr_1 (value_range_t *vr, else min = fold_unary_to_constant (NEGATE_EXPR, expr_type, max); } - else if (code == MINUS_EXPR) - { - /* If we have a MINUS_EXPR with two VR_ANTI_RANGEs, drop to - VR_VARYING. It would take more effort to compute a precise - range for such a case. For example, if we have op0 == 1 and - op1 == 1 with their ranges both being ~[0,0], we would have - op0 - op1 == 0, so we cannot claim that the difference is in - ~[0,0]. Note that we are guaranteed to have - vr0.type == vr1.type at this point. */ - if (vr0.type == VR_ANTI_RANGE) - { - set_value_range_to_varying (vr); - return; - } - - /* For MINUS_EXPR, apply the operation to the opposite ends of - each range. */ - min = vrp_int_const_binop (code, vr0.min, vr1.max); - max = vrp_int_const_binop (code, vr0.max, vr1.min); - } else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR) { bool int_cst_range0, int_cst_range1;