窥孔优化
用类似于前面所介绍的简单代码产生器依次地把一条条中间代码翻译为目标代码时,可能会使目标代码中包含冗余的指令或者出现不太优的结构。在目标代码这一级上,我们可以借助于一种简单但有效的技术改进代码质量,它就是窥孔优化(peephole opti-mization)。窥孔优化方法是通过考察一小段目标指令(称为窥孔)并把这些指令替换为更短和更快的一段指令,从而提高目标代码的质量。
这里,窥孔是目标程序中的一个可移动的小窗口。窥孔中的代码不一定是相邻的,尽量有的实现有这样的要求。窥孔优化的一个特点是,优化后所产生的结果可能会给后面的优化提供进一步的机会。为了得到最大的优化效果,有时需对目标代码进行若干遍的处理。下面介绍几种典型的窥孔优化技术。
l 冗余存取
如果有下面指令:
(1)ST R0,A
(2)LD R0,A
则我们可删除指令(2)。因为指令(1)的执行能够保证A的值在R0中。注意,如果(2)带有标号,我们就不能保证指令(2)一定是紧接着(1)执行,这时不能删除(2)。如果(1)和(2)在同一个基本块,这种变换一定是安全的。
还要说明一下的是,如果我们采用的是11.3节中的代码生成算法,则上述指令序列不会出现。
l 不可达代码
另一种窥孔优化是删除不可达代码。在无条件转跳指令之后的无标号指令应该删除。这种操作可以重复,删除一序列指令。
例如,出于调试目的,在一个大程序里可能会插入一些调试语句,这些调试语句只有在调试“开关”打开时(即 debug为 1时)才执行。用 C语言写的源代码如下:
# define debug 0
…
if(debug) {
打印调试信息
}
翻译为中间代码可能是
if debug﹦1 goto L1
goto L2
L1: 打印输出调试信息
L2: …
经过初步优化,可能把它转换为
if debug≠1 goto L2
打印调试信息
L2:
现在,既然在程序开始时已把debug置为0。因此debug ≠l相当于0 ≠l,它的值恒为真。因此,上述程序段相当于
goto L2
打印调试信息
L2:
显然打印调试信息的指令序列是不可达的,应该在这时把它删除。
l 控制流优化
按照第七章介绍的中间代码生成算法,可能会产生连续跳转的情况。这种不必要的连续跳转可以在窥孔优化时删除。例如:
goto L1
…
L1:goto L2
可以替换为
goto L2
…
L1:goto L2
现在,如果没有别的语句跳到 L1,则如果 L1:goto L2是紧跟在一个无条件语句之后,就可以把它删除。
类似地,代码
if a < b goto L1
…
L1:goto L2
可以替换为
if a < b goto L2
…
L1:goto L2
还有一种情况,如果只有一条指令跳向L1,而且L1是紧跟在一条无条件指令的后面,则代码序列
goto L1
…
L1: if a < b goto L2
L3:
可以替换为
if a < b goto L2
goto L3
…
L3:
显然替换后的指令条数与原来一样,但后一种情况有时可跳过无条件转换,而在前一种情况无条件转换总是要执行。
l 强度削弱
有的指令可以用花费时间更短的指令代替。如假设shiftleft为左移操作指令,则
MUL R,#2 可替换为 shiftleft R,#0
MUL R,#4 可替换为 shiftleft R,#2
l 删除无用操作
有的操作的执行不会改变数据的结果,这种操作可看成无用操作,可以删除。如
ADD R,#0
MUL R, #1
都是无用操作,可以把它们删除。
还有其它一些窥孔优化技术,我们不一一介绍。
相关阅读:
下一篇文章:没有了
网友评论:
- 最新试题
- 考试大纲
加载中...
返回顶部


