将常量浮点载入SSE寄存器

cod*_*ave 11 assembly sse

我试图找出一种有效的方法将编译时常量浮点数加载到SSE(2/3)寄存器中.我试过做这样简单的代码,

const __m128 x = { 1.0f, 2.0f, 3.0f, 4.0f }; 
Run Code Online (Sandbox Code Playgroud)

但是这会从内存中生成4个movss指令!

movss       xmm0,dword ptr [__real@3f800000 (14048E534h)] 
movss       xmm1,dword ptr [__real@40000000 (14048E530h)] 
movaps      xmm6,xmm12 
shufps      xmm6,xmm12,0C6h 
movss       dword ptr [rsp],xmm0 
movss       xmm0,dword ptr [__real@40400000 (14048E52Ch)] 
movss       dword ptr [rsp+4],xmm1 
movss       xmm1,dword ptr [__real@40a00000 (14048E528h)] 
Run Code Online (Sandbox Code Playgroud)

它将标量加载到内存中......(?!?!)

这样做虽然..

float Align(16) myfloat4[4] = { 1.0f, 2.0f, 3.0f, 4.0f, }; // out in global scope
Run Code Online (Sandbox Code Playgroud)

产生.

movaps      xmm5,xmmword ptr [::myarray4 (140512050h)]
Run Code Online (Sandbox Code Playgroud)

理想情况下,如果我有常量它们将是一种不甚至触摸内存的方式并且只是使用直接样式指令(例如编译到指令本身的常量).

谢谢

Fra*_*kH. 6

如果你想强制它加载一个,你可以尝试(gcc):

__attribute__((aligned(16))) float vec[4] = { 1.0f, 1.1f, 1.2f, 1.3f };
__m128 v = _mm_load_ps(vec); // edit by sor: removed the "&" cause its already an address
Run Code Online (Sandbox Code Playgroud)

如果您有Visual C++,请使用__declspec(align(16))请求适当的约束.

在我的系统上,这个(编译为gcc -m32 -msse -O2;没有优化使代码混乱,但仍保留movaps最终的单个)创建以下汇编代码(gcc/AT&T语法):

    andl    $-16, %esp
    subl    $16, %esp
    movl    $0x3f800000, (%esp)
    movl    $0x3f8ccccd, 4(%esp)
    movl    $0x3f99999a, 8(%esp)
    movl    $0x3fa66666, 12(%esp)
    movaps  (%esp), %xmm0
Run Code Online (Sandbox Code Playgroud)

请注意,它在分配堆栈空间并将常量放入其中之前对齐堆栈指针.__attribute__((aligned))根据您的编译器,离开可能会创建不正确的代码而不执行此操作,因此请注意,并检查反汇编.

另外:
由于您一直在询问如何将常量放入代码中,只需使用数组的static限定符来尝试上面的内容float.这会创建以下程序集:

    movaps  vec.7330, %xmm0
    ...
vec.7330:
    .long   1065353216
    .long   1066192077
    .long   1067030938
    .long   1067869798
Run Code Online (Sandbox Code Playgroud)