IFDS 问题是 Interprocedure, Finite, Distributive, Subset 问题的所写,代表了一类比较典型的静态分析问题。Interprocedure 与Intraprocedure相对,表示分析包含函数间关系;Finite 表data flow fact集合元素有限; Distributive表Join operator(也叫meet或者confluence)是并和交,也就是说lattice是基于power set, transfer func是满足f(x 并 y) = f(x) 并 f(y)的。很明显,并和交本身作为trans func即满足。本文所描述算法把IFDS问题转化成解决图内结点是否可达的问题,从而提供了一种比较通用和高效率的算法来解决IFDS问题。我在本文中只简述核心思想,不讨论细节和具体证明,有兴趣的读者可以去看原文。IFDS问题有很多,我们拿『判断程序中出现的变量在使用之前是否初始化』作为讲解的例子。先回顾下解决这个问题的一般数学模型,如下图所示:

假设我们要分析的程序一共包含3个变量,x,y 和z。流程图中的每个结点对应的lattice如图左边所示,是x, y 和z的power set。S集合的元素包含可能没被初始化过的变量。Transfer func包含3大类,第一个为gen, 代表了新声明的变量x;接着是kill, 表x变量被初始化了;output等语句对应的是identity func,表无影响,整个分析是前向的may分析(Join operator是并集),意味着是从程序入口向下分析,每个结点把前缀结点的值(为其在对应lattice的相应元素,即一个集合)并起来,表在该结点之前所有可能未被初始化的变量融入。与之相对照的问题是『该结点前肯定被初始化的变量』,是前向must分析(JOIN 操作符是交集),S包含的元素是肯定被初始化的变量。

为了把这个问题转成图的问题,我们首先把trans func表达成一种二元关系(relation representation) ,示意如下

图中0, a, b表示三个data flow facts。针对我们的问题我们可以把它们分别理解为有关数据流事实空集(看成是gen的容器),有关元素a的数据流事实和有关元素b数据流的事实。数据流事实代表了对应变量的在所关注问题下状况,如例子中数据流事实为是否被声明过和初始化。边代表数据流事实的动向,如传承,gen,kill和传递。lambda calculus中'.'左侧的S表输入的集合,右边表对S的操作。左一图即identity func,即对S无影响,原来啥样通过identity func还是啥样;中间图表gen(a), 即设定原来是空集(因为函数体内没有S),经过此func后并入a,在图中用0 -> a的边代表新生成有关a的数据流事实并把它的值设定为S所代表的值;最右表kill(a) and gen(b) (and untounch(c)),原先的a -> a, b -> b的线被切断,表示无论有关a和b的事实之前是什么样,都不再重要,只要知道经过此func后,a不再被包括在内(与S所代表的值相对),b被包括在内(与S所代表的值相同),而c没有受到印象。除了以上的,还有

表示a的值不变,而把a的值赋给b。这里的值不是说变量在程序中真正的值是多少,而是说有关此变量的数据流事实的值是什么,如a的值可以为被初始化了和未被初始化两种,对应的集合即不包括和包括a。数据流事实的值也被叫做有关此变量的数据流constrant。简而言之,基本操作就仨,不变,并入S中和踢出S中。复制是状态复制,当右边只有一个变量时,则相当于创建个别名。

我们来看个例子。read(x)表对x做了值初始化。

declare g: integer
program main begin
declare x: integer read(x)
call P (x)
end
procedure P (value a : integer) begin
if (a > 0) then read(g)
a := a − g call P (a) print(a, g)
fi end

右图即左手程序生成的控制流图和相应trans func。注意其中的interprocedure,对每个函数调用在原函数中都会生成调用点,返回点和配套的边。其中call-to-callee把与callee直接相关信息传递进去,如用形参替换实参;exit-to-return边把形参相关信息剔除;call-to-return边作用是把与被调用函数无关的其它变量信息传承下去,因为在翻译成类似汇编的中间语言后,每个函数正文开始前会把所有用到的变量列出来,也就能够知道后面的函数究竟使用了谁。

在有了带trans func的流程图后,下一步把其中的trans func转换成relation representation,

黑点表示可达点,即可能未被初始化的变量;白点表示不可达点。也就是确定的初始化过的变量。黑点的可达在relation representation所代表的边流动,直到遇到断边。遇到read断边时黑转白,白的事实将继续往下传,而call断边不改变颜色,只表示有关该变量的事实不再此处传承,return时点的颜色取决于被调用函数的返回。黑白点和连接它们边组成的图被称作exploded supergraph, 形式化定义为

N为点,E为边,R表representation relation的集合。

所以我们求解IFDS问题相当于求解exploded supergraph内各点是否可达,也就是找出可达路径。我们知道传统的worklist算法是利用了queue的特性,每次循环只考虑与被改变值结点的相关结点。论文中用于解决图可达问题的Tabulation 算法是基于worklist的动态规划算法,比传统worklist算法考虑interprocedure问题更精确也更省时。

Tabulation算法会调用四个函数,分别为

1. returnSite: 把call结点和return结点连起来

2. procOf: 把函数结点和它的函数主体关联

3. calledProc: 把函数调用结点(call)和代表被调用函数名关联上

4. callers: 把函数名映射到call结点所形成的集合关联

Tabulation算法用PathEdge集合记录了exploded supergraph路径上的同一级别的realizable的边的子集。同一级别realizable表示函数调用和返回是相互吻合的,没有把不同的函数调用和返回混淆在一起。更细一步说,PathEdge记录的是从<main, 0>所能到达的边,也即黑点所连接的边。

对于每个函数都有一个『总结边』直接连接call和return,用于总结被调用函数运行结果,从而以后在无需进入被调用的函数的情况下得知运行函数运行后各变量是否可达。『总结函数』利用了distributive的性质,return 结点等于流入各路径信息的并集,不会导致信息流失,所以单看return结点的结果即等同于看了完整的函数体(non-distributive在『总结』时会导致信息丢失,f(a V b) > f(a) V f(b)可能会生成T-top,也就无法准确反应内部可能出现的精确信息),在我们不关心函数内部data flow状况时。

Tabulation算法会渐渐的增加这两个边的集合。

declare PathEdge, WorkList, SummaryEdge: global edge set
algorithm Tabulate(G# )
begin
Let (N#, E#) = G#_IP
PathEdge := { 〈smain , 0〉 → 〈smain , 0〉 }
WorkList := { 〈smain , 0〉 → 〈smain , 0〉 }
SummaryEdge := ∅
ForwardTabulateSLRPs()
for each n ∈N* do
Xn :={d2 ∈D | ∃d1 ∈(D∪{0})suchthat〈sprocOf (n),d1〉→〈n, d2〉∈PathEdge}
od

用求解图内节点是否可达的算法来解决IFDS问题相关推荐

  1. 图的应用—求解最短路径(BFS、Dijkstra和Floyd算法)

    BFS算法虽然可以求解最短路径问题,但是需要注意的是该算法只能求解非带权图的单源最短路径问题,或者说带权值相同且为1的图单源最短路径问题. 1.图的邻接矩阵存储结构定义 #define MaxVerN ...

  2. 图卷积 节点分类_在节点分类任务上训练图卷积网络

    图卷积 节点分类 This article goes through the implementation of Graph Convolution Networks (GCN) using Spek ...

  3. 回溯法求解图着色问题

    回溯法求解图着色问题 #include <iostream> #include <cstdlib> using namespace std; #define n 5 #defi ...

  4. 图神经网络框架DGL学习 102——图、节点、边及其特征赋值

    101(入门)以后就是开始具体逐项学习图神经网络的各个细节.下面介绍: 1.如何构建图 2.将特征赋给节点或者边,及查询方法 这算是图神经网络最基础最基础的部分了. 一.如何构建图 DGL中创建的图的 ...

  5. Dijkstra算法求解图中最短路径距离

    前言:这里是自学内容,讲解的是用python来实现Dijkstra算法,算是入门求解图中最短路径问题的典型案例. 算法简介: 迪杰斯特拉(Dijkstra)算法是一个按照路径长度递增的次序产生的最短路 ...

  6. 证明kruskal算法求解图的最小生成树具有贪心选择性质_将并查集应用在图论中的最小生成树算法——Kruskal...

    点击上方蓝字,和我一起学技术. 今天是算法和数据结构专题的第19篇文章,我们一起来看看最小生成树. 我们先不讲算法的原理,也不讲一些七七八八的概念,因为对于初学者来说,看到这些术语和概念往往会很头疼. ...

  7. 关于echarts人物关系图,节点展现为图片

    echarts示例中人物关系图中节点是原点或其他形状,但人物关系图中节点呈现为人物图像更为合适. 有些情况下,使用symbol: require('@/assets-')可以使用本地资源中的图片进行展 ...

  8. iframe标签(属性介绍(sandbox、srcdoc、scrolling)、iframe对象、onload事件、父集获取iframe内节点(同源和不同源情况)、domain修改规则和示例)

    目录 iframe标签 属性简要汇总 部分属性详细介绍 align fameborder height|width marginheight|width name sandbox scrolling ...

  9. css多图标在一张图内如何正确显示它们

    图标在一张图内做法 参考QQ微博的做法:icon:两张图标上下结构在一张图内,需要分别显示在两个地方. icon: 需做成的样子: .header .qqwb ul li{ display: inli ...

最新文章

  1. Go语言学习笔记 - PART11 - 面向对象
  2. 【工具类】页面静态化 --- Freemarker的使用
  3. 完整mes代码(含客户端和server端_Ice简介+Qt代码示例
  4. 【php内核与扩展开发系列】PHP生命周期---启动、终止与模式
  5. Python爬虫入门四urllib库的高级用法
  6. QT中关于信号与槽机制的实现原理
  7. 密码机分类--签名验签服务器
  8. 踏进字节的那一瞬间,我泪目了,这457天的外包经历值了....
  9. php网盘 开源 web版 手机版
  10. Web前端是干嘛的 为什么要学Web前端
  11. 【ELM预测】基于粒子群算法PSO优化极限学习机预测含Matlab源码
  12. TensorFlow CTPN Demo Windows 无痛搭建
  13. 《嵌入式 - Lwip开发指南》第5章 LWIP测速
  14. plumber r_使用Plumber和React缩放R
  15. 以《天天炫斗》的兴衰看动作类手游运营策略
  16. 【UnityShader】凹凸映射之高度贴图和法线贴图
  17. 等比数列二分求和(首项为0次项与1次项的方法)
  18. 金蝶 EAS BOS F7监听器
  19. Web容器启动Spring
  20. sor迭代法matlab实例,SOR迭代法求线性方程组

热门文章

  1. 阿里Mycat 和京东ShardingSphere:分布式数据库中间件哪家强?
  2. vue2 时间倒计时
  3. NKOJ P1006 护卫队
  4. 通过二维码上传手机文件到服务器
  5. 金蝶KIS专业版V14.1销售毛利润明细表增加新列和修复报表成本算法
  6. mysql 死锁 navicat
  7. 一些电脑使用问题:电脑桌面图标变白
  8. SIP协议-05 SDP协议
  9. Netty取Http Post body
  10. 快商通AI技术再获殊荣,荣膺厦门市“科学技术进步奖”