Почему встроенная функция FMA _mm256_fmadd_pd() имеет 3 мнемоники asm: "vfmadd132pd", "231" и "213"?

Может ли кто-нибудь объяснить мне, почему существуют 3 варианта команды плавного умножения-накопления: vfmadd132pd, vfmadd231pd и vfmadd213pd, в то время как существует только один C intrinsics _mm256_fmadd_pd?

Чтобы сделать вещи простыми, в чем разница (в синтаксисе AT & T)

vfmadd132pd  %ymm0, %ymm1, %ymm2
vfmadd231pd  %ymm0, %ymm1, %ymm2
vfmadd213pd  %ymm0, %ymm1, %ymm2

Я понятия не имел из руководства по интуиции Intel. Я спрашиваю, потому что я вижу их все на выходе ассемблера куска кода C, который я написал. Спасибо.


Чистый ответ (повторное формирование ответов ниже)

Для варианта ijk значение vfmaddijkpd:

  • Синтаксис Intel: op(i) * op(j) + op(k) -> op(1)
  • Синтаксис AT & T: op(4-i) * op(4-j) + op(4-k) -> op(3)

где op(n) обозначает n-й операнд после команды. Таким образом существует преобразование reverse между двумя:

n <- 4 - n

Ответ 1

Слитые инструкции умножения-сложения умножают два (упакованные) значения, добавляют третье значение и затем перезаписывают одно из значений результатом. Только одно из трех значений может быть операндом памяти, а не регистром.

Это работает так, что все три инструкции перезаписывают ymm0 и позволяют только ymm2 быть операндом памяти. Выбор инструкции определяет, какие два операнда умножаются, а какие добавляются.

Предполагая, что ymm0 является первым операндом в синтаксисе Intel (или последним в синтаксисе AT & T):

vfmadd132pd:  ymm0 = ymm0 * ymm2/mem + ymm1
vfmadd231pd:  ymm0 = ymm1 * ymm2/mem + ymm0
vfmadd213pd:  ymm0 = ymm1 * ymm0 + ymm2/mem 

При использовании встроенных функций C этот выбор не требуется: встроенная функция не перезаписывает значение, а возвращает его результат, а также позволяет всем трем значениям считываться из памяти. Компилятор добавит чтение/запись памяти, если необходимо, и выделит временный регистр для хранения результата, если он не хочет, чтобы какое-либо из трех значений было перезаписано. Он выберет одну из трех инструкций по своему усмотрению.

Ответ 2

Это находится в инструкции по сборке, а также в его HTML-фрагментах, например в записи для VFMADD * PD:

VFMADD132PD: Умножение двух или четырех упакованных с двойной точностью значения с плавающей точкой от первого исходного операнда до двух или четыре упакованных значения с плавающей точкой двойной точности в третьем источнике операнд, добавляет промежуточный результат бесконечной точности к двум или четыре упакованных значения с плавающей запятой двойной точности в втором исходный операнд, выполняет округление и сохраняет полученные два или четыре упакованные значения с плавающей запятой двойной точности к месту назначения операнд (первый исходный операнд).

VFMADD213PD: Умножает два или четыре упакованных значения с плавающей запятой двойной точности из второго исходный операнд с двумя или четырьмя упакованными с двойной точностью Значения с плавающей точкой в первом исходном операнде добавляют бесконечность Точность промежуточного результата до двух или четырех упакованных значения с плавающей запятой двойной точности в третьем операнде источника, выполняет округление и сохраняет полученные два или четыре упакованных значения с плавающей запятой двойной точности для целевого операнда (первый операнд источника).

VFMADD231PD: Умножает два или четыре упакованных значения с плавающей запятой двойной точности из второго источника в два или четыре упакованных значения с плавающей точкой двойной точности в третьем операнд источника, добавляет промежуточный результат с бесконечной точностью к два или четыре упакованных значения с плавающей точкой двойной точности в первый исходный операнд, выполняет округление и сохраняет полученные два или четыре упакованных значения с плавающей точкой двойной точности к desti- операнд нации (операнд первого источника).