为什么这段代码使用VMULPD写入将被VFMADD覆盖的寄存器?这没用吗?

时间:2017-12-10 13:43:02

标签: assembly avx

在审核this段代码时,我注意到以下四条说明:

vmulpd  %ymm1,%ymm3,%ymm4 /* aim*bim */
vmulpd  %ymm0,%ymm3,%ymm6 /* are*bim */
vfmadd231pd %ymm2,%ymm1,%ymm6
vfmsub231pd %ymm0,%ymm2,%ymm4

现在,如果您在AT& T表示法中考虑到这些说明的格式为operator source,source,destination,那么第一条指令是否无效?

%ymm4 = f(%ymm1, %ymm3)
%ymm6 = f(%ymm0, %ymm3)
%ymm6 = f(%ymm2, %ymm1)
%ymm4 = f(%ymm0, %ymm2)

前两个值显然从未读过,因此不应计算它们。但是,似乎情况并非如此,因为如果删除这些行,测试将失败。

1 个答案:

答案 0 :(得分:5)

FMA是3输入指令,计算a * b + c;目标是读写操作数(与SSE2 mulpd %xmm0, %xmm1一样)。

FMADD / FMSUB / FNMADD / FNMSUB(甚至FMADDSUB / FMSUBADD)指令分别以3个操作数顺序排列,以便您选择3个操作数(a,b或c)中的哪一个是读写目的地操作数,以及哪一个可以是内存操作数。请参阅the docs for vfmadd231pd/ 132PD / 213PD以查看哪些输入相乘,哪些是代码中的“累加器”。 (我永远无法将编号方案直接保留在我的脑海中:这是一种使用内在函数编写更容易的情况。但目标仍然是最后的。)

请注意,英特尔文档使用英特尔语法dst, src1, src2, ...。反转操作数列表以获得AT& T语法,例如, ..., src2, src1, dst。请参阅the at&t-syntax tag wiki以及the intel-syntax tag wiki

顺便说一句,有一个FMA4 ISA扩展,其中FMA指令有3个输入和单独的输出。请参阅https://en.wikipedia.org/wiki/FMA_instruction_set

英特尔原本打算实施FMA4,但随后改为目前的FMA3(由于反竞争原因,直到尽可能晚地告诉AMD:参见Agner Fog的博文Stop the instruction set war)。对于AMD Bulldozer来说,改变为时已晚,所以Bulldozer只支持FMA4。打桩机支持FMA3和FMA4。 Ryzen只支持FMA3。英特尔CPU只支持FMA3。

目前Ryzen芯片显然正确解码并执行FMA4指令,但不报告CPUID中的FMA4支持。 (有one sketchy report of incorrect FMA4 results, but nobody else reproduced it。)不过,我建议不要在Ryzen上使用不受支持的FMA4指令。