电脑疯子技术论坛|电脑极客社区

微信扫一扫 分享朋友圈

已有 519 人浏览分享

GCC 对于加法运算的优化

[复制链接]
519 0
编译器对于加法运算的优化

优化常见的几种方式

常量传播

将编译期间可计算出结果的变量转换为常量,减少变量的使用

#include <iostream>
int main()
{
    int nVar = 1;
    printf("nVar = %d \n",nVar);
}

对于上述代码,如果没有进行优化,那么处理的逻辑为:

QQ截图20221025143607.png

会先将该值放入栈中,在 printf要输出它时,再将其拿到 esi中,通过 rsi传给 printf进行输出

进行 O1优化以后

666.png

由于变量 nVar是一个在编译期间可以计算出结构的变量,所以将其替换为常量直接用1来替代
printf要使用时直接传入1即可。

O2优化中在对变量的处理一致

659.png

常量折叠

在公式中出现多个常量进行计算的情况中,且编译器可以算出结果的情况下,在编译期间直接用计算结果替代

#include <iostream>

int main()
{
    int nNum = 1 + 8 * 7 - 10;
    printf("nNum = %d \n",nNum);
}

对于上述代码,如果没有进行优化,那么处理的逻辑为:

658.png

但其实这也进行了一定的优化,没有将常量的计算生成对应的计算指令,而是编译器直接将计算的结
果传入栈中,接下来再从栈中拿值

进行 O1优化以后

656.png

此时在上面的基础上,没有将结果放入栈中,由于后面 printf要使用该参数,直接传入 edx
后面通过 rdx直接传入 printf

复写传播

#include <iostream>

int main(int argc)
{
    int nNum = argc;
    printf("nNum = %d \n",nNum);
}

此时我们将 main函数的参数值赋给了 main中的变量 nNum

对于上述代码,如果没有进行优化,那么处理的逻辑为:

339.png

可以看到,为了将 edi中的的参数 1 (argc)放入到栈 nNum的位置,进行了很繁琐的操作

进行O1优化以后

338.png

直接删除掉了 nNum(因为之后没有对 nNum重新赋值) 用存在于 edi中刚刚传入的 argc
值直接代替他就完事了

337.png

后面调用 printf时,由于其已经被传入了 edi,若直接通过 rdi传给 printf就完事了,非常的简便

具体在代码中的优化

#include <cstdio>
#include <iostream>
int main()
{
    int nVarOne = 0;
    int nVarTwo = 0;
    nVarOne = nVarOne + 1;
    nVarOne = 1 + 2;
    nVarOne = nVarOne + nVarTwo;
    printf("nVarOne = %d \n",nVarOne);
    return 0;
}

对于上述代码,如果没有进行优化,那么处理的逻辑为:

336.png

但还是在编译期间提前做了进行了简单的将常量的计算

进行O1优化以后

335.png

代码结构发生大变,处理的流程为:

常量替换变量,所以 nVarOne``nVarTwo开始都被直接替换为常量 0
接下来代码中对 nVarOne做了两次赋值操作,由于第二次赋值操作会覆盖第一次赋值的操作
所以直接去掉第一次赋值,第二次赋值为 3
再次用常量替换变量,由于 printf会使用到该参数,直接把 3 传入 edx,等待后续通过 rdx传入 printf即可
所以最终反映到汇编指令中,只有一条 mov edx,0x3实属省事啊。。。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

关注

0

粉丝

9021

主题
精彩推荐
热门资讯
网友晒图
图文推荐

Powered by Pcgho! X3.4

© 2008-2022 Pcgho Inc.