diff options
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 3af81f7..cba58e0 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -171,6 +171,53 @@ vrp_val_is_min (const_tree val) && operand_equal_p (val, type_min, 0))); } +/* VR_TYPE describes a range with mininum value *MIN and maximum + value *MAX. Restrict the range to the set of values that have + no bits set outside NONZERO_BITS. Update *MIN and *MAX and + return the new range type. + + SGN gives the sign of the values described by the range. */ + +enum value_range_type +intersect_range_with_nonzero_bits (enum value_range_type vr_type, + wide_int *min, wide_int *max, + 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); + + /* 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)) + { + std::swap (*min, *max); + *max = wi::round_down_for_mask (*max, nonzero_bits); + gcc_checking_assert (wi::le_p (*min, *max, sgn)); + return VR_RANGE; + } + + *min = wi::round_down_for_mask (*min, nonzero_bits); + gcc_checking_assert (wi::le_p (*min, *max, sgn)); + + /* Check whether we now have an empty set of values. */ + if (*min - 1 == *max) + return VR_UNDEFINED; + } + return vr_type; +} /* Set value range VR to VR_UNDEFINED. */ |