aboutsummaryrefslogtreecommitdiff
path: root/gcc/value-range.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/value-range.cc')
-rw-r--r--gcc/value-range.cc64
1 files changed, 30 insertions, 34 deletions
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 5136674..a770b41 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2251,37 +2251,9 @@ irange::invert ()
verify_range ();
}
-// Remove trailing ranges that this bitmask indicates can't exist.
-
-void
-irange_bitmask::adjust_range (irange &r) const
-{
- if (unknown_p () || r.undefined_p ())
- return;
-
- int_range_max range;
- tree type = r.type ();
- int prec = TYPE_PRECISION (type);
- // If there are trailing zeros, create a range representing those bits.
- gcc_checking_assert (m_mask != 0);
- int z = wi::ctz (m_mask);
- if (z)
- {
- wide_int ub = (wi::one (prec) << z) - 1;
- range = int_range<5> (type, wi::zero (prec), ub);
- // Then remove the specific value these bits contain from the range.
- wide_int value = m_value & ub;
- range.intersect (int_range<2> (type, value, value, VR_ANTI_RANGE));
- // Inverting produces a list of ranges which can be valid.
- range.invert ();
- // And finally select R from only those valid values.
- r.intersect (range);
- return;
- }
-}
-
-// If the mask can be trivially converted to a range, do so and
-// return TRUE.
+// If the mask can be trivially converted to a range, do so.
+// Otherwise attempt to remove the lower bits from the range.
+// Return true if the range changed in any way.
bool
irange::set_range_from_bitmask ()
@@ -2326,7 +2298,28 @@ irange::set_range_from_bitmask ()
set_zero (type ());
return true;
}
- return false;
+
+ // If the mask doesn't have any trailing zero, return.
+ int z = wi::ctz (m_bitmask.mask ());
+ if (!z)
+ return false;
+
+ // Remove trailing ranges that this bitmask indicates can't exist.
+ int_range_max mask_range;
+ int prec = TYPE_PRECISION (type ());
+ wide_int ub = (wi::one (prec) << z) - 1;
+ mask_range = int_range<2> (type (), wi::zero (prec), ub);
+
+ // Then remove the specific value these bits contain from the range.
+ wide_int value = m_bitmask.value () & ub;
+ mask_range.intersect (int_range<2> (type (), value, value, VR_ANTI_RANGE));
+
+ // Inverting produces a list of ranges which can be valid.
+ mask_range.invert ();
+
+ // And finally select R from only those valid values.
+ intersect (mask_range);
+ return true;
}
void
@@ -2334,6 +2327,10 @@ irange::update_bitmask (const irange_bitmask &bm)
{
gcc_checking_assert (!undefined_p ());
+ // If masks are the same, there is no change.
+ if (m_bitmask == bm)
+ return;
+
// Drop VARYINGs with known bits to a plain range.
if (m_kind == VR_VARYING && !bm.unknown_p ())
m_kind = VR_RANGE;
@@ -2408,7 +2405,7 @@ irange::intersect_bitmask (const irange &r)
{
gcc_checking_assert (!undefined_p () && !r.undefined_p ());
- if (m_bitmask == r.m_bitmask)
+ if (r.m_bitmask.unknown_p () || m_bitmask == r.m_bitmask)
return false;
irange_bitmask bm = get_bitmask ();
@@ -2427,7 +2424,6 @@ irange::intersect_bitmask (const irange &r)
if (!set_range_from_bitmask ())
normalize_kind ();
- m_bitmask.adjust_range (*this);
if (flag_checking)
verify_range ();
return true;