Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 760
Cory Kramer Avatar asked Jun 19 '19 12:06

Cory Kramer


1 Answers

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 232, 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).

like image 155
Martin Bonner supports Monica Avatar answered Oct 02 '22 15:10

Martin Bonner supports Monica