https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119712
--- Comment #4 from Andrew Macleod <amacleod at redhat dot com> --- The change tweaks an issue that I haven't seen in the cache before. When it is propagating values in the cache (the only real iteration ranger has) the values are always suppose to get "better", and in the interest of speed, the cache performs an update when the newly calculated value is different than the old. This avoid the overhead of doing an intersect every time the cache propagates values. That decision also predates integrating bitmasks into irange. In this particular case, the physical range remains the same, but the mask changes. Iteration one: FWD visiting block 4 for _11 starting range : [irange] int [-INF, 2147483644] MASK 0xfffffffc VALUE 0x1 edge 6->4 :[irange] int [-INF, 2147483644] MASK 0xfffffffc VALUE 0x1 edge 7->4 :[irange] int [0, 1] edge 3->4 :[irange] int [1, 1] MASK 0xfffffffc VALUE 0x1 Updating range to [irange] int [-INF, 2147483644] MASK 0xfffffffd VALUE 0x0 [-INF, 2147483644] MASK 0xfffffffc VALUE 0x1 maps to [-INF, -1][1, 1][4, 2147483626] MASK 0xfffffffc VALUE 0x1 and [irange] int [-INF, 2147483644] MASK 0xfffffffd VALUE 0x0 maps to [-INF, 1][4, 2147483626] MASK 0xfffffffd VALUE 0x0 Note that the new range is *different* but not better. Its actually worse... The result of the union of these 3 ranges includes zero, but then original does not. When this value is then propagated through a few blocks and the updated returns to block 4, : FWD visiting block 4 for _11 starting range : [irange] int [-INF, 2147483644] MASK 0xfffffffd VALUE 0x0 edge 6->4 :[irange] int [-INF, 2147483644] MASK 0xfffffffc VALUE 0x1 edge 7->4 :[irange] int [1, 1] edge 3->4 :[irange] int [1, 1] MASK 0xfffffffc VALUE 0x1 Updating range to [irange] int [-INF, 2147483644] MASK 0xfffffffc VALUE 0x1 Note the newly refined range from edge 7->4 no longer includes zero, so the new range is different again, and in fact is back to the original value. And thus we hang in an infinite cycle up update because we storied a value which was NOT better during the initial update. We should be intersecting during the cache update now that we have masks. Intersect will only return TRUE if the resulting range is *better*, thus avoiding the cycle. I am checking the Correctness and timing difference if I DTRT, like so: diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index ecf03319cd4..29dfcf894e5 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -1368,9 +1368,9 @@ ranger_cache::propagate_cache (tree name) } // If the range on entry has changed, update it. - if (new_range != current_range) + if (current_range.intersect (new_range)) { - bool ok_p = m_on_entry.set_bb_range (name, bb, new_range); + bool ok_p = m_on_entry.set_bb_range (name, bb, current_range); // If the cache couldn't set the value, mark it as failed. if (!ok_p) m_update->propagation_failed (bb); What do i add to the testsuite to timeout the compilation after a few seconds? It should normally compile very fast.