Bug 87680 - Small program produces 160 meg .o file
Summary: Small program produces 160 meg .o file
Status: RESOLVED DUPLICATE of bug 92385
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 8.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2018-10-22 01:43 UTC by Corey Kosak
Modified: 2022-01-07 00:46 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-10-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Corey Kosak 2018-10-22 01:43:46 UTC
This small program takes over a minute to compile and produces a 160 meg object file. sizeof(Bar) is large and it looks like the compiler wants to write down a precompiled version of it to the object file for the benefit of Bar's constructor. There are no static variables or anything like that so the object file really should be modest in size.

% cat test.cc
constexpr int size = 10000000;

class Foo {
  int a = 10;
  int b = 11;
  int c = 12;
  int d = 13;
};

class Bar {
  Foo foo[size];
};

void somefunc(const Bar *);

int main() {
  Bar *bar = new Bar();
  somefunc(bar);
}


% time g++ -O2 -c test.cc

real    1m9.696s
user    1m6.486s
sys     0m2.806s


% ls -l test.o
-rw-rw-r-- 1 kosak kosak 160001760 Oct 22 01:41 test.o
Comment 1 Richard Biener 2018-10-22 08:53:51 UTC
Confirmed.  I believe we have dups of this bug.
Comment 2 Jonathan Wakely 2018-10-22 09:04:14 UTC
Yes, there are dups. IIRC the problem is that every element of the array introduces a new try/finally block so that if one of the Foo objects throws an exception, all the earlier elements in the array get destroyed.

That shouldn't be needed here, because Foo can never throw on construction.
Comment 3 Jonathan Wakely 2018-10-22 09:06:51 UTC
PR 70277 is the one I was thinking of, and there's PR 55402 too.
Comment 4 Corey Kosak 2018-10-22 15:31:35 UTC
To my eye it doesn't seem to be related to exceptions or initializer lists, so I don't think it's the same bug, but you all would know better than me.

When I look at the .s file I see a giant sequence of the form

.LC0:
        .long   10
        .long   11
        .long   12
        .long   13
        .long   10
        .long   11
        .long   12
        .long   13
        .long   10
        .long   11
        .long   12
        .long   13
...

and then the constructor uses .LC0 to initialize the object with a single memcpy. Which might be a fine strategy for objects of reasonable size, but maybe there should be a size cutoff.
Comment 5 Richard Biener 2018-10-22 16:01:35 UTC
I believe this bug (and other existing dups) are about the C++ FE for array initializers not emitting a loop for initialization but an initializer for each element.  It does that via

;; Function constexpr Bar::Bar() (null)
;; enabled by -tree-original


{
  <<cleanup_point <<< Unknown tree: expr_stmt
  (void) (((struct Bar *) this)->foo = <<< Unknown tree: vec_init_expr
  D.2381
   >>>) >>>>>;
}

which eventually is gimplified to

Bar::Bar (struct Bar * const this)
{
  this->foo[0].a = 10;
  this->foo[0].b = 11;
  this->foo[0].c = 12;
  this->foo[0].d = 13;
  this->foo[1].a = 10;
  this->foo[1].b = 11;
...

via cp_gimplify_expr.
Comment 6 Andrew Pinski 2021-12-11 01:23:57 UTC
Also very similar to PR 92385.
Comment 7 Andrew Pinski 2022-01-07 00:46:28 UTC
Yes this is fixed after the patch which fixes PR 92385.
We get now:
.LC0:
        .long   10
        .long   11
        .long   12
        .long   13


  _3 = operator new (160000000);
  MEM[(struct Bar *)_3] = {};
  MEM <vector(4) int> [(int *)_3] = { 10, 11, 12, 13 };
  vectp.6_7 = _3 + 16;
  ivtmp.12_16 = (unsigned long) vectp.6_7;
  _9 = (unsigned long) _3;
  _13 = _9 + 160000000;

  <bb 3> [local count: 106300463076]:
  # ivtmp.12_18 = PHI <ivtmp.12_17(3), ivtmp.12_16(2)>
  _8 = (void *) ivtmp.12_18;
  MEM <vector(4) int> [(int *)_8] = { 10, 11, 12, 13 };
  ivtmp.12_17 = ivtmp.12_18 + 16;
  if (_13 == ivtmp.12_17)
    goto <bb 4>; [1.00%]
  else
    goto <bb 3>; [99.00%]

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