为什么VS 2015编译器不能在浮点数的abs()实现中优化分支?
Why can't the VS 2015 compiler optimise a branch in an abs() implementation on float numbers?
__declspec(dllexport)
float foo(float x) {
return (x < 0) ? x * -1 : x;
}
这是计算abs(x)
的一个非常简单的实现,其中x
是float
。我在发布模式下编译它,并启用了我能找到的所有优化。所得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);
。
相关文章:
- 如果没有malloc,链表实现将失败
- 空基优化子对象的地址
- 如何在c++中实现处理器调度模拟器
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- C++分离功能,实现性能优化
- 迭代可汗求和的优化实现
- 为什么仅 -fno-signed-0 就可以实现优化,而似乎也需要 -ffinite-math-only (gcc)
- clang实现char8_t的方式是否存在缺陷,或者标准的某个黑暗角落是否禁止优化?
- 实现move构造函数如何影响返回值优化
- 快速排序实现优化
- 编译器优化合并了相同的函数实现,这意味着在运行时要绕过存根
- 优化读/写锁的实现
- 优化代码/实现"for"循环而不是长"if - else if - else"
- 分形编程-任何优化此代码以实现实时渲染的方法
- 表达式模板实现未优化
- 如何在 std::atomic 上实现一个简单的自旋锁<T>,以便编译器不会对其进行优化?
- 实现任意类型擦除的小缓冲区优化的简单方法(如std::function.)
- 为什么VS 2015编译器不能在浮点数的abs()实现中优化分支?
- 优化子集和实现
- 需要优化 - 算法实现占用太多内存