[llvm-dev] Where's the optimiser gone (part 11): use the proper instruction for sign extension

Stefan Kanthak via llvm-dev llvm-dev at lists.llvm.org
Sun Mar 3 23:06:13 PST 2019


Compile with -O3 -m32 (see <https://godbolt.org/z/yCpBpM>):

long lsign(long x)
{
    return (x > 0) - (x < 0);
}


long long llsign(long long x)
{
    return (x > 0) - (x < 0);
}


While the code generated for the "long" version of this function is quite
OK, the code for the "long long" version misses an obvious optimisation:


lsign: # @lsign
    mov     eax, dword ptr [esp + 4]    |    mov     eax, dword ptr [esp + 4]
    xor     ecx, ecx                    |
    test    eax, eax                    |    cdq
    setg    cl                          |    neg     eax
    sar     eax, 31                     |    adc     edx, edx
    add     eax, ecx                    |    mov     eax, edx
    ret                                 |    ret

llsign: # @llsign
    xor     ecx, ecx                    |    xor     edx, edx
    mov     eax, dword ptr [esp + 8]    |    mov     eax, dword ptr [esp + 8]
    cmp     ecx, dword ptr [esp + 4]    |    cmp     edx, dword ptr [esp + 4]
    sbb     ecx, eax                    |    sbb     edx, eax
    setl    cl                          |    cdq
    sar     eax, 31                     |    setl    al
    movzx   ecx, cl                     |    movzx   eax, al
    add     eax, ecx                    |    add     eax, edx
    mov     edx, eax                    |    ret
    sar     edx, 31
    ret

NOTE: not just here this sequence SHOULD be replaced with

    mov     edx, eax                    |    cdq
    sar     edx, 31

Although CDQ is the proper instruction for sign extension, LLVM/clang doesn't
seem to like it.

stay tuned
Stefan Kanthak


More information about the llvm-dev mailing list