C++ 是什么阻止gcc优化此函数?

C++ 是什么阻止gcc优化此函数?,c++,gcc,compilation,compiler-optimization,C++,Gcc,Compilation,Compiler Optimization,在我的一节课上,我们讨论了编译器如何很好地优化我们自己糟糕的代码 我正在测试它,并编写了以下两个非常可怕的函数 unsigned int add2 (unsigned int a, unsigned int b) { unsigned int sum = a; for (int i = 0; i < b; i++) { sum++; } return sum; } unsigned int mul2 (unsigned int a, uns

在我的一节课上,我们讨论了编译器如何很好地优化我们自己糟糕的代码

我正在测试它,并编写了以下两个非常可怕的函数

unsigned int add2 (unsigned int a, unsigned int b) {
    unsigned int sum = a;
    for (int i = 0; i < b; i++) {
        sum++;
    }
    return sum;
}

unsigned int mul2 (unsigned int a, unsigned int b) {
    unsigned int result = 0;
    for (int i = 0; i < a; i++) {
        result = add2(result, b);
    }
    return result;
}
unsigned int add2(unsigned int a,unsigned int b){
无符号整数和=a;
对于(int i=0;i
使用
-O3
-Ofast
编译时,
add2
函数直接编译为简单的加法。然而,
mul2
函数的指令和分支非常混乱。我不会单独考虑这个问题,但是如果你把这个调用改为<代码> ADD2<代码>,简单地添加<代码>结果< /代码>和<代码> b>代码>编译器将它直接优化为一个乘法指令。p> 这看起来很奇怪,因为编译器本质上认为
add2
是一个加法,而编译器认为
mul2
是一个乘法,为什么当它们组合在一起时它不能正确地优化它呢

更明确地显示这一点

编辑:

我更感兴趣的是,通过编译将
-Os
编译为标准乘法指令来优化空间。这似乎意味着另一个版本更快,这似乎没有任何意义


输出显示代码在其当前形式下是正确的,至少对于琐碎的输入是正确的。

代码非常好-它以优化的方式完全按照您的要求执行。但是,mul2中有一个逻辑错误。考虑代码纠正时的输出:@ ReHaveHdges,我添加了一个链接,该版本生成一个控制台输出进行测试,正如您将看到的,更改为+=产生不正确的结果作为结果,B已经被添加到ADD2功能中,是的,我的歉意。我看错了。有趣的是,-O2的代码也比-O3短。看起来-O3更喜欢展开循环,而不是用乘法替换多个加法。确实很有趣。然而,我不想说“一堆糟糕的指令”,因为它只是内联函数
add2
(我用ARM编译器看了一下,因为我更喜欢它)。可能只是GCC优化算法的一个限制,但很难理解根本原因。根据我的经验,通常很难理解所做的优化,即使这些优化显然有99%的时间是合理的。无论是加法还是乘法,替换都是在SCCP过程中完成的。当add2(尚未优化)内联到mul2中时,SCCP确实能够优化加法,但是我们可能需要几个过程来清理这些内容,然后重新运行SCCP来优化乘法。这并没有做到,因为它会增加编译时间以获得很少的收益。如果您愿意,您仍然可以在gcc的bugzilla上提交一个增强请求,也许有一些简单的技巧可以让SCCP优化外部循环。