gpt4 book ai didi

c++ - 为什么 VS 2015 编译器不能优化 float 的 abs() 实现中的分支?

转载 作者:太空狗 更新时间:2023-10-29 20:36:18 25 4
gpt4 key购买 nike

__declspec(dllexport)
float foo(float x) {
return (x < 0) ? x * -1 : x;
}

这是计算 abs(x) 的非常简单的实现,其中 x 是一个 float。我在 Release模式下编译了它并启用了我能找到的所有优化。生成的 asm 是:

; 4    :    return (x < 0) ? x * -1 : x;

movss xmm1, DWORD PTR _x$[ebp]
xorps xmm0, xmm0
comiss xmm0, xmm1
jbe SHORT $LN3@foo
xorps xmm1, DWORD PTR __xmm@80000000800000008000000080000000
$LN3@foo:
movss DWORD PTR tv66[ebp], xmm1
fld DWORD PTR tv66[ebp]

如您所见,这仍然包含分支和条件跳转。然而 float 是由 IEEE754 定义的,因此我可以更改实现以简单地将符号位设置为 0:

__declspec(dllexport)
float foo(float x) {
void* bar = &x;
__int32 y = ((*(__int32*)bar) & ~(1 << 31));
return *(float*)&y;
}

它不会跳转并且需要更少的命令:

; 3    :        void* bar = &x;
; 4 : __int32 y = ((*(__int32*)bar) & ~(1 << 31));

mov eax, DWORD PTR _x$[ebp]
and eax, 2147483647 ; 7fffffffH
mov DWORD PTR _y$[ebp], eax

; 5 : return *(float*)&y;

fld DWORD PTR _y$[ebp]

我原以为该操作甚至存在特定命令,但也许这仅适用于非常特殊的架构?

那么编译器无法捕获此优化的原因是什么?还是我这样做有误?

最佳答案

因为这会产生负零的错误结果!

负零不小于零,所以它的符号保持为负,使得条件分支的消除无效。

考虑使用类似的东西

copysign(x, 0.0);

相反。

关于c++ - 为什么 VS 2015 编译器不能优化 float 的 abs() 实现中的分支?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39216210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com