编译原理复习---中间代码优化

适用于电子科技大学编译原理期末考试复习。

1. 基本块

基本块(Basic Block)是程序中一段连续的指令序列,它具有以下特点:

  1. 只有一个入口:程序只能从基本块的第一条指令进入。

  2. 只有一个出口:程序只能从基本块的最后一条指令离开。

  3. 顺序执行:基本块内的指令按照顺序依次执行,不会出现分支或跳转。

基本块在编译过程中是一个重要的概念,它是编译器进行代码优化和分析的基本单位。通过将程序划分为基本块,编译器可以更好地理解程序的结构和逻辑,从而进行各种优化操作,例如循环优化、代码重排和冗余代码消除等。

基本块的划分方法

基本块的划分通常基于程序的控制流图(Control Flow Graph, CFG)。以下是划分基本块的一般步骤:

  1. 确定入口语句

    • 程序的第一条语句。

    • 转移语句(如条件跳转或无条件跳转)的目标语句。

    • 紧跟在条件转移语句后面的语句。

      扫描二维码关注公众号,回复: 17570238 查看本文章
  2. 划分基本块

    • 每个入口语句对应一个基本块。

    • 基本块由该入口语句到下一入口语句(不含下一入口语句),或到一转移语句(包括该转移语句),或到一停语句(包括该停语句)之间的代码序列组成。

  3. 删除不可达语句:凡未被纳入某一基本块的语句,都是程序中控制流程无法到达的语句,可以删除。

2. 流图

流图的结点是基本块。从基本块B到基本块C之间有一条边当且仅当基本块C的第一个指令可能紧跟在B的最后一条指令之后执行。

有两种方式可以确认这样的边:

  • 有一个从B的结尾跳转到C的开头的条件或无条件跳转语句。

  • 按照原来的三地址语句序列中的顺序,C紧跟在之B后,且B的结尾不存在无条件跳转语句。

3. 局部优化

局部优化(Local Optimization)是指在编译过程中,对程序的基本块进行优化的过程。

局部优化的方法:

  1. 常量传播:如果一个变量在基本块内被赋值为常量,那么在后续使用该变量的地方可以直接使用该常量。

  2. 删除公共子表达式:如果基本块内有多个相同的表达式,可以只计算一次,并在后续使用该表达式的地方重用结果。

  3. 删除死代码:如果基本块内有一些代码在任何情况下都不会被执行,可以将其删除。

  4. 删除无用赋值:无用赋值是指在程序中,某个变量被赋值后,其值在后续的代码中从未被使用过。这种赋值操作是冗余的,因为它不会影响程序的输出或行为。

  5. 复写传播:变量的值在被复制后没有被修改。在这种情况下,编译器可以将使用被复制变量的地方替换为使用原始变量,从而消除不必要的变量使用。

3.1 常量传播

 A = op B 或者 A = B op C

若B和C都是常数,则在编译时可将A的值计算出来。

例如:x = 5; y = x * 2; z = a[y]; ,可以替换为 z = a[10]。(至于x和y能不能删除的问题,需要涉及到活跃变量分析)

3.2 删除公共子表达式

U = A - C * D
V = B + C * D

如果两个语句之间C和D的值未改变    则将公共表达式结果记为T:

T = C * D
U = A - T
V = B + T

3.3 删除死代码

if B then S1 else S2

如果B的值固定为 “真” 或 “假” ,则其中一个分支永远不会执行,这些分支的代码可以删除。

3.4 删除无用赋值

A = B + C
...
A = M + N

假如在两次赋值之间,A没有被使用过,那么第一个赋值语句就可以被删除。

3.5 复写传播

B = A
...
C = B * 2

假如两句代码之间,B的值没有发生变化,则可以用A来代替B。

B = A
...
C = A * 2

复写传播本身对效率没有任何提升,但是却为无用赋值的出现创造了条件。例如上面的例子中,我们减少了对B的使用,使得 B = A 这一语句更有可能成为无用赋值而被删除。

4. 全局优化

这里,我们只讨论对循环的优化。

  • 循环:程序流图中有唯一入口结点的强连通子图。

  • 强连通子图:任意两个结点均可互相连通的子图。

  • 入口结点n:从循环外到循环内任何结点的所有通路都必通过此入口结点。

  • 子图的首结点:子图中最早被执行的结点。

4.1 流图中的循环

  • 必经结点:从程序流图的首结点出发,到达结点n的任一通路都必须经过的结点d,称d为n的必经结点,记为d DOM n。任何结点都是自己的必经结点。

  • 必经结点集:程序流图中结点n的所有必经结点的集合称为n的必经结点集,记为D(n)。

  • 回边:对于程序流图G = (N, E, n0)中的有向边n→d,如果d是n的必经结点,即d∈D(n) ,则称n→d为流图的一条回边。

程序流图G = (N, E, n0)中,n → d是回边,M是G中到达n而不经过d的结点集合,则{n, d} ∪ M 构成一个循环。

4.2 循环的优化方法

  1. 代码移动(代码外提):将循环不变量(即在循环中不改变的表达式)移到循环外面,减少计算量。

  2. 强度削弱:将一些复杂的运算替换为更简单的运算,例如将乘法替换为加法。

  3. 删除归纳变量:如果基本块内有一些代码在任何情况下都不会被执行,可以将其删除。

 

猜你喜欢

转载自blog.csdn.net/2302_80372340/article/details/144631145
今日推荐