理论教育 编译器设计之路:运行时特定化

编译器设计之路:运行时特定化

时间:2023-11-04 理论教育 版权反馈
【摘要】:DyC是一个基于运行时特定化实现的动态C编译器,它借助于一些用户标记实现运行时的特定化。图10-2 DyC的总体结构不过,值得注意的是,动态优化是不能也不可能代替静态优化的。在DyC中,静态编译组件会基于机器模板进行大量的静态全局优化,这些优化对于运行时特定化是相当有用的。DyC采用了两遍数据流分析,第1遍用于标识运行时刻的常量,而第2遍则用于分析运行时刻常量的到达定值信息。

编译器设计之路:运行时特定化

特定化(specialization)是一种依据程序及上下文环境完成的程序变换技术。根据执行时刻的不同,程序特定化又可以分为编译时特定化和运行时特定化。其中,编译时特定化是静态优化的话题,暂不作讨论。这里,只关注运行时特定化的相关技术。

运行时特定化(run-time specialization)指的就是该特定化的工作是在程序运行过程中完成的。那么,研究运行时特定化的意义是什么呢?事实上,其意义是非常深远的,这里简单提两点:

(1)程序封装技术限制了静态编译器的分析、优化范围,使得编译器无法得到关于程序整体的结构信息。例如,用户程序依赖于某个二进制共享库。那么,在静态编译中,这个共享库对于编译器是一个黑盒。对其进行任何数据流、控制流分析都是徒劳的,因此,这种情况对于优化是非常不利的。即使是过程间优化对此也是束手无策的。

(2)面向对象技术的动态绑定机制也为静态分析带来了不便。

在现代编译器设计中,类似的应用需求将日益增多。这里,笔者举一个简单的实例,如表10-2所示。

表10-2 动态优化示例

978-7-111-32164-4-Chapter10-32.jpg

如果(a)、(b)两个函数是在同一个项目中,那么,应用过程间优化就很容易实现常量传播。但如果(b)存在于一个二进制的共享库(注意,不是obj文件)中,任何静态优化都将无能为力。当然,在不苛求的情况下,即使不进行优化也是可以接受的。不过,在动态编译技术中,这类程序通常可以得到更优的效果。在运行过程中,动态分析aa()函数的返回值是完全可能的,因此,进一步的常量传播是有意义的。而运行时特定化的工作就是尽可能分析得到这种特殊值的集合,以便产生更优的目标代码。

在运行时特定化领域中,UW Dynamic Compilation(缩写为“DyC”)是一个比较经典的实例,它是由华盛顿大学动态编译器小组设计与实现的。下面,简单介绍一下DyC。

DyC是一个基于运行时特定化实现的动态C编译器,它借助于一些用户标记实现运行时的特定化。DyC包括一个静态编译组件和一个动态编译组件,结构如图10-2所示。

其中,静态编译组件根据输入源程序生成三个输出部分:机器码模板、设置代码、指导命令。机器码模板中包含了一些空洞,以回填存储运行时计算得到的常量值。而设置代码则用于计算运行时常量的值。指导命令则用于指导如何应用模板及设置代码生成可执行程序。动态编译组件则遵循指导命令来复制机器码模板,并将常量值填充到模板的空洞中。(www.daowen.com)

978-7-111-32164-4-Chapter10-33.jpg

图10-2 DyC的总体结构

不过,值得注意的是,动态优化是不能也不可能代替静态优化的。由于动态优化对时间的要求比较苛刻,因此,设计者通常会在静态编译时尽可能提高代码的质量,以减轻动态优化的工作。事实上,动态优化是在静态优化的基础上追求更完美的过程,而不是将动态优化变成编译器的主体优化。在DyC中,静态编译组件会基于机器模板进行大量的静态全局优化,这些优化对于运行时特定化是相当有用的。

在DyC中,静态编译组件只编译未被用户标识为动态区域(dynamic region)的函数,而对于动态区域,静态编译组件的处理如下:

(1)标识动态区域中的变量、表达式在运行时刻将是常量。在算法实现中,DyC是基于SSA形式进行数据流分析的。DyC采用了两遍数据流分析,第1遍用于标识运行时刻的常量,而第2遍则用于分析运行时刻常量的到达定值信息。

(2)将每个动态区域划分为设置子图和模板代码子图,并替换区域原始的子图。

(3)应用标准的优化算法进行控制流相关优化。

(4)生成机器代码及指导命令。

不过,手工插入指导性的注释来标识程序是一项麻烦的工作,Calpa系统解决了这个问题,实现了自动注释的功能。它结合了profile信息和程序分析来自动获得注释。关于DyC的更多资源,读者可以访问http://www.cs.washington.edu/research/dyncomp/。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈