diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2023-10-31 11:51:34 -0400 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2023-11-03 12:54:50 -0400 |
commit | a291237b628f419d7f7ac264dd7b42947b565222 (patch) | |
tree | aa34be42614ff3921c052cbaf49045653e6ea82f | |
parent | 751fc7bcdcdf25e7cc0d9821f69313b6571a62e3 (diff) | |
download | gcc-a291237b628f419d7f7ac264dd7b42947b565222.zip gcc-a291237b628f419d7f7ac264dd7b42947b565222.tar.gz gcc-a291237b628f419d7f7ac264dd7b42947b565222.tar.bz2 |
Remove simple ranges from trailing zero bitmasks.
During the intersection operation, it can be helpful to remove any
low-end ranges when the bitmask has trailing zeros. This prevents
obviously incorrect ranges from appearing without requiring a bitmask
check.
* value-range.cc (irange_bitmask::adjust_range): New.
(irange::intersect_bitmask): Call adjust_range.
* value-range.h (irange_bitmask::adjust_range): New prototype.
-rw-r--r-- | gcc/value-range.cc | 30 | ||||
-rw-r--r-- | gcc/value-range.h | 2 |
2 files changed, 32 insertions, 0 deletions
diff --git a/gcc/value-range.cc b/gcc/value-range.cc index fcf53ef..a1e72c7 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -1857,6 +1857,35 @@ irange::get_bitmask_from_range () const return irange_bitmask (wi::zero (prec), min | xorv); } +// 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 the mask can be trivially converted to a range, do so and // return TRUE. @@ -2002,6 +2031,7 @@ 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; diff --git a/gcc/value-range.h b/gcc/value-range.h index e9d81d2..84f65ff 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -139,6 +139,8 @@ public: void verify_mask () const; void dump (FILE *) const; + void adjust_range (irange &r) const; + // Convenience functions for nonzero bitmask compatibility. wide_int get_nonzero_bits () const; void set_nonzero_bits (const wide_int &bits); |