assembly - 为什么 FMA _mm256_fmadd_pd() 内在函数有 3 个 asm 助记符, "vfmadd132pd"、 "231"和 "213"?

标签 assembly x86 simd instruction-set fma

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

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

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

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

一个干净的答案(在下面重新格式化答案)

对于变体 ijkvfmaddijkpd的含义:
  • 英特尔语法:op(i) * op(j) + op(k) -> op(1)
  • AT&T 语法:op(4-i) * op(4-j) + op(4-k) -> op(3)

  • 哪里op(n)表示指令后的第 n 个操作数。所以有一个 反向 两者之间的转换:
    n <- 4 - n
    

    最佳答案

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

    它的工作方式是所有三个指令都覆盖 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 内在函数时,此选择不是必需的:内在函数不会覆盖值而是返回其结果,并且允许从内存中读取所有三个值。如果需要,编译器将添加内存读/写,如果不希望三个值中的任何一个被覆盖,它将分配一个临时寄存器来存储结果。它将选择它认为合适的三个指令之一。

    关于assembly - 为什么 FMA _mm256_fmadd_pd() 内在函数有 3 个 asm 助记符, "vfmadd132pd"、 "231"和 "213"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36391719/

    相关文章:

    没有操作数 2 的 ARM v7 ORRS 助记符

    c - mac安装AVR开发平台出现错误

    困惑如何阅读汇编指令

    x86 - 多核/NUMA 上的 CPUID

    performance - 对x86上的L1缓存行的独占访问?

    c++ - C++ 中的 asm block 作为宏

    assembly - 如何确定常量字符串的长度?

    c - 数组结构和内存访问模式

    c - SSE 优化代码的性能与普通版本类似

    c - 模拟 XMM 内在函数时在 WebAssembly 中进行对齐检查?