为什么这个C包装器类没有被内联?

编辑 – 我的构建系统的一些东西.我还在弄清楚究竟是什么,但是gcc产生了奇怪的结果(即使它是一个.cpp文件),但是一旦我使用了g,它就会按预期工作.

这是一个非常简化的测试用例,我遇到了一些麻烦,使用数字包装类(我认为会被内联)使我的程序慢了10倍.

这与优化级别无关(尝试使用-O0和-O3).

我在包装类中遗漏了一些细节吗?

C

我有以下程序,其中我定义了一个包装double并提供运算符的类:

#include <cstdio>
#include <cstdlib>

#define INLINE __attribute__((always_inline)) inline

struct alignas(8) WrappedDouble {
    double value;

    INLINE friend const WrappedDouble operator+(const WrappedDouble& left, const WrappedDouble& right) {
        return {left.value + right.value};
    };
};

#define doubleType WrappedDouble // either "double" or "WrappedDouble"

int main() {
    int N = 100000000;
    doubleType* arr = (doubleType*)malloc(sizeof(doubleType)*N);
    for (int i = 1; i < N; i++) {
        arr[i] = arr[i - 1] + arr[i];
    }

    free(arr);
    printf("done\n");

    return 0;
}

我认为这会编译成同样的东西 – 它正在进行相同的计算,并且所有内容都是内联的.

但是,它不是 – 无论优化级别如何,它都会产生更大更慢的结果.

(这个特殊的结果并没有明显变慢,但我的实际用例包括更多的算法.)

编辑 – 我知道这不是构建我的数组元素.我认为这可能会产生更少的ASM,所以我可以更好地理解它,但如果这是一个问题,我可以改变它.

编辑 – 我也知道我应该使用new [] / delete [].不幸的是,gcc拒绝编译,即使它是在.cpp文件中.这是我的构建系统被搞砸的症状,这可能是我的实际问题.

编辑 – 如果我使用g而不是gcc,它会产生相同的输出.

编辑 – 我发布了错误版本的ASM(-O0而不是-O3),所以本节没有帮助.

部件

我在我的Mac上使用XCode的gcc,在64位系统上.结果是相同的,除了for循环的主体.

如果doubleType为double,则它为循环体生成的内容:

movq    -16(%rbp), %rax
movl    -20(%rbp), %ecx
subl    $1, %ecx
movslq  %ecx, %rdx
movsd   (%rax,%rdx,8), %xmm0    ## xmm0 = mem[0],zero
movq    -16(%rbp), %rax
movslq  -20(%rbp), %rdx
addsd   (%rax,%rdx,8), %xmm0
movq    -16(%rbp), %rax
movslq  -20(%rbp), %rdx
movsd   %xmm0, (%rax,%rdx,8)

WrappedDouble版本更长:

movq    -40(%rbp), %rax
movl    -44(%rbp), %ecx
subl    $1, %ecx
movslq  %ecx, %rdx
shlq    $3, %rdx
addq    %rdx, %rax
movq    -40(%rbp), %rdx
movslq  -44(%rbp), %rsi
shlq    $3, %rsi
addq    %rsi, %rdx
movq    %rax, -16(%rbp)
movq    %rdx, -24(%rbp)
movq    -16(%rbp), %rax
movsd   (%rax), %xmm0           ## xmm0 = mem[0],zero
movq    -24(%rbp), %rax
addsd   (%rax), %xmm0
movsd   %xmm0, -8(%rbp)
movsd   -8(%rbp), %xmm0         ## xmm0 = mem[0],zero
movsd   %xmm0, -56(%rbp)
movq    -40(%rbp), %rax
movslq  -44(%rbp), %rdx
movq    -56(%rbp), %rsi
movq    %rsi, (%rax,%rdx,8)

解决方法:

当您使用-O3打开优化时,两个版本都会产生与g和clang相同的汇编代码.

上一篇:javascript – 如何将html解析为React组件?


下一篇:将PHP编译成独立的可执行文件(更快?)