aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-02-13 15:48:38 +0000
committerJeff Law <law@gcc.gnu.org>2018-02-13 08:48:38 -0700
commitff67aff425f2ea1e8c4608783e17eb48556d53e0 (patch)
tree5f324b6586bb67d7c7022702e0076b23f29bc7e8 /gcc/tree-vrp.c
parent62e12268e613eff1b267f4c2538f2b7211067ecc (diff)
downloadgcc-ff67aff425f2ea1e8c4608783e17eb48556d53e0.zip
gcc-ff67aff425f2ea1e8c4608783e17eb48556d53e0.tar.gz
gcc-ff67aff425f2ea1e8c4608783e17eb48556d53e0.tar.bz2
re PR tree-optimization/84321 (ice in intersect_range_with_nonzero_bits, at tree-vrp.c:213)
2018-02-12 Richard Sandiford <richard.sandiford@linaro.org> 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
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c64
1 files changed, 44 insertions, 20 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index cba58e0..625e65b 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;
}