1 / 59

第 11 章 代码优化

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

helene
Download Presentation

第 11 章 代码优化

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第11章 代码优化

  2. 11.1 代码优化种类 局部优化 从范围上分为: 全局优化 主要的局部优化有基本块上的优化和循环上的优化。 基本块上的优化主要有常表达式节省(合并常数)、公共表达式节省(消除多余运算)。

  3. 循环上的优化主要有不变表达式外提和削减运算强度。循环上的优化主要有不变表达式外提和削减运算强度。 除了这些较典型的优化外还有: 1.消除无用赋值。 2.删除无用的0和1: A*1 处理为A A*0 处理为0

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

  5. 11.2 基本块 基本块可定义于原代码,中间代码,也可定义于目标代码。 关于目标代码的基本块的定义是:说一个目标代码是基本块,当且仅当该段只有一个入口和一个出口。 定义于原代码,中间代码的基本块定义类似。

  6. 基本块类似程序中的函数,软件工程中的模块。基本块类似程序中的函数,软件工程中的模块。 基本块的特点是其中的代码要么全执行,要么全不执行,不能在中途转出,也不能从中间转入。

  7. 2. 当遇标号性四元式时,结束当前块,并作为新块的入口四元式。 标号性四元式 …… 基本块的划分方法: 1. 把第一个四元式作为第一个基本块的入口四元式。 第一个四元式 第一个四元式 …… ……

  8. 4. 当遇形如(=:, A , —, X)的赋值四元式(其中X为引用形参)时,结束当前块,并作为该块的出口四元式。 含引用形参 赋值四元式 …… 3. 当遇转移性四元式时,结束当前块,并作为当前块的出口四元式。他们的后继四元式作为新的入口四元式。 转移性四元式 ……

  9. 标号性的四元式有: ( label,—,—, l ) ( while,—,—, — ) ( proc, q,Noff,Moff ) ( func, f,Noff,Moff ) ( ifend,—,—, — ) 等。

  10. 转移性的四元式有: ( goto, —, —, l ) ( then, B, —, — ) ( else, —, —, — ) ( whend,—, —, — ) ( call, g, —, — ) ( call, f, —, T )等。

  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;

  12. 则相应四元式代码如下: (=:, 1 ,—, Y ) Y:=1 (label,—,—,100) (>, A, B, T1) A>B (then,T1,—,—) (=:, 0, —, X ) X:=0 (else,—,—, —) (=:, 0 , —,Y ) Y:=0

  13. ( 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

  14. 相应四元式代码的分块情况如下: 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

  15. 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

  16. B1 B2 B3 B4 B5 B6 B7 程序图如下:

  17. 11.3 常表达式节省 常表达式节省也叫合并常数。它的优化范围通常取基本块。 优化工作可在生成四元式的同时进行,也可在生成四元式后进行。前一种方法叫单遍扫描法,而后一种叫多遍扫描法。

  18. 例:程序代码 a:=10;b:=2*a;c:=a*b; 可以转化为:a:=10;b:=20;c:=200; 优化后的四元式: 1)(=:, 10,-, a) 2)(=:, 20,-, b) 3)(=:,200,-, c)

  19. NAME VALU VVL[k]: 下面介绍独立进行的多遍扫描法,用到变量值表VVL,其结构如下: 变量名部分 值部分

  20. 多遍扫描常表达式节省算法 • VVL表置空,令i指向本块的第一个四元式. • 若对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]:=($, -, -, -) (四元式节省)

  21. 转向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名字的项,如果没有那种项,则什么也不做.

  22. 6.i:=i+1;若QT[i]不是出口型四元式,则转向2,否则结束.6.i:=i+1;若QT[i]不是出口型四元式,则转向2,否则结束. 例:合并常数 i:=2+5; j:=i+3; k:=2*i+j; i:=i*j+k+m;

  23. 源代码 合并前的 合并后的 VVL表 i:=2+5; 1.(+,2,5,T1) ($,-,-,-) 1.(T1,7) 2.(=:,T1,-,i) (=:,7,-,i) 2.(i,7) j:=i+3; 3.(+,i,3,T2) ($,-,-,-) 3.(T2,10) 4.(=:,T2,-,j) (=:,10,-,j) 4.(j,10) k:=2*i+j; 5.(*,2,i,T3) ($,-,-,-) 5.(T3,14) 6.(+,T3,j,T4) ($,-,-,-) 6.(T4,24) 7.(=:,T4,-,k) (=:,24,-,k) 7.(k,24) i:=i*j+k+m; 8.(*,i,j,T5) ($,-,-,-) 8.(T5,70) 9.(+,T5,k,T6) ($,-,-,-) 9.(T6,94) 10.(+,T6,m,T6) (+,94,m,T7) 11.(=:,T7,-,l) (=,T7,-,l)

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

  25. 例:设有程序段: D:=D+C*B; A:=D+C*B; C:=D+C*B; 问:是否可以写成下面的程序? T:=D+C*B; D:= T; A:= T; C:= T;

  26. 它的四元式所构成的基本块为: 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

  27. 其中四元式1,4,7的运算符、OPR1、OPR2均相等,所以可以用T1代替T3、T5。其中四元式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

  28. 其中四元式2,5,8的运算符、OPR1、OPR2均相等 但5、8中的D与2中的不同所以不可以用T2代替T4、T6。 四元式5和8相同因此四元式8对5是多余的。

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

  30. 公共表达式节省是通过四元式的节省来实现的。目前已提出多种实现方法,其中包括:值编码法,依赖数法,逻辑尺法,DAG法等。公共表达式节省是通过四元式的节省来实现的。目前已提出多种实现方法,其中包括:值编码法,依赖数法,逻辑尺法,DAG法等。 值编码方法: 按一定规则给四元式中的每个变量进行编码,使得具有相同编码的变量具有相同值。判定两个四元式是否等价的方法是看其分量的编码是否分别相同。

  31. 判断四元式等价的关键是判断两个变量的值是否等价。使问题复杂化的主要因素是间接变量的存在。判断四元式等价的关键是判断两个变量的值是否等价。使问题复杂化的主要因素是间接变量的存在。 间接变量:引用型形参变量 存复合变量地址的临时变量 为了判断一个变量是否依赖于间接变量,引进编码 # ,首先使间接变量取编码#; 其次,假设(ω, A , B , C)且A , B 中有一个编码取#,则令C的编码取#。如果四元式有一分量的编码为#,则该四元式就不可节省。

  32. 设当前四元式为(ω, 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

  33. 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

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

  35. 四 元 式 编 码 1.(=:,1,-,X) 1 1 2.(*, X,Y,T1) 1 2 3 3.(=:, T1,-,Z) 3 3 4.(=:, 1,-,X) 1 1 5.(*, X, Y,T2) 1 2 4 6.(=:, T2,-,W) 4 4

  36. 多边扫描公共表达式节省算法: 设新老变量名表为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.

  37. 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;若本块未完转,否则结束. 例: A:=3*X+Y B:=(3*X+Y)*A 得到的四元式如下:

  38. 优 化 前 编 码 优 化 后 1.(*,3,X,T1) 1 2 3 (*,3,X,T1) 2.(+,T1,Y,T2) 3 4 5 (+,T1,Y,T2) 3.(=:,T2,-,A) 5 5 (=:,T2,-,A) 4.(*,3,X,T3) 1 2 6 ($,-,-,-) 5.(+,T3,Y,T4) 3(6) 4 7 ($,-,-,-) 6.(*,T4,A,T5) 5(7) 5 8 (*,T2,A,T5) 7.(=:,T5,-,B) 8 8 (=:,T5,-,B)

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

  40. 优化前 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 )

  41. 优化前 编码 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)

  42. 优化前 编码 优化后 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)

  43. 优 化 前 编 码 优 化 后 1.(-,i, 1,T1) 1 2 3 (-,i, 1,T1) 2.(*,T1,10,T2) 3 4 5 (*,T1,10,T2) 3.([],a,T2,T3) 6 5 # ([],a,T2,T3) 4.(-,j, 1,T4) 7 2 8 (-,j,1,T4) 基本块上的优化算法(同时进行常表达式和公共表达式节省。 例:设有 VAR a:ARRAY[1…10] OF [1…10] OF integer 和 a[i][j]:=a[i][j-1]

  44. 5.([],T3,T4,T5) # 8 # ([],T3,T4,T5) 6.(-,i,1,T6) 1 2 9 ($,-,- ,-) 7.(*,T6,10,T7) 3 4 10 ($,-,- ,-) 8.([],a,T7,T8) 6 5 # ($,-,- ,-) 9.(-,j,1,T9) 7 2 11 ($,-,- ,-) 10.(-,T9,1,T10) 8 2 12 (-,T4,1, T10) 11.([],T6,T10,T11) # 12 # ([],a,T10,T11) 12.(=:,T11,-, T5) # # (=:,T11,-,T5)

  45. 11.5 不变表达式外提 如果一个表达式E在一个循环中不改变值,则称它为该循环的不变表达式. 不变表达式外提的意思是把循环中的不变表达式提到循环外边去。 例:设有 i:=1; WHILE i<=1000 DO A[i]:=X*Y 则从编译程序角度看它就等价于

  46. 由于X*Y在循环体中始终不改变值,它是循环中的不变表达式。把它提到外边得:由于X*Y在循环体中始终不改变值,它是循环中的不变表达式。把它提到外边得: i:=1; T:=X*Y; WHILE i<=1000 DO A[i]:=T 例:设有 j:=1; WHILE j<=1000 DO A[i][j]:=0 则从编译程序角度看它就等价于

  47. 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 把循环的不变表达式提到循环外边,则得到如下的程序段:

  48. 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 外提优化通常只考虑加、减、乘等算法以及关系运算和逻辑运算等,称它们为可外提运算。一般不考虑除法运算。

  49. 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 变量也可分为可外提量与不可外提量。

  50. 为了识别哪些变量是循环不变量,对每个循环构造一个变量定义表VDL。该表记录循环中被定义的变量。外提时首先把被提的四元式提到外提区YTL中,最后再把它插到四元式区中。为了识别哪些变量是循环不变量,对每个循环构造一个变量定义表VDL。该表记录循环中被定义的变量。外提时首先把被提的四元式提到外提区YTL中,最后再把它插到四元式区中。 当进行循环上的优化时,基本块上的优化已结束。

More Related