第11章 代码优化

合集下载

编译原理第十一章解析

编译原理第十一章解析
25
26
此处要用到的有向图,是一种其结点带有下述标记或附 加信息的DAG: ① 图的叶结点,即无后继的结点,以一标识符(变 量名)或常数作为标记,表示这个结点代表该变量或常数 的值。如果叶结点用来代表某变量A的地址,则用addr (A)作为这个结点的标记。通常把叶结点上作为标记的 标识符加上下标0,以表示它是该变量的初值。 ② 图的内部结点,即有后继的结点,以一运算符作为 标记,表示这个结点代表应用该运算符对其后继结点所代 表的值进行运算的结果。 ③ 图中各个结点上可能附加一个或多个标识符,表 示这些变量具有该结点所代表的值。
30
下面是仅含0,1,2型四元式的基本块的DAG构造算法。
首先,DAG为空。 对基本块的每一四元式,依次执行: 1. 如果NODE(B)无定义,则构造一标记为B的叶结点并定 义NODE(B)为这个结点; 如果当前四元式是0型,则记NODE(B)的值为n,转4。 如果当前四元式是1型,则转2.(1)。 如果当前四元式是2型,则:(Ⅰ)如果NODE(C)无定义, 则构造一标记为C的叶结点并定义NODE(C)为这个结点,(Ⅱ) 转2.(2)。 2. (1) 如果NODE(B)是标记为常数的叶结点,则转2.(3), 否则转3.(1)。 (2) 如果NODE(B)和NODE(C)都是标记为常数的叶结 点,则转2.(4),否则转3.(2 (3) 执行op B(即合并已知量),令得到的新常数为P。如 果NODE(B)是处理当前四元式时新构造出来的结点,则删除它。 如果NODE(P)无定义,则构造一用P做标记的叶结点n。置NODE (P)=n,转4.。 (4) 执行B op C(即合并已知量),令得到的新常数为P。如 果NODE(B)或NODE(C)是处理当前四元式时新构造出来的结 点,则删除它。如果NODE(P)无定义,则构造一用P做标记的叶 结点n。置NODE(P)=n,转4.。

7hh第11章 代码优化

7hh第11章 代码优化

注意: ① 转移语句结点的右边可附加一语句 位置, 用于指示转移目标, 其余结点 的右边只允许附加标识符;
② 数组元素赋值的结点有三个后继 , 其余结点最多只有两个后继。
利用DAG进行优化的基本思想: 首先按基本块内四元式序列的顺 序把所有四元式构造成一个 DAG, 然后按构造结点的次序将 DAG 还 原成四元式序列。 由于在构造 DAG 的同时作了局部 优化{合并已知量、删除公共子表 达式、删除无用赋值}, 因此, 得到 的是优化的四元式序列。
DAG构造算法的基本步骤: (1) 构造叶结点 (2) 合并已知量 (3) 构造op结点 {删除公共子表达式} (4) 添加附加信息 {删除无用赋值}
基本块的DAG构造算法: { 仅含0,1,2型四元式: A=B, A= op B, A=B op C } (1) 构造叶结点: 若 Node(B) 无定义 , 则构造一标记 为B的叶结点, 并做下述处理: ①若当前四元式是0型, 转(4); ②若当前四元式是1型, 转(2)①; ③若当前四元式是2型, 则 若Node(C)无定义, 则构造一标 记为C的叶结点; 转(2)②;
两者对比:
(1) T0 = 3.14 (2) T1 = 2*T0 (3) T2 = R+r (4) A = T1*T2 (5) B = A (6) T3 = 2*T0 (7) T4 = R+r (8) T5 = T3*T4 (9) T6 = R-r (10) B = T5*T6
(1) T0=3.14 (2) T1=6.28 (3) T3=T1 (4) T2=R+r (5) T4=T2 (6)A=6.28*T2 (7) T5=A (8) T6= R−r (9) B=A*T6
11.1.2 基本块的DAG表示

代码优化的概念

代码优化的概念

代码优化的概念代码优化是指通过对程序进行调整和重构来提高代码的效率和性能,以达到更好的运行效果和用户体验。

优化的目标是在不改变程序功能的前提下,尽可能减少时间和空间的占用,使程序更加高效、可维护和可扩展。

优秀的代码优化不仅能提高代码的执行速度、响应速度和稳定性,还能改善代码的可读性和可维护性,有利于程序完整性的保持和可靠性的提高。

代码优化的重要性代码优化是开发过程中必不可少的环节,因为优化后的代码相较于低效的代码,具备以下优势:1. 提高程序运行效率:绝大多数程序的瓶颈在于运行时间和机器资源的占用,而代码优化可以通过降低算法复杂度、减少不必要的循环和分支、避免重复计算等方式,使程序运行速度更快,更加节省计算机资源占用。

2. 改善用户体验:快速响应和流畅的界面对于用户来说是至关重要的,而优化的代码可以使程序更加快速响应,避免界面卡顿和延迟,从而提高用户的使用体验。

3. 提高程序稳定性:优化后的代码往往更加清晰、逻辑更加严谨、异常处理更加完善,从而可以减少程序崩溃和错误的发生,提高程序的健壮性和可靠性。

4. 提高代码可维护性:优化后的代码结构更加清晰,名称规范可读性更高,抽象层次更为明确,从而可以减少后期编码的时间和困难,增强代码的可维护性和可扩展性。

代码优化的方法和技巧对代码进行优化通常需要考虑多种方式和角度,下面列举几种常用的优化方法和技巧:1. 使用高效的算法和数据结构:优化程序的算法和数据结构是优化代码的基础,它可以显著提高程序性能。

对于复杂程序来说,使用适当的数据结构(如散列表、二叉树、图等)可以有效减少程序的运行时间。

此外,应该尝试使用高效的排序算法和查找算法(如归并排序、快速排序、二分查找等)来进一步提高程序的效率。

2. 避免重复计算和内存浪费:在编写代码时应该避免进行重复计算,避免浪费计算资源占用。

同样,应该尽可能避免内存浪费(如重复创建列表对象、使用过多的全局变量等),这不仅会浪费更多的内存,而且会导致程序变慢。

代码优化

代码优化

(5) T3:=T2[T1] (6) T4:=T1 (8) T6:=T5[T4] (9) T7:=T3*T6 (10)PROD:=PROD+T7 (11)I:=I+1 (3’) T1:=T1+4 (12)if I<=100 goto (5)
9
2013-8-12
莆田学院许振和
对于这个中间代码段,可用以下六种方法进 行优化:
① 删除多余运算(公共子表达式): 如(3),(6)都用了4*I,而I在(3)(6)之间并没有变化, 所以(6)可以用T4:=T1代替。 ② 代码外提: (4),(7)中的地址运算每次执行时都完全一样,因此 没有必要每循环一次运行一次,可以提到循环体的外面。 ③ 强度削弱: 把乘除运算转换成加减运算,如中间代码块B2中的 T1:=4*I,I每增加1,则T1增加4。所以可以用加法来代 替。经过上述变化,中间代码Ⅰ可以变成Ⅱ的形式。
2013-8-12
莆田学院许振和
12

(1) (4) (7) (3) PROD:=0 T2:=addr(A)-4 T5:=addr(B)-4 T1:=4 从Ⅰ到Ⅲ,程序运行 结果一点没变,但是少 了:200次乘法、198次 减法,少用了一个存储 单元I和一个临时单元T4。 显然,运算速度大大加 快,占用空间相对减少 了。 以上介绍的是具体采 用的优化措施,根据这 些措施应用的范围不同, 通常把优化分成三个级 别:局部优化,循环优 化和全局优化,以下分 别讨论。
2013-8-12 莆田学院许振和 15
例:求最大公因子 (1) read X (1) read X (2) read Y (2) read Y (3) R:=X mod Y (3) R:=X mod Y (4) if R=0 goto (8) (4) if R=0 goto (8) (5) X:=Y (6) Y:=R (8) write Y (5) X:=Y (7) goto(3) (9) halt (6) Y:=R (8) write Y (7) goto(3) (9) halt

编译原理课后第十一章答案

编译原理课后第十一章答案

对假设(2) B:=3 D:=A+C E:=A*C F:=D+E K:=B*5 L:=K+F
计算机咨询网()陪着您
10
《编译原理》课后习题答案第十一章
第7题 分别对图 11.25 和 11.26 的流图: (1) 求出流图中各结点 n 的必经结点集 D(n)。 (2) 求出流图中的回边。 (3) 求出流图中的循环。
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13)
i:=m-1 j:=n t1:=4*n v:=a[t1] i:=i+1 t2:=4*i t3:=a[t2] if t3< v goto (5) j:=j-1 t5:=4*j t5:=a[t4] if t5> v goto (9) if i >=编译原理》课后习题答案第十一章
第 5 题: 如下程序流图(图 11.24)中,B3 中的 i∶=2 是循环不变量,可以将其提到前置结点吗? 你还能举出一些例子说明循环不变量外移的条件吗?
图 11.24 答案: 不能。因为 B3 不是循环出口 B4 的必经结点。 循环不变量外移的条件外有: (a)(I)s 所在的结点是 L 的所有出口结点的必经结点 (II)A 在 L 中其他地方未再定值 (III)L 中所有 A 的引用点只有 s 中 A 的定值才能到达 (b)A 在离开 L 之后不再是活跃的,并且条件(a)的(II)和(III)成立。所谓 A 在离开 L 后不再是活跃的是指,A 在 L 的任何出口结点的后继结点的入口处不是活跃的(从此点后 不被引用) (3)按步骤(1)所找出的不变运算的顺序,依次把符合(2)的条件(a)或(b)的 不变运算 s 外提到 L 的前置结点中。如果 s 的运算对象(B 或 C)是在 L 中定值的,则只有 当这些定值四元式都已外提到前置结点中时,才可把 s 也外提到前置结点。

代码优化概述

代码优化概述

代码优化概述1.1.代码优化简介代码优化是指对程序进行各种等价变换,使得从变换后的程序出发,能生成更高效的目标代码。

目标代码的质量,通常有两个衡量的标准:空间效率和时间效率。

有时空间优化也会导致时间优化(如减少指令条数),但通常它们是一对矛盾,不能兼顾。

代码优化的目的是产生更高效的代码,使程序以更快的速度、占用更少的空间运行。

对于编译器,代码优化分为三个阶段:图1-1 代码优化流程图为了获得更优化的程序,可以从各个环节着手。

首先,在源代码这一级,程序员可以通过选择适当的算法和安排适当的实现语句来提高程序的效率。

其次,再设计语义动作时,要尽可能产生高效的中间代码,同时还可以安排专门的编译优化阶段对中间代码进行各种等价变换,改进代码的效率。

最后,在目标代码这一级上,应该考虑如何有效地利用寄存器,如何选择指令,以及进行窥孔优化等。

对于编译优化,最主要的时机是在语法、语义分析生成中间代码之后,在中间代码上进行。

这一类优化不依赖于具体的计算机,而取决于语言的结构。

另一类优化则是在生成目标程序时进行的,它在很大程度上与具体的计算机有关。

由优化编译程序提供的对代码的各种变换必须遵循如下原则[1]:1)等价:经过优化后不改变程序运行的结果;2)有效:优化后产生的目标代码运行时间较短,占用的存储空间较小;3)合算:应尽可能以较低的代价取得较好的优化效果。

如果为实现一种优化变换所花时间和精力,以及编译器编译源程序时的额外开销,不能从目标程序的运行中得到补偿,那么是没有意义的。

在设计一个编译程序时,究竟应考虑哪些优化项目以及各种优化项目进行到何种程度,应权衡利弊,根据具体情况而定。

其中,控制流分析主要目的是分析出程序的循环结构.循环结构中的代码的效率是整个程序的效率的关键。

数据流分析进行数据流信息的收集,主要是变量的值的定义和使用情况的数据流信息.包括到达-定值分析;可用表达式;活跃变量。

最后,根据上面的分析,对中间代码进行等价变换。

代码优化

代码优化
第11章 代码优化
主要内容
优化的概念 代码优化的基本技术 局部优化 机器代码优化-窥孔技术
2
11.1 代码优化的概念
代码优化在整个编译过程的位置
源程序 编译前端 中间代码 中间代码生成 中间代码 目标代码生成 目标程序
中间代码
中间代码优化
目标代码优化
程序员和编译器可能改上程序的位置
同样,可以对归纳变量i和t2进行强度消弱。
17
11.2 代码优化的基本技术
对t4 := j*4 和t2 := i*4完成强度消弱以后, 变量i和j除了在B4中语句if i>= j goto B6
之外,不再被引用。因此,可以删除这 些归纳变量i和j,把这个语句变换为if t2 >= t4 goto B6。 经过强度消弱和删除归纳变量,图11.7以及 图11.5最后就变换为图11.8。
11
11.2 代码优化的基本技术
删除公共子表达式后的B5和B6 分别是
B5
B6
t6 := t2 x := a[t6] t7 := t6 t8 := t4 t9 := a[t8] a[t7] := t9 t10 := t8 a[t10] := x goto B2
t11 := t2 x := a[t11] t12 := t11 t13 := t1 t14 := a[t12] a[t12] := t14 t15 := t1 a[t15] := x
这种变换称为代码外提。在给出的快速排序程序中, 没有可以代码外提之处。
16
11.2 代码优化的基本技术
强度消弱和删除归纳变量
考察图11.7的循环B3。j和t4的值保持着线性关系 t4 := j*4,每循环一次,j的值每减1,t4的值就减 去4。这种变量称为归纳变量。

北京航空航天大学《编译原理》第11章 代码优化(2)

北京航空航天大学《编译原理》第11章 代码优化(2)

global_c s_c
运行栈
子程序/函数运行时所需的基本空间 进入子程序/函数时分配,地址空间向下生长 (从高地址到低地址) 从子程序/函数返回时,当前运行栈将被废弃 递归调用的同一个子程序/函数,每次调用都 将获得独立的运行栈空间
运行栈
一个典型的运行栈包括
函数的返回地址 全局寄存器的保存区 临时变量的保存区 未分配到全局寄存器的局部变量的保存区 其他辅助信息的保存区
主要内容
中间代码(补充) 代码生成 代码优化 现代编译技术综述
代码生成
代码生成器的总体设计 目标程序 运行时的存储管理 指令选择 寄存器的分配和管理
代码生成器在编译系统中的位置
中间代码 源程序 前端 优化器
中间代码
代码生成 器
目标程序
符号表
教学编译器架构
代码生成器的输入
源程序的中间表示
线性表示(波兰式) 三地址码(四元式) 栈式中间代码(P-CODE/Java Bytecode) 图形表示
丰富的运行库支持
J2ME:CLDC1.1, MIDP2.0, etc. J2SE:SWING, AWT, etc.
Java字节码举例: z = x + 1
iload x iconst_1 iadd
mov eax, esi add eax, 1
x 1 x x+1
esi 1 esi eax
istore z
(下载到本地)
Class loader
(Bytecode verification)
Java class libraries
Java Just-in-time Interpreter compiler
Run-time System Java 字节码 (*.class)

第十一章代码优化

第十一章代码优化
➢G中(3)(7)的公共子表达式R+r
只计算一次,删除了多余运算
利用DAG进行优化
删除在基本块后不被引用变量的赋值
假如T0,T1,…,T6在基本块后 都不被引用,则这些符号可在
DAG附加标识符中删去,重写四
n6
元式得到进一步的优化:
*
(1) S1:=R+r
(2) A:=6.28*S1
n8 B *
A, T5
n T0
31.14
8* n A, B,T5
6*
T2,T4
n
n T6
5+
-7
n T1,T3 n
n
62.28
3R
4r
➢ni是结点编号
➢结点下面的符号(运算符、标识符或常量) 是各结点的标记
➢结点右边的标识符是结点的附加标识符
2. 四元式及其相应的DAG结点形式
0型: A:=B (:=, B, -,A) n1 A
(6) T3:=2*T0 (7) T4:=R+r (8) T5:=T3*T4 (9) T6:=R-r (10) B:=T5*T6
n1 T0 3.14
2
n8 B
*
n6 A ,B ,T5
*
n5 T2 ,T4 n7 T6
+

n2 T1 ,T3 n3
n4
6.28
R
r
2
11.2.3 DAG的应用
在一个基本块被构造成相应的DAG的过程中, 进行了如下基本的优化工作: 1) 合并已知量 在DAG构造算法中,如果运算量都是已知量, 则不生成计算该结点值的内部结点,而执行 该运算,将计算结果生成一个叶结点,实现 了合并已知量优化

第11章 代码优化 new

第11章 代码优化 new

数等价的集合:如x:=x+0 x:=x*1 x:=y**2(变换成x:=y*y)
例如四元式程序: t1 := 4 – 2 t2 := t1 /2 t3 := a * t2 化简为: t1 := a + a t1 := b + t1 c := t1 * t1
t4 := t3 * t1
t5 := b + t4 c := t5 * t5
这种变换把循环不变运算,提到循环前面。上例中,可
以把(4)和(7)提到循环外,经过删除多余运算和代码外提后, 代码变换成图11.3:
9
3.强度削弱:
把强度大的运算换算成强度小的运算,例如把乘法运 算换成加法运算。在图11.3中,可以把循环中计算T1值的
乘法运算变换成在循环前进行一次乘法运算,而在循环中
因此,图11.4中,四元式(3)可变为T1=4,
12
5.合并已知量不复写传播:
复写传播 复写传播是指尽量不引用那些 在程序中仅仅只传递信息而不改 变其值,也不影响其运行结果的 变量。
图中,T4 就是这样一种变量。四元式 (6)T4=T1,下一个四元式 (8)T6=T5[T4],这之间T4的值没有 变化,因此将(8) 变换为 : T6=T5[T1] 。
21
例 给以下四元式序列划分基本块。
(1)read C 四元式序列的第一个语句 (2)A=0 (3)B=1 由条件转移语句或无条件转移语句 (4)L1 : A=A+b 转移到的语句 (5)if B≥C goto L2 紧跟在条件转移语句后面的语句 (6)B=B+1 (7)goto L1 由条件转移语句或无条件转移语句 (8)L2 : write A 转移到的语句 (9)halt
27

第11章代码优化

第11章代码优化

(29) t15 := 4n
/* 程序段结束*/
(15) x := a[t6]
(30) a[t15] := x
quicksort(m, j);
quicksort(i+1, n); }
图11.4 快速排序部分程序的三地址代码
图11.3 快速排序的C代码
8
11.2 代码优化的基本技术 i := m -1 j := n
goto B2
t11 := 4i
B6
x := a[t11]
t12 := 4i
t13 := 4n
t14 := a[t12]
a[t12] := t14
t15 := 4n
a[t15] := x
9
11.2 代码优化的基本技术
例如,在图11.5的B5中分别把公
共子表达式4*i和4*j的值赋给t7和 这是仅限于基本块的局部优化,
主要内容
❖ 优化的概念 ❖ 代码优化的基本技术 ❖ 局部优化 ❖ 机器代码优化-窥孔技术
1
11.1 代码优化的概念
代码优化在整个编译过程的位置 ❖ 源程序 编译前端 中间代码 中间代码生成 中间代码 目标代码生成 目标程序
中间代码
中间代码优化
目标代码优化
程序员和编译器可能改上程序的位置
源程序
编译前端
(3)经济原则:代码优化需要占用计算机和编译 程序的资源,代码优化取得的效果应该超出优化 工作所付出的代价。否则,代码优化就失去了意 义。
3
11.1 代码优化的概念
❖ 代码优化依据机器相关性、优化范围和优化语言级别的 分类
按照与机器相关的程度,可以分为与机器相关的代码优化和与 机器无关的代码优化。 ❖ 与机器相关的优化一般有寄存器的优化、多处理器的优化、特 殊指令的优化以及无用指令的消除等技术。显然, 这几类优 化与具体机器的特性密切相关,例如寄存器的总数,寄存器的 具体使用规定,等等。这类优化通常的在目标代码生成之后进 行。 ❖ 与机器无关的优化是在目标代码生成以前进行,主要是根据程 序的控制信息和数据信息,对程序进行优化,与机器无关。

编译第11章

编译第11章

6.删除无用赋值
(1)P:=0 (2)I:=1 (4)T2:=addr(A)-4 (7)T5:=addr(B)-4 (3)T1:=4 (5)T3:=T2[T1] (6)T4:=T1 (8)T6:=T5[T1] (9)T7:=T3*T6 (10)P:=P+T7 (3’)T1:=T1+4 (12)if T1<=80 goto(5) (1)P:=0 (4)T2:=addr(A)-4 (7)T5:=addr(B)-4 (3)T1:=4
3.强度削弱
•基本思想:把强度大的运算换算成强度小的。 例如: a) i*2 = 2*i = i+i = i<<1 b) i/2 = (int)(i*0.5) c) 0-1 = -1 d) f*2 = 2.0 * f = f + f e) f/2.0 = f*0.5
(1)P:=0
(2)I:=1 (4)T2:=addr(A)-4 (7)T5:=addr(B)-4 (3)T1:=4*I (5)T3:=T2[T1] (6)T4:=T1 (8)T6:=T5[T4] (9)T7:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (12)if I<=20 goto(3)
五、常用优化技术简介
1.删除多余运算 2.循环不变代码外提 3.强度削弱 4.变换循环控制条件 5.合并已知量与复写传播 6.删除无用赋值
1.删除多余运算(删除公共子表达式):
目的:提高目标代码速度。 例如: P:=0 for I:=1 to 20 do P:=P+A[I]*B[I]
(1)P:=0 (2)I:=1
n1
D
n2
C
n3
B
4、DAG结点的数据表示法

第11章 代码优化

第11章 代码优化

X+1 X:=X+1 Y-1 Y:=Y-1 A<B
Z:=0
相应四元式代码的分块情况如下:
B1: (=:, 1 ,—, Y ) B2: (label,—,—,100) (>, A, B, T1) (then,T1,—,—) B3: (=:, 0, —, X ) (else,—,—, —) B4: (=:, 0 , —,Y ) Y:=1
C*B D+C*B D:=D+C*B
被省略
D+C*B A:=D+C*B
被省略
D+C*B C:=D+C*B
其中四元式2,5,8的运算符、OPR1、OPR2 均相等 但5、8中的D与2中的不同所以不可以 用T2代替T4、T6。 四元式5和8相同因此四元式8对5是多 余的。
经优化后可得到下列四元式代码: 1.(*, C, B,T1) 2.(+, D, T1,T2) 3.(=:,T2,—,D) 4.( )被省略 5.(+, D, T1,T3) 6.(=, T3,—,A) 7.( )被省略 8.( )被省略 9.( =:,T3,—,C)
其中四元式1,4,7的运算符、OPR1、 OPR2均相等,所以可以用T1代替T3、T5。 1.(*,C, B, 2.(+, D, T1, 3.(=:,T2,—, 4.( 5.(+, D, T1, 6.(=:,T4,—, 7.( 8.(+, D, T1, 9.(=: T6,—, T1) T2) D ) ) T4) A ) ) T6) C )
该四元式是否为赋值语句)
4. 如果QT[i].OPRj(j=1,2)都是常数,则计算结 果,填VVL表,并删除四元式QT[i]: ENTRY(QT[i].RESU, cons) (填写表中值) QT[i]:=($, -, -, -) (四元式节省)

第十一章 代码优化

第十一章 代码优化

read X read Y R:=X mod Y if R=0 goto (8) X:=Y Y:=R goto (3) write Y halt
1.求出四元式程序中各个基本块的入口 语句: 1) 程序第一个语句,或 2) 能由条件转移语句或无条件转移语 句转移到的语句,或 3) 紧跟在条件转移语句后面的语句。
(1)P:=0 (2)I:=1 (4)T2:=addr(A)-4 (7)T5:=addr(B)-4
代码 外提 (3)T1:=4*I (5)T3:=T2[T1] (6)T4:=T1 (8)T6:=T5[T4] (9)T7:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (12)if I<=20 goto(3)
删除多 余运算
(1)P:=0 (2)I:=1 (3)T1:=4*I (4)T2:=addr(A)-4 (5)T3:=T2[T1] (6)T4:=T1 (7)T5:=addr(B)-4 (8)T6:=T5[T4] (9)T7:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (12)if I<=20 goto(3)
11.2 局部优化
• 局限于基本块范围内的优化称为基本块内的优化,或 称局部优化。
• 在一个基本块内通常可以实行下面的优化: – 删除公共子表达式 – 删除无用赋值 –合并已知量 – 临时变量改名 – 交换语句的位置 – 代数变换(pow(y,2) 等价于 y*y)
11.2.1 基本块的划分
• 划分四元式程序为基本块的算法: 1.求出四元式程序中各个基本块的入口语句 入口语句: 1) 程序第一个语句,或 2) 能由条件转移语句或无条件转移语句转移到的语 句,或 3) 紧跟在条件转移语句后面的语句。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

对于删除公共子表达式和删除无用代码这两种优化技术, 我们在11.1中已经讨论过,这里简单介绍重新命名临时变量 和交换语句次序是什么含义。 重新命名临时变量:假如有语句t∶=b+c,其中t是临时 变量。如果把这个语句改为u∶=b+c,其中u是新的临时变量, 并且把这个t的所有引用改成u,那么基本块的运算结果不变。 交换语句次序: 如果基本块有两个相邻的语句: t1∶=b+c t2∶=x+y 当且仅当x和y都不是t1,b和c都不是t2时,我们可以交换这 两个语句的次序。
B
1
B
2
图 11.5变换循环控制条件, 合并已知量,复写传播
图11.4中,四元式(3) 可变为T1=4,这种变换称为 合并已知量。 图11.4中,四元式(6)把T1 的值复写到T4中,四元式(8) 要引用T4的值,而从四元式 (6)到四元式(8)之间未改 变T4和T1的值,则将四元式 (8)改为T6∶=T5[T1],这种 变换称为复写传播.复写传播之 后运算结果保持不变。 图11.4经过变换循环控制 条件,合并已知量和复写传播 等变换后,变为图11.5。
另外依据优化所涉及的程序范围,又可分为局部优化、 循环优化和全局优化三个不同的级别。局部优化指的是在 只有一个入口、一个出口的基本程序块上进行的优化。循 环优化是对循环中的代码进行的优化。全局优化是在整个 程序范围内进行的优化。
编译程序的优化工作旨在生成较好性能的目标代码, 为此,编译程序需要对代码(中间代码或目标代码)进行 各种方式的变换。变换的宗旨是: 等价-经优化工作变换后的代码运行结果应与原来程序运行 结果一样。 有效-经优化工作变换后的代码应运行时间较短,占用的存 储空间较小。 合算-获得较好性能的目标代码是优化工作的意图,而优化 本身包括大量的代码分析和变换工作,这里有个权衡: 应尽可能以较低的代价取得较好的优化效果。
11.2.1 基本块的划分
我们先定义基本块的入口语句。 所谓入口语句有三种,就是: ① 程序的第一个语句; ② 条件转移语句或无条件转移语句的转移目标语句; ③ 紧跟在条件转移语句后面的语句。
有了入口语句的概念之后,我们就可以给出划分中间 代码(四元式程序)为基本块的算法。
划分中间代码(四元式程序)为基本块的算法:
图11.2 中间代码段
B2
1)删除多余运算(删除公共子表达式) 优化的目的在于使生 成的目标代码较少而执行 速度较快。
(1)P:=0 (2)I:=1
B1
四元式(6)变换成: T4∶=T1。这种优化称为 删除多余运算或称为删除 公共子表达式。
(3)T1:=4*I (4)T2:=addr(A)-4 (5)T3:=T2[T1] (6)T4:=4*I (7)T5:=addr(B)-4 (8)T6:=T5[T4] (9)T4:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (12)if I≤20 goto (3)
(1)P:=0 (2)I:=1 (4)T2:=addr(A)-4 (7)T5:=addr(B)-4 (3)T1:=4
(5)T3:=T2[T1] (6)T4:=T1 (8)T6:=T5[T1] (9)T4:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (3 )T1:=T1+4 (12)if T1≤80 goto (5)B1B Nhomakorabea2
图 11.6 删除无用赋值
11.2 局部优化
我们所说的局部优化是指基本块内的优化。
所谓基本块,是指程序中一个单入口、单出口的线性 程序块(顺序执行的语句序列)。
控制流只能从其入口语句进入,从其出口语句退出, 没有中途停止或分支。 局部优化工作包括对于一个给定的程序,把它划分为 一系列的基本块,在各个基本块范围内分别进行优化。 局限于基本块范围内的优化称为基本块内的优化,也 称为局部优化。
(5)T3:=T2[T1] (6)T4:=T1 (8)T6:=T5[T4] (9)T4:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (3 )T1:=T1+4 (12)if I≤20 goto (5)
图11.4强度削弱
B2
4)变换循环控制条件
图11.4的代码中,四元式 (12)的循环控制条件I≤20 变换成T1≤80,这样整个程序 的运行结果不变。这种变换 称为变换循环控制条件。 经过这一变换后,循环 中I的值在循环后不会被引用, 四元式(11)成为多余运算, 可以从循环中删除。变换循 环控制条件可以达到代码优 化的目的。
(1)P:=0 (2)I:=1 (4)T2:=addr(A)-4 (7)T5:=addr(B)-4 (3)T1:=4*I
(5)T3:=T2[T1] (6)T4:=T1 (8)T6:=T5[T4] (9)T4:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (3 )T1:=T1+4 (12)if T1≤80 goto (5)
先求出四元式程序中各个基本块的 入口语句: 1. 语句(1)是程序的第一个语句, 因此它是入口语句。 2. 语句(4)和语句(8)是条件转移 语句或无条件转移语句的转移目标 语句,因此是入口语句。 3. 语句(6)是紧跟在条件转移语句 后面的语句,因此是入口语句。
(1) read (C) (2) A:= 0 (3) B:= 1 (4) L1: A:=A + B (5) if B>= C goto L2 (6) B:=B+1 (7) goto L1 (8) L2: write (A) (9) halt
我们以下述四元式程序为例来说明如何划分基本块的。 例11.1:有四元式程序如下,构造其基本块。 (1) read (C) (2) A:= 0 (3) B:= 1 (4) L1: A:=A + B (5) if B>= C goto L2 (6) B:=B+1 (7) goto L1 (8) L2: write (A) (9) halt
① 求出四元式程序中各个基本块的入口语句。 ② 对每一入口语句,构造其所属的基本块。它是由该入 口语句到下一入口语句(不包括下一入口语句),或 到一转移语句(包括该转移语句),或到一停语句 (包括该停语句)之间的语句序列组成的。 ③ 凡未被纳入某一基本块的语句、都是程序中控制流程 无法到达的语句,因而也是不会被执行到的语句,可 以把它们删除。
第11章 代码优化
11.1 代码优化技术 11.2 局部优化 11.3 控制流程分析和循环
【学习目标】 通过本章学习: ◇ 理解所谓代码优化是指什麽? ◇ 知道最常用的代码优化技术有哪些? ◇ 知道实现代码优化要进行哪些工作? 【学习指南】 所谓代码优化是指对程序代码进行等价变换。程序 代码可以是中间代码(如四元式代码),也可以是目标代 码。优化的含义是最终生成的目标代码短(而运行速度 快),时空效率优化。最常用的代码优化技术有删除多余 运算,循环不变代码外提,强度削弱,变换循环控制条 件,合并已知量与复写传播,以及删除无用赋值等等。 【难重点】 从概念上理解什么是代码优化,编译过程中可进行 哪些优化,以及进行优化所需要的基础都没有难点,但 在实现上是有相当复杂的工作。
优化可在编译的不同阶段进行,对同一阶段,涉及 的程序范围也有所不同,在同一范围内,可进行多种优 化。目前编译程序的优化工作一般是在中间代码生成之 后和(或)目标代码生成之后进行。如图11.1所示。
源程序 编译前端
中间代码
代码生成
目标代码
目标程序
中间代码优化
目标代码优化
中间代码的优化是对中间代码进行等价变换。目标代 码的优化是在目标代码生成之后进行的,因为生成的目标 代码对应于具体的计算机,因此,这一类优化在很大程度 上依赖于具体的机器,我们不做详细讨论。
图11.3 删除公共子表达式和代码外提
3)强度削弱
强度削弱的思想是 把强度大的运算换算 成强度小的运算。
(1)P:=0 (2)I:=1 (4)T2:=addr(A)-4 (7)T5:=addr(B)-4 (3)T1:=4*I
B1
循环中计算T1值的 乘法运算变换成在循 环前进行一次乘法运 算,而在循环中将其 变换成加法运算。变 换后如图11.4所示。
B1
B2
图 11.5变换循环控制条件, 合并已知量,复写传播
6)删除无用赋值
在图11.5中,(6)对T4 赋值,但T4未被引用;另外, (2)和(11)对I赋值,但只 有(11)引用I。所以,只要 程序中其它地方不需要引用T4 和I,则(6),(2)和(11) 对程序的运行结果无任何作用。 我们称之为无用赋值,无用赋 值可以从程序中删除,如图 11.6所示。 比较图11.2和图11.6可看 出,经过优化后的代码的执行 效率提高了很多。当然,实现 这些优化的一系列工作是非常 复杂的,代价也是很大的。
B2
图11.2 中间代码段
2)代码外提
减少循环中代码总数的一 个重要办法是循环不变代码外 提。这种变换把循环不变运算, 即其结果独立于循环执行次数 的表达式,提到循环的前面,使 之只在循环外计算一次。
(1)P:=0 (2)I:=1
B
1
(4)T2:=addr(A)-4 (7)T5:=addr(B)-4
11.0 概述
源语言程序经过词法分析、语法分析、语义分析和中 间代码生成等编译前期工作(编译前端),得到了与源程 序等价的中间代码程序。中间代码程序的质量将直接影响 目标程序执行的效率。程序执行的效率体现在两个方面: 目标程序运行时刻所占用的存储空间和目标程序运行时刻 所耗费的时间。 所谓优化,是为了提高程序的执行效率而对程序代码 进行的等价变换。使得变换后的代码运行结果与变换前代 码运行结果相同,而运行速度加大或占用存储空间少,或 两者都有。 编译过程中可进行的优化可按阶段划分:优化可在编 译的不同阶段进行,分为中间代码一级和目标代码一级的 优化。可按优化涉及的程序范围划分:对同一阶段,分为 局部优化,循环优化和全局优化。可按优化是否涉及具体计 算机来划分:分为与计算机有关的优化和与计算机无关的 优化。
相关文档
最新文档