在查看此代码时,我注意到以下四个说明:
vmulpd %ymm1,%ymm3,%ymm4 /* aim*bim */
vmulpd %ymm0,%ymm3,%ymm6 /* are*bim */
vfmadd231pd %ymm2,%ymm1,%ymm6
vfmsub231pd %ymm0,%ymm2,%ymm4
现在,如果您在att& 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)中的哪个是读取的write write目标。操作数,哪一个可以是内存操作数。请参阅vfmadd231pd
/132PD
/213PD
的文档以查看哪些输入乘以乘以"累加器"。在您的代码中。(我永远无法将编号方案保持在我的脑海中:这是一种具有内在编写要容易得多的情况。但是目的地仍然始终持久。)
请注意,英特尔文档使用Intel语法dst, src1, src2, ...
。扭转以获取AT& t语法的操作数列表,例如..., src2, src1, dst
。请参阅AT& t-syntax tag wiki,以及Intel-Syntax标签Wiki。
顺便说一句,有一个FMA4 ISA扩展,其中FMA指令有3个输入和A 单独的输出。请参阅https://en.wikipedia.org/wiki/fma_instruction_set。
Intel最初是要实施FMA4,但随后更改为当前的FMA3(出于反竞争的原因,直到尽可能迟到了AMD:请参阅Agner Fog的博客文章停止指令SET SET WAR)。对于AMD推土机来说,更改为时已晚,因此推土机只支持FMA4。PITRIVER支持FMA3和FMA4。直到Zen2。
ryzen Zen1/Zen 芯片显然可以正确解码并执行FMA4指令,但不要在CPUID中报告FMA4支持。(有一份粗略的FMA4结果报告,但没有其他重现它。似乎只是根据该报告发行的FUD谣言,可能是软件错误而不是芯片问题。)
但是, Zen 2 di 不支持支持fma4 ;非法指令(#UD
)例外。