为什么这个SSE2程序(整数)生成movaps(float)?

时间:2017-02-15 13:02:39

标签: gcc assembly x86 sse simd

以下循环将整数矩阵转置为另一个整数矩阵。当我有趣地编译时,它会生成movaps指令以将结果存储到输出矩阵中。为什么gcc这样做?

数据:

int __attribute__(( aligned(16))) t[N][M]  
  , __attribute__(( aligned(16))) c_tra[N][M];

循环:

for( i=0; i<N; i+=4){
    for(j=0; j<M; j+=4){

        row0 = _mm_load_si128((__m128i *)&t[i][j]);
        row1 = _mm_load_si128((__m128i *)&t[i+1][j]);
        row2 = _mm_load_si128((__m128i *)&t[i+2][j]);
        row3 = _mm_load_si128((__m128i *)&t[i+3][j]);

        __t0 = _mm_unpacklo_epi32(row0, row1);
        __t1 = _mm_unpacklo_epi32(row2, row3);
        __t2 = _mm_unpackhi_epi32(row0, row1);
        __t3 = _mm_unpackhi_epi32(row2, row3);

        /* values back into I[0-3] */
        row0 = _mm_unpacklo_epi64(__t0, __t1);
        row1 = _mm_unpackhi_epi64(__t0, __t1);
        row2 = _mm_unpacklo_epi64(__t2, __t3);
        row3 = _mm_unpackhi_epi64(__t2, __t3);

        _mm_store_si128((__m128i *)&c_tra[j][i], row0);
        _mm_store_si128((__m128i *)&c_tra[j+1][i], row1);
        _mm_store_si128((__m128i *)&c_tra[j+2][i], row2);
        _mm_store_si128((__m128i *)&c_tra[j+3][i], row3);



    }
}

汇编生成的代码:

.L39:
    lea rcx, [rsi+rdx]
    movdqa  xmm1, XMMWORD PTR [rdx]
    add rdx, 16
    add rax, 2048
    movdqa  xmm6, XMMWORD PTR [rcx+rdi]
    movdqa  xmm3, xmm1
    movdqa  xmm2, XMMWORD PTR [rcx+r9]
    punpckldq   xmm3, xmm6
    movdqa  xmm5, XMMWORD PTR [rcx+r10]
    movdqa  xmm4, xmm2
    punpckhdq   xmm1, xmm6
    punpckldq   xmm4, xmm5
    punpckhdq   xmm2, xmm5
    movdqa  xmm5, xmm3
    punpckhqdq  xmm3, xmm4
    punpcklqdq  xmm5, xmm4
    movdqa  xmm4, xmm1
    punpckhqdq  xmm1, xmm2
    punpcklqdq  xmm4, xmm2
    movaps  XMMWORD PTR [rax-2048], xmm5
    movaps  XMMWORD PTR [rax-1536], xmm3
    movaps  XMMWORD PTR [rax-1024], xmm4
    movaps  XMMWORD PTR [rax-512], xmm1
    cmp r11, rdx
    jne .L39

gcc -Wall -msse4.2 -masm="intel" -O2 -c -S skylake linuxmint

-mavx2-march=naticve生成VEX编码:vmovaps

1 个答案:

答案 0 :(得分:6)

功能上这些说明是相同的。 我不想复制+粘贴其他人的陈述,因为很少有链接解释它:

Difference between MOVDQA and MOVAPS x86 instructions?

https://software.intel.com/en-us/forums/intel-isa-extensions/topic/279587

http://masm32.com/board/index.php?topic=1138.0

https://www.gamedev.net/blog/615/entry-2250281-demystifying-sse-move-instructions/

简短版本:

  

因此,在大多数情况下,您应该尝试使用移动指令   对应于您将要使用的操作   寄存器。但是,还有一个复杂的问题。负荷和   存储器与内存之间的存储在与整数不同的端口上执行   和浮点单位;因此指令从内存加载到   从寄存器到存储器的寄存器或存储器将经历   无论您附加到移动的数据类型如何,都会有相同的延迟。的因此   在这种情况下,movaps,movapd和movdqa将具有相同的延迟否   无论你使用什么数据。因为movaps(和movups)是编码的   二进制形式比其他两个字节少一个字节,这是有意义的   无论数据类型如何,都将它用于所有reg-mem移动。

所以这是GCC优化。