From b20f1dce46fb8bb1b142e9087530e546a40edec8 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 31 Oct 2023 11:51:34 -0400
Subject: [PATCH 1/2] 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.
---
gcc/value-range.cc | 30 ++++++++++++++++++++++++++++++
gcc/value-range.h | 2 ++
2 files changed, 32 insertions(+)
@@ -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;
@@ -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);
--
2.41.0