https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115499
Andrew Pinski <pinskia at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Severity|normal |enhancement Ever confirmed|0 |1 Last reconfirmed| |2024-06-15 --- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> --- What happens is fold simplifies `(b || c)` into `!!b | !!c` too early. In fn1 jump threading and ifcombine (and phiopt) together provides: if (m.2_2 != 0) goto <bb 4>; [50.00%] else goto <bb 3>; [50.00%] <bb 3> [local count: 536870912]: _11 = _1 != 1; _12 = c_9(D) != 0; _6 = _11 & _12; goto <bb 5>; [100.00%] <bb 4> [local count: 536870912]: _3 = c_9(D) != 0; _13 = _1 != 1; _14 = _3 & _13; <bb 5> [local count: 1073741824]: # iftmp.0_5 = PHI <_14(4), _6(3)> ... And then see that iftmp.0_5 is the same on both branches and removes the whole branch. In the other cases we have: ``` _1 = (int) a_8(D); _2 = b_9(D) != 0; _3 = c_10(D) != 0; _4 = _2 | _3; _5 = (int) _4; _14 = _1 != _5; _15 = _3 & _14; _6 = (long long unsigned int) _15; ``` Or simplier: ((cast)((b != 0) | (c != 0)) != a) & (c != 0) Or c & ((cast)(b | c) != a) which can be just folded into c & (1 != a). So maybe something like: (simplify (bit_and:c @0 (cmp:c (convert (bit_ior:c @0 @1)) @2) (bit_and @0 (cmp { build_one_cst (TREE_TYPE (@2)); } @2))) We also don't handle even simplier: ``` bool f(bool a, bool b, int d, int e) { a = e != 0; return a & ((int)a != d); } bool f1(bool a, bool b, int d, int e) { a = e != 0; return a & (1 != d); } ``` Nor (clang/LLVM does not handle this one either): ``` bool f(bool a, bool b, int d, int e) { return a & ((int)(a|b) != d); } bool f1(bool a, bool b, int d, int e) { return a & (1 != d); } ``` It can get even more complex if `(a|b)` is a much more complex expression. Maybe this requires some pass to do this rather than a simple match and simplify pattern.