https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104292
--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> --- This should do it I think: (for neeq (ne eq) (simplify (neeq (plus zero_one_valued_p@0 zero_one_valued_p@1) INTEGER_CST@2) (with { tree_code newcode = ERROR_MARK; bool notatend = false; tree cst1 = build_one_cst (type); wide_int cst = wi::to_wide (@2); // a + b == 2 -> a & b // a + b != 2 -> ~(a & b) if (cst == 2) newcode = BIT_AND_EXPR, notatend = neeq == NE_EXPR; // a + b == 1 -> a ^ b // a + b != 1 -> ~(a ^ b) -> a == b else if (cst == 1) newcode = BIT_XOR_EXPR, notatend = neeq == NE_EXPR; // a + b == 0 -> ~(a | b) // a + b != 0 -> a | b else if (cst == 0) newcode = BIT_IOR_EXPR, notatend = neeq == EQ_EXPR; } (if (notatend) (switch (if (newcode == BIT_IOR_EXPR) (bit_xor (bit_ior @0 @1) { cst1; })) (if (newcode == BIT_AND_EXPR) (bit_xor (bit_and @0 @1) { cst1; })) (if (newcode == BIT_XOR_EXPR) (eq @0 @1))) (switch (if (newcode == BIT_IOR_EXPR) (bit_ior @0 @1)) (if (newcode == BIT_AND_EXPR) (bit_and @0 @1)) (if (newcode == BIT_XOR_EXPR) (bit_xor @0 @1))) ) ) )