https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87009
Bug ID: 87009 Summary: Can't find XOR pattern applying De Morgan sequentially Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: mcccs at gmx dot com Target Milestone: --- Optimization: -Ofast Suggested debugging layout: https://godbolt.org/g/ERWctt int xor_int(int a, int b) { ... } Don't work: int x = ~(a|b); return ~(x|a)|~(x|b); return ~(~(a|b)|a)|~(~(a|b)|b); int x = ~a&~b; return ~((x|a)&(x|b)); return ~(((~a&~b)|a)&((~a&~b)|b)); int x = ~a&~b; return ~(x|a)|~(x|b); return ~((~a&~b)|a)|~((~a&~b)|b); int x = ~a&~b; return (~x&~a)|(~x&~b); int x = ~a&~b; return ~x&(~a|~b); Those two work: return (~(~a&~b)&~a)|(~(~a&~b)&~b); return ~(~a&~b)&(~a|~b); A different calculation: Don't work: return ~(~(~a&b)&~(a&~b)); return ~(~(~a|~b)|~(a|b)); return ~((a&b)|~(a|b)); This works: return ~(a&b)&(a|b); Different calculation: return ~((a|~b)&(~a|b)); return ~(a|~b)|~(~a|b); return (~a&b)|~(~a|b); This works: return (~a&b)|(a&~b); SUGGESTED SOLUTTION At match.pd:774 There's the De Morgan law for bitwise AND but there isn't one for OR. https://github.com/gcc-mirror/gcc/blob/fe4311f/gcc/match.pd#L774 No one noticed this, because it can (somehow) transform ~(~a|b) to a&~b sometimes, (for example, if BMI instructions is enabled, it can use the 'andn' instruction which calculates a&~b) If I understand it correctly, it only works if it's not simplified a different way until RTL optimization comes. /* ~(~a | b) --> a & ~b */ (simplify (bit_not (bit_ior:cs (bit_not @0) @1)) (bit_and @0 (bit_not @1)))