On 11/28/25 03:00, Richard Biener wrote:
On Thu, Nov 27, 2025 at 7:39 PM Andrew MacLeod <[email protected]> wrote:
I do think this is the correct solution. I dont think there is any point
in enhancing the bitmask class to have a representation of UNDEFINED as
it would be such a transient thing, and serves little purpose in the
class itself.
ok?
OK.
Thanks,
Richard.
Pushed.
From d46828612c6481e3510af54335cab2b4cdab0e91 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Wed, 26 Nov 2025 14:21:13 -0500
Subject: [PATCH 1/7] 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.
---
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 82a994b4ca5..fb7d4742bb6 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 f93a7e5c53a..605f7081737 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 6ae46e17959..11d1ed75744 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.
--
2.45.0