编译原理陈火旺版10-11章.
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
以下通过一个实例简介各种优化方法。 例见P273 中的C语言程序,以下为其部分语句:
i=m-1;j=n;v=a[n]; While (1) {
do i=i+1; while (a[i]<v); do j=j-1; while (a[j]>v); if (i>=j) break; x=a[i]; a[i]=a[j]; a[j]=x;
二. 基本块的DAG表示及其应用
1.基本块的DAG表示 一个基本块的DAG为如下形式的图: (1) 叶子结点:以一个标识符或常数或变量的地址作 为标记。标识符可以0为下标,表示初值; (2) 内部结点:以运算符为标记; (3) 各结点可附加多个标识符,表示这些标识符等价, 且具有该结点的值。
例见P282 图 10.9(补充一简单例子)
aa[[TT12]]::==TT31;4; T15:=T1;a[T1]:=x;
四. 代码外提 对循环中的有些代码,若它的结果在循环中不变,
可将这些代码提到循环外,以避免循环执行。
例: while ( i<=limit-2) …
五. 强度削弱
变换为:
t:=limit-2 while ( i<= t )
B5
B6
a[T2]:=T5;
a[T4]:=T3; goto B2
a[T2]:=V; a[T1]:=T3;
10.2 局部优化
一 . 基本块及流图 基本块:程序中一顺序执行的语句系列,其中只有一
个入口和一个出口,第一个语句为入口,最后一个 语句为出口。
对于语句: x:=y+z 我们称该语句对x定值,对y和z引用。
例: T0:=3.14 T1:=2*T0 T2:=R+r A:=T1*T2 B:=A T3:=2*T0 T4:=R+r T5:=T3*T4 T6:=R-r B:=T5*T6
其DAG如右图所示:
8B *
B A 6 T5
*
5 +
T2 T4
7 -
T6
1 T0
2
T1 T3
3
4
3.14 6.28 R
r
由该图重写的代码序列如下:
T10:= T4; a[T4]:=T3;
Goto B2
三. 删除无用代码 对于如右图所示的B5,由于
X,T6,T7,T8,T9,T10 在程序中 不再使用,因此可删除对这些 变量的赋值语句。
B5
TT76:a:=[=TTT222];;:xT=:8T=:5T=;3T;4; T9:=aT[5T;4]a:[T=2T]3:;=T5; T10:= GT4o;toa[BT24]:=T3;
Goto B2
对于B6 可以像B5一样作相应的优化变换:
B6
T11:=4*i;x:=a[T11];
T12:=4*i;T13:=4*n; T14:=a[T13]; a[T12]:=T14;
T15:=4*n;a[T15]:=x;
变换为:
B6 TB161:=T2;x:=a[T2]; T12aT:[1T=4T2:2]=:;a=T[v1T;31:]=;T1;
定义,则构造叶结点n, NODE(P)=n, 执行0型2。 3、若B,C不是常数,查有无 B OP C 子树:
有:设 NODE(OP)=n, 执行0型2; 无:构造n结点OP, 执行0型2 。
在构造基本块的DAG时,当参与运算的结点均为常数时, 已直接计算结果,生成新常数结点(合并已知量)。
以下通过一个例子介绍基本块的DAG
例 现有赋值语句: A:=(B+C)*D+E 其对应的中间码: T1:=B+C T2:=T1*D A:=T2+E
20
若中间码
X:=Y+Z 可翻译为: LD R ,Y ADD R, Z ST R, X
则前述中间码可翻译为:
LD R, B ADD R, C ST R, T1 简化 LD R, T1 MUL R, D ST R, T2 LD R, T2 ADD R, E ST R, A
第十一章 目标代码生成
目标代码生成器的位置:
源 程序
编译前端
中间 代码
代码优化
中间 代码
代码生成器
目标 程序
符号表
目标代码的形式: 1、已定位的可立即执行的机器语言代码; 2、可浮动的机器语言代码,需装配连接再执行; 3、汇编语言目标代码,需汇编再执行。
目标代码应具有高效性:目标代码较短; 充分利用寄存器减少内存访问。
…
循环中的代码,由于循环执行多遍,应尽量用+、- 法
取代 *、/ 法等强度高的运算。
T2:=4*i;
B2
i:=i+1;T2:=4*i; T3:=a[T2];
if T3<v goto B2
变换为: B2 i:=i+1;T2:=T2+4; T3:=a[T2];
if T3<v goto B2
六. 删除归纳变量(图10.4) B2中的 i 每循环一次增值1,T2与 i 保持线性关系, B3中的 j 每循环一次递减1,T4与 j 保持线性关系,
2. 对以上入口语句,构造其所属的基本块:
此入口语句到下一条入口语句前,或下一条跳转语 句,或一条停语句的语句序列组成一个基本块。
3.删除未被纳入任何基本块的语句。
例:
(5) x:=y
(1) read x
(6) y:=R
(2) read y
(7) goto (3)
(3) R:=x mod y
(8) write y
经前述各种优化处理后,最终的中间代码如下:
B1
i:=m-1; j:=n ; T1:=4*n; v:=a[T1];
T2:=4*i; T4:=4*j;
B2
T2:=T2+4;T3:=a[T2]; if T3<v goto B2
B3
T4:=T4+4;T5:=a[T4]; if T5>v goto B3
B4 if T2>=T4 goto B6
T15:=4*n; a[T15]:=x;
一. 删除公共子表达式(多余运算)
B5
B5
T6:=4*i; x:=a[T6];
T6:=4*i; x:=a[T6];
T7:=4*i; T8:=4*j; 变换为: T7:= T6; T8:=4*j;
T9:=a[T8]; a[T7]:=T9;
T9:=a[T8]; a[T7]:=T9;
则可交换T1,T2两赋值语句
3. 代数变换:x:=y**2 可变换为 x:=y*y (强度削弱)
以基本块为结 点,构造程序的流程 图,称为流图。
如前例程序的流图为:
read x B1 read y
R:=x mod y B2 if R=0 goto (8)
x:=y B3 y:=R goto (3)
write y B4 halt
19
11.1 一个简单的代码生成器
P312中两个表给出了一个模拟机的指令系统(类似汇编)。
仅介绍一个简单的目标代码生成方法: 1、依次将每条中间代码变换成等价的若干条目标代码; 2、基本块内考虑充分利用寄存器的问题。
即:基本块内计算出的变量值尽量保留在寄存器中, 直至寄存器另有用途或已到基本块的出口; 引用变量时尽量用其在寄存器中的值。
第十章 优 化
优化主要为两类:中间代码的优化(不依赖硬件) 目标代码的优化(依赖硬件)
本章讨论的优化主要指对中间代码进行等价的变换, 使其成为执行效率更高的中间码。
P272 图10.1给出了代码优化的地位和结构。
10.1 概述
优化对代码进行的变换必须遵守以下原则: 1. 等价原则: 经优化的代码执行结果不变; 2. 有效原则: 优化后 确实执行时间短、占用空间少; 3. 合算原则: 以较低的代价,换取较好的优化效果。
} x=a[i]; a[i]=a[n]; a[n]=x;
该语句段的中间代码见P274 图10.2
B1
i:=m-1; j:=n ; T1:=4*n; v:=a[T1];
B2
i:=i+1;T2:=4*i;T3:=a[T2]; if T3<v goto B2
每个数组元素 占4个单元
B3
j:=j-1;T4:=4*j;T5:=a[T4]; if T5>v goto B3
我们称这些变量为归纳变量,T2、T4强度削弱后, i和j 仅在B4中引用,因此可将 i和j 的赋值语句删除, 并将B4改为: if T2>=T4 goto B6
七. 合并已知量
若某些表达式的运算量在编译时是已知的,则应 直接给出结果,而无须保留表达式。
例: i:=1; 变换为: T:=4*i;
i:= 1; T:= 4;
构造基本块的DAG的算法见P282,以下简单介 绍该算法。
0型:A:=B 1、NODE(B)无定义,则构造叶结点n,NODE(B)=n; 2、NODE(A)有定义,则删除A在原结点的标记。 令NODE(A)=n。
1型:A:= OP B 1、NODE(B)无定义,则构造叶结点n,NODE(B)=n; 2、若B为常数,则计算 OP B => P,若NODE(P)无定义,
T10:=4*j; a[T10]:=x;
T10:= T8; a[T10]:=x;
goto B2
Goto B2
因为:B2中已有T2:=4*i,且在进入B5前未改变过T2;
B3中已有T4:=4*j,且在进入B5前未改变过T4;
所以可将B5变换为:
T6:=T2; x:=a[T6];
T7:= T6; T8:=T4; B5 T9:=a[T8]; a[T7]:=T9;
对该基本块还可进行如下优化:
假设T0--T6在基本块后不再使用, 即可删除对其的赋值,得到如下 代码:
T2:=R+r A:=6.28*T2 T6:=R-r B:=A*T6 若调整语句顺序如下:
T6:=R-r T2:=R+r A:=6.28*T2 B:=A*T6 将可得到更优的目标代码。
T0:=3.14 T1:=6.28 T3:=6.28 T2:=R+r T4:= T2 A:=6.28*T2 T5:=A T6:=R-r B:=A*T6
T10:= T8; a[T10]:=x;
Goto B2
二. 复写传播
B5
B5
T6:=T2; x:=a[T6];
T6:=T2; x:=a[T2];
T7:= T6; T8:=T4; T9:=a[T8]; a[T7]:=T9;
变换为:
T7:= T2; T9:=a[T4];
T8:=T4; a[T2]:=T9;
如果一个变量在某语句之后还将被引用,则称变量在 该点(语句)是活跃的。
对于给定的一个程序,可以将其划分为一系列的基本 块,分别在块内进行局部优化(基本块内的优化)。
以下先给出划分基本块的算法。
1. 求出程序中可做基本块入口的语句,它们是: (1)程序的第一个语句;
(2)能由条件转移语句或无条件转移语句转移到的语句; (3)紧跟在条件转移语句后面的语句。
T10:= T8; a[T10]:=x;
T10:= T4; a[T4]:=x;
Goto B2
Goto B2
因为:B2中已有T3:=a[T2],且在进入B5前未改变过T3;
B3中已有T5:=a[T4],且在进入B5前未改变过T5;
所以可将B5变换为:
T6:=T2; x:=T3;
B5 T7:= T2; T8:=T4; T9:=T5; a[T2]:=T5;
B4 if i>=j goto B6
B5
B6
T6:=4*i; x:=a[T6]; T7:=4*i; T8:=4*j; T9:=a[T8]; a[T7]:=T9; T10:=4*j; a[T10]:=x;
goto B2
T11:=4*i; x:=a[T11];
T12:=4*i; T13:=4*n; T14:=a[T13]; a[T12]:=T14;
(4) if R=0 goto (8) (9) halt
入口语句有: (1) (3) (8) (5)
基本块有: {1,2} {3,4} {5,6,7} {8,9}
对基本块内的语句可以进行如下一些优化变换:
1. 合并已知量; 2. 交换语句位置: T1:=b+c
若 x,y均不为T1
T2:=x+y
b,c均不为T2
则构造叶结点n,NODE(P)=n, 执行0型2。 3、若B非常数,查有无 OP B 子树:
有:设 NODE(OP)=n, 执行0型2; 无:构造n结点OP, 执行0型2 。
2型:A:=B OP C 或 A:=B[C] 1、NODE(B)无定义,则构造叶结点B;
NODE(C)无定义,则构造叶结点C; 2、若B,C均为常数,则计算B OP C=> P, 若NODE(P)无
T0:=3.14
8B
T1:=6.28
*
T3:=6.28 T2:=R+r T4:= T2 A:=6.28*T2 T5:=A
B A 6 T5
*
5 +
T2 T4
7 -
T6
T6:=R-r
B:=A*T6 已完成了如下优化:
1 T0
2
T1 T3
源自文库
3
4
合并已知量;
3.14 6.28 R
r
删除无用代码;(B:=A)
删除公共子表达式。