改进干涉图节点
首先需要说明,目前的框架中尚未做这个改进,不过做起来也不太难,也许未来框架中会加上。
课堂上,以及上一章中,我们都将干涉图节点定义为虚拟寄存器。这其实并不是最优的,考虑下面这个程序:
虽然在两个循环中都使用i
作为循环变量,但是这两个i
其实是没有任何关系的。按照我们的翻译策略,自始至终都会以同一个虚拟寄存器来表示i
,这样与i
冲突的节点将包括两个循环中的虚拟寄存器。然而,如果这样改写程序:
这样与分别i1
和i2
冲突的节点都只包括一个循环中的虚拟寄存器。不难想象,修改后的程序构造出来的干涉图将更加容易着色。如果我们要在不修改程序的情况下,让第一个程序达到和第二个程序一样的效果,就必须允许在不同的程序点上,同一个虚拟寄存器使用不同的物理寄存器,也就是说干涉图节点不应该定义为虚拟寄存器。
我们引入生命周期的概念,一个生命周期由一个变量的定值点,以及所有这个定值活跃的程序点的集合组成。一个定值在一点活跃定义为:这个定值可以到达这里,并且这一点处定值的变量活跃。根据这个定义,不难设想生命周期的计算方式:先进行到达-定值分析和活跃变量分析,然后对于每个定值点,寻找所有这个定值可以到达并且定值的变量活跃的程序点。
我们希望能够对于每个生命周期分配一个物理寄存器,而不是为每个虚拟寄存器分配一个物理寄存器。为了达成这一点还需要做一点修正,考虑这个程序片段:
按照上面的定义,a
的两次定值会形成两个生命周期,它们可以使用不同的物理寄存器。但是这是不对的,因为下面的a
的使用点处只能使用一个确定的物理寄存器。为了避免这样的情况发生,需要进行生命周期的合并:如果同一个虚拟寄存器的两个生命周期发生了重叠,那么这两个生命周期需要被合并为一个,让它们只能使用同一个物理寄存器。
至此,干涉图的定义可以修改为:干涉图的节点是(合并后的)所有生命周期,如果两个生命周期有重叠,就在两个节点间连一条边。除了干涉图的定义之外,算法的其它部分不需要有任何变化。
对于修改前的例子,i
总共有4个定值点(假设循环体内只使用i
,没有给i
定值),两个for
中的i = 0
和i = i + 1
对应的生命周期会被合并成一个(因为它们在循环体内有重叠),从而总共有两个生命周期,它们在寄存器分配时作为两个独立的节点,这样就和修改后的例子效果完全一样了。
Last updated