https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108477
--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Roger Sayle <[email protected]>: https://gcc.gnu.org/g:53c3316a8c79bd873a884bf89c11144d42af7f7c commit r17-4953-g53c3316a8c79bd873a884bf89c11144d42af7f7c Author: Roger Sayle <[email protected]> Date: Wed Oct 7 09:50:53 2026 +0100 PR tree-optimization/108477: Use ranger to select PLUS vs IOR in expand. This patch is my proposed solution to PR tree-optimization/108477. The issue is that when the bits of A and B are disjoint, the expressions A+B, A|B and A^B all compute the same result. The challenge is that different targets (due to their instruction sets) sometimes prefer one form over another. As these preferences conflict, there is no universally right answer for the middle-end. A solution is for the backend to define/specify its preferred representation using the recently added aop_optab, where AOP stands for any-or-plus. This patch tweaks RTL expansion of BIT_IOR_EXPR and BIT_XOR_EXPR to use get_nonzero_bits (i.e. ranger) to determine if the operands are indeed disjoint, and if so expand this arithmetic operation via aop_optab to respect the backend's wishes. This approach was initially suggested by Jakub Jelinek https://gcc.gnu.org/pipermail/gcc-patches/2024-January/642255.html For Uros' testcase in comment #2 of the bugzilla PR: unsigned int foo (unsigned int a, unsigned int b) { unsigned int r = a & 0x1; unsigned int p = b & ~0x3; return r + p + 2; } unsigned int bar (unsigned int a, unsigned int b) { unsigned int r = a & 0x1; unsigned int p = b & ~0x3; return r | p | 2; } previously on x86_64, gcc -O2 would generate: foo: andl $1, %edi andl $-4, %esi orl %esi, %edi leal 2(%rdi), %eax ret bar: andl $1, %edi andl $-4, %esi orl %esi, %edi movl %edi, %eax orl $2, %eax ret with this patch, we now generate: foo: andl $1, %edi andl $-4, %esi leal 2(%rdi,%rsi), %eax ret bar: andl $1, %edi andl $-4, %esi leal 2(%rdi,%rsi), %eax ret Some missed-optimization failures (may) affect other targets. These are pre-existing missed-optimization issues, as the backends are expecting a different (but equivalent) RTL encoding. 2026-10-07 Roger Sayle <[email protected]> gcc/ChangeLog PR tree-optimization/108477 * expr.cc (expand_expr_real_2) <case BIT_IOR_EXPR>: Split from BIT_AND_EXPR path. Use get_nonzero_bits to determine if both operands a bit-wise disjoint, and if so, expand using the backend's preferred aop_optab. <case BIT_XOR_EXPR>: Likewise. gcc/testsuite/ChangeLog PR tree-optimization/108477 * gcc.target/i386/pr108477.c: New test case.
