[llvm-dev] BUGS n code generated for target i386 compiling __bswapdi3, and for target x86-64 compiling __bswapsi2()

Stefan Kanthak via llvm-dev llvm-dev at lists.llvm.org
Sun Nov 25 07:52:55 PST 2018


Hi @ll,

targetting i386, LLVM/clang generates wrong code for the following
functions:

unsigned long __bswapsi2 (unsigned long ul)
{
    return (((ul) & 0xff000000ul) >> 3 * 8)
         | (((ul) & 0x00ff0000ul) >>     8)
         | (((ul) & 0x0000ff00ul) <<     8)
         | (((ul) & 0x000000fful) << 3 * 8);
}

unsigned long long __bswapdi2(unsigned long long ull)
{
    return ((ull & 0xff00000000000000ull) >> 7 * 8)
         | ((ull & 0x00ff000000000000ull) >> 5 * 8)
         | ((ull & 0x0000ff0000000000ull) >> 3 * 8)
         | ((ull & 0x000000ff00000000ull) >>     8)
         | ((ull & 0x00000000ff000000ull) <<     8)
         | ((ull & 0x0000000000ff0000ull) << 3 * 8)
         | ((ull & 0x000000000000ff00ull) << 5 * 8)
         | ((ull & 0x00000000000000ffull) << 7 * 8);
}

You can find these sources in "compiler-rt/lib/builtins/bswapsi2.c"
and "compiler-rt/lib/builtins/bswapdi2.c", for example!


Compiled with "-O3 -target i386" this yields the following code
(see <https://godbolt.org/z/F4UIl4>):

__bswapsi2: # @__bswapsi2
    push  ebp
    mov   ebp, esp
    mov   eax, dword ptr [ebp + 8]
    bswap eax
    pop   ebp
    ret

__bswapdi2: # @__bswapdi2
    push  ebp
    mov   ebp, esp
    mov   edx, dword ptr [ebp + 8]
    mov   eax, dword ptr [ebp + 12]
    bswap eax
    bswap edx
    pop   ebp
    ret

__bswapsi2() is correct, but __bswapdi2() NOT: swapping just the
halves of a "long long" is OBVIOUSLY WRONG!

>From the C source, the expected result for the input value
0x0123456789ABCDEF is 0xEFCDAB8967452301; the compiled code but
produces 0x67452301EFCDAB89


And compiled for x86-64 this yields the following code (see
<https://godbolt.org/z/uM9nvN>):

__bswapsi2: # @__bswapsi2
    mov   eax, edi
    shr   eax, 24
    mov   rcx, rdi
    shr   rcx, 8
    and   ecx, 65280
    or    rax, rcx
    mov   rcx, rdi
    shl   rcx, 8
    and   ecx, 16711680
    or    rax, rcx
    and   rdi, 255
    shl   rdi, 24
    or    rax, rdi
    ret

__bswapdi2: # @__bswapdi2
    bswap rdi
    mov   rax, rdi
    ret

Both are correct, but __bswapsi2() should of course use BSWAP too!


Stefan Kanthak

PS: for comparision with another compiler, take a look at
    <https://skanthak.homepage.t-online.de/msvc.html#example5>


More information about the llvm-dev mailing list