C++ G+的范围+;非交换运算的编译器优化

C++ G+的范围+;非交换运算的编译器优化,c++,g++,compiler-optimization,C++,G++,Compiler Optimization,我担心G++优化器对算术运算的影响,特别是不一定是可交换的整数运算,例如*和/。当我查看gdb中使用-O3标志集编译的一个简单函数时,出现了这种担忧;总的来说,这是一个更好的功能,但它的形式与没有优化的情况下完全不同,操作被删除,一些被重新定位。下面是一个简单的函数,我将用它来说明我所关心的问题的关键 int ClipLower(int num, int dig){ int Mult10 = 1; while (dig != 0){ Mult10 *= 10, dig--;

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

int ClipLower(int num, int dig){
  int Mult10 = 1;
  while (dig != 0){
    Mult10 *= 10, dig--;
  }
  return ((num / Mult10) * Mult10);
}
此函数只需将数字“dig”下面的10位数字剪掉。我担心的是,编译器是否考虑到整数上的数学是非交换的事实?那么,编译器是否会尝试将(num/mult10)*mult10减少为num*1,当然会丢弃这个

我知道volatile可以避免这种情况,但我仍然希望我的代码尽可能优化。因此,本质上,我是在问gnu优化器是否会理解整数数学是非交流的,更进一步地说,优化出了差错究竟有多重要

也 这是-O4函数的反汇编,正如您所看到的,操作顺序很好

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

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

试试看程序集

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

一般来说,浮点型更容易出现问题。2/7带
float
s可能略有不同


使用
int
s时,无论进行何种优化,它都应始终为0,即使它乘以7。

尝试并查看程序集

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

一般来说,浮点型更容易出现问题。2/7带
float
s可能略有不同


使用
int
s时,无论进行何种优化,它都应始终为0,即使它乘以7。

尝试并查看程序集

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

一般来说,浮点型更容易出现问题。2/7带
float
s可能略有不同


使用
int
s时,无论进行何种优化,它都应始终为0,即使它乘以7。

尝试并查看程序集

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

一般来说,浮点型更容易出现问题。2/7带
float
s可能略有不同


对于
int
s,无论进行何种优化,它都应始终为0,即使它乘以7。

以下是g++中
-O3
相当于的标志列表:

现在,如果你仔细看,还有一个
-Ofast
,它被定义为
-O3
+其他一些,特别是
-ffast-math
。在
-ffast math
的说明中,您可以阅读:

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

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

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

顺便说一句,
Mult10*=10,挖--您是否试图失去遵循代码的人=D


编辑:另一个顺便说一下,查看
-O3
没有效果。除了一些人说你可能会溢出一些内部变量。我没有测试溢出,但我确信在编写本文时,
-O4
-O100
相当于
-O3

以下是g++中的
-O3
相当于的标志列表:

现在,如果你仔细看,还有一个
-Ofast
,它被定义为
-O3
+其他一些,特别是
-ffast-math
。在
-ffast math
的说明中,您可以阅读:

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

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

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

顺便说一句,
Mult10*=10,挖--您是否试图失去遵循代码的人=D


编辑:另一个顺便说一下,查看
-O3
没有效果。除了一些人说你可能会溢出一些内部变量。我没有测试溢出,但我确信在编写本文时,
-O4
-O100
相当于
-O3

以下是g++中的
-O3
相当于的标志列表:

现在,如果您仔细观察,还有一个定义为
-O3的
-Ofast