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

            Bug ID: 108614
           Summary: _subborrow_u32 generates suboptimal code when second
                    subtraction operand is constant on x86 targets
           Product: gcc
           Version: 12.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: john_platts at hotmail dot com
  Target Milestone: ---

Here is some C++ code that generates suboptimal code with the -O2
-march=skylake-avx512 -m32 options with gcc 12.2.0:
#include <stdint.h>
#include <utility>
#include <x86intrin.h>
#include <immintrin.h>

std::pair<uint32_t, uint32_t> ComputeHiMaskAndHiZeroAmt(uint32_t len) {
    uint32_t hiMask;
    uint32_t hiZeroAmt;

    _addcarry_u32(_subborrow_u32(0, len, 32, &hiZeroAmt),
        uint32_t{0xFFFFFFFFu}, 0, &hiMask);

    hiMask = _bzhi_u32(hiMask, hiZeroAmt);

    return std::make_pair(hiMask, hiZeroAmt);
}

Here is the assembly code that is generated when the above code is compiled
with gcc 12.2.0 with the -O2 -march=skylake-avx512 -m32 options:
_Z25ComputeHiMaskAndHiZeroAmtj:
        subl    $16, %esp
        movl    24(%esp), %eax
        movl    $32, %edx
        subl    %edx, %eax
        movl    20(%esp), %ecx
        movl    $-1, %edx
        adcl    $0, %edx
        movl    %eax, 4(%ecx)
        bzhi    %eax, %edx, %edx
        movl    %ecx, %eax
        movl    %edx, (%ecx)
        addl    $16, %esp
        ret     $4

Here is a more optimal version of the above code (for 32-bit x86):
_Z25ComputeHiMaskAndHiZeroAmtj:
        movl    8(%esp), %eax
        subl    $32, %eax
        movl    4(%esp), %ecx
        movl    $-1, %edx
        adcl    $0, %edx
        movl    %eax, 4(%ecx)
        bzhi    %eax, %edx, %edx
        movl    %ecx, %eax
        movl    %edx, (%ecx)
        ret     $4

Here is the assembly code that is generated when the above code is compiled
with gcc 12.2.0 with the -O2 -march=skylake-avx512 options:
_Z25ComputeHiMaskAndHiZeroAmtj:
        movl    $32, %eax
        subl    %eax, %edi
        movl    $-1, %eax
        adcl    $0, %eax
        bzhi    %edi, %eax, %eax
        salq    $32, %rdi
        movl    %eax, %eax
        orq     %rdi, %rax
        ret

Here is a more optimal version of the above code (for 64-bit x86):
_Z25ComputeHiMaskAndHiZeroAmtj:
        subl    $32, %edi
        movl    $-1, %eax
        adcl    $0, %eax
        bzhi    %edi, %eax, %eax
        salq    $32, %rdi
        movl    %eax, %eax
        orq     %rdi, %rax
        ret

Reply via email to