Всегда ли инструкции FMA (объединенное умножение-сложение) дают тот же результат, что и инструкция "умножение и сложение"?

У меня есть такая сборка (синтаксис AT&T):

mulsd   %xmm0, %xmm1
addsd   %xmm1, %xmm2

Я хочу заменить его на:

vfmadd231sd %xmm0, %xmm1, %xmm2

Будет ли это преобразование всегда оставлять эквивалентное состояние во всех задействованных регистрах и флагах? Или результаты поплавков как-то будут немного отличаться? (Если они отличаются, почему?)

(Об инструкциях FMA: http://en.wikipedia.org/wiki/FMA_instruction_set)


person Daryl    schedule 16.03.2015    source источник


Ответы (1)


Нет. На самом деле, основная часть преимущества объединенного умножения-сложения заключается в том, что он (не обязательно) дает тот же результат, что и раздельное умножение и сложение.

В качестве (несколько надуманного) примера предположим, что у нас есть:

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.

Обратите внимание, что мы не только получаем другой результат, но также были установлены разные флаги; раздельное умножение и вычитание устанавливает неточный флаг, тогда как объединенное умножение-сложение не устанавливает никаких флагов.

person Stephen Canon    schedule 16.03.2015