半格与数据流分析的五个要素(D、V、F、I、Λ)

五个要素的含义

方向(Direction, D)

指明数据流分析是沿着控制图向前 还是 向后 传播信息

  • 前向分析:从程序入口向出口传递信息(如可用表达式、到达定义)
  • 后向分析:从程序出口向入口传递信息(如活跃变量、非常忙表达式)

值(Value, V)

每个程序点(基本块入口/出口) 上需要记录的数据事实,通常是一个集合或映射

所有可能的值构成一个, 格中的元素具有偏序关系

例如:

  • 可用表达式分析中,V 是表达式的集合。常数传播中,V是变量到常数值的映射

转换函数(Transfer Function, F)

描述一个基本块如何改变数据流值。

对于前向分析,函数 f(in) = out 。对于后向分析, f(out) = in

  • 转换函数必须是单调的,以保证迭代收敛
  • 例如,在可用表达式分析中,基本块会"生成"新表达式(如 a + b), 并杀死哪些含有被重新定义变量的表达式

相遇运算(Meet Operation, Λ)

当控制流汇聚时(如多个前驱到达同一基本块),需要将来来自不同路径的信息 合并 成一个结果。

相遇运算是格上的一个二次运算,通常取 最大下界(greatest lower bound), 即保留所有路径信息的共同部分。

  • 例如,可用表达式分析使用 交集 作为相遇运算,因为一个表达式只有在所有前驱路径上都可用,在当前点才可用

初始值(Initial Value, I)

分析开始的初始数据流值,通常设置在程序入口(前向) 或 出口(后向)。

初始值的选择需确保分析从最保守或最乐观的状态开始,并逐步逼近正确的结果

  • 例如,可用表达式分析在入口处通常设为 空集 (最精确,认为没有表达式可用),然后通过迭代逐渐加入可能可用的表达式

与格(Lattice) 的关联

数据流分析的值集合 V 和相遇运算 Λ 共同构成一个 (更准确是, 半格)

偏序关系 ⊑

定义在 V 上,用于比较两个值的精确程度。

通常认为 信息越少越不精确,例如空集 , 比全集U 更精确(因为空集表示"没有任何表达式可用",这是一个确定的、保守的事实)

因此,我们可以定义 ∅ ⊑ U,即 ∅ 是更小的元素(更精确)。

最大下界(meet)

相遇运算 Λ 就是取两个元素的最大下界,即最精确的、同时小于等于两者的那个元素。

这个符合数据流合并的直觉:合并后的结果应比任何一个路径的信息都更精确

Top 和 Bottom

格中有两个特殊元素------Top(最大元素,最不精确)和 Bottom(最小元素,最精确)。

初始值通常设为 Top(乐观)或 Bottom(保守),取决于分析策略。在可用表达式分析中,我们采用保守策略,初始值为 Bottom(空集)。

格理论保证了数据流迭代算法的终止性和正确性:由于值集合有限(或具有有限高度),且转换函数单调,从初始值开始反复应用转换函数和相遇运算,最终一定收敛到不动点

详细举例:可用表达式分析

可用表达式(Available Expressions) 的定义: 在程序 p , 表达式 x op y 是可用的,如果从程序入口到 p 的所有路径上都计算该表达式,并且之后没有重新定义 xy

方向(D)

前向分析,从程序入口向出口传播信息。

值(V)

每个程序点上的数据流值是一个表达式集合,表示在该点可用的所有表达式。所有可能的集合构成一个幂集格

集合按包含关系 排序:S1 ⊑ S2 当且仅当 S1 ⊆ S2(即 S1 更精确,因为可用表达式更少)。

Top = 所有可能表达式的全集(最不精确,认为所有表达式都可用)。

Bottom = 空集 ∅(最精确,认为没有任何表达式可用)。

这个格是交半格,因为最大下界(meet)就是集合的交集。

转换函数(F)

每个基本块 B 的转换函数 f_B(in) = out 定义为:

out = (in - kill_B) ∪ gen_B

  • kill_B: 在 B 中因变量被重新定义而杀死的表达式集合。例如,若 B 中定义了变量 a,则所有含有 a 的表达式都被杀死
  • gen_B:在 B 中生成的新表达式集合。例如,若 B 中有语句 t = a + b,则表达式 a + b 被生成(前提是之后没有重新定义ab)。

相遇运算(Λ)

当多个前驱路径汇聚到同一个基本块时,使用交集合并信息:

text 复制代码
in[B] = Λ_{p ∈ preds(B)} out[p] = ⋂_{p ∈ preds(B)} out[p]

这是因为一个表达式必须在所有前驱路径上都可用,才能在 B 的入口处可用。

初始值(I)

程序入口处,没有表达式可用,因此 in[entry] = ∅(Bottom)。

这表示我们从最精确的假设开始,然后随着路径的展开逐渐加入可能可用的表达式。

迭代求解

通过不断迭代应用转换函数和相遇运算,直到所有 in[B]out[B]不再变化,即可得到每个程序点的可用表达式集合。

复制代码
1: a = x + y
2: b = a + z
3: if (...) goto 4 else goto 5
4: c = x + y
5: d = a + z

基本块划分:

  • B1: 语句1、2
  • B2: 语句3(条件分支)
  • B3: 语句4
  • B4: 语句5

分析可用表达式:

  • gen_B1 = {x+y, a+z},kill_B1 = {}(没有重新定义x、y、z、a?注意a被定义,但a+z中的a是新定义的,实际上表达式a+z依赖于a,而a在语句1被定义,所以a+z在语句2之后才生成,但语句2本身是a+z,所以a+z在B1内部生成后,后续仍可用?需仔细处理)。
  • 相遇运算:B2的两个后继B3和B4的入口值取交集。最终可计算出每个点可用的表达式。
相关推荐
kfaino27 分钟前
码农的AI翻身(六)你好,我叫 Parameter
后端·aigc
掘金者阿豪30 分钟前
把业务数据变成共享仪表盘:Metabase可视化与远程访问实践
前端·后端
猪猪拆迁队2 小时前
虚拟工厂仿真引擎的架构设计:让一条产线可编程、可观测、可干预
后端·ai编程
字节跳动数据库2 小时前
文章分享——相似函数处理方法
人工智能·后端·程序员
云技纵横2 小时前
@Transactional 失效的 7 种场景:第 5 种最难排查
后端
用户6757049885022 小时前
你知道 Go 结构体和结构体指针调用的区别吗?一文带你彻底搞懂!
后端·go
程序员cxuan3 小时前
读懂 Claude Code 架构分析系列,第一篇,开始!
人工智能·后端·架构
用户6757049885023 小时前
面试官问“装饰器模式”,这样回答薪资多要 3000!
后端
tntxia3 小时前
Geo Scene域名修改引起的一些问题
后端
用户298698530143 小时前
Java 实现 Word 文档加密与权限解除
java·后端