前面已经说过,基本块是一段连续的顺序执行的语句序列,拥有一个入口和一个出口。入口是该语句序列的首语句,出口是该语句序列的尾语句。执行该语句序列时,将从首语句开始,到尾语句终止。下面这段三地址语句序列就是一个基本块。
T1:=a*b
T2:=a*c
T3:=c+1
T4:=5+T2
T5:=T1*T2
T6:=b+T3
T7:=T5*T6
一条三地址语句x:=y+z称为对x定值并引用y和z。一个基本块中的一个名字在程序中的某个给定点是活跃的,指的是如果在程序中(包括在本基本块或在其他基本块中)它的值在该点以后被引用。上面这段代码将按照顺序依次执行,首先执行T1:=a*b,最后执行T7:=T5*T6,这其中并没有出现中断或者分支。对于一个含有中断或者分支结构的程序来说,可以按照一定的算法先将其划分为一系列的基本块,然后再对各个基本块进行优化。
将三地址代码序列划分为若干基本块的算法可以描述如下:
(1)确定基本块的入口语句,即首语句,规则如下:
①代码序列的第1条语句是入口语句;
②能由条件转移语句或者无条件转移语句转移到的语句是入口语句;
③紧随条件转移语句后面的语句是入口语句。
(2)依据(1)中得到的每一条入口语句,构建其基本块。它由该入口语句与下一入口语句(不包括该入口语句)之间的语句序列构成;或者由该入口语句与下一条转移语句(包括该转移语句)之间的语句序列构成;或者由该入口语句与一条停语句(包括该停语句)之间的语句序列构成。
(3)删除那些未出现在任何基本块中的语句。它们是控制流程无法到达的语句,不会被执行到。
例8.1 下面给出了一个使用辗转相除法求解两个自然数的最大公约数的源程序:
(www.xing528.com)
其三地址代码序列简写如下:
(0)read m (5)m:=t
(1)read n (6)goto(2)
(2)t:=n mod m (7)print m
(3)if t=0 goto(7) (8)halt
(4)n:=m
现在应用我们上面介绍过的算法划分基本块。
首先,依据(1)中的规则①,(0)read m是一个基本块的入口语句;依据②,(2)t:=n mod m和(7)print m也是基本块的入口语句;依据③,(4)n:=m也是基本块的入口语句。于是,按照入口语句的数量可以把上述语句序列划分为4个基本块。
然后,对于每个基本块的入口语句,使用规则(2)构建其基本块。对于入口语句(0)read m来说,其基本块为语句(0)read m和(1)read n;对于入口语句(2)t:=n mod m来说,其基本块为语句(2)t:=n mod m和(3)if t=0 goto(7);对于入口语句(4)n:=m来说,其基本块为语句(4)n:=m、(5)m:=t和(6)goto(2);而对于入口语句(7)print m而言,其基本块则为语句(7)print m和(8)halt。
对于已经划分基本块的三地址代码序列,我们可以将基本块作为结点,通过构造有向图的方式来描述程序的控制流信息,这种图称作流图。在流图中,以程序序列第一条语句作为入口语句的基本块称作流图的首结点。如果在某个执行顺序中,基本块B紧接在基本块A之后执行,则有一条从A指向B的有向边。如果:
(1)有一个条件转移语句或者无条件转移语句从A的最后一条语句转移到B的第一条语句;或者
(2)在程序的代码序列中,B紧接在A的后面,并且A的最后一条语句不是一个无条件转移语句。
就说A是B的前驱,B是A的后继。
由例8.1中的三地址代码的各基本块所构成的流图如图8-1所示。
图8-1 例8.1中三地址代码的流图
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。