]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Undefined bitmasks imply undefined ranges.
authorAndrew MacLeod <amacleod@redhat.com>
Wed, 26 Nov 2025 19:21:13 +0000 (14:21 -0500)
committerAndrew MacLeod <amacleod@redhat.com>
Fri, 28 Nov 2025 14:34:22 +0000 (09:34 -0500)
bitmask have no way of representing UNDEFINED, and as such, bitmask
intersection returns an unknown_p values instead.  This patch has the
function return false in this case, which will indicate UNDEFINED.

PR tree-optimization/122686
gcc/
* range-op.cc (operator_bitwise_and::op1_range): Check for
undefined bitmask.
* value-range.cc (prange::intersect): Handle undefined bitmask
intersection.
(irange::get_bitmask): Ditto.
(irange::intersect_bitmask): Ditto.
* value-range.h (irange_bitmask::intersect): Return false if the
result is UNDEFINED.

gcc/range-op.cc
gcc/value-range.cc
gcc/value-range.h

index 82a994b4ca555a33239a6490e59ed8503025d067..fb7d4742bb6d7a772f8660e2151f1b3dc7fed321 100644 (file)
@@ -3848,9 +3848,12 @@ operator_bitwise_and::op1_range (irange &r, tree type,
   // extraneous values thats are not convered by the mask.
   wide_int op1_value = lhs_bm.value () & ~op1_mask;
   irange_bitmask op1_bm (op1_value, op1_mask);
-  // INtersect this mask with anything already known about the value.
-  op1_bm.intersect (r.get_bitmask ());
-  r.update_bitmask (op1_bm);
+  // Intersect this mask with anything already known about the value.
+  // A return valueof false indicated the bitmask is an UNDEFINED range.
+  if (op1_bm.intersect (r.get_bitmask ()))
+    r.update_bitmask (op1_bm);
+  else
+    r.set_undefined ();
   return true;
 }
 
index f93a7e5c53a28873ec5fa73177a6e0976f7de175..605f708173757aa87442d9ba55441251bb40d3b7 100644 (file)
@@ -674,8 +674,10 @@ prange::intersect (const vrange &v)
 
   // Intersect all bitmasks: the old one, the new one, and the other operand's.
   irange_bitmask new_bitmask (m_type, m_min, m_max);
-  m_bitmask.intersect (new_bitmask);
-  m_bitmask.intersect (r.m_bitmask);
+  if (!m_bitmask.intersect (new_bitmask))
+    set_undefined ();
+  else if (!m_bitmask.intersect (r.m_bitmask))
+    set_undefined ();
   if (varying_compatible_p ())
     {
       set_varying (type ());
@@ -2528,10 +2530,9 @@ irange::get_bitmask () const
   irange_bitmask bm (type (), lower_bound (), upper_bound ());
   if (!m_bitmask.unknown_p ())
     {
-      bm.intersect (m_bitmask);
       // If the new intersection is unknown, it means there are inconstent
       // bits, so simply return the original bitmask.
-      if (bm.unknown_p ())
+      if (!bm.intersect (m_bitmask))
        return m_bitmask;
     }
   return bm;
@@ -2572,7 +2573,11 @@ irange::intersect_bitmask (const irange &r)
 
   irange_bitmask bm = get_bitmask ();
   irange_bitmask save = bm;
-  bm.intersect (r.get_bitmask ());
+  if (!bm.intersect (r.get_bitmask ()))
+    {
+      set_undefined ();
+      return true;
+    }
 
   // If the new mask is the same, there is no change.
   if (m_bitmask == bm)
index 6ae46e179595d48bdb6486994be28432cdb92a9b..11d1ed75744cfdb582da02ec6f7443f61c9d7f8f 100644 (file)
@@ -145,7 +145,7 @@ public:
   bool unknown_p () const;
   unsigned get_precision () const;
   void union_ (const irange_bitmask &src);
-  void intersect (const irange_bitmask &src);
+  bool intersect (const irange_bitmask &src);
   bool operator== (const irange_bitmask &src) const;
   bool operator!= (const irange_bitmask &src) const { return !(*this == src); }
   void verify_mask () const;
@@ -247,20 +247,16 @@ irange_bitmask::union_ (const irange_bitmask &src)
     verify_mask ();
 }
 
-inline void
+// Return FALSE if the bitmask intersection is undefined.
+
+inline bool
 irange_bitmask::intersect (const irange_bitmask &src)
 {
   // If we have two known bits that are incompatible, the resulting
-  // bit is undefined.  It is unclear whether we should set the entire
-  // range to UNDEFINED, or just a subset of it.  For now, set the
-  // entire bitmask to unknown (VARYING).
+  // bit and therefore entire range is undefined.  Return FALSE.
   if (wi::bit_and (~(m_mask | src.m_mask),
                   m_value ^ src.m_value) != 0)
-    {
-      unsigned prec = m_mask.get_precision ();
-      m_mask = wi::minus_one (prec);
-      m_value = wi::zero (prec);
-    }
+    return false;
   else
     {
       m_mask = m_mask & src.m_mask;
@@ -268,6 +264,7 @@ irange_bitmask::intersect (const irange_bitmask &src)
     }
   if (flag_checking)
     verify_mask ();
+  return true;
 }
 
 // An integer range without any storage.