第八章 中间代码优化

合集下载

编译器设计中的语法分析和中间代码优化

编译器设计中的语法分析和中间代码优化

编译器设计中的语法分析和中间代码优化在编译器的设计中,语法分析和中间代码优化是两个重要的阶段。

语法分析是将输入的源代码转化为语法树的过程,而中间代码优化则是对生成的中间代码进行改进,以提高目标代码的执行效率和代码质量。

一、语法分析语法分析是编译器设计中的一个重要环节,它的主要任务是将输入的源代码转化为一棵语法树。

语法树是编译器在进一步处理代码之前生成的一种数据结构,它以树的形式表示代码的语法结构。

在语法分析阶段,编译器会对源代码进行词法分析,并根据语法规则构建语法树。

1. 词法分析词法分析是将源代码分解为一个个的词法单元(Token)的过程。

每个Token代表着源代码中的一个有意义的单词,如变量名、操作符、关键词等等。

编译器会通过词法分析器识别出这些词法单元,并将其传递给语法分析器进行后续处理。

2. 语法规则语法规则定义了源代码中各种语句和表达式的结构和组织方式。

在语法分析阶段,编译器会根据这些语法规则来构建语法树。

语法规则一般使用上下文无关文法(Context-Free Grammar)来描述。

3. 构建语法树通过词法分析和语法规则,编译器可以逐步构建语法树。

语法树是一种树状数据结构,以根节点表示整个代码块,每个内部节点表示一个语法单元,叶节点表示一个词法单元。

编译器可以根据语法树进行后续的语义分析和代码生成。

二、中间代码优化中间代码优化是编译器设计的另一重要环节,它的主要目标是改进生成的中间代码,以提高目标代码的执行效率和代码质量。

在中间代码优化阶段,编译器会对生成的中间代码进行分析和改进。

1. 常量传播常量传播是一种中间代码优化技术,它的目标是将程序中的常量表达式计算出实际的结果,并将结果用于后续的代码生成。

常量传播可以减少运行时的计算量,提高程序的执行效率。

2. 冗余代码消除冗余代码是指程序中不会被执行的代码,它们不会对程序的结果产生任何影响。

冗余代码消除可以通过分析中间代码的控制流来判断哪些代码是冗余的,并将其消除掉。

编译原理代码优化

编译原理代码优化

(3) (+ R r t2 ) (4) (/ 6.28 t2 t3 ) (5) (= t3 _ A )
t4≡t1 t5≡t2 t6≡t3 B 没有引用! (9) (- R r t7 ) (10) (* t3 t7 t8 ) (11) (= t8 _ B )
※ 基本块内四元式的局部优化过程示例 优化的基本内容和方法:
※ 局部优化算法是以基本块为单位进行的,基本块 也是目标代码生成的基本单位。
【定义】基本块是程序中一段顺序执行的语 句序列,其中只有一个入口和一个出口。
基本块划分算法: 1.确定基本块的入口语句,它们是: (1) 程序的第一个语句或转向语句转移到的语句; (2) 紧跟在转向语句后面的语句。 2.确定基本块的出口语句,它们是: (1) 下一个入口语句的前导语句; (2) 转向语句(包括转向语句本身); (3) 停语句(包括停语句本身);
【开始】按结点编码顺序,依次读取每一结点 n1 信息: (1) 若 n1 为带有附加标记的叶结点: • 若 Ai 为非临时变量,则 生成: q1: Ai=B (i=1,2,…)
(2) 若 n1 为带有附加标记的非叶结点: ① 生成 q1: A=BC 或生成 q1: A=B ② 若Ai为非临时变量,则生成: q2: Ai=A (i=1,2,…) n1 B|A1,A2,… n1 A|A1,A2,… ni B|… nj C|… 以主标记 参加运算
删除 无用 赋值
常值 表达 式节 省
8.2.3 基于DAG的局部优化方法
(3) 若其它表达式 A = B C 或 A = B; ① 若在 n1 存在公共表达式: BC 或 B
n1 …
ni …B… nj …C…
则把A附加于n1上:

编译原理课件 第八章 代码优化

编译原理课件 第八章 代码优化
8.2.1 基本块与流图 一、 基本块 是指程序中一顺序执行的语句序列, 其中只有一个入口和一个出口, 入口就 是其中的第一个语句,出口就是其中 最后一个语句。 对一个基本块来说,执行时,只能 从入口进入,从出口退出
计算机学院 辛明影
R=10; Pi=3.14
一个给定的程序,可以把 它划分为一系列的基本块
计算机学院
辛明影
删除无用赋值后
i=m-1 j=n t1=4*n v=a[t1]
B1
i=i+1 B2 t2=4*i t3=a[t2] if t3<v goto B2 j=j-1 B3 t4=4*j t5=a[t4] if t5<v goto B3 if i>=j goto B6 B4 B5 B6
a[t2]=t5 a[t4]=t3 goto B2
计算机学院 辛明影
中 间 代 码
① read x ② read y ③ r=x mod y ④ if r=0 goto ⑧ ⑤ x=y ⑥ y=r ⑦ goto ③ ⑧ write y ⑨ end
计算机学院
辛明影
入口语句: 入口语句: ① 、③、⑤、⑧ 基本块: 基本块: ①、②; ③、④;⑤、⑥、⑦; 、⑨; ⑧ 基本块内除可用: 基本块内除可用:删除公共子表达式 复写传播 删除无用赋值 还可用下面的变换: 还可用下面的变换:
2。临时变量改名 1。合并已知量 3。交换语句的位置 4。代数变换 代数变换
计算机学院 辛明影
二、程序流图 程序流图为一以基本块为结点的有向图; 含有程序中第一条语句的结点叫作首结点 含有程序中第一条语句的结点叫作首结点 程序流图构造方法: 程序流图构造方法: 条件或无条件语句从B1转到B2 B1转到 1。条件或无条件语句从B1转到B2 B2紧跟在B1后面 紧跟在B1后面( B1最后语句 2。B2紧跟在B1后面(且B1最后语句 不是无条件转移语句) 不是无条件转移语句) 此时称B2为 的后继 的后继, 为 的前驱 此时称 为B1的后继,B1为B2的前驱

第8章+语义分析和中间代码生成

第8章+语义分析和中间代码生成
(2)数组形式:三列(操作符或操作对象、左儿子位置和右儿子位置)
的二维数组,一结点一行,行号表示结点的位置。 【例】 a=b*c+b*d
1 2 a = 1 3 4 7 6 5 8 9
3
4 5 6 7 8 9
第8章 语义分析和中间代码生成
b
* c + b * d
8.2 中间代码
8.2.3 三地址码
1. 三地址码 (i)x := y op z (1) (2) (3) (4) t1:=b*c t2:=b*d t3:=t1+t2 a:=t3
(c,real)填入符号表,D.t =real
10
D
#
结束
8.3 自底向上语法制导翻译
第8章 语义分析和中间代码生成
8.3.2 说明语句的翻译
2. 数组说明的翻译
数组内情向量:存放数组的相关信息。
内情向量的地址存于符号表中。
数组引用的关键问题 —— 数组元素的地址计算

第8章 语义分析和中间代码生成
语义: E.val=T1.val+T2.val
E (E.val= T1.val+T2.val=12)
T1(T1.val=5)
第8章 语义分析和中间代码生成
T2(T1.val=7)
8.1 语义分析
8.1.2 语义的描述
(2)继承属性 一个文法符号N在产生式的右边出现,若它的t属性由该产生 式的左部非终结符或右部的其他符号的属性决定,则N.t为N的继 承属性。
第8章 语义分析和中间代码生成
8.1 语义分析
8.1.2 语义的描述
例:变量说明语句的文法 D→TL T→real | int L→id | L1, id T.type由real或int决定; 标识符表类型L.in由T.type确定, 且依次传给表中的每一个标识符。

代码优化与代码生成-编译原理-08-(二)

代码优化与代码生成-编译原理-08-(二)

(1) i := 0 (2) if i >= 20 goto (8)
(1) i := 0 (2) t1 := z * 6 (3) if i >= 20 goto (8)
(3) x := 4 * i (4) i := i + 1 (5) t1 := z *6 (6) y := t1 + x (7) goto (2) (4) x := 4 * i (5) i := i + 1 (6) y := t1 + x (7) goto (3)
交换语句次序
减少临时变量
8.3 循环优化
循环体是优化的重点
反复执行
循环的定义
有唯一入口点的强连接子图
强连接子图:
任意两结点间的通路上各结点属于子图
方法 1:代码外提

将循环不变运算移到循环外
例 8-2:程序优化 i = 0; while( i < 20 ) { x = 4 * i; i++; y = z * 6 + x; }
专用寄存器
R2 分配给 R3 分配给
x t1
生成目标代码
指令种类 赋值 MOV 比较 CMP 条件转移 JLE 转移 JMP 累加 ADD
(1) MOV R0, Z (2) ADD R0, 6 (3) MOV R3, R0 (4) MOV R2, -4 (5) CMP R2, 76 (6) JLE (12) (7) ADD R2, 4 (8) MOV R0, R3 (9) ADD R0, R2 (10) MOV Y, R0 (11) JMP (5)
方法 3: 消除归纳变量
利用归纳变量相关的计算代替
归纳变量的计算

ch8-语法制导翻译和中间代码生成(1)

ch8-语法制导翻译和中间代码生成(1)
常用属性文法描述程序语言语义;采用语法制导翻译方 法对语法成分进行翻译。 语法制导翻译法就是为每个产生式配上一个语义子程 序,在语法分析过程中,在选用某个产生式的同时,执行
该产生式所对应的语义子程序来进行翻译的一种办法。
6
8.1 属性文法
1、文法的属性
属性是常用于描述事物或人的特征、性质或品质等。 在上下文无关文法中,为每个文法符号(终结符或非终结符) 例如:物体可以用颜色属性描述。 引入若干“值”(称为属性)。属性代表与文法符号相关 的信息,属性可以是类型、值、代码序列、符号表内容 (入口)等。属性可计算或传递。属性的加工过程即是语 义处理的过程。 对于文法的每个产生式都加入了一组属性的计算规则-语 义规则。
25
依赖图举例
假设A.a=f(X.x,Y.y)是对应于产生式A->XY的一个语 义规则,它确定了依赖于属性X.x和Y.y的综合属性A.a。 若在语法树中应用这个产生式,则在依赖图中会有三个结 点A.a、 X.x和Y.y。由于A.a依赖于X.x,所以有一条有向 边从X.x连到A.a;由于A.a依赖于Y.y ,所以有一条有向 边从Y.y连到A.a。 若 与 产 生 式 A - >XY 对 应 的 语 义 规 则 还 有 X.i=g(A.a,Y.y),则图中还有两条有向边,一条从A.a连到 X.i,另一条从Y.y连到X.i。
2
静态语义分析包括的主要内容-2
3)一致性检查。在很多场合要求对象只能被定义一次。例 如 Pascal语言规定同一标识符在一个分程序中只能被说 明一次,同一case语句的标号不能相同,枚举类型的元素 不能重复出现等等。 4)相关名字检查。有时,同一名字必须出现两次或多次。 例如,在Ada 语言程序中,循环或程序块可以有一个名字 出现在这些结构的开头和结尾,编译程序必须检查这两个 位臵用的名字是否相同。 5)名字的作用域分析

第8章 代码优化

第8章 代码优化

n2 n1 B A op n1 B
(b)A= op B
A
n3 op n1
B (c)A= B op C
A
n3 =[]
n2
C
n1
B (d)A= B [ C]
n2
C
n3
S
n3
=[ ]
n1 rop n1
C D
S
n1
B
n2
n2
C
n3
B (g)goto(S)
(e)if B rop C goto(S)
(f)D[C]=B
与机器相关的优化是在目标机上进行的,这
类优化主要包括①寄存器的优化②并行分支 优化③窥孔优化等。与机器相关的优化依赖 于机器。
源代码
前端
中间代码
代码生成
目标代码
目标代码优化 中间代码优化
图8-1编译的优化工作阶段
优化技术的简介 为了说明问题,我们来看下面的例子,源程 序如下: p:=0 for I:=1 to 20 do p:=p+A[I]*B[I]
n5 + n1 T 0 3.14
(a) T0=3.14
n1 T 0
n2 T1 6.28
n1 T 0 3.14
n2 T1 6.28
(c)T3=R+r
n3 R
n4 r
3.14
(b)T1=2* T0
3.强度削弱 强度削弱就是把强度大的运算换算成强度小的运算, 例如把乘法运算换算成加法运算等。例如:(3) T1:=4*I和(11)I=I+1变为T1:=T1+4 中间代码就变为图8-4。 4.变换循环控制条件 将上面的循环控制条件变为: (12)if I≤20 goto(3)改为T1≤80,这样整个程序的 运行结果不变。这种变换称为变换循环控制条件, 经过这一变换后,循环中I的值在循环后不会被引用, 四元式(11)可以从循环中删除,如图8-5所示。

编译原理compiler8_中间代码

编译原理compiler8_中间代码

有如下if语句 有如下if语句:if <expr> then <stmt1> else <stmt2> 语句: 波兰表示为:<expr>BZ<label1><stmt1>BR<label2><stmt2> 波兰表示为:<expr>BZ<label1><stmt1>BR<label2><stmt2> if语句的波兰表示可生成如下的目标程序框架: 语句的波兰表示可生成如下的目标程序框架 由if语句的波兰表示可生成如下的目标程序框架: 例:If x>y then z:=x else z:=y+1; M=z+2; <expr> X-y BZ label1 BZ, label1 <stmt1> Z:= X BR label2 BR, label2 label1: label1:<stmt2> Label: Z:= Y+1 label2: label2: Label2: M=z+2 : 其他语言结构很容易将其翻译成波兰表示, 其他语言结构很容易将其翻译成波兰表示,
语句 if a<b or c<d and e<f then S1 else S2 的四元式
(1) if a<b goto ( E.true ) (2) goto (3) (3) if c<d goto (5) (4) goto (E.false) (5) if e<f goto ( E.true ) (6) goto (E.false) (E.true)( S 1 的四元式序列 …… ……) ) (p) goto (q) (E.false) (S2 的四元式序列 …… (q-1) ……) ) (q)

08 中间代码优化

08  中间代码优化

时间:运行时间尽可能短 ; 空间:所占空间尽可能少;
技术分类:
(1)与机器无关的优化——对中间代码进行。对中间代码进行等 与机器无关 对中间代码进行 价变换:
前端
控制流分析
代码优化
数据流分析
后端
代码变换
(2)依赖于机器的优化——对目标代码进行。在目标代码生成之 依赖于机器 后进行的,因为生成的目标代码对应于具体的计算机,因此, 这一类优化在很大程度上依赖于具体的机器。 —— 具体参见《
2012.05.21
于老师
第8单元 代码优化
代码优化
1. 综述 2. 局部优化 3. * 控制流分析与循环查找 4. * 数据流分析基础 5. * 循环优化的实施
8.1 基本概念
所谓代码优化: 代码优化
—— 在不改变程序运行效果的前提下,对被编译的 程序进行等价变换,使之能生成更加高效的目标代码。 等价变换 高效
n3 (S) rop n1 B n2 C n1 D
n4 =[ ] n2 C (6) D[C]=B n3 B (7) goto (S) n1 (S)
(5) if B rop C goto (S)
仅含0、1、2型四元式的基本块构造DAG的算法如下: 算法 8.1 基于基本块的DAG的构造算法
首先,将DAG初始化为空; 接着,对基本块中每一个四元式依次执行以下步骤: 1. 如果NODE(B)无定义,则构造一标记为B的叶结点并定义 NODE(B)为这个结点; ① 如果当前四元式是0型,则记NODE(B)的值为n,转4。 ② 如果当前四元式是1型,则转2(1)。 ③ 如果当前四元式是2型,则: I. 如果NODE(1)无定义,则构造一标记为C的叶结点并定 义NODE(1) 为这个结点; II. 转2 (2);

第八章中间代码优化

第八章中间代码优化
( , j ,10, t3 ) ([ ], t2, t3, t4 ) ( , i , j, t6 )
([ ], t4, k , t5 ) ( , t6,k, t7 ) ( , t7, t5 )
基于值编码的优化实例
A:=B*C+B*C D:=B E:=D*C+B*C
循环不变式外提优化
循环的识别:识别循环的入口、重复体、出口部分。 识别方法:基于程序文本,基于程序图。 外提对象:循环不变式。 安全性: 除法表达式不能外提(除零溢出);
赋值表达式不能外提(不一定执行该循环)。 外提原理:
(ASSIGN, x,a) (ADDI,b,5,t2) (ASSIGN,t2,c)
(t1,2)( b,2)
(ASSIGN,a,x)
(t1,2)(b,2)(t2,7) ( )
(t1,2)(b,2) (t2,7)(c,7)
(ASSIGN,7,c)
基于值编码的公共表达式局部优化
按值等价原理 优化思想
基本块和程序流图
基本块:单入口单出口的程序段。 程序流图:以基本块为结点的有向图,有向边表示
程序执行的流程。 中间代码基本块的划分:
❖ 初始代码为第一个基本块的入口。 ❖ 遇转移性中间代码时,结束当前基本块,下一条
代码作为新基本块的入口。 ❖ 遇标号性代码结束当前基本块,代码本身作为新
基本块的入口。 ❖ 遇(ASSIG, A, X)时,如果X为引用型形参时结
第八章 中间代码优化
引言 常量表达式优化 公共表达式优化 循环不变式外提
优化的目标: 优化的要求: 优化的对象:深层循环和下标变量地址的计算 优化的种类:
常表达式优化(合并常数项) 公共表达式优化(消除重复操作) 循环不变表达式外提 削减运算强度等等 优化方法: 全局优化:全局信息 局部优化:局部信息

编译原理-中间代码优化

编译原理-中间代码优化
/* Global variables */
/********************************************************************/
Four *fhead;
DagNode*nhead;
std::list<DagNode*>list_Dag;
vector<string>input_source;
input_source.push_back("*,2,T0,T3");
input_source.push_back("+,R,r,T4");
input_source.push_back("*,T3,T4,T5");
input_source.push_back("-,R,r,T6");
input_source.push_back("*,T5,T6,B");
/* Deceleration of structures */
/********************************************************************/
structFour{
string op;//操作符
string arg1;//第一个操作数
string arg2;//第二个操作数
break;
case1:
tmp1->bsf=fhead->arg1;
tmp1->var= "";
tmp1->flag = 0;
tmp1->lchild= NULL;
tmp1->rchild= NULL;

编译原理优化

编译原理优化

编译原理
长春工业大学计算机科学与工程学院
考虑求最大公因子的三地址代码程序: (1) read X (2) read Y (3) R=X % Y (4) if R= 0 goto(8) (5) X=Y (6) Y=R (7) goto(3) (8) write Y (9) halt 基本块分别为: (1)(2), (3)(4), (5)(6)(7), (8)(9)
n1 T0 n2 6.28 n3 R
*
n3
T1
n4 r
T1
n4 r
3.14
6.28
R
(4)A = T1*T2
(5)B = A
编译原理
长春工业大学计算机科学与工程学院
n6
A, B n5 T2 +
*
n1 T0 n2 6.28 T1, T3 n3 R
n4 r
3.14
(6) T3= 2*T0 处理过程与T1=2*T0类似, 但生成P时因其已在 DAG中, 故不生成新结点而直接将T3附加到结点 6.28上。
编译原理
长春工业大学计算机科学与工程学院
解: 按算法顺序处理每个三地址代码后构造 出的DAG如图所示:
n1 B A n1 T0
3.14
A=B
n3 A op n1 B n2
(1)T0 = 3.14
n3 T1 6.28 * n1 n2 2 n1 3.14 T0 n2 6.28 T1
C
3.14
A=B op C
编译原理
长春工业大学计算机科学与工程学院
通过观察DAG图中所有叶结点、内部结点 及附加标识符, 可得出如下结论: (1) 在基本块外被定值并在基本块内被引 用的所有标识符均为DAG中叶结点上标记的标 识符; (如R, r) (2) 在基本块内被定值且该值能在基本块 后面被引用的标识符均为DAG各结点上的附加 标识符。(如T1, T2, T3 )

中间 代码

中间 代码

1. 说明类代码 var x label类代码 x=y x = op y x = y op z
三地址码
3. 转移类代码 goto L if x goto L ifz x goto L
4. 函数类代码 begin end x = call L return x
相关知识
一、主持人的语言特点 主持人通过使用轻松、诙谐、明快、委婉的语言,营造出愉悦、自然、亲切的氛围,建立起情 感的纽带,增进人与人之间的关系。 (一)情感化 【案例1】 背景:中央台、天津台联合录制的少儿春节晚会中的一段。 鞠萍:啊呀!这么高的电视塔!我还是第一次见到!(与孩子们同惊、同喜)我们天津的小朋 友们有福气啊。你们知道吗?世界上最高的电视塔在加拿大,你们看到的天塔是咱们亚洲最高 的电视塔。除了加拿大的多伦多电视塔、莫斯科电视塔,我们天津的电视塔数世界第三呢!我 们工人叔叔只用了3年零100天的时间,就把这么高的电视塔建成了,他们伟大不伟大啊?
中间代码
中间代码是一种介于源代码和目标代码之间的代码,它独立于任何一种具体的 目标机器,形式简单而语义明确。
使用中间代码作为语义分析的输出具有以下优点: 1. 便于表达语义 2. 便于优化 3. 便于移植
三地址码
中间代码有多种不同的形式(如三地址码、四元式、后缀式、语法树等),本 课程采用三地址码的形式。常见的三地址码有:
第八章 语义分析
第一节 语义分析概述 第二节 中间代码 第三节 说明语句的翻译 第四节 赋值语句的翻译
中间代码
编译程序的任务是将源程序翻译成目标程序。在语义分析阶段,操作各符号的 语义值只是手段,其目的还是为了完成源程序中各个语句的翻译,将源代码翻 译成目标代码。
出于可移植性、优化等方面的考虑,语义分析阶段并不会直接将源程序翻译成 目标程序,而是翻译成某种特定形式的中间代码。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。


中间代码优化的分类
– 按照优化范围:分为局部优化和非局部优化(循
环优化和全局优化) – 按照优化方法:分为常量表达式优化,公共子表 达式优化,循环不变量外提优化
8.1 中间代码优化概述

常量表达式优化(合并常数)
– v = a*b+c, 若a = 2, b=3, c=5 则可用v = 11替换
– u = v +3;

常量表达式:任何时候都取固定常数值的表达式 优化方法:用常量值替换原来的运算 – i = 30; j = 2*i; k = i*j; 可用 k=1800代替 优化的关键:知道哪些量取常数值 方法:建立常量定义表ConDef (id, value) 优化算法:
1. 在入口处,ConDef为空; 2. 读取一个四元式tuple,对tuple中的分量进行值替换得newtuple; 3. 若newtuple是(,A,B,t)情形:且A,B都是常数值,则计算A B的值v,

(ASSIG,1,-i) (WHILE,-,-,-) (LE,i,100,t1) (DO,t1,-,-) (MULTI,i,k,t2) (MULTI,t2,5,t3) (ASSIG,t3,-,z) (MULTI,2,k,t4) (MULTI,t4,2,t5) (ADDI,t4,t5,t6) (ASSIG,t6,-,a) (ADDI,i,1,t7) (ASSIG,t7,-,i) (ENDWHILE,-,-,-)
B3 B4
B7
B5
(ASSIG,0,-,z)
B8
程序流图:以基本块为结点的有向图 B1 在一个基本块上进行的优化称为局部优 化 B2 在多个基本块上进行的优化称为非局部 优化 B3 – 循环优化(多个基本块) B4

– 全局优化(整个程序流图)
B5
B6
B7
B8
8.3 常量表达式的局部优化
– 识别循环:(WHILE,-,-,-) –入口 – (DO,e.form,-,-) –循环体开始 – (ENDWHILE,-,-,-) –出口 – 识别循环不变量:建立循环定义表LoopDef
8.5 循环不变式外提优化

外提对象: 除法运算不外提
– while e do
if y=0 then x=y; else x=a/y; 赋值不外提: (赋值操作的左部和右部都是 循环不变述 8.2 基本块划分
8.3 常量表达式局部优化
8.4 公共表达式局部优化 8.5 循环不变式外提 8.6 其他各类优化介绍
8.1 中间代码优化概述

为什么在中间代码上进行优化?
– 有些优化只在中间代码一级进行
优化的目标
– 最小的代价,提高目标程序运行速度 – 是否优化,优化到何种程度取决于编译器设计者
y= 1; L: if A and B then x=0 else y=0; x=x+1; y=y-1; while x+y>0 do x=x-1; z=0;
(ADDI,x,y,t3)
(GT,t3,0,t4) (DO,t4,-,-) (SUBI,x,1,t5)
(ASSIG,t5,-,x)
(ENDWHILE,-,-,-) (ASSIG,0,-,z)
u替换成14

公共子表达式节省(消除重复操作)
– t = b*c; e = b*c+b*c; c=b*c+10; d = b*c+d; – t = b*c; e = t+t; c=b*c+10;d = b*c+d;

循环不变量外提
– while (k<10) {a[k] = b*c; k=k+1} – t = b*c; while(k<10){a[k]=t;k=k+1;}

在基本块入口处,置ValuNum, UsableExpr,PAIR为空
逐条扫描基本块的中间代码。
对当前四元式tuple中运算分量进行等价替换(用PAIR替换), 设所得代码为newtuple.

如果newtuple是dj : (,A’,B’,tj),进行如下操作:
– –
若A’是首次出现,则把(A’,NewVN)填入ValuNum; 若B’是首次出现,则把(B’,NewVN)填入ValuNum; 式,则删除tuple,将(ti,tj)填入PAIR,同时(tj) = (ti);
(t2,t1) (t4,t1) (t5,t1) (t6,t3)
5. (:=,b,-,d)
6. (*,d,c,t4) 7. (*,b,c,t5)
t1 t1 8. (+t4,t5,t6)
9. (:=,t6,-,e) t3
8.5 循环不变式外提优化

思想: 将值在循环里不发生改变的表达式运算提 到循环外面进行 i =1; while i<1000 do a[i] = x*y; i =1; t = x*y; while i<1000 do a[i] = t; 关键: 识别循环结构(循环入口,循环体,循环出口) 判断循环不变式 判断循环不变量 方法:
并在ConDef中填入(t,v),同时删除四元式(,A,B,t); 4. 若newtuple是(ASSIG,A,-,B)情形:若A是常数,则把(B,A)填入 ConDef中(若已有B的表项,则只需修改B的值);否则,从ConDef 中删除B的表项。 5. 重复2-4直到基本块结束

x = 10 y = x+1; x=a; z=y+5;
B1 B2
(ASSIG,1,-,y)
(LABEL,-,-,L) (AND,A,B,t) (THEN,t,-,-) (ASSIG,0,-,x) (ELSE,-,-,-) (ASSIG,0,-,y) (ENDIF,-,-,-) (ADDI,x,1,t1) (ASSIG,t1,-,x)
(SUBI,y,1,t2) (ASSIG,t2,-,y) (WHILE,-,-,-) (ADDI,x,y,t3) (GT,t3,0,t4) (DO,t4,-,-) (SUBI,x,1,t5) (ASSIG,t5,-,x) (ENDWHILE,-,-,-) B6
8.2 基本块划分
标号性四元式: (LABEL, -, -, L) (ENTRY, Lf, size, Level) (WHILE, -, -, -) (ENDIF,-,-,-)

转移性四元式: (JMP/JMP0/JMP1, -, -, L) (THEN,E,-,-) (ELSE,-,-,-) (DO,E,-,-) (ENDWHILE,-,-,-) (ENDFUNC,-,-,-)
– 凡是循环不变式都外提
– 只外提一定被执行的循环不变式
8.5 循环不变式外提优化

1. 2. 3.
4.
生成中间代码过程中构造本层循环的LoopDef; 当结束一层循环的中间代码时,做如下操作: 扫描本层循环的一个中间代码,设(,A,B,t) 若不是可外提操作码,则转1扫描下一代码; 若是外提操作码,则检查A,B是否属于本层 LoopDef,若都不属于,则转4,否则转1; 若A和B都是本层循环不变量,则作:
1. (*,b,c,t1)
2. (*,b,c,t2)
3. (+,t1,t2,t3) t1
4. (:=,t3,-,a)
ValuNum (b,1) (c,2) (t1,3) (t2,3) (t3,4) (a,4) (d,1) (t4,3) (t5,3) (t6,4) (e,4) UsableExpr 1 3 PAIR

设有源程序如下:
(ASSIG,1,-,y)
(LABEL,-,-,L) (AND,A,B,t) (THEN,t,-,-) (ASSIG,0,-,x) (ELSE,-,-,-) (ASSIG,0,-,y) (ENDIF,-,-,-) (ADDI,x,1,t1) (ASSIG,t1,-,x) (SUBI,y,1,t2) (ASSIG,t2,-,y) (WHILE,-,-,-)

等价四元式: 两个运算型四元式(1,A1,B1,t1)和 (2,A2,B2,t2),若1= 2, A1和A2的值相同,B1和B2的值 相同,则称这两个四元式等价

公共表达式节省:当一个基本块中出现多个等价四元式时, 除第一个四元式以外,其他的均可节省。 关键:判断四元式等价 方法:建立可用表达式表UsableExpr 建立值编码表ValuNum (id, Vno) 建立临时变量等价表PAIR: (ti,tj)
– 若存在di : (,A,B,ti)UsableExpr,使得dj代码是di代码的公共表达

否则,把(tj, NewVN)填入ValuNum中,把dj加到UsableExpr中;

如果newtuple是dj: (ASSIG,A’,-,B’),进行如下操作:
– – –
从UsableExpr中删除含B’的所有可用表达式代码; 若A’是首次出现,则把(A’,NewVN)填入ValuNum; 令 (B’) = (A’);


将(,A,B,t)外提到本层循环入口处; 把t从本层LoopDef移到外层LoopDef. 删除原(,A,B,t)。
5. 重复1-4直到本层循环结束。

i =1; while i<=100 do begin z=i*k*5; a = 2*k+2*k*2; i=i+1; end








LoofDef 1 …… j-1 j
…… …… …… i t1 t2 t3 z t4 t5 t6 a t7 i
(ASSIG,t6,-,a) (ADDI,i,1,t7) (ASSIG,t7,-,i) (ENDWHILE,-,-,-)
相关文档
最新文档