非交换操作的G ++编译器优化范围

时间:2015-07-06 22:39:46

标签: c++ g++ compiler-optimization

我担心G ++优化器对算术运算的影响,特别是不一定是可交换的整数运算,例如*和/。当我查看gdb中使用-O3标志集编译的简单函数时,出现了这种担忧;这一切都是一个更好的功能,但它的形式完全不同于没有优化,操作已被删除,一些已被重新安置。这是一个简单的功能,我将用它来展示我关注的关键;

int ClipLower(int num, int dig){
  int Mult10 = 1;
  while (dig != 0){
    Mult10 *= 10, dig--;
  }
  return ((num / Mult10) * Mult10);
}

此功能只是剪掉数字'dig'下方的base10数字。我担心的是,编译器是否会考虑整数数学是非交换的事实?那么,编译器是否会尝试将(num / mult10)* mult10 缩减为 num * 1 ,当然会丢弃那个?

我知道 volatile 会避免这种情况,但我仍然希望尽可能优化我的代码。所以从本质上讲,我问的是gnu优化器是否会理解整数数学是非交际的,还有更多的关注优化 - 实际上是错误的。

这里是-O4函数的反汇编,如你所见,操作顺序很好

  13        return ((num / Mult10) * Mult10);
       cltd
       idiv   %ecx
       imul   %ecx,%eax
       ret

有趣的是,编译器在函数之后生成了一系列无操作,可能是填充因为它最终变小了。

2 个答案:

答案 0 :(得分:2)

以下是g ++中-O3等同于的标记列表:https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

现在,如果仔细查看,还会-Ofast定义为-O3 +其他一些,尤其是-ffast-math。在-ffast-math的说明中,您可以阅读:

  

除了-Ofast之外,任何-O选项都不会打开此选项,因为它可能导致依赖于数学函数的IEEE或ISO规则/规范的精确实现的程序的输出不正确。但是,对于不需要保证这些规范的程序,它可能会产生更快的代码。

这样做是为了确保默认编译器标志不会违反舍入误差和其他浮点标准规范。

还有一个关于SO的相关问题,为什么编译器不会优化a*a*a*a*a*a(a*a*a)^2,答案是一样的。 (我找不到链接atm = /)

顺便说一下,Mult10 *= 10, dig--;你是否试图让人失去你的代码? = d

编辑:顺便说一句,越过-O3没有效果。除了有些人说你可能会溢出一些内部变量。我没有测试溢出,但我确信-O4-O100在写这篇文章的时候相当于-O3

答案 1 :(得分:1)

尝试并查看程序集

优化不应影响输出,只影响速度。应该保持舍入。但是现在可能会发生很多错误。

通常,浮点数问题更有可能发生。带有<td><%= link_to "@wine_maker.name", @wine_maker %></td> 的2/7可能略有不同。

对于float s,无论优化程度如何,它都应该始终为0,即使它乘以7也是如此。

相关问题