我正在考虑一个定点算术库,为了决定库本身应该做多少优化(通过表达式模板),我开始质疑优化器已经完成了多少工作。以下面的示例为例:
//This is a totally useless function to exemplify my point
void Compare(FixedPoint a, FixedPoint b) {
if(a/b>10) {
... do stuff
}
}
现在,在此函数中,FixedPoint
类的典型实现将导致
if( ( (a_<<N) / b_) > (10 <<N) ) {
... do stuff
}
其中N
是小数位数。该表达式可以数学转换为:
(a_ > 10*b_)
即使这种转换不在您考虑整数溢出时也会导致相同的行为。我的库的用户可能会关心数学等价,而宁愿使用简化版本(可能通过表达式模板提供)。
现在,问题是:优化器本身是否敢于进行优化,即使行为不完全相同?我应该为这样的优化而烦恼吗?请注意,此类优化并非易事。实际上,如果你实际进行这些优化,那么当你使用定点算术时,你很少需要做任何位移。
答案 0 :(得分:1)
这取决于a_
和b_
类型是签名还是未签名。
在C和C ++中,有符号溢出在技术上是未定义的行为,而无符号溢出是使用二补码算法完成的。
然而,一些编译器拒绝优化该代码,因为许多程序依赖于签名溢出的双补码行为。
好的现代编译器可以选择启用/禁用这个特定的假设:有符号整数不会溢出。默认的选项因编译器而异。
例如,使用GCC,请参阅选项-fstrict-overflow/-fno-strict-overflow
和相关警告-Wstrict-overflow
。