作为自我教育项目的一部分,我研究了g ++如何处理std::complex
- 类型,并对这个简单的函数感到困惑:
#include <complex>
std::complex<double> c;
void get(std::complex<double> &res){
res=c;
}
使用g++-6.3 -O3
(或-Os
)为Linux64编译,我得到了以下结果:
movsd c(%rip), %xmm0
movsd %xmm0, (%rdi)
movsd c+8(%rip), %xmm0
movsd %xmm0, 8(%rdi)
ret
因此它将实部和虚部单独移动为64位浮点数。但是,我希望程序集使用两个movups
而不是四个movsd
,即将实部和虚部同时移动为128位包:
movups c(%rip), %xmm0
movups %xmm0, (%rdi)
ret
这不仅是我的机器(Intel Broadwell)的两倍,而是movsd
- 版本,但只需要16个字节,而movsd
- 版本需要36个字节。
g ++使用movsd
创建程序集的原因是什么?
movups
的使用,我应该在-O3
旁边使用?movups
我不知道?更多上下文:我尝试比较两种可能的函数签名:
std::complex<double> get(){
return c;
}
和
void get(std::complex<double> &res){
res=c;
}
由于SystemV ABI,第一个版本必须将实部和虚部放入不同的寄存器(xmm0
和xmm1
)。但是对于第二个版本,人们可以尝试利用SSE操作的一些优点,这些优势可以在128位上运行,但是它不适用于我的g ++版本。
编辑:正如肯尼特的回答所暗示的那样,g ++似乎产生了非最佳装配。它总是使用4个movsd将std :: complex从一个内存位置复制到另一个内存位置,例如在
中void get(std::complex<double> *res){
res[1]=res[0];
}
现在有一个bug-report提交给gcc-bugzilla ..
答案 0 :(得分:2)
clang
和icc
都只使用一个SSE寄存器。您可以在https://godbolt.org/g/55lPv0中查看已编译的代码。
get(std::complex<double>&):
movups c(%rip), %xmm0
movups %xmm0, (%rdi)
ret