int f1(int n) { return n - (((n > 63) ? n : 63) & -64); } This can be optimized to `return (n <= 63) ? n : (n & 63);` (and presumably the same optimization should be doable with other powers of 2). PS: I found this optimization while looking at how this : int f1(int n) { while (n >= 64) n -= 64; return n; } is optimized. LLVM outputs the first example I gave here, while GCC outputs the optimization I gave here.
_1 = MAX_EXPR <n_3(D), 63>; _2 = _1 & -64; _4 = n_3(D) - _2; Something like: (simplify (minus @0 (bit_and (max @0 INTEGER_CST@1) INTEGER_CST@2)) (if (@1 == (@2)-1) (if (TYPE_SIGN (type) == UNSIGNED) (bit_and @0 @1) (cond (le @0 @1) @0 (bit_and @0 @1)) ) ) ) Note LLVM handles the unsigned case already. Also note also even though GCC can handle the loop case for signed, it only handles it on the RTL level, for gimple GCC produces: _3 = n_2(D) + -64; _8 = (unsigned int) n_2(D); _9 = _8 + 4294967232; // _9 = _3 - 64 _10 = _9 >> 6; // _10 = _9/64 _11 = (int) _10; _12 = _11 * -64; n_1 = _3 + _12;
> @1 == (@2)-1 Should have been: @1 == -(@2-1) maybe check that @1 is a mask.
The master branch has been updated by Jeff Law <law@gcc.gnu.org>: https://gcc.gnu.org/g:d9fa599dc7584d89e758a09a3d68982f12d8751c commit r13-1587-gd9fa599dc7584d89e758a09a3d68982f12d8751c Author: Sam Feifer <sfeifer@redhat.com> Date: Sat Jul 9 12:08:01 2022 -0400 [PATCH] match.pd: Add new bitwise arithmetic pattern [PR98304] PR tree-optimization/98304 gcc: * match.pd (n - (((n > C1) ? n : C1) & -C2)): New simplification. gcc/testsuite: * gcc.c-torture/execute/pr98304-2.c: New test. * gcc.dg/pr98304-1.c: New test.
Fixed