大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说编译原理笔记(七)之代码优化「建议收藏」,希望能够帮助大家进步!!!
代码优化
- 1. 局部优化
- 1.1 基本块的优化
- 1.2 窥孔优化
- 1.3 表达式的优化代码生成
代码优化的含义:进行一系列的保持语义的等价变换,逐步将代码段A变换成代码段B
1. 局部优化
包括:基本块的优化、窥孔优化、表达式优化等;
1.1 基本块的优化
- 基本块的DAG表示 许多局部优化的重要技术都是从将基本块变换为有向无环图(简称DAG) 开始的。第4章已经简单介绍了表达式的DAG表示,目的是消除树中的公共子树。现在我们将DAG的概念扩展到一个基本块中的表达式集合,用下述方法构造基本块的DAG:
- 出现在基本块中的每个变量的初始值在DAG中有一个节点。
- 块中的每条语句s关联一个节点N。N的孩子节点是那些先于s并且是s中所用变量的最后定值的语句对应的节点。
- 节点N由s 中的算符所标记,同时与N关联的有一个在块中最后定值的变量列表。(4)某些特定的节点被称为输出节点。输出节点的特点是其中的变量在退出基本块后仍然活跃,即变量的值在流图的其他基本块中可能会被引用。找出局部公共子表达式
当需要在DAG中加入一个新节点M时,考察是否已存在其孩子个数、次序以及运算符均与M相同的节点N,若有,则N和M计算的是相同的值并且可以用N取代M.
- 死代码消除 DAG上对应死代码消除的操作可以这样实现:从 DAG中删除没有附加任何活跃变量的根(即没有前驱的节点)。重复此操作可以消除掉DAG中所有相应的死代码。
- 代数恒等式的使用 基本块优化中重要的一类是利用代数恒等式化简。例如,可以用下述算术恒等式消除基本块中的一些计算: x 0=0 x = x x -0-x x_1=1_x = x x/1 =x 另一类优化被称为强度削弱,即用开销小的运算代替开销大的运算,例如用x*x代替,用x x 代替2*x,用x*0.5代替x/2,等等。 第三类优化是常量求值。将编译时可以确定的常量表达式的值计算出来并且用值替换常量表达式,例如常量表达式2*3.14可以被替换为6.28. 还有一类优化利用基本块的 DAG实现。DAG的构造过程可以帮助我们应用如交换律和结合律这样的变换。例如,如果程序设计语言中规定*是可交换的,即x*y = y*x,那么当生成左孩子是M、右孩子是N的“*”节点时,除了查看此节点是否已存在之外,也需要检查左孩子是N、右孩子是M的“*”节点是否存在。
- 数组引用的表示
- 指针赋值与过程调用
- 有DAG重组基本块
1.2 窥孔优化
另一个简单但有效的目标代码的局部改进技术是“窥孔优化”。通过考察目标代码的一个被称为窥孔(peephole)的滑动窗口,尽可能用较短、较快的代码序列代替原来的序列。窥孔优化也可以应用在独立于机器的优化中以改进中间代码。
窥孔是程序中的一个小的滑动窗口。窥孔中的代码无需连续(尽管有些实现要求它们连续)。窥孔优化的一个重要特征就是每一个改进都给后边的改进提供机会,所以为了达到最大收益,有时需要反复扫描目标代码。下面是几个典型的窥孔优化的程序变换。
1.3 表达式的优化代码生成
当一个基本块中仅有一个表达式或者有足够的资源一次生成基本块中的表达式的目标代码时,可以优化地选择寄存器。下述算法中,为表达式树(表达式的语法树)节点引入一种计数模式,以帮助生成有固定个数寄存器的表达式树上表达式计算的优化代码。