https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66952
--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- Hmm, I can't see what is wrong with the pattern. We just replace _13 = (int) c_4; if (_13 <= 0) with <bb 3>: _13 = (int) c_4; if (c_4 <= 0) with c_4 being signed char. Something else must go wrong here. Still -fno-tree-forwprop fixes the bug. There is a missed optimization in VRP1 which ends up ifcombine doing sth. VRP2 manages to mess things up then: <bb 2>: a.0_4 = a; c_5 = (char) a.0_4; _6 = (int) c_5; if (c_5 == 0) goto <bb 3>; else goto <bb 4>; <bb 3>: b = 0; goto <bb 5>; <bb 4>: _9 = ASSERT_EXPR <_6, _6 != 0>; b = 0; _10 = _9 | 128; if (_10 < 0) a.0_4: VARYING c_5: VARYING _6: [0, 127] _9: [1, 127] EQUIVALENCES: { _6 } (1 elements) _10: [128, 255] .MEM_15: VARYING as you can see _6 is already bogus. Which is because of <bb 2>: a.0_4 = a; c_5 = (char) a.0_4; # RANGE [0, 127] NONZERO 127 _6 = (int) c_5; which is because of ifcombine hoisting the def of _6 in if (c_5 >= 0) goto <bb 3>; else goto <bb 5>; <bb 3>: # RANGE [0, 127] NONZERO 127 _6 = (int) c_5; if (c_5 == 0) goto <bb 4>; else goto <bb 5>; above the guarding check! <bb 2>: a.0_4 = a; c_5 = (char) a.0_4; # RANGE [0, 127] NONZERO 127 _6 = (int) c_5; if (c_5 == 0) goto <bb 3>; else goto <bb 4>;