Bug 71165 - std::array with aggregate initialization generates huge code
Summary: std::array with aggregate initialization generates huge code
Status: RESOLVED DUPLICATE of bug 92385
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.3.1
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: compile-time-hog, missed-optimization
Depends on:
Blocks:
 
Reported: 2016-05-17 16:22 UTC by isa
Modified: 2021-11-25 23:53 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-07-10 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description isa 2016-05-17 16:22:19 UTC
[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.
Comment 1 Andrew Pinski 2016-07-10 20:18:11 UTC
Confirmed, I had saw another bug like this before ...
Comment 2 Andrew Pinski 2016-07-10 20:18:28 UTC
.
Comment 3 Aleksey Covacevice 2016-07-29 19:09:05 UTC
I also confirm this. Also present in 5.4.0 and 6.1.0 (at least).

The following test case contains 3 scenarios, each one originated from uncommenting the respective line in main():

    #include <iostream>

    using namespace std;

    struct X {
    	X() { cerr << __func__ << endl; }
	~X() { cerr << __func__ << endl; }
    };

    template<typename Type>
    struct Object1 { Type Value; };

    template<typename Type>
    struct Object2 { Type Value{}; };

    int main() {
    	//X object[0x1000];           // (1)
    	//Object1<X[0x1000]> object;  // (2)
    	//Object2<X[0x1000]> object;  // (3)
    }

Scenarios (1) and (2) produce roughly the same executable, in either -O0 and -Ofast. Scenario (3) takes an enormous time to compile, produces a much larger executable, -Winline complains about not being able to inline things and, on occasion, cc1plus crashes (specially if you raise the size of the arrays involved).

Output (for scenario 3):
    Test.c++: In function 'int main()':
    Test.c++:14:8: warning: inlining failed in call to 'constexpr Object2<X [4096]>::Object2() noexcept (false)': --param large-function-growth limit reached [-Winline]
     struct Object2 { Type Value{}; };
        ^
    Test.c++:19:21: warning: called from here [-Winline]
      Object2<X[0x1000]> object;  // (3)
Comment 4 Andrew Pinski 2021-11-25 23:53:06 UTC
Dup of bug 92385.

*** This bug has been marked as a duplicate of bug 92385 ***