我怎样才能让clang向量化一个简单的循环?

时间:2019-04-06 02:05:44

标签: c clang vectorization compiler-optimization sse

我有以下循环:

float* s;
float* ap;
float* bp;

... // initialize s, ap, bp

for(size_t i=0;i<64;++i) {
   s[i] = ap[i]+bp[i];
}

似乎是矢量化的良好候选者。尽管我已经打开了优化功能,但是当我查看程序集输出时,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

如何获取clang / Xcode来向量化此简单循环?

2 个答案:

答案 0 :(得分:6)

使用非古代版本的clang / LLVM 。 Apple clang / LLVM与主线clang / LLVM不同,但是它们共享一个通用的代码库。

主线clang3.3及更高版本在-O3自动对循环进行矢量化处理。 Clang3.4及更高版本自动将其矢量化,即使在-O2

在没有restrict的情况下,clang 确实发出asm来检查目标和两个源之间的重叠(回退到标量),因此您将从{ {1}}。

float *restrict s

使用最差的索引寻址模式和循环开销将https://dev.mysql.com/doc/refman/5.7/en/using-explain.html编译为这种简单的asm,但至少将其向量化。较新的clang喜欢展开,尤其是在针对最近的Intel(例如#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]; } } )进行调整时

-march=skylake

请注意,如果没有AVX,就无法为# 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 使用内存源操作数,因为没有编译时对齐保证。

clang8.0 -O3 -march = skylake使用YMM向量完全展开,例如具有相同选项的gcc。

答案 1 :(得分:0)

最好使用Accelerate对此进行明确说明。在这种情况下,vDSP_vadd将解决问题。