info
南京大学「软件分析」课程 Data Flow Analysis 部分的学习笔记。
Data Flow Analysis - Applications
Overview of Data Flow Analysis
data flow analysis 的核心就是 how data flows on CFG?,将这句话拆开了讲就是:
- how application-specific data:对数据的 abstraction,例如 +、-、0 等
- flows through the:根据分析的类型作出 approximation
- may-analysis: outputs information that may be true. 是一种 over-approximation,也是大多数静态分析采用的类型
- must-analysis: output information that must be true. 是一种 under-approximation
- nodes and: 数据如何 transfer,用 transfer function 表示,例如
+ op - = -
等 - edges of: 数据流如何处理,例如两个控制流汇入一个结点
- CFG
Preliminaries of Data Flow Analysis
Each execution of an IR statement transforms an input state to a new output state.
Every input/output state is associated with a program point, corresponds to an edge of CFG.
对于每一个 program point,我们用一个 data-flow value 表示对于当前所有可能的 program states 的 abstraction。
-
transfer function's contraints: 分为 forward analysis 和 backward analysis 两种,用 表示经过 definition 的 transfer function
-
control flow's contraints:
- within a BB: IN[] = OUT[]
- among BBs: OUT[B] = IN[B],其中 是 的复合函数
Reaching Definitions Analysis
为了减少复杂性,这里的 RDA 不包括 method calls 和 aliases。
一个 definition 可以 reach program point 当且仅当存在一条路径 到 使得 不会在这条路径上被 kill 掉。
对于变量 的 definition 就是指对 的赋值语句,如果原来的 definition 对 ,经过的某个 BB 中有另一个 也对 进行了赋值,那么就说 被 kill 掉了。
在 reaching definition analysis 中,data flow value 被设置为长度与 definitions 的数量相等的 bit vector,每个 bit 对应一个 definition,0/1 表示到达这个 program point 时对应的 definition 是否被 kill 了。
由于每个 definition 都被定义为独一无二的,所以每经过一个 BB 就会“产生新的 definition”,因此 transfer function 被定义为 。
RDA 的 algorithm 如下图所示:
由于 和 是始终不变的,因此只要 不变那么 也一定不会变。每次经过一轮迭代,上一轮 中为 1 的 bit 仍然会是 1,从而 "never shrinks",因此 也会是 "never shrinks" 的,而 bit 的数目是有限的,所以 迟早会 reach a fixed point,从而这个算法一定可以终止。
Live Variables Analysis
如果存在一条以 program point 为起点的路径,使得 variable 在这条路径上能够被使用(),同时没有在被使用前 redefined,就称 is live at ,否则就称 is dead at .
LVA 对于 data flow values 的设置是与 RDA 类似的,只是将 definition 换成了 variable。
基于以上定义,LVA 的 algorithm 是一种 backward analysis,我们根据 来求出 ,对应的 transfer function 为 。
LVA 的 algorithm 如下图所示:
Available Expressions Analysis
表达式 x op y
() 在 program point 是 available 的当且仅当以下两个条件成立:
- 从 Entry 到 的所有路径都需要经过 the evaluation of
- 在经过最后一次 evaluation of 之后没有再对 或者 进行 redefine
AEA 的 flow data values 也是 bit vector 的形式。
显然 AEA 中的 是指 B 中新的 expression, 指的是 B 中对 的 expressions 的 variables 的 redefine 语句。
AEA 允许我们在有多条路径可以到达 时,无需重复计算 expression ,而是直接用 last evaluation of 的值进而达到优化的目的。
从 AEA 的定义中,不难看出这是一种 must-analysis,并且 需要取的是前继的交集。
AEA 的 algorithm 如下图所示:
需要注意的是, 的初始化与前面的 may-analysis 是不同的。
Reaching Definitions | Live Variables | Available Expressions | |
---|---|---|---|
Domain | Set of definitions | Set of variables | Set of expressions |
Direction | Forwards | Backwards | Forwards |
May/Must | May | May | Must |
Boundary | OUT[entry]=∅ | IN[exit]=∅ | OUT[entry]=∅ |
Initialization | OUT[B]=∅ | IN[B]=∅ | OUT[B]=U |
Transfer function | |||
Meet |
Data Flow Analysis - Foundations
Iterative Algorithm, Another View
在前面 DFA 的迭代算法中,以 forward analysis 为例,假设一共有 k 个 node,每次迭代后所有的 可以抽象为一个 k-tuple,令 domain 为 ,迭代的过程可以看作一个函数 ,而迭代的出口就是到达这个函数的不动点 。
由以上的抽象,我们可以考虑几个问题:
- 这个函数是否一定存在不动点?
- 是否会存在多个不动点?如果是,我们的算法求出的不动点是否是最优解?
- 什么时候才能到达不动点?
Data Flow Analysis Framework via Lattice
一个 data flow analysis framework 由以下几个部分组成:
- : forward / backward analysis
- : lattice, includes the domain and the meet/join operator
- : a family of transfer functions from to
从 lattice 的角度来看,data flow analysis 的算法相当于迭代地在一个 lattice 上运用 transfer function 和 meet/join 操作。
Monotonicity and Fixed Point Theorem
再回到前面提出的几个问题。
由 是 “never shrinks” 的性质,我们可以推出这个 transfer function 一定存在不动点。
关于第二个问题,仅仅从函数的角度上考虑,一个函数的不动点实则是它与直线 的交点,那么很显然,不动点是可能存在多个的。
但是这里的函数是 lattice 上的函数,自然也会具有一些特性。
- monotonicity: 如果函数 满足任给 ,有 就称它是 monotonic 的
- fixed point theorem: 对于一个 complete lattice ,如果 上的函数 是 monotonic 的,并且 是 finite 的,那么
- 最小的 fixed point 可以通过不断迭代 直到 reach a fixed point 的方式找到
- 最大的 fixed point 可以通过不断迭代 直到 reach a fixed point 的方式找到
证明 fixed point theorem 可以分为以下两个部分进行证明:
- existence of fixed point: 由于 是 monotonic 的,因此我们对 进行每次迭代的值都是递增的,而这个 lattice 又是 finite 的,那么一定会达到一个最大值不动,这个最大值就是一个不动点,对 做的迭代也是类似的。
- least fixed point: 反证法。假设 是最小的 fixed point,由 的定义,必然有 ,然后对两边一直做迭代,左边会达到一个非最小的不动点 ,右边仍然是 ,由 monotonicity 的定义可知,,这与 是最小的 fixed point 的假设矛盾,因此 least fixed point 的算法是正确的,同理,greatest fixed point 的算法也是正确的。
我们之前设计的 DFA 的算法都是从 或者 开始迭代,因此求出的不动点一定是 least/greatest fixed point,在某些定义上可以认为我们的算法求出来的是最优解。
以上关于函数性质的论证都是基于 lattice 的,要证明我们的 DFA 迭代算法也有同样的性质,还需要(尽可能)将我们的算法与 fixed point theorem 建立关联。
Relate Iterative Algorithm to Fixed Point Theorem
根据 fixed point theorem 的条件,我们首先 relate iterative algorithm 中的 fact 和 lattice。
假设有 个 node,那么经过 轮迭代后得到的 fact 的形式为 ,对于 node ,每轮迭代产生的 组成的集合与集合的 关系可以看作一个 finite 且 complete 的 lattice ,从而整个 fact 就是这些 lattice 的笛卡尔积 ,从而 fact 也是一个 finite 且 complete 的 lattice。
之后只需 relate transfer + meet/join function 与 monotonic 的函数 。
从前面证明 是 never shrinks 的过程中,我们已经可以知道 transfer function 是满足 monotonic 的条件的了。而对于 meet/join function,我们根据 monotonic 的定义可以很简单的证明。
因此,我们可以 relate the algorithm to the fixed point theorem。也就可以很自信的认为对前两个问题的回答是正确的了。
现在我们回答第三个问题。我们定义 lattice 的高度是从 到 的最长路径的长度,假设单个结点的 lattice 的高度是 ,CFG 的结点数为 ,每次迭代至少可以让一个结点往上爬一个高度,所以最坏的情况下的迭代次数是 。
May and Must Analysis, a Lattice View
MOP and Distributivity
Meet Over All Paths Solution (MOP) 是考虑所有可能到达结点 的路径,将这些路径的 OUT 取 meet/join 来得到 的 IN 或者说 MOP[],也就是根据所有路径的计算结果取 lub/glb。
但是 CFG 中某些 path 是 not executable 的,也会有 unbounded、not enumerable 的路径,所以显然 MOP 是 not fully precise、impractical 的。
对比 iterative algorithm,可以发现我们算法的形式是 的,而 MOP 的形式是 的,由 是 monotonic 的和 lattice 的性质可以推出 ,所以 iterative algorithm 的精度是不如 MOP 的。
但是,当 是 distributive 时,iterative algorithm 的精度是和 MOP 一样的。再分析 iterative algorithm 的 ,可以发现 bit-vector 或 gen/kill problems 都是 distributive 的,所以前面介绍的几种算法精度都是与 MOP 相当的。
Constant Propagation
决策在 program point 的一个 variable 是否是一个常量的问题就是 constant propagation。
- direction: forward analysis
- lattice:
- OUT: a set of pairs
- domain of : UNDEF / values(-2, -1, 0…) / NAC
- :
- NAC = NAC
- UNDEF =
- transfer function:
- s:
x = c
orx = y
orx = y op z
- s:
从下图中的简单例子可以看出 constant propagation 的 是 non-distributive 的:
Worklist Algorithm
worklist algorithm 实现了对 iterative algorithm 的优化:如果经过一个 BB,它的 IN 没有变化,那么之后这个 BB 的 OUT 一定不会变化。因此,我们只需维护一个 worklist of BBs,如果当前的 BB 的 OUT 发生了变化,我们才将它所有的后继加入 worklist。
Author: f1a3h
Permalink: https://blog.rbkou.me/Study-Notes/Program-Analysis/nju-spa-dfa/
文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。
Comments