From: Andrew MacLeod Date: Tue, 31 Oct 2023 15:51:34 +0000 (-0400) Subject: Remove simple ranges from trailing zero bitmasks. X-Git-Tag: basepoints/gcc-15~5030 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a291237b628f419d7f7ac264dd7b42947b565222;p=thirdparty%2Fgcc.git 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. --- diff --git a/gcc/value-range.cc b/gcc/value-range.cc index fcf53efa1dd6..a1e72c78f8ba 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 e9d81d22cd08..84f65ffb5910 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);