https://gcc.gnu.org/g:1ff32875e93be6617e093c0ef1413d506c58f045
commit r16-5696-g1ff32875e93be6617e093c0ef1413d506c58f045 Author: Andrew MacLeod <[email protected]> Date: Wed Nov 26 14:21:13 2025 -0500 Undefined bitmasks imply undefined ranges. 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. Diff: --- gcc/range-op.cc | 9 ++++++--- gcc/value-range.cc | 15 ++++++++++----- gcc/value-range.h | 17 +++++++---------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 82a994b4ca55..fb7d4742bb6d 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -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; } diff --git a/gcc/value-range.cc b/gcc/value-range.cc index f93a7e5c53a2..605f70817375 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -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) diff --git a/gcc/value-range.h b/gcc/value-range.h index 6ae46e179595..11d1ed75744c 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -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.
