简体   繁体   中英

Array initialization optimization

When compiling the following code snippet (clang x86-64 -O3 )

std::array<int, 5> test()
{
    std::array<int, 5> values {{0, 1, 2, 3, 4}};
    return values;
}

It produced the typical assembly that I would expect

test():                               # @test()
        mov     rax, rdi
        mov     ecx, dword ptr [rip + .L__const.test().values+16]
        mov     dword ptr [rdi + 16], ecx
        movups  xmm0, xmmword ptr [rip + .L__const.test().values]
        movups  xmmword ptr [rdi], xmm0
        ret
.L__const.test().values:
        .long   0                       # 0x0
        .long   1                       # 0x1
        .long   2                       # 0x2
        .long   3                       # 0x3
        .long   4                       # 0x4

However for small arrays, it seems to have figured out a trick?

std::array<int, 3> test()
{
    std::array<int, 3> values {{0, 1, 2}};
    return values;
}

This was the corresponding assembly

test():                               # @test()
        movabs  rax, 4294967296
        mov     edx, 2
        ret

Where did that magic number ( 4294967296 ) come from? Is that essentially a value that can be reinterpret_cast back into an array of int somehow?

A std::array<int, 3> is 96 bits wide on your implementation. As such the ABI declares that it should be returned in RAX + the low 32 bits of RDX (aka EDX).

4294967296 is 2 32 , in hex it is $1'0000'0000 . So the movabs stores 0 in the low order 32 bits of RAX, and 1 in the high order bits of RAX. The mov stores 2 in EDX (which is exactly what you wanted).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM