]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Remove simple ranges from trailing zero bitmasks.
authorAndrew MacLeod <amacleod@redhat.com>
Tue, 31 Oct 2023 15:51:34 +0000 (11:51 -0400)
committerAndrew MacLeod <amacleod@redhat.com>
Fri, 3 Nov 2023 16:54:50 +0000 (12:54 -0400)
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
gcc/value-range.h

index fcf53efa1dd6a54f89f50bce98f750ff16327110..a1e72c78f8bad66ce2db7464648711ecf49b05fc 100644 (file)
@@ -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;
index e9d81d22cd08f1cee09ce27bcc4db1cb760d61f2..84f65ffb59100ddafe149774c0d2ba7892d1c0b9 100644 (file)
@@ -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);