为啥 MSVC 使用 SSE2 指令来处理这种琐碎的事情?

Posted

技术标签:

【中文标题】为啥 MSVC 使用 SSE2 指令来处理这种琐碎的事情?【英文标题】:Why does MSVC use SSE2 instruction for such trivial thing?为什么 MSVC 使用 SSE2 指令来处理这种琐碎的事情? 【发布时间】:2015-01-23 10:50:47 【问题描述】:

代码:

double Ret_Value=0;

在默认设置下 VS2012 编译为:

10112128  xorps       xmm0,xmm0  
1011212E  movsd       mmword ptr [Ret_Value],xmm0

如果在项目设置中禁用 SSE2,则编译为:

101102AC  fldz  
101102AE  lea         eax,[Ret_Value]  
101102B1  push        eax  
101102B2  fstp        qword ptr [Ret_Value] 

编辑:我不确定pushlea 是否与此初始化有关,也许是为了在那之后完成的工作,只是反汇编显示了这行C++ 代码。

SSE2 明显更好吗?除了它是 2 指令短?这里做了什么样的优化?

这是如何发现的:应用在不支持 SSE2 的旧处理器上开始出现故障。

【问题讨论】:

我认为这是一个简单的代码大小优化。较短的代码对缓存更友好,因此速度更快。此外,不使用堆栈可以节省一些内存访问。 不确定中间的 2 条指令应该做什么。只需要将Ret_Value 归零,您只需要fldz; fstp [Ret_Value] 检查this post,它解释了为什么 FPU 是邪恶的,英特尔决定更换它。编译器作者花了一段时间才效仿,微软是最后一个主流。 带有 /arch:IA32 的 MSVC 不会为 32 位代码生成任何 SSE 指令。 MSVC x64 本机代码生成使用 SSE/SSE2 并且没有 x87 指令。使用 /arch:SSE 或 /arch:SSE2 的 MSVC 32 位尝试使用 SSE 指令和其他 x64 本机代码生成机制。从 VS 2012 开始,32 位编译器默认为 /arch:SSE2——Windows 8.0 明确要求 x86(32 位)支持 SSE/SSE2,并且所有 Windows x64 处理器都需要它。 SSE2 是 x86-64 的基线,无论 Windows 是什么,以防有人想知道。 (当然,在 64 位代码中,您也可以 push qword 0mov qword ptr [rsp+8], 0 在一条指令中存储 8 个字节的零。) 【参考方案1】:

英特尔优化参考手册第 3.8.1 节(优化浮点代码的指南)说 -

通过适当的开关使编译器能够使用 SSE、SSE2 和更高级的 SIMD 指令集(例如 AVX)。 支持标量 SIMD 代码生成以替代 x87 代码生成。

第 3.8.5 节继续解释:

除非您需要 x87 功能,否则请使用 Streaming SIMD Extensions 2 或 Streaming SIMD Extensions。大多数 SSE2 算术运算的延迟都比 X87 对应的要短,并且它们消除了与 X87 寄存器栈的管理。

【讨论】:

以上是关于为啥 MSVC 使用 SSE2 指令来处理这种琐碎的事情?的主要内容,如果未能解决你的问题,请参考以下文章

这种悲伤教学的奇怪行为的原因是啥?

为啥 FxCop 不报告 CA2000 对于这种未处置的类实例的琐碎情况?

SSE、SSE2、SSE3指令集的区别?

为啥 clang 处理这个琐碎的 std::variant 代码的异常?

与 SSE2 相比,为啥 AVX 没有进一步提高性能?

sse2_FloatToInt