https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118953
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I think the bug is in irange::union_bitmask with *this [irange] long long unsigned int [0, 0][17, 17][25, 25] MASK 0xffffffffffffc000 VALUE 0x2d and r [irange] long long unsigned int [0, 0] r.m_bitmask is MASK 0xffffffffffffffff VALUE 0x0. 2447 irange_bitmask bm = get_bitmask (); 2448 irange_bitmask save = bm; 2449 bm.union_ (r.get_bitmask ()); 2450 if (save == bm) 2451 return false; uses get_bitmask though, which first computes independently 2375 irange_bitmask bm 2376 = get_bitmask_from_range (type (), lower_bound (), upper_bound ()); and because lower_bound () is 0 (this is already partially merged) and upper_bound () is 25, bm is then MASK 0x1f VALUE 0x0 This is then 2377 if (!m_bitmask.unknown_p ()) 2378 bm.intersect (m_bitmask); and we get MASK 0xffffffffffffffff VALUE 0x0 which is returned. Now, obviously bm.union_ (r.get_bitmask ()); yields the same MASK 0xffffffffffffffff VALUE 0x0 and so the code thinks ok, there is no change, we don't need to update m_bitmask. The comments talk about semantic bitmasks (what get_bitmask () returns) vs. what is stored in m_bitmask, it is true that the semantic bitmask didn't really change, it was already MASK 0xffffffffffffffff VALUE 0x0 when the range was just [irange] long long unsigned int [17, 17][25, 25] MASK 0xffffffffffffc000 VALUE 0x2d but guess this testcase shows that it is really undesirable to keep random garbage in m_bitmask when the semantic bitmask didn't change, because we can later union it with something that will change the semantic bitmask. So wonder at least about --- gcc/value-range.cc.jj 2025-01-02 11:23:25.118396777 +0100 +++ gcc/value-range.cc 2025-02-26 18:49:10.713107905 +0100 @@ -2447,7 +2447,7 @@ irange::union_bitmask (const irange &r) irange_bitmask bm = get_bitmask (); irange_bitmask save = bm; bm.union_ (r.get_bitmask ()); - if (save == bm) + if (m_bitmask == bm) return false; m_bitmask = bm; which fixes the testcase. I.e. still return false, just update m_bitmask.