我想实施Linear Scan Register Allocation algorithm proposed by Poletto and Sarkar。它非常直接,并为每个实时间隔分配寄存器或堆栈位置。
当已分配寄存器的有效间隔数等于寄存器数(即没有更多空闲寄存器)时,堆栈位置仅分配给一个间隔。
算法:
假设x86指令add a, b
其中a
和b
是由此算法分配了堆栈位置(溢出)的变量。无法使用两个存储器操作数对此指令进行编码,因此至少有一个操作数必须驻留在寄存器中。我会在指令前插入一个mov REG, a
,但据我所知,算法在代码中此处有 no 空闲寄存器。这通常是如何解决的?
答案 0 :(得分:1)
根据此paper(在第7节中),线性扫描寄存器分配算法需要保留暂存寄存器。
这对具有较少寄存器的体系结构(如Intel IA-32体系结构)产生负面影响,因为它会增加寄存器压力。特别是,如果不保留暂存寄存器,就不可能实现该算法:当溢出的间隔被需要寄存器中操作数的指令使用时,必须将该间隔临时重新加载到暂存寄存器中。
假设您具有以下程序集和3个寄存器:
mov t1, 1
mov t2, 2
mov t3, 3
mov t4, 4
mov t5, 5
add t4, t5
push t1
push t2
push t3
push t4
push t5
您将分配前两个寄存器(保留第三个寄存器以防溢出):
mov r1, 1
mov r2, 2
mov r3, 3
mov [sp + 4], r3
mov r3, 4
mov [sp + 8], r3
mov r3, 5
mov [sp + 12], r3
mov r3, [sp + 8]
add r3, [sp + 12]
push r1
push r2
mov r3, [sp + 4]
push r3
mov r3, [sp + 8]
push r3
mov r3, [sp + 12]
push r3
似乎有一种不需要暂存器的替代方法,称为拆分,但我尚未对此进行研究,但上述论文对此进行了描述。
另一个想法是使用一种不同的算法,该算法根据溢出产生的新指令重新运行自身,并使用将溢出更长范围的溢出试探法,这样就不会再次溢出由溢出产生的新临时变量。