int f(int a) { return (a < 0) ? ~a : a; } This can be optimized to `return (a >> 31) ^ a;`. This transformation is done by LLVM, but not by GCC.
Created attachment 49874 [details] gcc11-pr96928.patch Untested fix.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:576714b309b330df0e80e34114bcdf0bba35e146 commit r11-6472-g576714b309b330df0e80e34114bcdf0bba35e146 Author: Jakub Jelinek <jakub@redhat.com> Date: Tue Jan 5 16:35:22 2021 +0100 phiopt: Optimize x < 0 ? ~y : y to (x >> 31) ^ y [PR96928] As requested in the PR, the one's complement abs can be done more efficiently without cmov or branching. Had to change the ifcvt-onecmpl-abs-1.c testcase, we no longer optimize it in ifcvt, on x86_64 with -m32 we generate in the end the exact same code, but with -m64: movl %edi, %eax - notl %eax - cmpl %edi, %eax - cmovl %edi, %eax + sarl $31, %eax + xorl %edi, %eax ret 2021-01-05 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/96928 * tree-ssa-phiopt.c (xor_replacement): New function. (tree_ssa_phiopt_worker): Call it. * gcc.dg/tree-ssa/pr96928.c: New test. * gcc.target/i386/ifcvt-onecmpl-abs-1.c: Remove -fdump-rtl-ce1, instead of scanning rtl dump for ifcvt message check assembly for xor instruction.
Fixed.
Note while moving this optimization to match-and-simplify I noticed that the gimple produced is: (~a) ^ b But this get changed around to: ~(a ^ b) By PRE latter on. I only noticed this because the testcase is failing as it depends being that.