bitmask intersection does not update the m_bitmask field if the new mask matches the get_bitmask () result.

the get_bitmask () routine also incorporates a mask calculated from the  range itself.

THe problem in intersection is we use the get_bitmask() version to compare to the new one to see if the mask has changed.  We should compare it to the actual stored mask so that if there are changes via the range , they can be incorporated into the stored mask.

That all sounds very convoluted, but it boils down to the following example:

_3 starts with a range of     [irange] int [-INF, +INF] MASK 0x5f VALUE 0x0

when we intersect this with [0,4], the range is intersected first, and we get

[irange] int [0, 4] MASK 0x5f VALUE 0x0

and then the bitmask is intersected.    well get_bitmask() incorporates the range in the calculation now, and produces MASK 0x7 VALUE 0x0

which is the same mask the the [0,4] was intersected with, so we never update the bitmask... and the range looks funny.

This is not a correctness issue as we do get the right mask with get_bitmask (), but it is very awkward and may lead to less accurate masks down the road...  better to simply set it now if we know what it should be.

bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.

From eb11ee3d7d8ed9a3b024740343a5fe9467ec9e0f Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Thu, 12 Jun 2025 14:48:50 -0400
Subject: [PATCH 4/4] intersect_bitmask - Always update bitmask.

The bitmask wasn't always being updated, resulting in some less than
perfect masks being stored.:x

	* value-range.cc (irange::intersect_bitmask): Always update the
	stored mask to reflect the current calculated mask.
---
 gcc/value-range.cc | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 348c68ec902..0f0770ad705 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2548,15 +2548,14 @@ irange::intersect_bitmask (const irange &r)
   irange_bitmask bm = get_bitmask ();
   irange_bitmask save = bm;
   bm.intersect (r.get_bitmask ());
-  if (save == bm)
-    return false;
-
+  // Use ths opportunity to make sure mask reflects always reflects the
+  // best mask we have.
   m_bitmask = bm;
 
   // Updating m_bitmask may still yield a semantic bitmask (as
   // returned by get_bitmask) which is functionally equivalent to what
   // we originally had.  In which case, there's still no change.
-  if (save == get_bitmask ())
+  if (save == bm || save == get_bitmask ())
     return false;
 
   if (!set_range_from_bitmask ())
-- 
2.45.0

Reply via email to