我正在尝试使用SSE或新的AVX指令为Windows x64目标编写一些计算量大的代码,并在GCC 4.5.2和4.6.1,MinGW64(TDM GCC构建和一些自定义构建)中进行编译。我的编译器选项是-O3 -mavx
。 (暗含-m64
)
简而言之,我想对打包浮点数的4个3D向量进行一些冗长的计算。这需要4x3 = 12 xmm或ymm寄存器进行存储,并需要2或3个寄存器来获得临时结果。 IMHO应该恰好适合16位可用于64位目标的SSE(或AVX)寄存器。但是,GCC仅使用寄存器xmm0-xmm10
以及将数据从堆栈中移出堆栈,就产生了寄存器溢出的非常不理想的代码。我的问题是:
是否有办法说服GCC使用所有寄存器xmm0-xmm15
?
要修正想法,请考虑以下SSE代码(仅用于说明):
void example(vect<__m128> q1, vect<__m128> q2, vect<__m128>& a1, vect<__m128>& a2) {
for (int i=0; i < 10; i++) {
vect<__m128> v = q2 - q1;
a1 += v;
// a2 -= v;
q2 *= _mm_set1_ps(2.);
}
}
这里
vect<__m128>
只是3 struct
的__m128
,具有自然的加法和标量乘法。当a2 -= v
行被注释掉时,即我们只需要3x3寄存器来存储,因为我们忽略了a2
,因此生成的代码确实很简单,没有任何 Action ,所有操作都在寄存器xmm0-xmm10
中执行。当我删除注释a2 -= v
时,代码非常糟糕,寄存器和堆栈之间经过大量改组。即使编译器可以只使用寄存器xmm11-xmm13
之类的东西。我实际上还没有看到GCC在我所有代码中的任何地方都使用
xmm11-xmm15
寄存器。我究竟做错了什么?我知道它们是被调用者保存的寄存器,但是通过简化循环代码可以完全证明这种开销。
最佳答案
两点:
因此,如果您想更好地分配寄存器,则基本上有两个选择:
关于gcc - 如何强制gcc使用所有SSE(或AVX)寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5960707/