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)))

Reply via email to