当前位置:文档之家› 优化和目标代码生成(PPT课件)

优化和目标代码生成(PPT课件)


• 代码优化在整个编译过程的位置
源程序 编译前端 中间代码 中间代码生成 中间代码 目标代码生成 目标程序 中间代码 中间代码优化 目标代码优化
程序员和编译器可能改上程序的位置
源程序 编译前端 中间代码 目标代码生成 目标程序
程序员可以改进 算法,改变循环
编译器可以改进过程调 用、循环和地址计算
编译器可以利用寄存器, 选择指令和窥孔优转换
3
7.1.1 数据类型
类型的合法性检查是判断数据类型是否与上下文的要求一致 数据类型是对该类型数据(变量或常量)的取值是否合法以 及对该类型数据的运算是否合法的一种说明。
4
7.1.2 数据结构
一个程序设计语言如允许使用的数组、记录、字符串、 表、栈等形式的数据结构,在编译程序中应为它们提供相 应的翻译。 为了能对数据结构中的元素进行引用,必须完成从逻辑结 构到能够访问这些数据元素的物理结构的映射。应考虑: 1映射算法相对简单,根据逻辑结构容易计算出物理地址 2从逻辑结构投影到物理结构时,不至于超界或存储溢出 3使用的数据结构承担这种程序设计语言的主要功能 4在这些数据结构定义相关的运算
25
• 指令选择
– 一个编译程序可以看成是一个转换系统,它把源程序转换成 等价的目标代码,也就是说,对源语言种各种语言结构,依 据语义确定相应的目标代码结构,即确定源语言于目标语言 之间的对应关系,确保正确实现语义。显然,能否建立这样 的关系直接影响到编译程序的质量。 – 目标机器指令系统的性质决定了指令选择的难以程度,指令 系统的一致性和完备性直接影响到这种对应关系的建立。如 果目标机器能一致地支持各种数据类型和寻址方式,不需特 别处理例外,这种对应关系的建立就容易得多。 – 指令执行速度和机器特点对产生目标代码的质量也十分重要。 显然,如果指令集合丰富的目标机器对于某种操作可提供集 中处理的时候,应该选择效率高、执行速度快的一种。
26
• 寄存器选择
– 计算机存储单元之间通常都是通过寄存器联系。寄存器可以 保存计算的中间结果,而且运算对象在寄存器的指令一般都 比运算对象在内存的指令要短且运算的快。因此,充分合理 地利用寄存器对生成高质量的代码十分重要。对于寄存器的 使用,应该考虑程序中的哪些变量驻留在寄存器中、驻留多 长时间。进一步,哪个变量驻留在哪个寄存器。这些问题可 以划分成两个子问题: • 在寄存器分配期间,为程序的某一点选择驻留在寄存器中 的一组变量; • 在随后的寄存器指派阶段,选择变量要驻留的具体寄存器。 – 选择最优的寄存器指派方案极其困难,从数学以上讲,这是 一个NP完全问题。如果考虑到目标机器的硬件、操作系统对 寄存器使用的一些要求时,这个问题就变得更加复杂。
• 指令选择 –RISC –CISC • 寄存器分配 –通用寄存器方案 –专用寄存器方案 –大寄存器方案
31
20
7.4 目标代码生成
——具体细节依赖于目标机器和操作系统
• 代码生成在整个编译过程的位置
符号表 语法树
语义分析
中间代码
中间代码生 成与优化 中间代码
中间代码
目标程序
代码生成
21
目标代码的生成
• 输入 –中间代码 • 三元式 • 四元式 • 输出 –可执行代码 –待装配的代码 –汇编代码
22
共同的问题:
编译原理
优化和目标代码生成(2h)
主讲:王海文 2005-2007
第七章
7.1
7.2 7.3 7.4
优化和目标代码生成
编译程序考虑的因素
运行时的内存分配 代码优化
目标代码生成
2
7.1
编译程序考虑的因素
编译程序设计时,除了需要用到前面介绍的 分析技术和制导翻译外,还要考虑如何从源程序 数据空间映射到具体物理存储空间,也就是运行 时的数据表示。 在运行的时候如何组织或存放数据、在源程 序中同名标识符是怎么样描述不同的对象、运行 时的程序控制权是如何转移的,参数是如何传递 以及如何生成质量较高的目标代码都是编译程序 设计者应该考虑的问题。
14
程序的执行效率是可以通过在编译期间进行优化 变换,不改变语义重写程序段以提高程序的工 作效率。虽然变换的方法很多,但是常用的大 致有以下几种: 1 编译求值 2 合并预算 3 删除死码 4 减少频率 5 强度削弱和变换循环条件 6 减少重写传播 15
局部优化: 所需要的开销相对较低,因此从优 化所得到的收益也相对较低。 局部优化只是 在较小的 程序段中进行优化,从而到达优化 的目的。 这种程序段称为基本段。 全局优化: 要产生高效的代码,编译程序仅在 基本块内优化是不够的,编译程序应把程序作 为一个整体来考虑,对各个基本块的信息进行 数据流的分析从而达到优化的目的。全局优化 同局部优化相比,全局优化需要更多的分析, 以便确定优化的可行性。
11
• 设计和实现编译程序代码优化的原则:
(1)等价原则:经过优化后的代码应该保持 程序的输入输出,不应改变程序运行的结果。 (2)有效原则:优化后的代码应该在占用空 间、运行速度这两个方面,或者其中的一个 方面得到改善。 (3)经济原则:代码优化需要占用计算机和 编译程序的资源,代码优化取得的效果应该 超出优化工作所付出的代价。否则,代码优 化就失去了意义。
M R *R c(R) *c(R)
地址
M R contents(R) c+contents(R)
增加的开销
1 0 0 1 1
间接索引方式
contents( c+contents(R))
29
例1:a:=b+c
1. MOV ADD MOV 2. MOV ADD b, R0 c, R0 R0, a b, a c, a cost=6
充分利用寄存器基本块中全局寄存器分配: 不把寄存器平均分配给各个变量使用,而是 从可用的寄存器中分出几个,固定分配给几个变 量单独使用。 标准:以各变量在循环内需要访问主存单元的次 数为标准。 选择计算机指令系统
选择计算次序
23
目标代码的三种形式
地址代真的机器代码 待装配的机器代码模块 汇编语言(宏汇编)
13
优化分类
按阶段分: 与机器无关的优化---对中间代码进行 依赖于机器的优化---对目标代码进行 根据优化所涉及的程序范围分成: (1)局部优化:(基本块)应用于仅包含少量语 句的小程序的优化变换。 (2)循环优化:对循环中的代码进行优化 (3)全局优化:大范围的优化应用于一个程序 单元,如一个函数或一个过程的优化变换。
代码优化
目标: 作为一个高级语言的使用者很希望编译程序所产生 的代码能够和直接用机器语言编写的程序效果一样好。
什么是代码优化
宗旨: 获得较好性能的代码 阶段: source code 用户 front end I.R code generator target code
中间代码 优化
目标代码 优化
10
6
7.1.4 控制结构
一个程序设计语言的控制结构是该语言在程序运行期 间用于改变控制流的语言特征集合。
7
7.2
运行时的内存分配
编译程序需要为源程序中的数据分配执行时的存 储空间,编译程序从操作系统中申请编译程序 计算出的所需的内存,或编译程序生成在运行 时需申请内存的指令。 (1) 确定用来表示某一数据项的内存大小。 (2) 使用适当的内存分配策略,实现具体数 据的作用域和生存期。 (3) 确定以适当的算法访问生存期内的数据, 包括基本型数据结构构造类型。
12
例:
int arr[10000]; void Binky() { int i; for (i=0; i < 10000; i++) arr[i] = 1; } int arr[10000]; void Winky() { register int *p; for (p = arr; p < arr + 10000; p++) *p = 1; }
16
优化的基本方法
• 去处冗余
• 削减强度Hale Waihona Puke • 使用更快的指令17
局部优化
• 方法 –合并已知量 –临时变量改名 –交换语句位置 –代数变换
18
循环优化
• 代码外提 • 强度削弱 –A=A+1 –A++ • 删除归纳变量 –例如循环中加法变为,循环外乘法
19
窥孔优化
• 窥孔 –目标程序中的一个可以移动的窗口 • 优化方法 –冗余存取 –不可到达代码 –控制流优化 –强度削弱 –删除无用操作
cost=6
假定R0, R1和R2中分别存放了a, b和c的地址, 采用: 3. MOV *R1, *R0 ADD *R2, *R0 cost=2 假定R1和R2中分别包含b和c的值, 并且b的值在这 个赋值以后不再需要, 则还可有 4. ADD R2, R1 MOV R1, a cost=3
30
其他考虑
机器指令形式
(op source ,destination) ADD s,d // d+s SUB s,d //d-s MOV s,d //s d
机器指令开销 (cost)
MOV R,M ADD #1 ,R MOV R0,R1 开销 2 开销 2 开销 1
24
• 目标程序
– 绝对机器代码,程序所有的内存地址,特别是程序的起始地址,在编 译时都已经固定。这种代码的优点是装入机器后就可以立即执行,对 于小程序可以快速编译和运行。 – 可重定位机器代码(可重定位目标模块),代码装入内存的起始地址 可以任意改变。一组可重定位的若干目标模块,经过连接和装配后才 可以运行。尽管这些工作增加了程序运行的代价,但是,可重定位机 器代码的优点是灵活性。这种技术允许程序分模块编写,独立地编译 成目标模块,并且从目标模块库中调用其它已经编译好的模块,便于 程序开发。通常,可重定位机器代码中包含可重定位信息和连接信息。 – 如果目标代码是汇编语言程序,还需要汇编后才能运行。只要地址可 以由偏移址及符号表中的其它信息计算得到,代码生成器就可以产生 程序中名字的绝对地址或可重定位地址。这样生成代码的好处是不用 生成二进制的机器代码,而是产生符号指令并用宏机制来帮助产生机 器代码,使得代码生成过程变得容易。 – 为了可读性,采用汇编语言作为目标语言。
相关主题