d生成优化simd寄存器赋值
import core.simd;
double2 set0(double2 x, double* a)
{
x[0] = *a;
return x;
}
double2 set1(double2 x, double* a)
{
x[1] = *a;
return x;
}
GDC生成以下优化代码:
set0:
movlpd xmm0, QWORD PTR [rdi]
ret
set1:
movhpd xmm0, QWORD PTR [rdi]
ret
但DMD -O仍然会在栈内存中跑:
assume CS:.text.set1
push RBP
mov RBP,RSP
sub RSP,010h
movapd -010h[RBP],XMM0
movsd XMM1,[RDI]
movsd -8[RBP],XMM1
movapd XMM0,-010h[RBP]
mov RSP,RBP
pop RBP
ret
在dmd.backend.cod1.getlvalue中,因为后端未生成正确的赋值指令,向量变量不能放在寄存器中.如,对x[0] = *a,它会使用清除XMM0寄存器的高64位并意外设置'x[1]=0'的movsd.
修复此问题后,可允许把向量变量再次放入寄存器来改进生成SIMD代码.
double2 _mm_loadl_pd(double2 a, const(double)* mem_addr)
{
a[0] = *mem_addr;
return a;
}
函数,用-O生成
movsd XMM0,[RDI]
movapd XMM0,XMM0
movsd文档说:
源操作数是内存位置,目的操作数是XMM寄存器时,清理目的操作数的127:64位为0.
这无意中设置了a[1]=0,导致了该问题.我想知道赋值给a[1]时,dmd会生成哪个指令,而结果是,只要e.EV.Voffset > 0,它就会不把变量放入寄存器,而是回退至放入栈中,所以该补丁对向量类型变量都这样.
dmd除了分析数据流,我不相信优化.
我同意,一开始想找出优化/指令生成位置,发现
a[0] = *mem_addr;
重写为用TYdouble类型赋值,但仅此而已.(后端代码很难导航.)
我第一次天真地尝试添加MOVMSKPS导致非法指令,因为该指令不允许内存位置作为后端生成的操作数.
浙公网安备 33010602011771号