FMA(融合乘法 - 加法)指令总是产生与mul相同的结果然后添加指令吗?

Dar*_*ryl 9 floating-point x86 assembly fma

我有这个程序集(AT&T语法):

mulsd   %xmm0, %xmm1
addsd   %xmm1, %xmm2
Run Code Online (Sandbox Code Playgroud)

我想用以下代替:

vfmadd231sd %xmm0, %xmm1, %xmm2
Run Code Online (Sandbox Code Playgroud)

这种转换是否会在所有涉及的寄存器和标志中保持等效状态?或者结果浮点数会有些不同吗?(如果它们不同,为什么会这样?)

(关于FMA说明:http://en.wikipedia.org/wiki/FMA_instruction_set)

Ste*_*non 16

实际上,融合乘法 - 加法的一个主要好处是它(不一定)产生与单独乘法和加法相同的结果.

作为一个(有点人为的)例子,假设我们有:

double a = 1 + 0x1.0p-52 // 1 + 2**-52
double b = 1 - 0x1.0p-52 // 1 - 2**-52
Run Code Online (Sandbox Code Playgroud)

我们想要计算a*b - 1."数学上精确"的值a*b - 1是:

(1 + 2**-52)(1 - 2**-52) - 1 = 1 + 2**-52 - 2**52 - 2**-104 - 1 = -2**-104
Run Code Online (Sandbox Code Playgroud)

但是如果我们首先a*b使用乘法计算它会舍入到1.0,那么随后的1.0减法会产生零结果.

如果我们fma(a,b,-1)改为使用,我们就会消除产品的中间舍入,这样我们就能得到"真正的"答案-1.0p-104.

请注意,我们不仅得到了不同的结果,而且还设置了不同的标志; 单独的乘法和减法设置不精确的标志,而融合的乘法 - 加法不设置任何标志.