aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@redhat.com>2023-10-31 11:51:34 -0400
committerAndrew MacLeod <amacleod@redhat.com>2023-11-03 12:54:50 -0400
commita291237b628f419d7f7ac264dd7b42947b565222 (patch)
treeaa34be42614ff3921c052cbaf49045653e6ea82f /gcc
parent751fc7bcdcdf25e7cc0d9821f69313b6571a62e3 (diff)
downloadgcc-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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/value-range.cc30
-rw-r--r--gcc/value-range.h2
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);