在查看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)

前两个值显然是永远不会读取,因此不应计算它们。但是,似乎不是这样,因为如果删除这些行,测试将失败。

最佳答案

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 wikithe 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。直到Zen 2,Ryzen才正式支持这两种方法。IntelCPU仅支持FMA3。
Ryzen Zen1 / Zen +芯片显然可以正确解码并执行FMA4指令,但不会在CPUID中报告FMA4支持。 (有one sketchy report of incorrect FMA4 results, but nobody else reproduced it。似乎只是根据该报告散发的FUD谣言,可能是软件错误而不是芯片问题。)
但是, Zen 2不支持FMA4 ;非法指令(#UD)异常。

10-06 05:49