算术运算和编译器优化

Arithmetic operations and the compiler optimizations

本文关键字:优化 编译器 算术运算      更新时间:2023-10-16

我正在考虑一个定点算术库,为了决定库本身(通过表达式模板)应该做多少优化,我开始质疑优化器已经做了多少。以以下示例为例:

//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_)

即使当您考虑整数溢出时,此转换不会导致相同的行为。我的库的用户可能会关心数学等价性,并且更愿意使用精简版(可能通过表达式模板提供)。

现在,问题是:即使行为并不完全相同,优化器也敢自己进行优化吗?我应该为这样的优化而烦恼吗?请注意,这样的优化并非微不足道。事实上,如果你真的做了这些优化,那么当你使用定点算术时,你很少需要做任何比特移位。

这将取决于a_b_类型是有符号的还是无符号的。

在C和C++中,有符号溢出在技术上是未定义的行为,而无符号溢出是使用双补运算完成的。

尽管如此,一些编译器拒绝优化该代码,因为许多程序依赖于有符号溢出的双补行为。

优秀的现代编译器可以选择启用/禁用这一特定假设:有符号整数不会溢出。默认选项随编译器的不同而不同。

例如,对于GCC,请参阅选项-fstrict-overflow/-fno-strict-overflow和相关警告-Wstrict-overflow