Tay*_*lor 1 c sse vectorization clang compiler-optimization
我有以下循环:
float* s;
float* ap;
float* bp;
... // initialize s, ap, bp
for(size_t i=0;i<64;++i) {
s[i] = ap[i]+bp[i];
}
Run Code Online (Sandbox Code Playgroud)
似乎是矢量化的良好候选者。尽管我打开了优化功能,但是当我查看程序集输出时,clang(我正在使用Xcode)似乎没有向量化循环:
LBB33_1: ## =>This Inner Loop Header: Depth=1
movss (%rax,%rsi,4), %xmm0 ## xmm0 = mem[0],zero,zero,zero
addss (%rcx,%rsi,4), %xmm0
movss %xmm0, (%rdx,%rsi,4)
Ltmp353:
incq %rsi
Ltmp354:
cmpq $64, %rsi
Ltmp355:
jne LBB33_1
Run Code Online (Sandbox Code Playgroud)
如何获得clang / Xcode来向量化此简单循环?
使用非古代版本的clang / LLVM。Apple clang / LLVM与主线clang / LLVM不同,但是它们共享一个通用的代码库。
主线clang3.3及更高版本会自动对循环进行矢量化-O3。 Clang3.4及更高版本甚至在处也会对其自动矢量化-O2。
没有restrict,clang 会发出asm来检查目标和两个源之间的重叠(带有标量的后备),因此您将从中获得更有效的asm float *restrict s。
#include <stdlib.h>
void add_float_good(float *restrict s, float *restrict ap, float *restrict bp)
{
for(size_t i=0;i<64;++i) {
s[i] = ap[i]+bp[i];
}
}
Run Code Online (Sandbox Code Playgroud)
编译与clang3.4 -O3(在Godbolt编译器浏览器)与最差的索引寻址模式和循环开销的这个简单的ASM,但至少它量化。较新的clang喜欢展开,尤其是在针对最近的Intel进行调整时(例如-march=skylake)
# clang3.4 -O3
add_float_good:
xor eax, eax
.LBB0_1: # %vector.body
movups xmm0, xmmword ptr [rsi + 4*rax]
movups xmm1, xmmword ptr [rdx + 4*rax]
addps xmm1, xmm0
movups xmmword ptr [rdi + 4*rax], xmm1
add rax, 4
cmp rax, 64
jne .LBB0_1
ret
Run Code Online (Sandbox Code Playgroud)
请注意,没有AVX,就不能使用内存源操作数,addps因为没有编译时对齐保证。
clang8.0 -O3 -march = skylake使用YMM向量完全展开,例如具有相同选项的gcc。