https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116013

            Bug ID: 116013
           Summary: Missed optimization opportunity with andn involving
                    consts
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: bisqwit at iki dot fi
  Target Milestone: ---

Below are two short functions which work identically. While GCC utilizes the
ANDN instruction (of Intel BMI1) for test2, it fails to see that it could do
the same with test1.

    #include <stdint.h>
    uint64_t test1(uint64_t value)
    {
        return ~(value | 0x7F7F7F7F7F7F7F7F);
    }
    uint64_t test2(uint64_t value)
    {
        return ~value & ~0x7F7F7F7F7F7F7F7F;
    }

Assembler listings of both functions are below (-Ofast -mbmi):

    test1:
        movabsq $9187201950435737471, %rdx
        movq    %rdi, %rax
        orq     %rdx, %rax
        notq    %rax
        ret
    test2:
        movabsq $-9187201950435737472, %rax
        andn    %rax, %rdi, %rax
        ret

Tested compiler version:
GCC: (Debian 14-20240330-1) 14.0.1 20240330 (experimental) [master
r14-9728-g6fc84f680d0]

This optimization makes only sense if one of the operands is a compile-time
constant. If neither operand is a compile-time constant, then the opposite
optimization makes more sense — which GCC already does.
It is also worth noting, that GCC already compiles ~(var1 | ~var2) into ~var1 &
var2, utilizing ANDN. This is good.

Reply via email to