C++ 算术运算与编译器优化

C++ 算术运算与编译器优化,c++,c,optimization,arithmetic-expressions,C++,C,Optimization,Arithmetic Expressions,我正在考虑一个定点算术库,为了决定库本身应该做多少优化(通过表达式模板),我开始质疑优化器已经做了多少。以下面的例子为例: //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_&

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

//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
}

即使在考虑整数溢出的情况下,此转换也将<强> > < /强>导致相同的行为。我的库的用户可能会关心数学等价性,而宁愿使用简化版本(可能通过表达式模板提供)


现在,问题是:即使行为严格来说并不相同,优化器是否敢于自己进行优化?我应该为这样的优化而烦恼吗?请注意,这样的优化并不是微不足道的。实际上,如果您实际执行这些优化,那么在使用定点算法时很少需要进行任何位移位。

这将取决于
a
b
类型是有符号的还是无符号的

<>在C和C++中,符号溢出是技术上未定义的行为,而无符号溢出是用两个补码运算完成的。 然而,一些编译器拒绝优化该代码,因为许多程序依赖于有符号溢出的两个补码行为

好的现代编译器将有一个选项来启用/禁用这个特定的假设:有符号整数不会溢出。默认选项随编译器的不同而不同


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

简单规则:如果编译器无法向自己证明行为不会改变,则不会进行优化。此外,您已经找到了一个不匹配的示例。(溢出)这本身已经禁止编译器进行此优化。也就是说,编译器可能会执行其他技巧(例如升级到更大的类型)。但是一个快速的测试表明VS2010没有进行这种优化。@Mystical除了程序员之外,没有使用c标准来避免溢出,因此允许进行忽略溢出的优化。(我想这里有一个问题,所以循环不会终止,因为终止条件依赖于溢出(如果我记得正确的话,
for(int I=0;I>=0;I++);
))。但是我不能完全确定这一点。@ted真是巧合!你指的是我问的。:)在这种情况下,如果
10*b
发生故障,进行优化将导致溢出。因此,即使
a/b
没有溢出,
10*b
也可能溢出。所以编译器不能不升级到更大的类型。@Mystical:谢谢你,幸运的是,我现在从你的问题中学到了更多。谢谢你的回答,我想我最好通过表达式模板进行优化。这还取决于它们是大于还是小于
int
。小于
int
的无符号值将被提升为有符号值,而与上下文无关,这可能会导致未定义的行为,即使在计算的高位永远不会对结果产生任何定义的影响的情况下也是如此。
(a_ > 10*b_)