FMA指令_mm256_fmadd_pd():“132”,“231”和“213”?

时间:2016-04-03 21:57:20

标签: x86 x86-64 intel fma

有人可以向我解释为什么融合乘法累加指令有3种变体:vfmadd132pdvfmadd231pdvfmadd213pd,而只有一个C内在函数{{1} }?

为简单起见,(在AT& T语法中)有什么区别

_mm256_fmadd_pd

我没有从Intel's intrinsics guide得到任何想法。我问,因为我在我写的一大块C代码的汇编输出中看到了所有这些。感谢。

一个干净的答案(重新制作以下答案)

对于变体vfmadd132pd %ymm0, %ymm1, %ymm2 vfmadd231pd %ymm0, %ymm1, %ymm2 vfmadd213pd %ymm0, %ymm1, %ymm2 ijk的含义:

  • intel语法:vfmaddijkpd
  • AT& T语法:op(i) * op(j) + op(k) -> op(1)

其中op(4-i) * op(4-j) + op(4-k) -> op(3)表示指令后的第n个操作数。因此,两者之间存在反向转换:

op(n)

2 个答案:

答案 0 :(得分:12)

融合乘法 - 加法指令将两个(打包)值相乘,再加上第三个值,然后用结果覆盖其中一个值。三个值中只有一个可以是内存操作数而不是寄存器。

它的工作方式是所有三条指令都覆盖ymm0并且只允许ymm2作为内存操作数。指令的选择决定了哪两个操作数相乘,哪个被添加。

假设ymm0是Intel语法中的第一个操作数(或AT& T语法中的最后一个操作数):

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

使用C内在函数时,这种选择是不必要的:内在函数不会覆盖值而是返回其结果,并且它允许从内存中读取所有三个值。如果需要,编译器将添加内存读/写,并且如果不希望覆盖任何三个值,则将分配临时寄存器来存储结果。它将根据需要选择三条指令中的一条。

答案 1 :(得分:3)

这是instruction set reference

  

VFMADD132PD:将两个或四个打包的双精度相乘   从第一个源操作数到两个或更多的浮点值   第三个源中的四个打包双精度浮点值   操作数,将无限精度中间结果添加到两者中   或第二中的四个打包双精度浮点值   源操作数,执行舍入并存储生成的两个或四个   将双精度浮点值打包到目标   操作数(第一个源操作数)。

     

VFMADD213PD:将两者或两者相乘   来自 second 的四个打包双精度浮点值   源操作数为两个或四个打包的双精度   第一个源操作数中的浮点值添加无限   精确的中间结果到两个或四个包装   第三个源操作数中的双精度浮点值,   执行舍入并存储由此产生的两个或四个打包   目标操作数的双精度浮点值   (第一个源操作数)。

     

VFMADD231PD:将两个或四个打包相乘   从第二源到。的双精度浮点值   第三中的两个或四个打包双精度浮点值   源操作数,将无限精度中间结果添加到   两个或四个打包的双精度浮点值   第一个源操作数,执行舍入并存储生成的两个   或四个打包的双精度浮点值到desti-   国家操作数(第一来源操作数)。