Who is vfmaddrnd231pd??

本文为原文前 6,000 字符的节选翻译,完整内容请查看原文。

Who is vfmaddrnd231pd?? October 12, 2026 Hacker News Lobsters. vfmaddrnd231pd is a unique instruction from the FMA instruction set. Most instructions in that set have mnemonics like vfmadd231pd, but here rnd means something very specific. The Intel Software Development Manual documents it as: VFMADDRND231PD – Fused Multiply-Add of Packed Double-Precision Floating-Point Values with rounding control[…] The immediate byte defines several bit fields that control rounding, DAZ, FTZ, and exception suppression (See Table 5-3).

vfmaddrnd231pd 是 FMA 指令集中的一条独特指令。该指令集中的大多数指令助记符类似于 vfmadd231pd,但这里的 rnd 具有非常具体的含义。英特尔软件开发手册将其记录为:VFMADDRND231PD – 带有舍入控制的压缩双精度浮点值的融合乘加运算 […] 立即数字节定义了几个控制舍入、DAZ、FTZ 和异常抑制的位域(见表 5-3)。

Most x86 floating-point instructions use the global rounding mode and settings, changing which is pretty slow. But vfmaddrnd231pd allows the rounding mode to be controlled on a per-instruction basis, and since FMA can emulate addition, subtraction, and multiplication, this mechanism effectively allows any arithmetic to have controllable rounding without AVX-512 – making some algorithms that rely on rounding incredibly faster.

大多数 x86 浮点指令使用全局舍入模式和设置,而更改这些设置非常缓慢。但 vfmaddrnd231pd 允许在每条指令的基础上控制舍入模式,并且由于 FMA 可以模拟加法、减法和乘法,这种机制实际上允许任何算术运算在没有 AVX-512 的情况下实现可控舍入,从而使某些依赖舍入的算法速度大幅提升。

Or so it would, if this instruction actually existed. GNU assembler doesn’t recognize it. The Intel C/C++ Compiler intrinsics _mm_fmaddround_pd and _mm256_fmaddround_pd that SDM mentions are absent not only from Clang, but from ICC as well. Trying to assemble the instructions by hand from the SDM opcode list reveals another issue: VEX.DDS.128.66.0F3A.W1 B8 /r /ib. VEX is the VEX prefix, but what is DDS? This opcode is the only mention of DDS in the SDM, and this SO answer says that DDS is merely used for documentation and was removed from later SDM versions, but the fact that it’s still present here is suspicious. And when you actually run the instruction on a CPU that supports the FMA instruction set, like my Haswell, it raises #UD (“UnDefined instruction”)!

如果这条指令真的存在,情况确实会如此。GNU 汇编器无法识别它。SDM 中提到的英特尔 C/C++ 编译器内置函数 _mm_fmaddround_pd 和 _mm256_fmaddround_pd 不仅在 Clang 中缺失,在 ICC 中也同样不存在。尝试根据 SDM 操作码列表手动汇编这些指令揭示了另一个问题:VEX.DDS.128.66.0F3A.W1 B8 /r /ib。VEX 是 VEX 前缀,但 DDS 是什么?该操作码是 SDM 中唯一提到 DDS 的地方,Stack Overflow 上的一个回答称 DDS 仅用于文档记录,并在后来的 SDM 版本中被删除,但它仍然出现在这里的事实令人怀疑。当你真正在支持 FMA 指令集的 CPU(如我的 Haswell)上运行该指令时,它会引发 #UD(“未定义指令”)异常!

I already found it strange that the SDM only lists vfmaddrnd231pd and not other variants like using pd/ps/sd/ss or 132/213/231, which other FMA instructions have, but this confirmed my suspicions. It was at that point that I downloaded a more recent version of the SDM and noticed that this instruction is absent in the 2026 edition of the SDM, despite being present in the 2024 version.

我之前就觉得奇怪,SDM 只列出了 vfmaddrnd231pd,而没有列出其他 FMA 指令所具备的 pd/ps/sd/ss 或 132/213/231 等变体,这证实了我的怀疑。就在那时,我下载了更新版本的 SDM,并注意到该指令在 2026 年版的 SDM 中已不存在,尽管它曾出现在 2024 年的版本中。

I must say I’m incredibly confused. This instruction doesn’t look like a typo in the documentation, since the docs contain unique tables and pseudocode that isn’t similar to any other instruction. My best hypothesis is that Intel wanted to add the vfmaddrnd* set, then found an issue with it at the last moment and removed it from the CPU, but didn’t quite adjust the SDM correctly. But I have no way to confirm that. If anyone reading this has a friend at Intel, I’d love to know the answer.

我必须说我感到非常困惑。这条指令看起来不像文档中的拼写错误,因为文档中包含独特的表格和伪代码,与其他任何指令都不相似。我最好的假设是,英特尔曾想添加 vfmaddrnd* 指令集,但在最后一刻发现了问题并将其从 CPU 中移除,但没有正确调整 SDM。但我无法证实这一点。如果阅读本文的人有在英特尔工作的朋友,我很想知道答案。

Updates: eastarer and 039234562456 gave me enough pointers to crack this. Back in 2023, Intel failed to add AVX-512 support to consumer CPUs due to hardware limitations, but still wanted to add some goodies from AVX-512. That’s how AVX10 was born – a new extension that looked roughly like AVX-512, but had conditional support for 512-bit vector lengths.

更新:eastarer 和 039234562456 为我提供了足够的线索来破解这个问题。早在 2023 年,英特尔由于硬件限制未能将 AVX-512 支持添加到消费级 CPU 中,但仍希望加入 AVX-512 的一些优点。这就是 AVX10 的诞生过程——这是一个看起来大致类似于 AVX-512 的新扩展,但对 512 位向量长度提供了条件支持。

AVX-512 uses a strange instruction encoding with the EVEX prefix. For compactness, the bits responsible for the static rounding mode are reused for the operation width (128, 256, or 512 bits), so only scalar and 512-bit operations can customize rounding. This was a problem for AVX10, which didn’t support 512-bit operations: if it interpreted the same instruction as operating on 256-bit values instead of 512-bit ones, different CPUs would behave inconsistently. So AVX10 had to use a different encoding for its own custom rounding modes.

AVX-512 使用了一种带有 EVEX 前缀的奇怪指令编码。为了紧凑起见,负责静态舍入模式的位被重用于操作宽度(128、256 或 512 位),因此只有标量和 512 位操作可以自定义舍入。这对不支持 512 位操作的 AVX10 来说是个问题:如果它将同一指令解释为对 256 位值而不是 512 位值进行操作,不同 CPU 的行为就会不一致。因此,AVX10 必须为其自定义舍入模式使用不同的编码。

My theory is that originally, Intel decided that the easiest way to do this was to add an immediate byte that controls the rounding, which is how vfmaddrnd231pd and similar instructions for other arithmetic operations were born. Notice that it uses a VEX prefix, not the AVX-512-specific EVEX prefix – this would allow CPUs without 512-bit vectors to avoid handling the EVEX prefix at all. Since they added an entire byte, they utilized it in full: 2 bits for the rounding mode, 6 bits for everything else they thought might be useful.

我的理论是,英特尔最初认为最简单的方法是添加一个控制舍入的立即数字节,这就是 vfmaddrnd231pd 及其他算术运算类似指令的由来。请注意,它使用的是 VEX 前缀,而不是 AVX-512 特有的 EVEX 前缀——这使得没有 512 位向量的 CPU 可以完全避免处理 EVEX 前缀。由于他们增加了一个完整的字节,他们充分利用了它:2 位用于舍入模式,6 位用于他们认为可能有用的其他所有内容。

It seems like by 2024, Intel decided that this approach won’t work. And I get it: it’s odd that vfmaddrnd231pd was more powerful than AVX-512 instructions, but only supported 256-bit vectors. And if it supported 512-bit vectors, the rounding mode control built into AVX-512 would become obsolete for the most part. So Intel bit the bullet, dedicated the last unused bit in the EVEX prefix to enabling rounding modes for 256-bit vectors, and reused the AVX-512 instruction encoding for AVX10. This also allowed them to reuse the AVX-512 assembly syntax and avoid introducing new mnemonics, at which point the vfmaddrnd231pd mnemonic and others became unnecessary. During this process, someone forgot to remove vfmaddrnd231pd specifically from the SDM draft.

看来到了 2024 年,英特尔决定这种方法行不通。我理解这一点:vfmaddrnd231pd 比 AVX-512 指令更强大,却只支持 256 位向量,这很奇怪。如果它支持 512 位向量,那么 AVX-512 内置的舍入模式控制在很大程度上就会变得多余。因此,英特尔咬紧牙关,将 EVEX 前缀中最后一个未使用的位专门用于启用 256 位向量的舍入模式,并为 AVX10 重用了 AVX-512 指令编码。这也使他们能够重用 AVX-512 汇编语法并避免引入新的助记符,此时 vfmaddrnd231pd 等助记符就变得多余了。在此过程中,有人忘记从 SDM 草案中专门删除 vfmaddrnd231pd。

By 2025, AVX-512 was considered table stakes due to the popularity of Zen 4, and Intel finally decided to make 512-bit support unconditional in AVX10. This made this entire hack unnecessary, so Intel updated the AVX10 whitepaper: Removed references to 256-bit maximum vector register size, enumeration of vector-length support, and 256-bit instructions supporting embedded rounding. …and submitted patches to GCC removing 256-bit rounding support: In this new whitepaper, all the platforms will support 512 bit vector width (previously, E-core is up to 256 bit, leading to hybrid clients and Atom Server 256 bit only). Also, 256 bit rounding is not that useful because we currently have rounding feature directly on E-core now and no need to use 256-bit rounding as somehow a workaround. HW will remove that support.

到 2025 年,由于 Zen 4 的普及,AVX-512 被视为必备功能,英特尔最终决定在 AVX10 中实现无条件的 512 位支持。这使得整个变通方案变得多余,因此英特尔更新了 AVX10 白皮书:删除了关于 256 位最大向量寄存器大小、向量长度支持枚举以及支持嵌入式舍入的 256 位指令的引用。……并向 GCC 提交了删除 256 位舍入支持的补丁:在这份新白皮书中,所有平台都将支持 512 位向量宽度(此前,E-core 最高为 256 位,导致混合客户端和 Atom 服务器仅支持 256 位)。此外,256 位舍入并不是很有用,因为我们目前在 E-core 上直接具备了舍入功能,无需将 256 位舍入作为一种变通方法。硬件将移除该支持。

We can partially confirm this theory by inspecting the patches. One of them is named: Revert “AVX10.2 ymm rounding: Support vfmadd{132, 231, 213}p{s, d, h} intrins”… and removes multiple intrinsics, including _mm256_fmadd_round_pd, which is named very similarly to the documented intrinsic for the ghost instruction, _mm256_fmaddround_pd. At a later point, someone at Intel realized that vfmaddrnd231pd was still men

我们可以通过检查补丁来部分证实这一理论。其中一个补丁名为:Revert “AVX10.2 ymm rounding: Support vfmadd{132, 231, 213}p{s, d, h} intrins”……并删除了多个内置函数,包括 _mm256_fmadd_round_pd,它的命名与幽灵指令的记录内置函数 _mm256_fmaddround_pd 非常相似。后来,英特尔的某个人意识到 vfmaddrnd231pd 仍然被提及。