https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108523
--- Comment #11 from Richard Biener <rguenth at gcc dot gnu.org> --- So the issue is that we oscillate between recognizing the PHI as degenerate because of an equivalence recorded on the non-backedge(!) to the backedge value which in turn changes because of this change: Value numbering stmt = g_6_lsm.126_456 = PHI <g_6_lsm.126_304(19), g_6_lsm.126_338(108)> Setting value number of g_6_lsm.126_456 to _347 ... Value numbering stmt = _350 = g_6_lsm.126_456; Setting value number of _350 to _347 (changed) _347 is available for _347 Value numbering stmt = _352 = _348 ^ _350; _347 is available for _347 Match-and-simplified _348 ^ _350 to _346 RHS _348 ^ _350 simplified to _346 Setting value number of _352 to _346 (changed) _346 is available for _346 Value numbering stmt = g_6_lsm.126_304 = _352; Setting value number of g_6_lsm.126_304 to _346 (changed) _346 is available for _346 Looking for changed values of backedge 19->20 destination PHIs Setting value number of g_481.64_448 to g_481.64_448 Setting value number of .MEM_464 to .MEM_409 Predication says _347 and _346 are equal on edge 108 -> 20 Setting value number of g_6_lsm.126_456 to _346 (changed) Iterating to 25 BB20 ... Value numbering stmt = g_6_lsm.126_456 = PHI <g_6_lsm.126_304(19), g_6_lsm.126_338(108)> Predication says _347 and _346 are equal on edge 108 -> 20 Setting value number of g_6_lsm.126_456 to _346 ... Value numbering stmt = _350 = g_6_lsm.126_456; Setting value number of _350 to _346 (changed) _346 is available for _346 Value numbering stmt = _352 = _348 ^ _350; _346 is available for _346 Match-and-simplified _348 ^ _350 to _347 RHS _348 ^ _350 simplified to _347 Setting value number of _352 to _347 (changed) _347 is available for _347 Value numbering stmt = g_6_lsm.126_304 = _352; Setting value number of g_6_lsm.126_304 to _347 (changed) _347 is available for _347 Looking for changed values of backedge 19->20 destination PHIs Setting value number of g_481.64_448 to g_481.64_448 Setting value number of .MEM_464 to .MEM_409 Setting value number of g_6_lsm.126_456 to _347 (changed) Iterating to 25 BB20 and repeat. And we have: _348 = _346 ^ _347; and <bb 18> [local count: 42914375]: # g_1198.66_449 = PHI <_358(141), 0(17)> # g_6_lsm.126_131 = PHI <g_6_lsm.126_349(141), g_6_lsm.126_438(17)> g_481_lsm.127_447 = 1; _57 = g_6_lsm.126_131; _58 = _57 ^ _348; g_6_lsm.126_338 = _58; if (_346 != _347) goto <bb 150>; [5.50%] else goto <bb 108>; [94.50%] <bb 108> [local count: 40554084]: goto <bb 20>; [100.00%] So when the value we compare to oscillates. Interestingly when I try to feed a similar case into FRE1 that "works": int foo (int a, int b, int n) { int val = a; if (a == b) { do { val = (a ^ b) ^ val; } while (--n > 0); } return val; } but maybe this is by luck. So what we need to avoid is for an equivalence a == b, to oscillate between 'a' and 'b' as result.