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

Giu*_*llo 3 assembly avx

在查看这段代码时,我注意到以下四条说明:

vmulpd  %ymm1,%ymm3,%ymm4 /* aim*bim */
vmulpd  %ymm0,%ymm3,%ymm6 /* are*bim */
vfmadd231pd %ymm2,%ymm1,%ymm6
vfmsub231pd %ymm0,%ymm2,%ymm4
Run Code Online (Sandbox Code Playgroud)

现在,如果你认为在AT&T表示法中的说明是形式的operator source,source,destination,那么第一条指令是否无用?

%ymm4 = f(%ymm1, %ymm3)
%ymm6 = f(%ymm0, %ymm3)
%ymm6 = f(%ymm2, %ymm1)
%ymm4 = f(%ymm0, %ymm2)
Run Code Online (Sandbox Code Playgroud)

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

Pet*_*des 5

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

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

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


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

英特尔原本打算实施FMA4,但之后改为目前的FMA3(由于反竞争的原因,直到尽可能晚地告诉AMD:参见Agner Fog的博客文章停止指令集战争).对于AMD Bulldozer来说,改变为时已晚,所以Bulldozer只支持FMA4.打桩机支持FMA3和FMA4.Ryzen只支持FMA3.英特尔CPU只支持FMA3.

目前Ryzen芯片显然正确地解码和执行FMA4指令,但是不报告CPUID中的FMA4支持.(有一个关于错误的FMA4结果的​​粗略报告,但没有其他人再现它.)不过,我建议不要在Ryzen上使用不受支持的FMA4指令.