https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119712
--- Comment #7 from Andrew Macleod <amacleod at redhat dot com> --- Bah. almost but not quite. Rangers cache algorithm must remain as it is... it will always produce a better result.. but we need to calculate everything properly. Going back to the original analysis: 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 and second iteration: 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 The initial value of _11 is actually more precise than the second. It excludes the range of [0, 0] which the second one does not. The evaluation on the edge from 7->4 is the important thing to note. On the first iteration, it includes 0 which is why _11 contains 0 on the second iteration. Then it is reduces to 1 in the second case. During the GORI evaluation cycle, we end up utilizing adjust_range() during the calculation of 7->4 the second time because an intersection actually does something, and so we evaluate _11 with the mask expanded to -INF, 1][4, 2147483626] instead of [-INF, 2147483644].. this eliminates 0 from the range on that edge, and ends up causing the cycle of flip=flopping values. The Right thing to do would be to always expand those bits when we set a bitmask. The initial range would then become: [irange] int [-INF, -3][1, 1][4, 2147483644] MASK 0xfffffffc VALUE 0x1 And when this feeds into the update cycle, we no longer have this flip-flop issue because it contains the lack of zero on both iterations. This eliminates any bitmask effect on the algorithm and it returns to being correct. I am running regressions on this change now. There is a small timing penalty as making these adjustments to all ranges is a bit pervasive. Its only .18% over a compilation unit, but it adds up to about 1.3% in VRP. ick. Well probably see some minor improvement in other places due to the better subranges... but I will keep thinking about how to tweak that This is the new potential fix: diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 5136674b361..0730df2ded7 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -2341,6 +2341,8 @@ irange::update_bitmask (const irange_bitmask &bm) m_bitmask = bm; if (!set_range_from_bitmask ()) normalize_kind (); + // Trim out lower values from the range the which bitmask disallows. + m_bitmask.adjust_range (*this); if (flag_checking) verify_range (); }