没有合适的资源?快使用搜索试试~ 我知道了~
剑桥 L111 高级数据流分析讲义 剑桥 L111 高级数据流分析讲义 剑桥 L111 高级数据流分析讲义 =======================
资源推荐
资源详情
资源评论
学习指南
课程的讲授基本上按照这些笔记进行,其中有7节课专门讲解第A部分,5节课讲解第B部分
,还有3或4节课讲解第C和第D部分。第A部分主要包括对流程图的分析/转换对,而第B部
分包括对更复杂的分析(通常是在接近源语言的表示上进行)的分析,通常会给出一个通用
框架和一个实例。 第C部分包括介绍指令调度,第D部分介绍反编译和逆向工程。
可以将第A部分看作是中间代码到中间代码的优化,将第B部分看作是(如果需要的话)
已经输入的解析树到解析树的优化,将第C部分看作是目标代码到目标代码的优化。 第D部
分涉及到反向过程。
每个讲座的大致内容如下:
讲座1:介绍、流图、调用图、基本块、分析类型
讲座2:(转换)无法访问的代码消除
讲座3:(分析)活跃变量分析
讲座4:(分析)可用表达式
讲座5:(转换)活跃变量分析的用途
讲座6:(续)通过着色进行寄存器分配
讲座7:(转换)可用表达式的用途;代码移动
讲座8:静态单赋值;强度削减
讲座9:(框架)抽象解释
讲座10:(实例)严格性分析
讲座11:(框架)基于约束的分析;
(实例)控制流分析(用于 λ-terms)
讲座12:(框架)基于推理的程序分析
讲座13:(实例)效果系统
讲座13a:指针和别名分析
讲座14:指令调度
讲座15:同上,继续
讲座16:反编译。
2
书籍
• Aho, A.V., Sethi, R. & Ullman, J.D.编译器:原理、技术和工具.
Addison-Wesley, 1986. 现在有点老了,只涵盖了课程的第一部分。
查看http://www.aw-bc.com/catalog/academic/product/0,1144,0321428900,00.html
• Appel A.现代编译器实现:C/ML/Java(第2版)。CUP 1997.
查看http://www.cs.princeton.edu/~appel/modern/
• Hankin, C.L., Nielson, F., Nielson, H.R.程序分析原理. Springer 1999.
对第一部分和第二部分都很好。
查看http://www.springer.de/cgi-bin/search_book.pl?isbn=3-540-65410-0
• Muchnick, S.高级编译器设计与实现. Morgan Kaufmann, 1997.
查看http://books.elsevier.com/uk/mk/uk/subindex.asp?isbn=1558603204
• Wilhelm, R. 编译器设计 . Addison-Wesley, 1995.
查看http://www.awprofessional.com/bookstore/product.asp?isbn=0201422905
致谢
我非常感谢Tom Stuart不仅为这些讲义做出了各种补充和改进,而且还为这些讲义配套制作
了精美的幻灯片。
3
第一部分:经典的“数据流”优化
1 引言
回顾一下简单的非优化编译器的结构(例如来自CST第一部分b)。
字符
流
词法分析
标记
流
语法分析
解析
树
转换
中间代码
生成
目标
代码
在这样的编译器中,“中间代码”通常是一个面向堆栈的抽象机器代码(例如BCPL编译器中
的OCODE或Java中的JVM)。请注意,阶段“词法分析”、“语法分析”和“转换”原则上是源
语言相关的,但不是目标架构相关的,而阶段“生成”是目标相关的,但不是语言相关的。
为了简化优化(实际上是‘改善’!),我们需要一个中间代码,使得指令之间的依赖关系
明确,以便于移动计算。 通常我们使用3地址代码(有时称为‘四元组’)。 这也接近现代RIS
C架构,因此有助于目标相关阶段的‘生成’。 这个中间代码存储在一个流图 G中,它的节点
上标有3地址指令(或者后来的‘基本块’)。我们写作
pred(n) = {n
′
| (n
′
, n) ∈ edges(G)}
succ(n) = {n
′
| (n, n
′
) ∈ edges(G)}
表示给定节点的前驱和后继节点集合;我们假设常见的图论概念,如路径和循环。
三地址指令的形式(a, b, c是操作数, f是过程名, lab是一个标签):
• ENTRY f:没有前驱;
• EXIT:没有后继;
• ALUa, b, c:一个后继(ADD, MUL,等等);
• CMPconda, b, lab:两个后继(CMPNE, CMPEQ,等等)—在直线代码中,这些指令带
有一个标签参数(如果分支不发生,则继续执行下一条指令),而在流图中,它们有
两个后继边。
多路分支(例如case语句)可以被视为一系列CMP指令。 过程调用(CALL f)和间接调用
(CALLI a)被视为类似于ALUa, b, c的原子指令。 类似地,我们区分MOVa, b指令(忽略
一个操作数的ALU的特殊情况)和间接内存引用指令(LDIa, b和STIa, b)用于表示指针解
引用,包括访问数组元素。 间接分支(用于本地 goto exp)终止一个基本块(稍后会介绍
);它们的后继必须包括所有可能的分支目标(参见Fortran ASSIGNED GOTO的描述)。
4
一种安全的方法是将除了直接 goto l形式之外的所有标签都视为后继。 假设过程的参数和结
果存储在标准位置,例如全局变量 arg1, arg2, res1, res2等。这些通常是现代过程调用标
准中的机器寄存器。
作为一个简短的例子,考虑以下高级语言实现的阶乘函数:
int fact (int n)
{
if (n == 0) {
return 1;
} else {
return n * fact(n-1);
}
}
这可能最终被转化为以下的三地址代码:
入口 fact ;开始一个名为“fact”的过程
MOV t32,arg1 ;将arg1的副本保存在t32中
CMPEQ t32,#0,lab1;如果arg1 == 0,则跳转到lab1
SUB arg1,t32,#1 ;准备调用前将arg1减一
CALL fact ;将fact(arg1)保存在res1中(t32保持不变)
MUL res1,t32,res1
EXIT ;退出该过程
lab1: MOV res1,#1
EXIT ;退出该过程
口号:优化 = 分析 + 转换
转换通常很简单(例如删除此指令),但可能需要复杂的分析来证明其有效性。 还要注意,
为了进行编译时调试(例如,查看后面使用的LVA来警告可能未初始化的变量的数据流异常
),有时会使用分析而没有相应的转换。因此,编译器的新结构为:
字符
流
词法分析
标记
流
语法分析
解析
树
转换
中间代码
优化
生成
目标
代码
本课程仅考虑优化器,原则上是源语言和目标架构无关的,但某些粗略的目标特性可以被利
用(例如,用于寄存器分配阶段的可分配用户寄存器数量)。
5
剩余41页未读,继续阅读
资源评论
绝不原创的飞龙
- 粉丝: 1w+
- 资源: 1091
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功