写在前面的话
本渣有幸成为南京大学软件学院研究生,在前往仙林校区蹭课的时候偶然发现了这门宝藏课程,听了以后感觉深有收获,但又因为课程难度较大,国庆假期归来发现遗忘较多,因此开了一坑来记录自己对每节课知识点的理解。也由于这是本人第一次开坑写博客,结构内容自有诸多不合理之处,希望有问题的地方大家可以指出。
上一篇文章中讲到了静态分析的中间表示,并引出了用于分析的控制流图,本文将依据控制流图讲述数据流分析的方法。由于数据流分析的方法难度较大,内容较多,将分为上下两篇讲述。
系列文章目录
1.静态程序分析(Static Program Analysis)介绍
2.中间表示(Intermediate Representation)
3.数据流分析(Data Flow Analysis) (上):可达性分析(Reaching Definitions)
4.数据流分析Data Flow Analysis) (下):存活变量分析(Live Variables Analysis)及可用表达式分析(Available Expressions Analysis)
5.数据流分析基础(Data Flow Analysis-Foundations)
6.过程间分析(Interprocedural Analysis)
7.指针分析(Pointer Analysis)入门
8.指针分析基础知识(Pointer Analysis Foundations)
一、Live Variables Analysis
1.1 Live Variables的定义
定义:
如果程序点p处的变量v可以在CFG图中,以p为起始点的某条路径中被使用,则称其在程序点p上live,否则为dead。
(在v使用之前如果被redefined为v’,则相当于v已经死了)
Live Variables Analysis获得的信息可以用来进行寄存器分配。例如,在某程序点处所有的寄存器都已使用,就可以选择一个存储在此程序点处的dead节点的寄存器进行使用。
1.2 理解Live Variables Analysis
1.2.1 怎么表示Reaching Definitions
类似于Reaching Definitions的形式,一样是使用bit的形式表达,因此不再赘述。
1.2.2 Live Variables Analysis的传递函数
不同于Reaching Definitions的前向传播分析,Live Variables Analysis使用反向传播进行分析效果更好。
可以假设以下,如果从后往前搜索,只要在某程序点处找到一个变量vi的使用,就证明在此之前任意可达此点的、定义了vi的程序点处,vi都是live的;而如果使用前向传播的算法,每到一个程序点都要正向搜索一遍后方的路径才能确认变量在此处是否live,虽然也能进行分析,但是效率较低。
因此得到如图所示传递函数。
第一句控制流处理函数可以看出前一个BB的输出由后方BB的输入决定。
第二句传递函数解释如图及下方。
看左上方的CFG,已知S1,S2,通过控制流处理函数可以知道在OUT[B]这点v是live的。接下来就看B块中具体表达式是什么,如果不会让v死掉,那么IN[B]就仍是live,(即B中v没有被重定义或者在重定义以前被使用过)记作IN[B]={v}。
入情况5所示,v在被使用前就被重定义了,此时IN[B]为空,代表着IN[B]处的v已经dead,不会在后续路径中被调用了。
1.2.3 Live Variables Analysis的算法表示
算法如图,由于是反向传播,因此初始化的是所有的IN为空,别的类似之前的算法,不在赘述。
二、Available Expressions Analysis
2.1 Available Expressions Analysis的定义
定义:
程序点p处的表达式x op y是available(可替换)需满足2个条件:
- 从entry到p点的所有路径必须经过x op y
- 最后一次使用x op y之后,没有重定义操作数x、y
(如果重定义了x 或 y,如x = a op2 b,则原来的表达式x op y中的x或y就会被替代)
这个定义说明,在p处如果表达式available,就可以将其替换为最后一次运算的结果,或者可以检测全局通用表达式。
2.2 理解Available Expressions Analysis
2.2.1 表示Available Expressions Analysis
同上不赘述。
2.2.2 Available Expressions Analysis的传递函数
传递函数和控制流函数如果所示,经过一个BB块的运算,将kill掉包含被重定义过变量的表达式,并加入新的表达式。
由于是must分析,所以控制流使用meet交集。
(may分析是只要有某条路径可以就行,must分析是所有路径都要满足才行。may一般用于检测是否使用并删除未使用,must用于替换)
must分析是一种safe并且under的approximation,即允许漏报的分析。看右下角例子,按照算法其实这个错了,第二个块由于x被重定义导致OUT应该变为空集的。如果由一种特殊情况,x被重定义为和原本一样的数值,那么这个表达式仍然是可以替换的,但是为了safe,算法还是把他排除了,这就是一种漏报,成为under-approximation。
2.2.3 Available Expressions Analysis的算法表示
算法和示例如图,和之前的差不多。
三、算法总结
Domain:算法作用域
Boundary:算法的边界,即
以上便是这两章三种算法之间的总结,再次强调一下如何判断算法是must还是may:
Reaching Definitions表示只要从赋值语句到点p存在1条路径,则为reaching,结果不一定正确;
Live Variables表示只要从点p到Exit存在1条路径使用了变量v,则为live,结果不一定正确;
Available Expressions表示从Entry到点p的每一条路径都经过了该表达式,则为available,结果肯定正确;
换句话说,may用于报错,报多了也没事,over-approximation;must用于替换等操作,必须正确,under-approximation。
四、总结
本文和上一篇文章总共举了数据流中的三种算法为例子,可以引导我们如果设计类似的算法,以及数据流分析对程序的优化是怎么进行的,通过比较三种算法的共性和区别相信大家应该已经能初步理解数据流分析的思想了。