代码优化- 基本概念

思考一个问题:我们可以再抽象语法树上做编译优化吗?

答案是否定的,如果在抽象语法树上做编译优化的话,程序员所写的可能包含错误的代码,可能就被删除了,比如,对下面的程序做不可达代码删除优化,printf中应该首先给一个格式化字符串,而不是一个整型数,所以存在语义错误,如果先做优化,由于总是执行then分支,else分支执行不到,所以会把else分支删除,只保留if部分,那么编译器就不会爆语义错误了。这就违反了编译器中的一个基本原则--不能违反源程序的语义性质,这样的程序做类型检查时,程序员期待编译器报错,如果优化先做的话,那么这个错误消失了,所以对程序员理解这个程序的含义是相互矛盾的。

if (1) 
{
    ...
}
else
{
    printf(2);
}

所以必须要在语义分析做完之后,再做编译优化。

(注:图中的抽象语法树是做完语义分析之后的)

优化并不是局限于某一个中间表示,而是依附于不同的中间表示,在每一层上都可以做。

什么是代码优化?

代码优化是对被优化的程序进行的一种语义保持变换

语义保持:程序的可观察行为不能改变

变换的目的是让程序能够比变换前更小、更快、Cache行为更好、更节能等等

不存在“完全优化”

等价于停机问题:给定程序p(循环不终止的程序),把Opt(p)和下面的程序比较

(扩展:停机问题是可计算性和计算复杂性的基本定理:给定程序P,是否存在算法Q,Q将P作为输入,判断P是否可以运行终止。这是个不可计算问题,即不存在这样的算法Q)

L:
    jmp L

如果存在一个完全优化算法Opt,那么最终会将程序p优化成上面的样子,但是由于停机问题是不可计算问题,所以不可能存在这样的完全优化算法Opt。

这样的结论告诉我们,编译优化是一个没有尽头的过程。换句话说,我做完了第一个优化,将程序P通过O1优化为P1,为了加快程序的运行,我们可以继续通过O2将程序P1优化为P2,可以这样一直进行下去,也就意味着程序总是可以被优化的。

代码优化很困难

●  不能保证优化总能产生“好”的结果

●  优化的顺序和组合很关键

●  很多优化问题是非确定的

●  优化的正确性论证很微妙

对待编译优化正确的观点

(1)“把该做对的做对”,不是任何程序都会同概率出现,所以能处理大部分常见情况的优化就可以接受。

(2) “不期待完美编译器”,如果一个编译器有足够多的优化,则就是一个好的编译器。

编译优化路线图 

(1)前端优化

局部的、流不敏感的

常量折叠、代数优化、死代码删除等

(2)中期优化

全局的、流敏感的

常量传播、拷贝传播、死代码删除、公共子表达式删除等

(3)后端优化

在后端(汇编代码级)进行

寄存器分配、指令调度、窥孔优化等
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青衫客36

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值