第 11 章 代码优化

59
11 11 第第第第 第第第第

Upload: helene

Post on 13-Jan-2016

148 views

Category:

Documents


1 download

DESCRIPTION

第 11 章 代码优化. 11.1 代码优化种类. 局部优化. 从范围上分为 :. 全局优化. 主要的局部优化有 基本块上的优化 和 循环上的优化 。. 基本块上的优化主要有 常表达式节省 ( 合并常数 ) 、 公共表达式节省 ( 消除多余运算 ) 。. 循环上的优化主要有 不变表达式外提 和 削减运算强度 。 除了这些较典型的优化外还有 : 1. 消除无用赋值。 2. 删除无用的 0 和 1 : A*1 处理为 A A*0 处理为 0. A±0 处理为 A A/1 处理为 A - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 11 章  代码优化

第第 1111 章 代码优化章 代码优化第第 1111 章 代码优化章 代码优化

Page 2: 第 11 章  代码优化

11.1 代码优化种类

从范围上分为 :局部优化

全局优化 主要的局部优化有基本块上的优化和循环上的优化。

基本块上的优化主要有常表达式节省 (合并常数 )、公共表达式节省 (消除多余运算 )。

Page 3: 第 11 章  代码优化

循环上的优化主要有不变表达式外提和削减运算强度。

除了这些较典型的优化外还有 : 1. 消除无用赋值。 2. 删除无用的 0和 1: A*1 处理为 A A*0 处理为 0

Page 4: 第 11 章  代码优化

A±0 处理为 A A/1 处理为 A 0/A 处理为 0 等等。

3. 合并符号 :(-X)*(-Y) 处理为 X*Y 4. 用乘法代替指数运算 : A**2 处理为 A*A A**3 处理为 A*A*A 等。

Page 5: 第 11 章  代码优化

11.2 基本块

基本块可定义于原代码 ,中间代码 ,也可定义于目标代码。

关于目标代码的基本块的定义是:说一个目标代码是基本块 ,当且仅当该段只有一个入口和一个出口。

定义于原代码 ,中间代码的基本块定义类似。

Page 6: 第 11 章  代码优化

基本块的特点是其中的代码要么全执行 ,要么全不执行 ,不能在中途转出 ,也不能从中间转入。

基本块类似程序中的函数,软件工程中的模块。

Page 7: 第 11 章  代码优化

基本块的划分方法:1. 把第一个四元式作为第一个基本块的入口四元式。

……

第一个四元式

2. 当遇标号性四元式时,结束当前块,并作为新块的入口四元式。

……

标号性四元式

……

第一个四元式

Page 8: 第 11 章  代码优化

3. 当遇转移性四元式时,结束当前块,并作为当前块的出口四元式。他们的后继四元式作为新的入口四元式。

……

转移性四元式

4. 当遇形如 (=:, A , —, X) 的赋值四元式 ( 其中X 为引用形参 ) 时,结束当前块,并作为该块的出口四元式。

……

含引用形参赋值四元式

Page 9: 第 11 章  代码优化

标号性的四元式有:

( label ,—,—, l )( while ,—,—, — )( proc , q , Noff , Moff )( func , f , Noff , Moff )( ifend ,—,—, — ) 等。

Page 10: 第 11 章  代码优化

( goto , —, —, l )( then , B , —, — )( else , —, —, — )( whend ,—, —, — )( call , g , —, — )( call , f , —, T ) 等。

转移性的四元式有:

Page 11: 第 11 章  代码优化

例子:设有一程序段 Y:=1 ; 100 : if A>B then X:=0 else Y:=0; X:=X+1 ; Y:=Y-1 ; if A<B then goto 100 ; Z:=0 ;

Page 12: 第 11 章  代码优化

则相应四元式代码如下: (=: , 1 ,—, Y ) Y:=1

(label ,—,—, 100)

(> , A , B , T1) A

>B

(then , T1 ,—,— )

(= :, 0 , —, X ) X:=

0

(else ,—,—, — )

(= :, 0 , —, Y ) Y:=

0

Page 13: 第 11 章  代码优化

( ifend ,—,—,— )

( +, X , 1 , T2 ) X+

1

( =:, T2 , —, X ) X:=X

+1

( —, Y , 1 , T3 ) Y-1

( =:, T3, —, Y ) Y:=Y-1

( < , A , B , T4 ) A<B

( then, T4, —, — )

( goto, — ,—, 100 ) ( ifend, —, —, — ) ( =: 0 , —, Z ) Z:=0

Page 14: 第 11 章  代码优化

相应四元式代码的分块情况如下: B1: (=: , 1 ,—, Y ) Y:=1

B2: (label ,—,—, 100) 标号性四元式

(> , A , B , T1) A>

B

(then , T1 ,—,— ) 转移性四元式

B3: (= :, 0 , —, X ) X:=0

(else ,—,—, — ) 转移性四元式

B4: (= :, 0 , —, Y ) Y:=0

Page 15: 第 11 章  代码优化

B5: ( ifend ,—,—,— ) 标号性四元式

( +, X , 1 , T2 ) X+

1

( =:, T2 , —, X ) X:=X

+1

( —, Y , 1 , T3 ) Y-1

( =:, T3, —, Y ) Y:=Y-1

( < , A , B , T4 ) A<B

( then, T4, —, — ) 转移性四元式

B6: ( goto, — ,—, 100 ) 转移性四元式

B7: ( ifend, —, —, — ) 标号性四元式

( =: 0 , —, Z ) Z:=0

Page 16: 第 11 章  代码优化

B1

B2

B3 B4

B5

B6 B7

程序图如下 :

Page 17: 第 11 章  代码优化

11.3 常表达式节省常表达式节省也叫合并常数。它

的优化范围通常取基本块。优化工作可在生成四元式的同时

进行,也可在生成四元式后进行。前一种方法叫单遍扫描法,而后一种叫多遍扫描法。

Page 18: 第 11 章  代码优化

例:程序代码a:=10 ; b:=2*a ; c:=a*b ;

可以转化为: a:=10 ; b:=20 ; c:=200 ;优化后的四元式: 1)(=: , 10 , -, a) 2)(=: , 20 , -, b) 3)(=: , 200 , -, c)

Page 19: 第 11 章  代码优化

下面介绍独立进行的多遍扫描法,用到变量值表 VVL ,其结构如下:

VVL[k] : NAME VALU

变量名部分 值部分

Page 20: 第 11 章  代码优化

多遍扫描常表达式节省算法1. VVL 表置空,令 i指向本块的第一个四元式 .2. 若对 j=1,2, 存在 k’:QT[i].OPRj=VVL[k’].

NAME, 则做 QT[i].OPRj:=VVL[k’].VALU ( 从表中取值 )

3. 若 OT[i].ω不是运算符 ,则转向 5.( 进一步判别该四元式是否为赋值语句 )

4. 如果 QT[i].OPRj(j=1,2) 都是常数 ,则计算结果 ,填 VVL 表 ,并删除四元式 QT[i]:

ENTRY(QT[i].RESU, cons) ( 填写表中值 ) QT[i]:=( $ , - , - , - ) ( 四元式节省 )

Page 21: 第 11 章  代码优化

转向 6.其中 ENTRY 是填写 VVL 表的子程序 , cons 表示计算结果的 CONSL 表地址 . 若有同名项 , 则只改内容 .

5. 若 QT[i].ω≠“:=”则转向 6;否则 ( 赋值语句 )

(a) 若 QT[i].OPR1 是常数 ,则填 VVL 表 : ENTRY(QT[i].RESU, QT[i].OPR1) (b) 若 QT[i].OPR1 是非常数 ,则删 VVL 表 : DELET(QT[i].RESU) 其中 DELET(X) 表示从 VVL 表删去包含 X 名字的项 , 如果没有那种项 , 则什么也不做 .

Page 22: 第 11 章  代码优化

6.i:=i+1; 若 QT[i] 不是出口型四元式 ,则转向 2, 否则结束 .

例:合并常数 i:=2+5; j:=i+3; k:=2*i+j; i:=i*j+k+m;

Page 23: 第 11 章  代码优化

(=,T7,-,l) 11.(=:,T7,-,l)

(+,94,m,T7) 10.(+,T6,m,T6)

9.(T6,94) ($,-,-,-) 9.(+,T5,k,T6)

8.(T5,70)($,-,-,-) 8.(*,i,j,T5) i:=i*j+k+m;7.(k,24) (=:,24,-,k) 7.(=:,T4,-,k)

6.(T4,24) ($,-,-,-) 6.(+,T3,j,T4)

5.(T3,14) ($,-,-,-) 5.(*,2,i,T3) k:=2*i+j;4.(j,10) (=:,10,-,j) 4.(=:,T2,-,j)

3.(T2,10) ($,-,-,-) 3.(+,i,3,T2) j:=i+3;

2.(i,7) (=:,7,-,i) 2.(=:,T1,-,i)

1.(T1,7) ($,-,-,-) 1.(+,2,5,T1) i:=2+5;

VVL 表 合并后的合并前的源代码

Page 24: 第 11 章  代码优化

11.4 公共表达式节省 公共表达式节省的范围是一个基本块。如果两个四元式的ω和 OPR1及 OPR2的值分别相同 ,则称这两个四元式等价。如果在基本块中出现多个等价四元式 ,则除了第一个外其他的均可节省。

公共表达式节省工作是通过四元式的节省来实现的。实现四元式节省的关键是判别两个四元式是否等价。

Page 25: 第 11 章  代码优化

例 :设有程序段: D:=D+C*B; A:=D+C*B; C:=D+C*B;

问 : 是否可以写成下面的程序 ? T:=D+C*B; D:= T; A:= T; C:= T;

Page 26: 第 11 章  代码优化

它的四元式所构成的基本块为: 1 . (* , C, B, T1) C*B 2 . (+, D, T1, T2) D+C*B 3 . (=:,T2,—, D ) D:=D+C*B 4 . (*, C, B, T3) C*B 5 . (+, D, T3, T4) D+C*B 6 . (=:,T4,—, A ) A:=D+C*B 7 . (*, C, B, T5) C*B 8 . (+, D, T5, T6) D+C*B 9 . (=: T6,—, C ) C:=D+C*B

Page 27: 第 11 章  代码优化

其中四元式 1, 4, 7的运算符、 OPR1 、 OPR2均相等,所以可以用 T1 代替 T3 、T5 。 1 . (* , C, B, T1) C*B 2 . (+, D, T1, T2) D+C*B 3 . (=:,T2,—, D ) D:=D+C*B 4 . ( ) 被省略 5 . (+, D, T1, T4) D+C*B 6 . (=:,T4,—, A ) A:=D+C*B 7 . ( ) 被省略 8 . (+, D, T1, T6) D+C*B 9 . (=: T6,—, C ) C:=D+C*B

Page 28: 第 11 章  代码优化

其中四元式 2,5,8的运算符、 OPR1 、 OPR2均相等

但 5 、 8中的 D 与 2 中的不同所以不可以用 T2 代替 T4 、 T6 。

四元式 5和 8相同因此四元式 8对 5是多余的。

Page 29: 第 11 章  代码优化

经优化后可得到下列四元式代码: 1. (*, C, B , T1) 2. (+, D, T1 , T2) 3. (=:,T2,—, D) 4. ( ) 被省略 5. (+, D, T1 , T3) 6. (=, T3,—,A) 7. ( ) 被省略 8 . ( ) 被省略 9 . ( =:,T3,—,C)

Page 30: 第 11 章  代码优化

公共表达式节省是通过四元式的节省来实现的。目前已提出多种实现方法,其中包括:值编码法,依赖数法,逻辑尺法,DAG法等。

值编码方法: 按一定规则给四元式中的每个变量进行编码 ,使得具有相同编码的变量具有相同值。判定两个四元式是否等价的方法是看其分量的编码是否分别相同。

Page 31: 第 11 章  代码优化

判断四元式等价的关键是判断两个变量的值是否等价。使问题复杂化的主要因素是间接变量的存在。

间接变量 :引用型形参变量 存复合变量地址的临时变量

为了判断一个变量是否依赖于间接变量 ,引进编码 # ,首先使间接变量取编码 #; 其次 ,假设 (ω, A , B , C) 且 A , B 中有一个编码取 #,则令 C 的编码取 #。如果四元式有一分量的编码为 #, 则该四元式就不可节省。

Page 32: 第 11 章  代码优化

设当前四元式为 (ω, A, B, C) ,且用newn 表示新的编码值。值编码规则: 1.开始对一切 X, 令 n(X)=0, 以表示未编过码。 2. 若操作数 A是未编过码的并且是非间接变量,则给新的编码(否则给老的编码) IF indirect(A) THEN N(A):=# ELSE IF n(A)=0 THEN n(A)=newn

Page 33: 第 11 章  代码优化

3. 对操作数 B类似步骤 2 。 4. 对于 C的处理过程是: a) (=:, A, -, C) 情况 IF direct(C) THEN n(C):=n(A) ELSE n(C):=# b) ([ ],A,B,C),(·,A,B,C) 情况 n(C):=# c) 其他情况: IF n(A)=# ∨ n(B)=# THEN n(C):=# ELSE n(C):=newn

Page 34: 第 11 章  代码优化

例: (下边四元式中没有间接变量 ) X:=1 Z:=X*Y X:=1 W:=X*Y 得到的四元式如下:

Page 35: 第 11 章  代码优化

4 4 6.(=:, T2,-,W)

1 2 4 5.(*, X, Y,T2)

1 1 4.(=:, 1 , -,X) 3 3 3.(=:, T1,-,Z)

1 2 3 2.(*, X , Y,T1) 1 1 1.(= : ,1,-,X)

编 码 四 元 式

Page 36: 第 11 章  代码优化

多边扫描公共表达式节省算法: 设新老变量名表为 ML,每当一个四元式被节省时要填写 ML表。1.置 ML 表为空 ,令所有量均无编码 ,i:=i0.2. 若 QT[i] 的 OPR1或 OPR2∈ML, 则用 ML中的 老名代替 OPR1或 OPR2. (使用新老变量名表 ML)

3. 若 QT[i] 为非考虑类 ,则转 8. (处理下一四元式)

4. 对 QT[i] 中的三个变量进行编码 .5. 若 QT[i].ω=“=:”, 则转 8.

Page 37: 第 11 章  代码优化

例: A:=3*X+Y B:=(3*X+Y)*A得到的四元式如下:

6.若 QT[i] 的 OPR1或 OPR2 的编码为 #, 则转 8.7. 若存在 i’使 QT[i’]≈QT[i]( 等价 ), 则 a. QT[i]:= ($,- , - , -) b. ML[m]:=(QT[i].RESU, QT[i’].RESU) (填写新老变量名表 ML)

8.i:=i+1; 若本块未完转 ,否则结束 .

Page 38: 第 11 章  代码优化

(=:,T5,-,B) 8 8 7.(=:,T5,-,B)

(*,T2,A,T5) 5(7) 5 8 6.(*,T4,A,T5)

($,-,-,-) 3(6) 4 7 5.(+,T3,Y,T4)

($,-,-,-) 1 2 6 4.(*,3,X,T3)

(=:,T2,-,A) 5 5 3.(=:,T2,-,A)

(+,T1,Y,T2) 3 4 5 2.(+,T1,Y,T2)

(*,3,X,T1) 1 2 3 1.(*,3,X,T1)

优 化 后 编 码 优 化 前

Page 39: 第 11 章  代码优化

例:设有语句列 X:=X*Y+Z; Y:=X*Y+Z; Z:=X*Y-Z 试用值编码法写出优化和优化后的四元式中间代码。

Page 40: 第 11 章  代码优化

优化前1.(*, X,Y,T1 )2.(+,T1,Z,T2 )

3.(:=,T2,-,X )

4.(*, X, Y,T3 )

5.(+, T3,Z,T4 )

6.(:=,T4,-,Y )

7.(*, X, Y,T5 )

8.(-, T5,Z,T6 )

9.(:=,T6,-,Z )

Page 41: 第 11 章  代码优化

优化前 编码1.(*, X,Y,T1 ) (1,2,3)2.(+,T1,Z,T2 ) (3,4,5)

3.(:=,T2,-,X ) (5, 5)

4.(*, X, Y,T3 ) (5,2,6)

5.(+, T3,Z,T4 ) (6,4,7)

6.(:=,T4,-,Y ) (7, 7)

7.(*, X, Y,T5 ) (5,7,8)

8.(-, T5,Z,T6 ) (8,4,9)

9.(:=,T6,-,Z ) (9, 9)

Page 42: 第 11 章  代码优化

优化前 编码 优化后 1.(*, X,Y,T1 ) (1,2,3) (*,X, Y,T1)2.(+,T1,Z,T2 ) (3,4,5) (+,T1,Z,T2)

3.(:=,T2,-,X ) (5, 5) (:=,T2,-,X)

4.(*, X, Y,T3 ) (5,2,6) ( *,X,Y,T3)

5.(+, T3,Z,T4 ) (6,4,7) ( +,T3,Z,T4)

6.(:=,T4,-,Y ) (7, 7) (:=,T4,-,Y)

7.(*, X, Y,T5 ) (5,7,8) ( *,X,Y,T5)

8.(-, T5,Z,T6 ) (8,4,9) ( -,T5,Z,T6)

9.(:=,T6,-,Z ) (9, 9) (:=,T6,-,Z)

Page 43: 第 11 章  代码优化

基本块上的优化算法(同时进行常表达式和公共表达式节省。例:设有 VAR a:ARRAY[1…10] OF [1…10] OF integer 和 a[i][j]:=a[i][j-1]

(-,j,1 , T4) 7 2 8 4.(-,j, 1,T4)

([],a,T2,T3) 6 5 #3.([],a,T2,T3)

(*,T1,10,T2) 3 4 5 2.(*,T1,10,T2)

(-,i, 1,T1) 1 2 3 1.(-,i, 1,T1)

优 化 后 编 码 优 化 前

Page 44: 第 11 章  代码优化

(=:,T11,-,T5) # # 12.(=:,T11,-, T5)

([],a,T10,T11) # 12 # 11.([],T6,T10,T11)

(-,T4,1, T10) 8 2 12 10.(-,T9,1,T10)

($,- , - , -) 7 2 11 9.(-,j,1,T9)

($,- , - , -)6 5 #8.([],a,T7,T8)

($,- , - , -)3 4 10 7.(*,T6,10,T7)

($,- , - , -)1 2 9 6.(-,i,1,T6)

([],T3,T4,T5)# 8 #5.([],T3,T4,T5)

Page 45: 第 11 章  代码优化

11.5 不变表达式外提 如果一个表达式 E在一个循环中不改变值,则称它为该循环的不变表达式 . 不变表达式外提的意思是把循环中的不变表达式提到循环外边去。

例:设有 i:=1; WHILE i<=1000 DO A[i]:=X*Y则从编译程序角度看它就等价于

Page 46: 第 11 章  代码优化

由于 X*Y 在循环体中始终不改变值,它是循环中的不变表达式。把它提到外边得 : i:=1; T:=X*Y; WHILE i<=1000 DO A[i]:=T

例:设有 j:=1; WHILE j<=1000 DO A[i][j]:=0则从编译程序角度看它就等价于

Page 47: 第 11 章  代码优化

j:=1; WHILE j<=1000 DO BEGIN T1:=i-1; T2:=T1*10; T3:=A[]T2; T4:=j-1; T5:=T3[]T4; T5:=0 END 把循环的不变表达式提到循环外边,则得到如下的程序段:

Page 48: 第 11 章  代码优化

j:=1; T1:=i-1; T2:=T1*10 T3:=A[]T2 WHILE j<=1000 DO BEGIN T4=j-1; T5:=T3[]T4; T5:=0 END 外提优化通常只考虑加、减、乘等算法以及关系运算和逻辑运算等,称它们为可外提运算。一般不考虑除法运算。

Page 49: 第 11 章  代码优化

变量也可分为可外提量与不可外提量。

T:=a/Y;

WHILE B DO IF Y=0 THEN X:=Y ELSE X:=a/Y

WHILE B DO IF Y=0 THEN X:=Y ELSE X:=T

Page 50: 第 11 章  代码优化

为了识别哪些变量是循环不变量 ,对每个循环构造一个变量定义表 VDL 。该表记录循环中被定义的变量。外提时首先把被提的四元式提到外提区 YTL 中 ,最后再把它插到四元式区中。

当进行循环上的优化时,基本块上的优化已结束。

Page 51: 第 11 章  代码优化

外提算法 :1.求本层 QT 和 VDL区的始地址 .2. 若当前 QT[i] 是不可外提类 ,则转向 5.3. 若 QT[i] 的 OPR1或 OPR2∈VDL. 则转向5.4. ( QT[i] 可外提时) a) 把 QT[i] 提到外提表 YTL 中 . b) 把 QT[i].RESU 从本层 VDL 提到外层 VDL c) 删除四元式 QT[i].5.准备读下一四元式 ,若未读完则转向 2.6. 把外提表的内容插入到表的相应位置中 .

Page 52: 第 11 章  代码优化

VDL 表的设计形式 : t NAME VDL[d]:

其中 t取 0或 1 。 1表示该变量已经被外提。开始时 t取 0,每当相应变量被外提时把 t的位置置成 1。在查 VDL 表时只查 t=0 的元素。

Page 53: 第 11 章  代码优化

例:设有循环语句 i:=1; WHILE i≤ 100 DO BEGIN Z:=i*K*5; A:=2*K+2*K*2; i:=i+1 END 则当扫描完循环部分时生成的四元式和 VDL 表如下图所示。

Page 54: 第 11 章  代码优化

i:=1; WHILE: T1:=i≤100;TEST: T1?DO: T2:=i*K; Z:=T2*5; T3:=2*K; T4:=T3*2; T5:=T3+T4; A:=T5; i:=i+1WHEND i 0

A 0

T5 0

T4 0

T3 0Z 0

T2 0

T1 0外层 NAME t

VDL 表

Page 55: 第 11 章  代码优化

现在要回头扫描本层四元式并进行外提。

i:=1; T3:=2*K; T4:=T3*2; T5:=T3+T4; WHILE: T1:=i<=100;TEST: T1?DO: T2:=i*K; Z:=T2*5; A:=T5; i:=i+1WHEND

i 0

A 0

T5 1

T4 1

T3 1

Z 0

T2 0

T1 0

外层 NAME t

DVL 表

Page 56: 第 11 章  代码优化

11.6 消减运算强度消减运算强度是把强度大的运算换成强度

小的运算。主要的研究对象是形如 i*K 或 K*i 的运算,

其中 K是循环不变量, i是循环变量。

循环变量的特点是 ,每重复一次循环体 ,其值增加一个常数值 .设 a是 i的出始值 , b 是i的增量 ,则 i和 i*K的取值过程是 : a, a+b, a+2b,… a*K, a*K+b*K, a*K+2(b*K),… 即开始取 a*K, 以后每次增加 b*K 。

Page 57: 第 11 章  代码优化

例如有下列语句:for i:=E1 step E2 until E3 do S可不妨假设 E1,E2 和 E3 的值大于 0。它

的语义解释如下:INIT i:=E1; b:=E2;

TEST: i<=E3? DO: S ( D:=i*K ) INCR: i:=i+b; GOTO TEST

Page 58: 第 11 章  代码优化

设 S为 D:=i*K,则显然 K是上述循环的不变量, i是循环变量,则有:

INIT i:=E1

T1:=i*K T2:=E2*K TEST: i<=E3? DO: D:=T1

INCR: T1:=T1+T2

i:=i+T2

GOTO TEST 虽然增加了运算 ,但是减少了运算强度。

Page 59: 第 11 章  代码优化

消减运算强度算法:1. 如果 QT[k] 不是 T:=i*K 或 T:=K*i 的四元式。则转出口。其中 i是本层循环变量,K是本层循环不变量。2. 在 INIT 块中插入四元式: T:=A*K T’:=B*K其中 A是 eres(E1) , B是 eres(E2) , T’是新的临时变量名。3. 删除 DO 块中的当前四元式: T:=i*K4. 在 INCR 中插入四元式: T:=T+T’