On g++ 4.9.2 and 5.3.1, this code takes several seconds to compile and produces a 52,776 byte executable:
#include <array>
#include <iostream>
int main()
{
constexpr std::size_t size = 4096;
struct S
{
float f;
S() : f(0.0f) {}
};
std::array<S, size> a = {}; // <-- note aggregate initialization
for (auto& e : a)
std::cerr << e.f;
return 0;
}
Increasing size
seems to increase compilation time and executable size linearly. I cannot reproduce this behaviour with either clang 3.5 or Visual C++ 2015. Using -Os
makes no difference.
$ time g++ -O2 -std=c++11 test.cpp
real 0m4.178s
user 0m4.060s
sys 0m0.068s
Inspecting the assembly code reveals that the initialization of a
is unrolled, generating 4096 movl
instructions:
main:
.LFB1313:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
subq $16384, %rsp
.cfi_def_cfa_offset 16400
movl $0x00000000, (%rsp)
movl $0x00000000, 4(%rsp)
movq %rsp, %rbx
movl $0x00000000, 8(%rsp)
movl $0x00000000, 12(%rsp)
movl $0x00000000, 16(%rsp)
[...skipping 4000 lines...]
movl $0x00000000, 16376(%rsp)
movl $0x00000000, 16380(%rsp)
This only happens when T
has a non-trivial constructor and the array is initialized using {}
. If I do any of the following, g++ generates a simple loop:
- Remove
S::S()
; - Remove
S::S()
and initializeS::f
in-class; - Remove the aggregate initialization (
= {}
); - Compile without
-O2
.
I'm all for loop unrolling as an optimization, but I don't think this is a very good one. Before I report this as a bug, can someone confirm whether this is the expected behaviour?
[edit: I've opened a new bug for this because the others don't seem to match. They were more about long compilation time than weird codegen.]