GCC有时不会内联std :: array :: operator []

Joh*_*nck 5 c++ optimization gcc inline c++11

我有一个复杂的程序,std::array<double, N>它使用N的小值.它用于operator[]从这些数组中获取值.

我发现GCC 6.1有-O2-O3没有内联这些调用,导致这些C++数组比它们的C等价物慢.

这是生成的程序集:

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 
Run Code Online (Sandbox Code Playgroud)

为每个大小的数组发出相同的代码(因为没有边界检查).

这样一个数组的循环如下所示:

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
Run Code Online (Sandbox Code Playgroud)

这看起来很糟糕.问题是小型测试程序不会引发这种行为.

所以我的问题是:如何让GCC告诉我为什么它没有内联这些单指令调用,和/或让它内联它们?显然我无法修改<array>要添加的头文件__attribute__((inline)).

Joh*_*nck 2

GCC 5 和 6 的优化器中似乎存在一个错误,该错误在与相关选项__attribute__(("unroll-loops"))结合使用时会显现出来。-ffast-math

您可以在这里看到它的实际效果:https ://godbolt.org/g/ZBGCDB

如果您使用以下代码进行编译,则此代码会重现错误-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;
}
Run Code Online (Sandbox Code Playgroud)

-ffast-math如果没有,或者使用 GCC 4.9、GCC 7 或更高版本或 Clang 编译,它可以按预期工作。