一.常量表达式节省
在每一个基本块中创建常量表,对于当前基本块,每次读入一条语句,就执行以下步骤:
- 使用常量表中的数据对当前四元式进行替换
- 如果当前四元式为非赋值型四元式:形如 ( w , A , B , t ) (w,A,B,t) (w,A,B,t),如果A和B都在常量表里面,在执行完 1 1 1步骤之后,就将该表达式删去,并且把t填入到常量表里
- 如果当前四元式为赋值型四元式,形如 ( = , A , − , t ) (=,A,-,t) (=,A,−,t),如果A是常量,此时分为两种情况,如果 t t t就在常量表中,则把 t t t的值改成 A A A的值,如果 t t t不在常量表中,就把 t t t填入常量表。如果 A A A是变量(不在常量表里)同时 t t t是常量(在常量表里),就把 t t t从常量表中删去。注意:赋值表达式在这里不能被删去
注意:含有地址相加的不能作为常数写进常数表里
二.基于值编码方式的公共表达式节省
该方法涉及到的数据结构:
V
a
l
u
N
u
m
ValuNum
ValuNum(变量编码),可用表达式代码表
U
s
a
b
l
e
E
x
p
r
UsableExpr
UsableExpr,等价表
P
A
I
R
PAIR
PAIR
运行时,区分基本块,对于每一条读入的四元式遵循如下原则
i
f
if
if(当前运算符不是赋值运算符)
-
使用 P A I R PAIR PAIR表中的对四元式 ( w , A , B , t ) (w,A,B,t) (w,A,B,t)中的可能临时变量 A , B A,B A,B( A , B A,B A,B未必是临时变量)进行替换(因为此时有一些临时变量可能已经通过 U s a b l e E x p r UsableExpr UsableExpr删去了,如果该四元式需要被保留不能使用一个不存在的临时变量)
-
在 V a l u N u m ValuNum ValuNum表中寻找变量编码,在四元式中替换,不能被替换的变量新建编码。
-
将替换编码之后的四元式变换成映射编码四元式,形如 ( w , i , j , k ) (w,i,j,k) (w,i,j,k),其中 w w w为操作码且 w w w不为赋值运算符,其中 i , j , k i,j,k i,j,k为值编码 ( > = 1 ) (>=1) (>=1),如果发现在 U s a b l e E x p r UsableExpr UsableExpr中存在相同的映射编码四元式为 ( w , i , j , l ) (w,i,j,l) (w,i,j,l)
注意映射编码四元式相同应该定义为w,i,j分别相同而k和l可以相同可以不同
则将 k k k和 l l l所对应变量填入 P A I R PAIR PAIR表中,将 k k k编码为 l l l的编码,删去 ( w , i , j , l ) (w,i,j,l) (w,i,j,l)四元式(此时已经没有临时变量 k k k了)
e l s e else else
- ( : = , A , − , B ) (:=,A,-,B) (:=,A,−,B),将 B B B的编码赋值为 A A A,不做其他操作。
三.循环不变外提优化
首先要注意一些不能外提的:
- 除法表达式不能外提,防止除 0 0 0溢出
- 含引用型表达式 ( a [ 3 ] + 1 ) (a[3]+1) (a[3]+1)不外提,注意 a [ 3 ] a[3] a[3]可以外提
- 赋值表达式不外提
算法流程
- 扫描一遍循环内四元式,将全部的右值变量都加入 L o o p D e f LoopDef LoopDef表中
- 再扫描一遍,读入四元式 ( w , A , B , C ) (w,A,B,C) (w,A,B,C),如果发现 A A A和 B B B都不在 L o o p D e f LoopDef LoopDef表中,就把该四元式外提,同时把 C C C从 L o o p D e f LoopDef LoopDef表中删掉
这里有个问题:如果现在给删了,之后如果再出现这个变量怎么算?
喵喵喵,刚才问完老师了,不能用重复的中间变量
能秒回的老师我太爱了
注意:含有地址相加的可以往外提
练习: