https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97711
--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> --- So GCC already converts the following two functions at the gimple level: int f1 (int x) { return x - (x & 1); } char *g1 (char *x) { return x - ((__UINTPTR_TYPE__) x & 1); } ----- CUT ---- Even on the RTL level too, I Noticed that because the original testcase does the correct thing for aarch64, why it is not done for x86_64 I don't know. Anyways what we could do is take: if (_2 != 0) goto <bb 3>; [50.00%] else goto <bb 4>; [50.00%] <bb 3> [local count: 536870913]: iftmp.1_5 = x_4(D) + 18446744073709551615; <bb 4> [local count: 1073741824]: # iftmp.1_3 = PHI <iftmp.1_5(3), x_4(D)(2)> And convert that too: iftmp.1_3 = x - (type)(_2 != 0) So something simple as: (simplify (cond @0 (plus @1 integer_all_onesp@2) @1) (minus @1 (convert @0))) If you want to handle case where @2 is a power of 2 instead so you can use shift, that is another option.