https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71165

            Bug ID: 71165
           Summary: std::array with aggregate initialization generates
                    huge code
           Product: gcc
           Version: 5.3.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: personalmountains at gmail dot com
  Target Milestone: ---

[mostly copied from a thread on stackoverflow at
http://stackoverflow.com/questions/37260097]

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. I've reproduced this on g++ 4.9.2 and
5.3.1, but 6.1 also seems to do the same thing.

$ 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:

 1) Remove S::S();
 2) Remove S::S() and initialize S::f in-class;
 3) Remove the aggregate initialization (= {});
 4) Compile without -O2.

Bugs 59659, 56671 may be relevant. In particular, some of the test cases in bug
59659 seem to still be failing.

Reply via email to