为什么gcc只用_mm_set_ss添加这个movss指令?

orl*_*rlp 5 c optimization sse compiler-optimization

使用SSE考虑这两个函数:

#include <xmmintrin.h>

int ftrunc1(float f) {
    return _mm_cvttss_si32(_mm_set1_ps(f));
}

int ftrunc2(float f) {
    return _mm_cvttss_si32(_mm_set_ss(f));
}
Run Code Online (Sandbox Code Playgroud)

对于任何输入,两者的行为完全相同.但是汇编器输出是不同的:

ftrunc1:
    pushl   %ebp
    movl    %esp, %ebp
    cvttss2si   8(%ebp), %eax
    leave
    ret

ftrunc2:
    pushl   %ebp
    movl    %esp, %ebp
    movss   8(%ebp), %xmm0
    cvttss2si   %xmm0, %eax
    leave
    ret
Run Code Online (Sandbox Code Playgroud)

也就是说,额外ftrunc2使用一条movss指令!

这是正常的吗?有关系吗?当你只需要设置底部元素时,应该_mm_set1_ps总是优先考虑_mm_set_ss吗?


使用的编译器是GCC 4.5.2 -O3 -msse.

Mys*_*ial 5

_mm_set_ss直接映射到汇编指令(movss).但_mm_set1_ps事实并非如此.

从我在GCC,MSVC和ICC上看到的:

将一对一映射到汇编指令的SSE内在函数通常被视为"原样" - 黑盒子.因此编译器只会优化适用于整个指令本身.但它不会尝试进行任何需要对各个向量元素进行数据流/依赖性分析的优化.

_mm_set1_ps_mm_set_ps内在不映射到一个单一的指令,并有特殊的情况下,由大多数编译器处理.从我所看到的,我上面列出的所有三个编译器尝试对各个元素执行数据流分析优化.


当你把它们放在一起时,第二个例子就离开了,movss因为编译器没有意识到前三个元素并不重要.(它没有试图"打开" _mm_set_ss内在的东西.)