我有这个程序集(AT& T语法):
mulsd %xmm0, %xmm1
addsd %xmm1, %xmm2
我想将其替换为:
vfmadd231sd %xmm0, %xmm1, %xmm2
此转换是否总是在所有涉及的寄存器和标志中保持等效状态?或者结果浮点数会有些不同吗? (如果它们不同,那为什么?)
答案 0 :(得分:15)
没有。事实上,融合乘法加法的一个主要好处是它(不一定)产生与单独乘法和加法相同的结果。
作为一个(有点人为的)例子,假设我们有:
double a = 1 + 0x1.0p-52 // 1 + 2**-52
double b = 1 - 0x1.0p-52 // 1 - 2**-52
我们要计算a*b - 1
。 a*b - 1
的“数学上精确”值是:
(1 + 2**-52)(1 - 2**-52) - 1 = 1 + 2**-52 - 2**52 - 2**-104 - 1 = -2**-104
但是如果我们首先使用乘法计算a*b
它会舍入到1.0,那么随后的1.0减法会产生零结果。
如果我们改为使用fma(a,b,-1)
,我们会取消产品的中间舍入,这样我们就可以获得“真实”答案-1.0p-104
。
请注意,我们不仅得到了不同的结果,而且还设置了不同的标志;单独的乘法和减法设置不精确的标志,而融合的乘法 - 加法不设置任何标志。