我试图找出一种有效的方法将编译时常量浮点数加载到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)
理想情况下,如果我有常量它们将是一种不甚至触摸内存的方式并且只是使用直接样式指令(例如编译到指令本身的常量).
谢谢
如果你想强制它加载一个,你可以尝试(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)