编译原理第三版 第十章 代码优化
编译原理优化
v:=a[T1]
B1
i:=i+1
T2:=4*i T3:=a[T2]
B2
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
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
a[T12]=T14
T15:= T13
a[T15]=x
复写传播后
19
i:=m-1
j:=n
T1:=4*n
v:=a[T1]
B1
i:=i+1
T2:=4*i T3:=a[T2]
B2
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
合算原则
应尽可能以较低的代价取得较好的优化效果
6
10.1 概述
优化的三个不同级别
局部优化 循环优化 全局优化
优化的种类
删除多余运算(或称删除公用子表达式) 合并已知量 复写传播 删除无用赋值 代码外提 强度消弱 变换循环控制条件
7
void quicksort (m, n);
T14:=a [T13]
a[T12]=T14
T15:= T13
a[T15]=x
复写传播后
15
i:=m-1
j:=n
T1:=4*n
v:=a[T1]
编译原理chapter9优化
t11 := 4 * i x := a[t11] t12 := 4 * i t13 := 4 * n t14 := a[t13] a[t12] := t14 t15 := 4 * n a[t15] := x
10.2.2 公共子表达式删除
如果表达式E先前已计算,并且从先前的计算到E的再次出现,E中变量的 值没有改变,那么E的这个再次出现称为公共子表达式
(2) j := n
do i = i +1; while(a[i]<v); (3) t1 := 4 * n
do j =j 1;while (a[j]>v); (4) v := a[t1]
if (i >= j) break;
(5) i := i + 1
x=a[i]; a[i]=a[j]; a[j]=x; (6) t2 := 4 * i
}
(7) t3 := a[t2]
10.2 优化的主要种类
本节所用的例子
i = m 1; j = n; v = a[n]; (9) j := j 1
while (1) {
(10) t4 := 4 * j
do i = i +1; while(a[i]<v); (11) t5 := a[t4]
do j =j 1;while (a[j]>v); (12) if t5>v goto (9)
10.2.2 公共子表达式删除
B5 x=a[i]; a[i]=a[j]; a[j]=x;
t6 := 4 * i x := a[t6] t7 := 4 * i t8 := 4 * j t9 := a[t8] a[t7] := t9 t10 := 4 * j a[t10] := x
编译原理中的目标代码生成与优化
编译原理中的目标代码生成与优化编译原理是计算机科学中的一门重要课程,它研究的是将高级程序语言转化为机器语言的过程。
目标代码生成与优化是编译过程中的两个关键环节,本文将就这两个方面展开讨论。
一、目标代码生成目标代码生成是编译过程中的最后一步,它的任务是将中间代码转化为能够在目标机器上执行的机器代码。
目标代码生成的质量直接影响程序的执行效率和占用的存储空间。
1. 寄存器分配在进行目标代码生成之前,我们需要进行寄存器分配。
寄存器分配的目的是将中间代码中的临时变量分配到机器寄存器中,减少内存读写操作,提高程序的运行速度。
常用的寄存器分配算法有线性扫描算法和图着色法。
2. 目标代码生成技术目标代码生成的技术有很多,下面列举几种常见的技术:(1) 直接生成代码:直接将中间代码翻译为目标机器的指令序列。
这种方法简单直接,但生成的目标代码质量一般较低。
(2) 间接生成代码:先将中间代码翻译为一个中间形式,再将中间形式转化为目标机器的指令序列。
这种方法可以进行一些优化,生成的目标代码质量较高。
(3) 使用代码模板:事先定义一些目标机器的指令模板,并根据中间代码的特征选择合适的指令模板来生成目标代码。
这种方法可以充分利用目标机器的特性,生成的目标代码效率较高。
二、目标代码优化目标代码优化是指对生成的目标代码进行一系列的优化,以提高程序的运行效率和减少代码的空间占用。
1. 基本块优化基本块是由顺序执行的指令组成的,没有前驱指令和后继指令的指令序列。
基本块优化的目的是对基本块中的指令进行优化,以减少执行时间和空间开销。
常见的基本块优化技术有死代码删除、常量传播等。
2. 寄存器优化寄存器是计算机中的一块高速存储器,能够提供快速的数据访问速度。
寄存器优化的目的是将变量尽可能地存放在寄存器中,以减少内存读写操作,提高程序的执行效率。
常用的寄存器优化技术有寄存器分配、寄存器重命名等。
3. 循环优化循环是程序中的重要结构之一,对循环进行优化可以显著提高程序的执行效率。
编译原理总结10_优化及目标代码生成
7.1 编译程序考虑的因素
控制结构
一个程序设计语言的控制结构是该语言
在程序运行期间用于改变控制流的语言特征
集合。
5
7.2 运行时的存储分配
编译程序需要为源程序中的数据分配执行时的存储
空间,编译程序从操作系统中申请编译程序计算出的所
需的内存,或编译程序生成在运行时需申请内存的指令。 (1) 确定用来表示某一数据项的内存大小; (2) 使用适当的内存分配策略,实现具体数据的作用 域和生存期;
1.外提不变式:将循环中的不变运算提到循环前面 ,不变运算是指其运算结果不受循环影响的表达式。
2.强度削弱:把程序中执行时间较长的运算替换为 执行时间较短的运算 。 3.删除基本归纳变量:如果循环中对变量I只有唯一 的形如:I = I ± C的赋值,且C为循环不变量,则 称I为循环中的基本归纳变量;删除归纳变量在强度 削弱后进行。
10
7.3 代码优化
优化的基本方法
• 去处冗余
• 削减强度
• 使用更快的指令
11
7.3.1
局部优化
在一个基本块上进行的优化
基本块:程序中一个顺序执行的语句序列, 即一个程序段,它只有一个入口和一个出 口,入口是第一条语句,出口是最后一条 语句。
12
基本块划分方法
(1)确定各个基本块的的入口语句(基本块的第一个语句) ① 语句序列的第一个语句是入口语句; ② 能由条件转移语句或无条件转移语句转到的语句是入口语 句; ③ 紧跟在条件转移语句或无条件转移语句后面的语句是入口 语句。
2
7.1 编译程序考虑的因素
数据结构
一个程序设计语言如允许使用的数组、记录、字符串、表、
栈等形式的数据结构,在编译程序中应为它们提供相应的翻译。
编译原理 第10章(清华大学)
∶ ∶
(a) (a) 到 达 标 号 B1处 ;
BB 的 内 情 向 量 ZZ
BB11 的 TT OO P DISPLAY
形式单元 m,n 2
连接数据 A的TOP
∶ ∶ (b) (b)进 入 分 程 序 B1;
31
数 组B
B的 内 情 向 量 z
B1 的 T O P D I S P LAY
20
用Display表的方案
(1)主程序--->(2)P--->(3)Q--->(4)R
top
P的
display sp 活动记录
d[1]
主程序的
d[0]
活动记录
top display
主程序的
d[0]
sp 活动记录
(2)
(1)
21
用Display表的方案
• 主程序--->P--->Q--->R
d[2]displatyopsp
endmainmainqrmainqqtopr的活动记录q的活动记录spq的活动记录q的活动记录主程序全局主程序全局数据区数据区top临时工作单元局部简单变量局部数组的内情向量保存运行过程前的状态返回地址寄存器值??实参形式单元和参数个数sp控制链老sptop的数组区sp的活动记录q的活动记录主程序全局数据区嵌套过程语言的栈式分配方案l主要特点语言一个过程可以引用包围它的任一外层过程所定义的标识符如变量数组或过程等
地址 3 参数个数 4 形式单元
. . . d D ISP L A Y . 简单变量 . 数组内情向量 . 临时变量
• 当过程的层次为n, 它的 display为n+1个 值。 • 一个过程被调用时, 从调用过程的 DISPLAY表中自下向 上抄录n个SP值,再加 上本层的SP值。 •全局DISPLAY地址
程序设计语言编译原理第三版第10章
§10.2 局部优化
举例:考察下面的三地址代码程序
(1)Read X
(2)Read Y
B1
(3)R:=X mod Y (4)if R=0 goto (8) B2
(5)X:=Y
(6)Y:=R
B3
(7)goto(3)
(8)write Y B4
(9)halt
B1
B2
B3
B4
§10.2 局部优化
3.流图及其生成
标识符(包括常数)-结点 NODE(A)-描述上述对应关系的函数,其值或者是一个结点的编号,
或者无定义
(2)中间代码的三种形式:A:=B A:=op B A:=B op C 或 A:=B[C]
(3)构造算法: ①开始,DAG为空 ②对基本块中每一条中间代码式,依次执行以下步骤:
§10.2 局部优化
步骤: 1.如果NODE(B)无定义,则构造一标记为B的叶结点并定义
NODE(B)为这个结点 如果当前代码是0型,则记NODE(B)的值为n,转4 如果当前代码是1型,则转2(1) 如果当前代码是2型,则(ⅰ)如果NODE(C)无定义,则构造一标 记
为C的叶结点并定义NODE(C)为这个结点;(ⅱ)转2(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
(4)代数变换
§10.2 局部优化
二、基本块的DAG表示及其应用
1.基本块的DAG:
一种结点带有下述标记或附加信息的DAG
(1)图的叶结点以一标识符(变量名)或常数作为标记,表示该 结点代表该变量或常数的值。
编译原理课件-代码优化
Wensheng Li BUPT @ 2008
常數合併的實現
在符號表中增加兩個資訊域
–標誌域:指示當前是否存在與該變數相關的常數。 –常數域:如果常數存在,則該域存放的即是與該變數相
應的當前常數值。
常數合併時,注意事項:
–不能將結合律與交換律用於浮點運算式,因為浮點運算 的精度有限,這兩條定律並非是恒真的。
PI:=3.14; D-to-R:= 30P.I01/4117/814084.00;.0
i:=0 10: i:=i+1
... if i<10 goto 10
i:=0 10: i:=0+1
... if i<10 goto 10
... a[i]:=9.0 ... a[j]:=3.0 b:=a[i]
?
7/62
– 所謂等價,指不改變程式的運行結果 – 所謂有效,指目標代碼運行時間短、佔用空間少
基本塊的dag是一種結點上有標記的有向非迴圈圖
– 葉結點由變數名字或常量標記。 – 根據作用到名字上的算符,決定需要名字的左值還是右
值。大多數葉結點代表右值。 – 葉結點代表名字的初值,通常為識別字加上腳標0。 – 內部結點由運算符號標記,代表計算出來的值。 – 圖中各結點可能附加一個或多個識別字,表示這些識別
10.1 優化概述
代碼優化程式的任務
–將前端產生的中間代碼轉換為等價的目標代碼
代碼優化程式的要求
–等價變換 –提高目標代碼的執行速度 –減少目標代碼佔用的空間
代碼優化程式的地位
–目標代碼生成之前的中間代碼優化 –目標代碼生成之後的目標代碼優化
3/62
Wensheng Li BUPT @ 2008
代碼優化程式的位置
编译原理 第10章 代码优化
3、冗余子表达式的消除:在值不发生变化的情 况下,对同一个表达式只需计算一次,再次出现时 直接使用它的值。
例(P199) 有如下 程序段: ① a=b+c; 因为语句2和4之间a 和d没有变化,故应 优化为:
① a=b+c;
② b=a-d; ③ c=b+c; ④ d=b;
10.1 局部优化
基本块的DAG构造算法(续):
(4)若NODE(A)=null,则把A附加到结点n,并令 NODE(A)=n,转(4);否则,先从NODE(A)的附加标识 集中将A删去(注意,若NODE(A)有前驱或NODE(A)是 叶结点,则不能将A删去),然后再把A附加到新的结点 n,并令NODE(A)=n。
10.1 局部优化
基本块的优化技术: 1、常数合并:常数合并是将能在编译时计算出值 的表达式用其相应的值替代。 例(P199)
x=3.14*2
y=2*5*a; z=x+1; 转换成四元 式为: (*,3.14,2,t1) (=,t1,_,x) (*,2,5,t2) (*,t2,a,t3) (=,t3,_,y) (+,x,1,t4) (=,t4,_,z) 常数合并后 的代码如下: (=,6.28,_,x)
例(P212)
优化后
小 结
1、代码优化种类(按优化范围划分): 局部优化、循环优化和全局优化 2、基本块的划分、优化技术(常数合并、 删除无用赋值和冗余子表达式的消除) 和DAG表示 3、循环优化技术:外提循环中的不变表 达式、强度削弱和删除归纳变量
习 题
1. 对下列基本块应用 DAG进行优化: 1. (=,3,,B) 2. (+,A,C,D) 3. (*,A,C,E) 4. (+,D,E,F) 5. (*,B,F,G) 6. (+,A,C,H) 7. (*,A,C,I) 8. (+,H,I,J) 9. (*,B,5,K) 10.(+,K,J,L) 11.(=,L,,M) 2. 对下面程序段画出程 序流图,并进行循环优 化。 I=1; J=10; K=5; L1:X=K*I; Y=J*I; Z=X*Y; I=I+1 if I<100 goto L1;
编译原理:第十章 优化
i:=m-1
j:=n
T1:=4*n
v:=a[T1]
T2]
B2
if T3<v goto B2
10.1 概述
• 优化的三个不同级别:
• 局部优化 • 循环优化
• 全局优化
• 优化的种类:
• 删除多余运算(或称删除公用子表达式) • 代码外提 • 强度消弱 • 变换循环控制条件 • 合并已知量 • 复写传播 • 删除无用赋值
void quicksort (m, n); int m, n;
{ int i, j; int v, x; if (n<=m) return; /* fragment begins here*/ 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; }
if T5>v goto B3
if i>=j goto B6 B4
T6:= T2 x:=T3 T7:= T2 T8:= T4 T9:=T5 a [T2]=T5 T10:= T4 a [T4]= T3 goto B2
B5
T11:= T2 x:=T3
T12:= T2
T13:= T1
T14:= v
a [T2]=v
T4:=4*j
T2:= T2+4
编译原理 第十章 代码优化
第十章代码优化某些编译程序在中间代码或目标代码生成之后要对生成的代码进行优化。
所谓优化,实质上是对代码进行等价变换,使得变换后的代码运行结果与变换前代码运行结果相同,而运行速度加大或占用存储空间少,或两者都有。
优化可在编译的不同阶段进行,对同一阶段,涉及的程序范围也不同,在同一范围内,可进行多种优化。
一般,优化工作阶段可在中间代码生成之后和(或)目标代码生成之后进行。
中间代码的优化是对中间代码进行等价变换。
目标代码的优化是在目标代码生成之后进行的,因为生成的目标代码对应于具体的计算机,因此,这一类优化在很大程度上依赖于具体的机器,我们不做详细讨论。
另外依据优化所涉及的程序范围,又可分为局部优化、循环优化和全局优化三个不同的级别。
局部优化指的是在只有一个入口、一个出口的基本程序块上进行的优化。
循环优化对循环中的代码进行的优化。
全局优化是在整个程序范围内进行的优化。
本章重点:局部优化基本块的DAG表示第一节优化技术简介为了说明问题,我们来看下面这个例子,源程序是:P :=0For I :=1 to 20 doP :=P+A[I]*B[I];经过编译得到的中间代码如图10-1-1所示,这个程序段由B1和B2两个部分组成,B2是一个循环,假定机器按字节编址。
那么,对于这个中间代码段,可进行如下这些优化。
1、删除多余运算(删除公共子表达式)优化的目的在于使目标代码执行速度较快。
图10-1-1中间代码(3)和(6)中都有4*I的运算,而从(3)到(6)没有对I赋值,显然,两次计算机的值是相等的。
所以,(6)的运算是多余的。
我们可以把(6)变换成:T4 :=T1。
这种优化称为删除多余运算或称为删除公共子表达式。
2、代码外提减少循环中代码总数的一个重要办法是代码外提。
这种变换把循环不变运算,即其结果独立于循环执行次数的表达式,提到循环的前面。
使之只在循环外计算一次,上例中,我们可以把(4)和(7)提到循环外。
经过删除多余运算和代码外提后,代码变成图10-1-2。
编译原理-第10章-代码优化
x := t3 t14 := a[t1] a[t2] := t14 a[t1] := x
16
10.1.1公共子表达式删除
B6 x = a[i]; a[i] = a[n]; a[n] = x; a[t1]能否作为公共子表达式? t11 := 4 * i x := a[t11] x := t3 t12 := 4 * i t14 := a[t1] t13 := 4 * n a[t2] := t14 t14 := a[t13] a[t1] := x a[t12] := t14 t15 := 4 * n a[t15] := x
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 B5
2014-7-6
B4
B6
8
10.1.1公共子表达式删除
15
10.1.1公共子表达式删除
B6 x = a[i]; a[i] = a[n]; a[n] = x; t11 := 4 * i x := a[t11] t12 := 4 * i t13 := 4 * n t14 := a[t13] a[t12] := t14 t15 := 4 * n a[t15] := x
2014-7-6
t6 := 4 * i x := a[t6] t8 := 4 * j t9 := a[t8] a[t6] := t9 a[t8] := x goto B2
x := a[t2] t9 := a[t4] a[t2] := t9 a[t4] := x goto B2 x := t3 a[t2] := t5 a[t4] := x goto B2
编译原理-清华大学-第10章1-代码优化
(1)P:=0 (2)I:=0 (4)T2:=addr(A) (7)T5:=addr(B) (3)T1:=0
(5)T3:=T2[T1] (6)T4:=T1 (8)T6:=T5[T4] (9)T7:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (3‘)T1:=T1+4 (12)if I<=20 goto(5)
2、代码外提
目的:减少循环中代码总数。 方法:把循环不变运算,即其结果独立
于循环执行次数的表达式提到循环的前 面,使之只在循环外计算一次。
(1)P:=0 (2)I:=0
(3)T1:=4*I (4)T2:=addr(A) (5)T3:=T2[T1] (6)T4:=T1 (7)T5:=addr(B) (8)T6:=T5[T4] (9)T7:=T3*T6 (10)P:=P+T7 (11)I:=I+1 (12)if I&l经过变换循环的控制条件后,有些变 量不被引用,可以从循环中删除。
(1)P:=0 (2)I:=0 (4)T2:=addr(A) (7)T5:=addr(B) (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 (3’)T1:=T1+4 (12)if I<=20
2)在运行基本块时,只能从其入口进入, 从出口退出。
2、划分基本块算法
(1)求出各基本块的入口语句 1)程序的第一个语句 ; 2)能由条件转移语句和无条件转移语句转
移到达的语句; 3)紧跟在条件转移语句后面的语句。
(2) 对以上求出的每个入口语句,确定其所 属的基本块。它是由该入口语句到下一入 口语句(不包括该入口语句) 之间的语句序 列组成的。
编译原理第三版 第十章 代码优化
(1) P:=0
(2) I:=1 B1 (4) T2:=addr(A) - 4 (7) T5:=addr(B) - 4 (3) T1:=4*I
(5) T3:=T2[T1] B2 (8) T6:=T5[T1] (9) T7:=T3*T6 (10) P:=P+T7 (11) I:=I+1 (3‘) T1:=T1+4 (12) if I≤20 goto (5)
方法:循环查找算法、数据流分析;复杂、高效。 全局优化:在整个程序上的优化 方法:全局控制流分析、全局数据流分析; 特点:代价大、高效。
10.2 局部优化
问题: 什么是基本块? 怎样划分基本块? 在基本块中可以进行哪些优化? 怎样进行局部优化? 10.2.1 基本块和流图 对一给定的程序,将其划分为若干个基本块, 在各个基本块中分别进行优化即称为局部优化。
图3 删除无用代码和代码外提
图4 运算强度削弱
(1) P:=0
(2) I:=1 B1 (4) T2:=addr(A) - 4 (7) T5:=addr(B) - 4 (3) T1:=4*I (5) T3:=T2[T1] B2 (8) T6:=T5[T1] (9) T7:=T3*T6 (10) P:=P+T7 (11) I:=I+1 (3’) T1:=T1+4 (12) if I≤20 goto (5)
优化不是目的,只是手段
3. 优化方法 按优化所涉及的程序范围分: 局部优化: 在基本块上进行的优化 • 合并已知量
• 删除无用赋值(无用代码) • 删除多余运算(公共子表达式)
方法:DAG; 特点: 简单、成熟。 循环优化:在循环块上进行的优化 • 代码外提
• 运算强度削弱 • 删除归纳变量
编译原理优化
编译原理优化
编译原理优化是指在编译过程中对程序进行优化,以提高程序的执行性能和效率。
优化可以在不改变程序的功能和语义的前提下,通过改变程序的结构和算法,以及使用各种编译技术来提高程序的执行速度和资源利用率。
在编译过程中,优化的主要目标是减少程序的执行时间和提高计算资源的利用效率。
为了达到这个目标,编译器可以对程序进行各种优化,包括代码重排、循环展开、常量传播、消除冗余代码等。
代码重排是一种常见的优化技术,它通过改变程序中指令的顺序,以提高指令的局部性和并行度。
例如,通过将频繁执行的指令放在一起,可以减少指令的Cache Miss次数,从而提高
程序的执行速度。
循环展开是一种针对循环结构的优化技术,它可以将循环中的多次重复计算的指令展开成多个相同的指令,从而减少循环的迭代次数,提高程序的执行效率。
常量传播是一种优化技术,它通过将程序中的变量替换为其常量值,以避免运行时的计算开销。
如果变量的值在程序中是不变的,那么在编译的过程中可以将其替换为常量,从而减少了变量的内存访问和计算开销,提高了程序的执行速度。
消除冗余代码是一种优化技术,它通过删除程序中没有实际作用的代码,以减少程序的执行时间和内存占用。
例如,如果一个变量在程序中没有被使用,那么可以将其从程序中删除,从而减少了内存的占用和程序的执行时间。
除了上述的优化技术之外,编译原理还有很多其他的优化技术,如代码传递优化、局部变量优化、全局变量优化等。
这些优化技术都可以通过改变程序的结构和算法,以及使用各种编译技术来提高程序的执行性能和效率。
编译原理10-优化
识别在程序中活跃的变量,优化其存
常量传播
2
储和访问方式。
将变量替换为常量的值,减少不必要
的计算。
3
公共子表达式消除
避免重复计算相同的子表达式,提高 运行效率。
代码生成优化
指令调度
重新排序和调整指令的执行顺序,提高指令级别 的并行性。
寄存器分配
将变量分配到寄存器中,减少内存访问的次数。
常见的优化工具和编译器
用。
3
难以预测的程序行为
某些程序具有复杂的控制流和数据依 赖关系,使优化变得困难。
硬件限制
优化技术受限于硬件架构和指令集。
GCC编译器
广泛使用的开源编译器,提供了丰富的编译优化选项。
LLVM编译器
Modular Language Infrastructure的缩写,具有强大的优化能力。
Intel C++编译器
专为Intel处理器优化的编译器,提供了特定的优化选项。
优化的挑战和限制
1
时间和空间的权衡
2
优化常常需要平衡执行时间和内存占
内联函数
将函数调用替换为函数体,减少了函数调用 的开销。
常数传播
将常量直接替换为计算结果,减少变量和内 存的使用。
寄存器分配
将变量存储在寄存器中,提高了访问速度。
控制流优化
控制流图
分支预测
通过分析代码的控制流图来优化程序的执行路径。 通过预测条件分支的结果来提高程序的执行效率。
数据流优化
1
活跃变量分析
编译原理10-优化
在这个章节中,我们将深入ห้องสมุดไป่ตู้究编译原理中的优化技术。了解编译器优化的 定义和目标,并介绍一些常见的优化技术。
编译原理分知识点习题 代码优化
1.与机器有关的代码优化有那些种类,请分别举例说明。
解答:与机器有关的优化有:寄存器优化,多处理优化,特殊的指令优化,无用的指令消除等四类。
冗余指令删除假设源程序指令序列a:=b+c; c:=a-d;编译程序为其生成的代码很可能是下列指令序列:MOV b, R0ADD c, R0MOV R0,aSUB d, R0MOV R0,c假如第四条指令没有标号,上述两个赋值语句在一个基本块内,则第四条指令是多余的,可删除。
特殊指令的使用例如,如果目标机器指令系统包含增1指令INC,对于i:=i+1的目标代码MOV i, R0ADD #1, R0MOV R0, i便可被代之以1条指令Inc i说明:优化的特点是每个改进可能会引发新的改进机会,为了得到最好的改进,一般可能需要对目标代码重复扫描进行优化。
2.设有语句序列a:=20b:=a*(a+10);c:=a*b;试写出合并常量后的三元式序列。
解答:该语句序列对应的三元式序列为:(1)(:=, 20,a)(2)(+, a, 10)(3)(*, a, (2) )(4)(:=, a, b)(5)(* a, b)(6)(:=, (5), c)合并常量后的三元式序列为:(1)(:=, 20,a)(2)(:=, 600, b)(3)(:=, 12000, c)3、试写出算术表达式a+b*c-(c*b+a-e)/(b*c+d)优化后的四元式序列。
解答:该表达式的四元式序列为:(1)(*,b,c,T1)(2)(+,a,T1,T2)(3)(*,c,b,T3)(4)(+,T3,a,T4)(5)(-,T4,e,T5)(6)(*,b,c,T6)(7)(+,T6,d,T7)(8)(/,T5,T7,T8)(9)(-,T2,T8,T9)可对该表达式进行删除公共子表达式的优化。
优化后的四元式序列为:(1)(*,b,c,T1)(2)(+,a,T1,T2)(3)(-,T2,e,T5)(4)(+,T1,d,T7)(5)(/,T5,T7,T8)(6)(-,T2,T8,T9)4.设有算术表示式(a*b+c)/(a*b-c)+(c*b+a-d)/(a*b+c)试给出其优化后的三元式序列。
山东大学编译原理Chapter10_Code optimization
Chapter 10 Code optimization Basic Blocks and flow graphs 3.Partition into basic blocks • Input. A sequence of three-address statements • Output. A list of basic blocks with each three-address statement in exactly one block. • Method. 1) We first determine the set of leaders, the first statements of basic blocks.The rules we use are the following:
Chapter 10 Code optimization Basic Blocks and flow graphs 1.Flow graph • A directed graph that are composed of the set of basic blocks making up a program
(9) j := j 1 (10) t4 := 4 * j (11) t5 := a[t4] (12) if t5>v goto (9) (13) if i >=j goto (23) (14) t6 := 4 * i (15 ) x := a[t6] . . .
Chapter 10 Code optimization
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 B5 B4 B6
编译原理课件 第10章 优化
把四元式程序划分为基本块的算法: (1) 确定满足以下条件的入口语句: ①四元式序列的第一个语句; ②能由条件转移或无条件转移语句转移 到的语句; ③紧跟在条件转移语句后面的语句。 (2) 确定满足以下条件的出口语句: ① 下一个入口语句的前导语句; ② 转移语句;③ 停语句。
例如,考察下述三地址代码程序: (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)、(3)、(5)、(8)
n8 B
*
n6 A,T 5 * n5 T ,T n7 T 2 4 6 + n1
3.14
T0
n2
6.28
T1,T 3
n3
R
n4 r
10.1.3 利用DAG进行基本块的优化 利用DAG进行基本块优化的基本思想: 按构造DAG结点的顺序,对每个结点写出相 应的四元式表示。 例如,上例四元式序列G‘如下: (1) T0=3.14 (2) T1=6.28 (3)T3=6.28 (4) T2=R+r (5) T4=T2 (6) A=6.28*T2 (7) T5=A (8) T6= R−r (9) B=A*T6
一个控制流图是具有唯一首结点的有向图。 所谓首结点,就是从它开始到控制流图中任何 一个结点都有一条通路的结点。 控制流图可表示成一个三元组G=(N,E,n0), 其中,N代表图中所有结点集,E代表图中所 有有向边集,n0代表首结点。 一个程序可用一个流图表示。流图的有限 结点集N是程序的基本块集,流图中结点是程 序的基本块,流图的首结点是包含程序第一个 语句的基本块。流图的有向边集E是这样构成 的:假设流图中结点i和结点j分别对应于程序 的基本块i和基本块j,则当下述条件之一成立 时从结点i有一条有向边引到结点j:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(1) P:=0 (2) I:=1
B1
(1) P:=0
ห้องสมุดไป่ตู้
③删除无用代码 ④外提循环不变 式:(4)、(7)为循环
不变式,可外提至 B1中
(2) I:=1 B1 (4) T2:=addr(A) - 4 (7) T5:=addr(B) - 4
(3)T1:=4* I B2 (4) T2:=addr(A) - 4 (5) T3:=T2[T1] (6) T4:= T1 (7) T5:=addr(B) - 4 (8) T6:=T5[T1] (9) T7:=T3*T6 (10) P:=P+T7 (11) I:=I+1 (12) if I≤20 goto (3)
• 检查公共子表达式:若四元式为公共子表达式,
则把已有的结点作为它的结点(即加右标记); • 检查无用赋值: 若NODE[A]已是某结点的右标记, 则从该右标记集合中删除后再建立新结点。
算法框图:
初始化
取下一条四元式 (0)A:=B、(1)A:=opB、(2)A:=BopC N
NODE(B)定义? Y
⑥变换循环控制条件 (1) P:=0 删除归纳变量
(12) if I≤20 goto (5) 分析I的作用: •计算 T1:=4*I •循环控制条件 I≤20 •递归赋值: I:=I+1 变换控制条件: •计数法: I≤20 •比较法: T1≤80 删除(11)
B1
(4) T2:=addr(A) - 4 (7) T5:=addr(B) - 4 (3) T1:=4
⑦合并已知量
(5) T3:=T2[T1] B2 (8) T6:=T5[T1] (9) T7:=T3*T6 (10) P:=P+T7 (3’) T1:=T1+4 (12) if T1≤80 goto (5)
图4. 运算强度削弱
B1中(2) I:=1 (3)T1:=4*I (3) 可改为: (3) T1:=4 图5. 变换循环控制条件与合并 删除(2) 已知量
结点集N为基本块集; 首结点n0为含有第一个语句的基本块;
有向边集E的构成规则:
i
j
基本块j紧跟在基本块 i 之后, 且基本块 i 的出口语句不是无条件转移语句或停语句; 基本块i 的出口语句是 goto (s) 或 if . . . goto (s) 且 (s) 是基本块j 的入口语句 ;
(4) if R=0 goto (8)
(5) X:= Y (6) Y:=R B3 (7) goto (3)
(8) write Y (9) halt
B4
程 序 流 图
4.基本块内的优化
[例]对以下求向量内积的PASCAL程序段的中间代码进行优化: P := 0; (设low=1,w=4) for I := 1 to 20 do (A[I]地址:I*w+(base-low*w) P:= P + A[I] * B[I] (1) P:=0
计算P=op B
计算P=Bop C
删除刚生成 的新结B和C
DAG中有以B、 C为后继且标记 为op的结点?
NODE(A)定义? N 将A标记在结点n上
Y
将A 从原 结删除
有,设为n 构造新结点 n标为P,令 N NODE(P)定义? Y B、C为其 生成新结n标为P 找到结点设n 左右后继
[例] 试构造以下基本块的DAG (1) T0:=3.14 (2) T1:=2*T0 (3) T2:=R+S (4) A:=T1*T2 构造DAG n6 (5) B:=A * (6) T3:=2*T0 (7) T4:=R+S n2 (8) T5:=T3*T4 2 T3 (9) T6:=R - S n1 T0 n2 T1 (10) B:=T5*T6 3.14 6.28
图3 删除无用代码和代码外提
图4 运算强度削弱
(1) P:=0
(2) I:=1 B1 (4) T2:=addr(A) - 4 (7) T5:=addr(B) - 4 (3) T1:=4*I (5) T3:=T2[T1] B2 (8) T6:=T5[T1] (9) T7:=T3*T6 (10) P:=P+T7 (11) I:=I+1 (3’) T1:=T1+4 (12) if I≤20 goto (5)
第十章
本章要点
阶段: 编译的第四阶段
代码优化
源程序 词法分析 表 语法分析 格 错
出
任务:对程序进行各种 等价变换,使得从变换后 的程序出发,能生成更有 效的目标代码。 重点: 局部优化 循环优化
中间代码生成
管 优 理 目标代码生成 目标程序 化 处 理
10.1 优化概述
1. 问题的提出 (1) 编译程序的作用 使计算机的使用方式从用机器语言编程发展到用 高级语言编程。是计算机发展史上的一次飞跃。 (2) 早期编译程序的不足 占用的空间大 目标程序质量差 运行的时间长 2. 解决的方法: 代码优化:即对程序进行各种等价变换,使得从变 换后的程序出发能生成更有效的目标代码。 优化原则:等价、有效、合算
[小结]
局部优化: ①删除公共子表达式
⑤合并已知量 ⑥复写传播 ⑦删除无用赋值 循环优化: ②外提循环不变式 ③运算强度削弱 ④变换循环控制条件 优化前后比较: 循环B2 四元式个数 乘法个数 优化前 10 3 优化后 6 1
以上优化方法均可用算法实现
基本块内还可进行以下几种变换 临时变量改名.
优化不是目的,只是手段
3. 优化方法 按优化所涉及的程序范围分: 局部优化: 在基本块上进行的优化 • 合并已知量
• 删除无用赋值(无用代码) • 删除多余运算(公共子表达式)
方法:DAG; 特点: 简单、成熟。 循环优化:在循环块上进行的优化 • 代码外提
• 运算强度削弱 • 删除归纳变量
交换语句的位置. 代数变换.
说明:
无用赋值的判定:
• 对A赋值后, A不被引用 (全局数据流分析)
• 对A赋值后, 引用前又重新赋值 ( 容易判定) • A仅在递归赋值(A:=A+C)中被引用(全局数据 流分析)
#
10.2.2. 基本块的DAG表示及其应用
1. 无环路有向图DAG (Directed Acyclic Graph) (1) 定义: 若有向图中所有通路均非环路, 则称其为DAG (2) 基本块的DAG(用于描述计算过程): a:=b*-c+b*-c的 := 是为结点附加了信息的DAG。 DAG(中间代 a + 码的图形表 叶结点: 示) •下标记: 常数或标识符 * •右标记: 标识符 @ 内结点: b •下标记: 运算符 c • 右标记: 标识符 (2) A:= op B (3) A:=B op C (3) 结点形式 n3 A n2 A (1) A:=B op op n1 A n1 n2 n1 B B C B 0型
方法:循环查找算法、数据流分析;复杂、高效。 全局优化:在整个程序上的优化 方法:全局控制流分析、全局数据流分析; 特点:代价大、高效。
10.2 局部优化
问题: 什么是基本块? 怎样划分基本块? 在基本块中可以进行哪些优化? 怎样进行局部优化? 10.2.1 基本块和流图 对一给定的程序,将其划分为若干个基本块, 在各个基本块中分别进行优化即称为局部优化。
(1) P:=0 (2) I:=1
B1
①删除公共子表达式
(3)、(6)为公共子式 可将(6)改为T4:=T1
(2) I:=1
B1
(3)T1:=4*I B2 (4) T2:=addr(A) - 4 (3) T1:=4*I ②进行复写传播 (5) T3:=T2[T1] (4) T2:=addr(A) - 4 T4:=T1 (5) T3:=T2[T1] B2 B2中(6)T6:=T5[T4] (6) T4:= T1 (8) (7) T5:=addr(B) - 4 (6) T4:=4*I T4:=T1 可改为(8)T6:=T5[T1] (8) T6:=T5[T1] (7) T5:=addr(B) - 4 (9) T7:=T3*T6 (8) T6:=T5[T4] T6:=T5[T1] (10) P:=P+T7 (9) T7:=T3*T6 (11) I:=I+1 (10) P:=P+T7 (12) if I≤20 goto (3) (11) I:=I+1 (12) if I≤20 goto (3) 图1 优化前的四元式 图2 删除公共子表达式和复写传播
(3)T1:=4*I (5) T3:=T2[T1] B2 (8) T6:=T5[T1] (9) T7:=T3*T6 (10) P:=P+T7 (11) I:=I+1 (12) if I≤20 goto (3)
图2 删除公共子表达式和 复写传播
图3删除无用代码和代码外 提
(1) P:=0
(2) I:=1 B1 (4) T2:=addr(A) - 4 ⑤运算强度削弱 (7) T5:=addr(B) - 4 由(3) T1:=4*I (11) I:=I+1 (3)T1:=4*I 可改为: 将(3)外提至B1 (5) T3:=T2[T1] B2 (11)后增加(3‘) (8) T6:=T5[T1] (3’) T1:=T1+4 (9) T7:=T3*T6 (10) P:=P+T7 (11) I:=I+1 (12) if I≤20 goto (3)
(1) P:=0
(2) I:=1 B1 (4) T2:=addr(A) - 4 (7) T5:=addr(B) - 4 (3) T1:=4*I
(5) T3:=T2[T1] B2 (8) T6:=T5[T1] (9) T7:=T3*T6 (10) P:=P+T7 (11) I:=I+1 (3‘) T1:=T1+4 (12) if I≤20 goto (5)