有人可以向我解释为什么融合乘法累加指令有3种变体:vfmadd132pd
,vfmadd231pd
和vfmadd213pd
,而只有一个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
的含义:
vfmaddijkpd
op(i) * op(j) + op(k) -> op(1)
其中op(4-i) * op(4-j) + op(4-k) -> op(3)
表示指令后的第n个操作数。因此,两者之间存在反向转换:
op(n)
答案 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)
VFMADD132PD:将两个或四个打包的双精度相乘 从第一个源操作数到两个或更多的浮点值 第三个源中的四个打包双精度浮点值 操作数,将无限精度中间结果添加到两者中 或第二中的四个打包双精度浮点值 源操作数,执行舍入并存储生成的两个或四个 将双精度浮点值打包到目标 操作数(第一个源操作数)。
VFMADD213PD:将两者或两者相乘 来自 second 的四个打包双精度浮点值 源操作数为两个或四个打包的双精度 第一个源操作数中的浮点值添加无限 精确的中间结果到两个或四个包装 第三个源操作数中的双精度浮点值, 执行舍入并存储由此产生的两个或四个打包 目标操作数的双精度浮点值 (第一个源操作数)。
VFMADD231PD:将两个或四个打包相乘 从第二源到。的双精度浮点值 第三中的两个或四个打包双精度浮点值 源操作数,将无限精度中间结果添加到 两个或四个打包的双精度浮点值 第一个源操作数,执行舍入并存储生成的两个 或四个打包的双精度浮点值到desti- 国家操作数(第一来源操作数)。