/d2vzeroupper MSVC 编译器优化标志在做什么?

What is the /d2vzeroupper MSVC compiler optimization flag doing?

/d2vzeroupper MSVC 编译器优化标志在做什么?

我正在通读这个编译器选项快速参考指南 对于 AMD 的 Epyc CPU:https://developer.amd.com/wordpress/media/2020/04/Compiler%20Options%20Quick%20Ref%20Guide%20for%20AMD%20EPYC%207xx2%20Series%20Processors.pdf

对于 MSVC,为了“针对 64 位 AMD 处理器进行优化”,他们建议启用 /favor:AMD64 /d2vzeroupper

/favor:AMD64 所做的很清楚,在 MSVC 文档中有相关文档。但我似乎根本找不到 /d2vzeroupper 在互联网上的任何地方被提及,任何地方都没有文档。它在做什么?

TL;DR:使用 /favor:AMD64 时添加 /d2vzeroupper 以避免 SSE 代码在当前 AMD CPU 和 Intel CPU 上的性能非常差。


通常 /d1.../d2... 是“秘密”(未记录)MSVC 选项,用于调整编译器行为。 /d1...适用于编译器前端,/d2...适用于编译器后端。


/d2vzeroupper 启用编译器生成的 vzeroupper 指令

有关详细信息,请参阅

一般都是默认的。您可以通过 /d2vzeroupper- 禁用它。看这里:https://godbolt.org/z/P48crzTrb

/favor:AMD64 开关抑制 vzeroupper,因此 /d2vzeroupper 启用它。

最新的 Visual Studio 2022 已修复此问题,因此 /favor:AMD64 仍会发出 vzeroupper 并且不需要 /d2vzeroupper 来启用它。


原因:当前的 AMD 优化指南(可从 AMD site; direct pdf link 获得)建议:

2.11.6 Mixing AVX and SSE

There is a significant penalty for mixing SSE and AVX instructions when the upper 128 bits of the YMM registers contain non-zero data. Transitioning in either direction will cause a micro-fault to spill or fill the upper 128 bits of all 16 YMM registers. There will be an approximately 100 cycle penalty to signal and handle this fault. To avoid this penalty, a VZEROUPPER or VZEROALL instruction should be used to clear the upper 128 bits of all YMM registers when transitioning from AVX code to SSE or unknown code

较旧的 AMD 处理器不需要 vzeroupper,因此 /favor:AMD64 对其进行了优化,即使对 Intel CPU 不利。来自 MS docs:

/favor:AMD64

(x64 only) optimizes the generated code for the AMD Opteron, and Athlon processors that support 64-bit extensions. The optimized code can run on all x64 compatible platforms. Code that is generated by using /favor:AMD64 might cause worse performance on Intel processors that support Intel64.