为什么Visual Studio在解除引用之前递增循环指针?

jap*_*iss 7 c++ assembly code-generation pipelining visual-studio-2012

我从以下SIMD代码中检出了Visual Studio 2012的程序集输出:

    float *end = arr + sz;
    float *b = other.arr;
    for (float *a = arr; a < end; a += 4, b += 4)
    {
        __m128 ax = _mm_load_ps(a);
        __m128 bx = _mm_load_ps(b);
        ax = _mm_add_ps(ax, bx);
        _mm_store_ps(a, ax);
    }
Run Code Online (Sandbox Code Playgroud)

循环体是:

$LL11@main:
    movaps  xmm1, XMMWORD PTR [eax+ecx]
    addps   xmm1, XMMWORD PTR [ecx]
    add ecx, 16                 ; 00000010H
    movaps  XMMWORD PTR [ecx-16], xmm1
    cmp ecx, edx
    jb  SHORT $LL11@main
Run Code Online (Sandbox Code Playgroud)

为什么增加ecx16,只有当存储到下一行时减去16?

Igo*_*sky 7

嗯,这里基本上有两种选择.

 add ecx, 16
 movaps XMMWORD PTR [ecx-16], xmm1 ; stall for ecx?
 cmp ecx, edx
 jb loop
Run Code Online (Sandbox Code Playgroud)

要么

 movaps XMMWORD PTR [ecx], xmm1
 add ecx, 16
 cmp ecx, edx ; stall for ecx?
 jb loop
Run Code Online (Sandbox Code Playgroud)

在选项1中,你add和之间有一个潜在的失速movaps.在选项2中,你add和之间有一个潜在的失速cmp.但是,还存在使用执行单元的问题.addcmp(= sub)使用ALU,而我[ecx-16]使用AGU(地址生成单元),我相信.因此我怀疑选项1中可能会略微获胜,因为ALU使用与AGU使用交错.