EOF*_*EOF 6 gcc simd compiler-optimization avx2
我最近制作了一些矢量代码和一个合适的Godbolt 示例。
typedef float v8f __attribute__((vector_size(32)));
typedef unsigned v8u __attribute__((vector_size(32)));
v8f f(register v8f x)
{
return __builtin_shuffle(x, (v8f){0}, (v8u){1, 2, 3, 4, 5, 6, 7, 8});
}
Run Code Online (Sandbox Code Playgroud)
f:
vmovaps ymm1, ymm0
vxorps xmm0, xmm0, xmm0
vperm2f128 ymm0, ymm1, ymm0, 33
vpalignr ymm0, ymm0, ymm1, 4
ret
Run Code Online (Sandbox Code Playgroud)
我想看看不同的优化 ( -O0/O1/O2/O3
) 设置如何影响代码,并且几乎都-O0
给出了相同的代码。-O0
给出了可预测的帧指针垃圾,并且x
无缘无故地将参数复制到堆栈局部变量。为了解决这个问题,我添加了register
存储类说明符:
typedef float v8f __attribute__((vector_size(32)));
typedef unsigned v8u __attribute__((vector_size(32)));
v8f f(register v8f x)
{
return __builtin_shuffle(x, (v8f){0}, (v8u){1, 2, 3, 4, 5, 6, 7, 8});
}
Run Code Online (Sandbox Code Playgroud)
对于-O1/O2/O3
,生成的代码是相同的,但在-O0
:
f:
vxorps xmm1, xmm1, xmm1
vperm2f128 ymm1, ymm0, ymm1, 33
vpalignr ymm0, ymm1, ymm0, 4
ret
Run Code Online (Sandbox Code Playgroud)
gcc
想出如何避免冗余寄存器副本。虽然这样的副本可能会被移动消除,但这仍然会增加代码大小而没有任何好处(-Os
大于-O0
?)。
如何/为什么gcc
产生在这个更好的代码-O0
比-O3
?