https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115494
--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> --- ANTIC_IN[6] := { _5 (0005), _16 (0014), {bit_not_expr,_16} (0016), {bit_ior_expr,_5,_19} (0017) } ANTIC_IN[8] := { _5 (0005), _16 (0014), {bit_not_expr,_16} (0016), {bit_ior_expr,_5,_17} (0017) } ANTIC_IN[11] := { _5 (0005), _16 (0014), {bit_not_expr,_16} (0016), {bit_ior_expr,_5,_24} (0017) } merge 8 + 11: ANTIC_IN[7] := { b.0_1 (0001), _5 (0005), _16 (0014), {bit_not_expr,_16} (0016), {bit_ior_expr,_5,_17} (0017), {bit_ior_expr,_5,_24} (0017) } merge 7 + 6: ANTIC_IN[5] := { b.0_1 (0001), iftmp.2_9 (0008), {nop_expr,iftmp.2_9} (0005), {bit_not_expr,_5} (0006), {nop_expr,b.0_1} (0014), {bit_not_expr,_16} (0016), {bit_ior_expr,_5,_19} (0017), {bit_ior_expr,_5,_17} (0017), {bit_ior_expr,_5,_24} (0017) that's all OK. Note all exprs have the same value (0017) here. Then we PHI-translate to where _5 == 0: ANTIC_IN[14] := { b.0_1 (0001), {nop_expr,b.0_1} (0014), {bit_not_expr,_16} (0016) } which is OK, 0 | .. gets simplified to ~16 Then we PHI-translate to where _5 == 1: ANTIC_IN[4] := { b.0_1 (0001), {nop_expr,b.0_1} (0014), {bit_not_expr,_16} (0016), {bit_ior_expr,_17,1} (0027), {bit_ior_expr,_24,1} (0028) } even that's OK, you see that we simplified just _5 | _19 to 1 (constants are not tracked in the set, the translated _17 | _5 and _24 | _5 got different value numbers). But then: Found partial redundancy for expression {bit_ior_expr,_5,_19} (0017) ... Created phi prephitmp_29 = PHI <1(4), _28(14)> in block 5 (0017) see how we figured the redundancy for value 0017 (because _5 | _19 simplified to 1) and we use the same value for the PHI as for all of the expressions. That we now keep all PRE exprs didn't save us here. _19 _is_ the leader for the expression as we translate it. The problem is the other expressions for the same value do not translate the same. This is probably a longer latent issue since we scrapped resetting ranges which likely means since RPO VN. It's always a bit of luck but I guess since we now track all expressions we have for a value this got more robust in triggering. It of course also needs a suitable simplification to manifest. I have to think about this. Simplifying to sth like if (flag) a = 1; if (b & 1 == b) // b [0,1] x = a | b; else x = a | b; return x; should be possible.