I have a complex program which uses std::array<double, N>
for small values of N. It uses operator[]
to get values from these arrays.
I have discovered that GCC 6.1 with -O2
or -O3
does not inline these calls, leading to these C++ arrays being slower than their C equivalents.
Here's the generated assembly:
340 <std::array<double, 8ul>::operator[](unsigned long) const>:
340: 48 8d 04 f7 lea (%rdi,%rsi,8),%rax
344: c3 retq
345: 90 nop
346: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
34d: 00 00 00
The very same code is emitted for each size of array (since there is no bounds checking).
A loop over such an array looks like this:
4c0: e8 7b fe ff ff callq 340 <std::array<double, 8ul>::operator[](unsigned long) const>
4c5: be 07 00 00 00 mov $0x7,%esi
4ca: 4c 89 f7 mov %r14,%rdi
4cd: 48 89 44 24 78 mov %rax,0x78(%rsp)
...6 more copies of this...
4d2: e8 69 fe ff ff callq 340 <std::array<double, 8ul>::operator[](unsigned long) const>
4d7: 48 89 44 24 70 mov %rax,0x70(%rsp)
4dc: 31 f6 xor %esi,%esi
4de: 4c 89 ef mov %r13,%rdi
This seems obviously bad. The problem is that small test programs don't elicit this behavior.
So my question is: how can I get GCC to tell me why it isn't inlining these one-instruction calls, and/or make it inline them? Obviously I can't modify the <array>
header file to add __attribute__((inline))
.
There appears to be a bug in the optimizer of GCC 5 and 6 which manifests when using __attribute__(("unroll-loops"))
in combination with -ffast-math
or related options.
You can see it in action here: https://godbolt.org/g/ZBGCDB
This code reproduces the error if you compile with -O3 -ffast-math
:
#include <array>
typedef std::array<double, 2> Array;
void foo(Array& a) __attribute__((optimize("unroll-loops")));
void foo(Array& a)
{
for (size_t ii = 0; ii < a.size(); ++ii)
a[ii] = 1.0;
}
It works as expected without -ffast-math
, or if compiled with GCC 4.9, GCC 7 or later, or Clang.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With