Take: ``` bool fn5(bool a, bool c) { return a != c && (a || c); } int fn6(int a, int c) { return (a ^ c) & (a | c); } ``` these 2 are optimized to (a^c) on the RTL level only (well fn5 is not done for aarch64). We should be able to optimize them on the gimple level too.
Note sometimes it can get complex for bool case: ``` bool fn1(bool a, bool b, bool c) { return a != c && (b || (c || a)); } bool fn2(bool a, bool b, bool c) { return a != c && (b || c || a); } bool fn3(bool a, bool b, bool c) { return a != c && (a || b || c); } bool fn4(bool a, bool b, bool c) { return a != c && (a || c || b); } ``` The above is from https://github.com/llvm/llvm-project/issues/95946 . For those we have: ``` <bb 2> [local count: 1073741824]: if (a_3(D) != c_4(D)) goto <bb 3>; [66.00%] else goto <bb 4>; [34.00%] <bb 3> [local count: 708669600]: _8 = c_4(D) | b_5(D); _7 = a_3(D) | _8; <bb 4> [local count: 1073741824]: # iftmp.0_2 = PHI <_7(3), 0(2)> return iftmp.0_2; ``` Which really we know that (a|c) will be 1. But maybe that is a different issue all together.
Another testcase: ``` bool test1(bool a, bool b) { return (a | b) ? (a ^ b) : (a & b); } ``` Right now I am not worried about comment #1 though.