这是南京大学《软件分析》课程的课程笔记,全部内容来自于课程网站
活跃变量分析(Live Variable Analysis)
定义:
对于数据流中点P上的变量v,活跃变量分析判断v是否在P后的任何一条数据流中被使用(作为右值)。活跃变量分析常用来为变量分配寄存器。
分析:
这是一个may analysis,因为允许假阳性。
domain为所有的变量,初始值为空。
简便起见,算法被设计为从下往上分析。
算法:
说明:
首先,给控制流图所有节点的IN置空。从exit节点开始,迭代更新每个节点的IN。
transfer function为:
O
U
T
[
B
]
=
∪
s
s
u
c
c
e
s
s
o
r
o
f
B
I
N
[
S
]
I
N
[
B
]
=
u
s
e
b
∪
(
O
U
T
[
B
]
−
d
e
f
B
)
OUT[B]=\cup_{s \, successor \, of \, B\,}IN[S]\\ IN[B]=use{_b} \,\cup\, (OUT[B]-def_B)
OUT[B]=∪ssuccessorofBIN[S]IN[B]=useb∪(OUT[B]−defB)
即
- 节点 B B B 的 O U T OUT OUT 为所有后继节点的 I N IN IN 的并。
- 节点 B B B 的 I N IN IN 为 O U T [ B ] OUT[B] OUT[B] 中kill掉state中被赋值的变量(赋值语句左边),再加上被使用的变量(赋值语句的右边)。
从exit节点,溯数据流图而上,直至enter节点称为一次迭代。数次迭代完成后,如在下一次迭代后,所有节点的 I N IN IN 不在变化,活跃变量分析即完成。
可达性分析(Reaching Definitions Analysis)
定义:
数据流开端P处定义了d,若从数据流P→Q中d没有被killed(被重新赋值),则说在数据流点P处的定义d到点Q是可达的。
常用于检测未被声明的变量。
分析:
这是一个may analysis,因为允许假阳性。实际使用中,在enter处将所有变量定义为undefined,假设变量v在Q处被使用,若从enter到Q,v的定义是可达的,则发现一个未声明变量的语法错误。
domain为所有的赋值语句,初始值为空。
简便起见,算法被设计为从上往下分析。
算法:
说明:
将所有节点的 O U T OUT OUT 置空。从entry节点开始,迭代更新每个节点。
transfer function为:
I
N
[
B
]
=
∪
P
p
r
e
d
e
c
e
s
s
o
r
o
f
B
O
U
T
[
P
]
O
U
T
[
B
]
=
g
e
n
B
∪
(
I
N
[
B
]
−
k
i
l
l
B
)
IN[B]=\cup_{P \,predecessor \, of \, B\,}OUT[P]\\ OUT[B]=gen{_B} \,\cup\, (IN[B]-kill_B)
IN[B]=∪PpredecessorofBOUT[P]OUT[B]=genB∪(IN[B]−killB)
即
- 每个节点的 I N IN IN 为所有前驱节点 O U T OUT OUT 的交。
- 每个节点的 O U T OUT OUT 为当前节点的 I N IN IN 除去被killed的部分(赋值语句的左边),再加上被killed之前被使用的部分(赋值语句的右边)。
从entry节点,顺数据流图而下,直至exit节点称为一次迭代。数次迭代完成后,如在下一次迭代后,所有节点的 O U T OUT OUT 不再变化,可达性分析即完成。
可用表达式分析(Live Variable Analysis)
定义:
数据流中有表达式 x op y
和点P,若从entry到P处的所有路径都必须计算表达式 x op y
,且最后一次计算 x op y
后,x
或 y
都未被重新赋值,则称表达式 x op y
在P处是可用的。
常用于编译优化中对表达式值的替换。
分析:
这是一个must analysis,因为不允许假阳性。
domain为所有的表达式的集合。
简便起见,算法被设计为从上往下分析。
算法:
说明:
将初始entry节点的 O U T OUT OUT 置空。将其余节点的 O U T OUT OUT 置满。从entry节点开始,迭代更新每个节点。
trans function为:
I
N
[
B
]
=
∩
P
p
r
e
d
e
c
e
s
s
o
r
o
f
B
O
U
T
[
P
]
O
U
T
[
B
]
=
g
e
n
B
∪
(
I
N
[
B
]
−
k
i
l
l
B
)
IN[B]=\cap_{P \,predecessor \, of \, B\,}OUT[P]\\ OUT[B]=gen{_B} \,\cup\, (IN[B]-kill_B)
IN[B]=∩PpredecessorofBOUT[P]OUT[B]=genB∪(IN[B]−killB)
即:
- 将每个节点的 I N IN IN 为所有前驱节点的 O U T OUT OUT 的交。
- 每个节点的 O U T OUT OUT 为 当前节点的 I N IN IN 除去被killed的部分(表达式中任意变量被重新赋值,左值),再加上被新计算的部分(右值)
从entry节点,顺数据流图而下,直至exit节点称为一次迭代。数次迭代完成后,如在下一次迭代后,所有节点的 O U T OUT OUT 不再变化,可用表达式分析即完成。
总结:
加上被新计算的部分(右值)
从entry节点,顺数据流图而下,直至exit节点称为一次迭代。数次迭代完成后,如在下一次迭代后,所有节点的 O U T OUT OUT 不再变化,可用表达式分析即完成。