https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103281
--- Comment #8 from Andrew Pinski <pinskia at gcc dot gnu.org> --- Hmm: # RANGE [irange] char [0, 2] NONZERO 0x3 c_9 = (charD.7) b.4_5; _1 = c_9 <= 0; Should _1 be replaced with c_9 == 0 which then can be simplified to b.4_5 == 0 That is PR 28794 I think. And then after that we get: b.4_5 == (unsigned int)(b.4_5 == 0) Which should be optimized down to false though we don't either. unsigned f(unsigned t) { unsigned a = t == 0; return t == a; } The general CST cases (I hope I did these correctly): a == (a == CST) -> CST == 0 -> false CST == 1 -> a == 1 | a == 0 others -> a == 0 a != (a == CST) -> CST == 0: false CST == 1: a != 0 || a != 1 others : a != 0 a != (a != CST) -> CST == 0: a == 1 | a == 0 CST == 1: true others : a != 1 a == (a != CST) -> CST == 0: a == 1 | a == 0 CST == 1: false others : a == 1