https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80588
--- Comment #1 from Marc Glisse <glisse at gcc dot gnu.org> --- Thanks. Let me copy what I had in the other PR: we have an old optimization in fold_unary (like other "do ... if ... simplifies" it is not straightforward to move it to match.pd) and thus it only applies when everything is part of the same expression in the source code. /* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */ If you use even less macros and more lines, things optimize a bit better: m_xnor: TYPE tmp=!!a^!!b; return !tmp; but we still have some discrepancy where we optimize (a^b)==0 but not ~(a^b) (for _Bool type).