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.

Reply via email to