From: Richard Sandiford Date: Tue, 13 Feb 2018 15:48:38 +0000 (+0000) Subject: re PR tree-optimization/84321 (ice in intersect_range_with_nonzero_bits, at tree... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ff67aff425f2ea1e8c4608783e17eb48556d53e0;p=gcc.git re PR tree-optimization/84321 (ice in intersect_range_with_nonzero_bits, at tree-vrp.c:213) 2018-02-12 Richard Sandiford gcc/ PR tree-optimization/84321 * tree-vrp.c (intersect_range_with_nonzero_bits): Fix VR_ANTI_RANGE handling. Also check whether the anti-range contains any values that satisfy the mask; switch to a VR_RANGE if not. gcc/testsuite/ PR tree-optimization/84321 * gcc.dg/pr84321.c: New test. From-SVN: r257629 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6c1e5e38d63..c582ae17c1c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-02-13 Richard Sandiford + + PR tree-optimization/84321 + * tree-vrp.c (intersect_range_with_nonzero_bits): Fix VR_ANTI_RANGE + handling. Also check whether the anti-range contains any values + that satisfy the mask; switch to a VR_RANGE if not. + 2018-02-13 Paolo Bonzini PR sanitizer/84340 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0a1a4f924a2..b11f10a6179 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-02-12 Richard Sandiford + + PR tree-optimization/84321 + * gcc.dg/pr84321.c: New test. + 2018-02-13 Vladimir Makarov PR target/84359 diff --git a/gcc/testsuite/gcc.dg/pr84321.c b/gcc/testsuite/gcc.dg/pr84321.c new file mode 100644 index 00000000000..8f8186b58f2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr84321.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fwrapv" } */ + +int c; + +void +foo (int *a, int b) +{ + int e; + if (b == 1) + return; + for (e = 0; e < (b & ~7); e += 8) + ; + for (++e; e < b;) + c = a[e]; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index cba58e02791..625e65b1184 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -184,37 +184,61 @@ intersect_range_with_nonzero_bits (enum value_range_type vr_type, const wide_int &nonzero_bits, signop sgn) { - if (vr_type == VR_RANGE) - { - *max = wi::round_down_for_mask (*max, nonzero_bits); - - /* Check that the range contains at least one valid value. */ - if (wi::gt_p (*min, *max, sgn)) - return VR_UNDEFINED; - - *min = wi::round_up_for_mask (*min, nonzero_bits); - gcc_checking_assert (wi::le_p (*min, *max, sgn)); - } if (vr_type == VR_ANTI_RANGE) { - *max = wi::round_up_for_mask (*max, nonzero_bits); + /* The VR_ANTI_RANGE is equivalent to the union of the ranges + A: [-INF, *MIN) and B: (*MAX, +INF]. First use NONZERO_BITS + to create an inclusive upper bound for A and an inclusive lower + bound for B. */ + wide_int a_max = wi::round_down_for_mask (*min - 1, nonzero_bits); + wide_int b_min = wi::round_up_for_mask (*max + 1, nonzero_bits); + + /* If the calculation of A_MAX wrapped, A is effectively empty + and A_MAX is the highest value that satisfies NONZERO_BITS. + Likewise if the calculation of B_MIN wrapped, B is effectively + empty and B_MIN is the lowest value that satisfies NONZERO_BITS. */ + bool a_empty = wi::ge_p (a_max, *min, sgn); + bool b_empty = wi::le_p (b_min, *max, sgn); + + /* If both A and B are empty, there are no valid values. */ + if (a_empty && b_empty) + return VR_UNDEFINED; - /* If the calculation wrapped, we now have a VR_RANGE whose - lower bound is *MAX and whose upper bound is *MIN. */ - if (wi::gt_p (*min, *max, sgn)) + /* If exactly one of A or B is empty, return a VR_RANGE for the + other one. */ + if (a_empty || b_empty) { - std::swap (*min, *max); - *max = wi::round_down_for_mask (*max, nonzero_bits); + *min = b_min; + *max = a_max; gcc_checking_assert (wi::le_p (*min, *max, sgn)); return VR_RANGE; } - *min = wi::round_down_for_mask (*min, nonzero_bits); + /* Update the VR_ANTI_RANGE bounds. */ + *min = a_max + 1; + *max = b_min - 1; gcc_checking_assert (wi::le_p (*min, *max, sgn)); - /* Check whether we now have an empty set of values. */ - if (*min - 1 == *max) + /* Now check whether the excluded range includes any values that + satisfy NONZERO_BITS. If not, switch to a full VR_RANGE. */ + if (wi::round_up_for_mask (*min, nonzero_bits) == b_min) + { + unsigned int precision = min->get_precision (); + *min = wi::min_value (precision, sgn); + *max = wi::max_value (precision, sgn); + vr_type = VR_RANGE; + } + } + if (vr_type == VR_RANGE) + { + *max = wi::round_down_for_mask (*max, nonzero_bits); + + /* Check that the range contains at least one valid value. */ + if (wi::gt_p (*min, *max, sgn)) return VR_UNDEFINED; + + *min = wi::round_up_for_mask (*min, nonzero_bits); + gcc_checking_assert (wi::le_p (*min, *max, sgn)); } return vr_type; }