我正在检查一些使用/fp:precise
and/fp:fast
标志的代码。
根据MSDN/fp:precise
文档:
在 x86 处理器上使用 /fp:precise 时,编译器将对 float 类型的变量执行舍入,以达到赋值和强制转换以及将参数传递给函数时的正确精度。这种舍入保证数据不会保留任何大于其类型容量的重要性。使用 /fp:precise 编译的程序可能比没有 /fp:precise 编译的程序更慢和更大。/fp:precise 禁用内在函数;而是使用标准运行时库例程。有关详细信息,请参阅 /Oi(生成内部函数)。
查看对sqrtf
(调用/arch:SSE2
,目标x86/Win32
平台)的调用的反汇编:
0033185D cvtss2sd xmm0,xmm1
00331861 call __libm_sse2_sqrt_precise (0333370h)
00331866 cvtsd2ss xmm0,xmm0
根据这个问题,我相信现代 x86/x64 处理器不使用 80 位寄存器(或至少不鼓励使用它们),因此编译器会执行我认为次优的操作,并使用 64 位双精度数进行计算。并且由于内部函数被禁用,因此调用了库 sqrtf 函数。
好的,很公平,这似乎符合文档所说的内容。
但是,当我为 x64 架构编译时,发生了一些奇怪的事情:
000000013F2B199E movups xmm0,xmm1
000000013F2B19A1 sqrtps xmm1,xmm1
000000013F2B19A4 movups xmmword ptr [rcx+rax],xmm1
计算不是使用 64 位双精度执行的,而是使用内部函数。/fp:fast
据我所知,结果与使用标志完全相同。
为什么两者之间存在差异?/fp:precise
根本不适用于 x64 平台吗?
现在,作为健全性检查,我在 VS2010 x86 中使用/fp:precise
and测试了相同的代码/arch:SSE2
。令人惊讶的是,sqrtpd
内在函数被使用了!
00AF14C7 cvtps2pd xmm0,xmm0
00AF14CA sqrtsd xmm0,xmm0
00AF14CE cvtpd2ps xmm0,xmm0
这里发生了什么?为什么 VS2010 使用内部函数,而 VS2012 调用系统库?
针对 x64 平台测试 VS2010 的结果与 VS2012 相似(/fp:precise
似乎被忽略了)。
我无法访问任何旧版本的 VS,因此无法在这些平台上进行任何测试。
作为参考,我正在使用 Intel i5-m430 处理器在 Windows 7 64 位中进行测试。