【问题标题】:How to deal with multiple spilled values as operands for a single instruction?如何处理多个溢出值作为单个指令的操作数?
【发布时间】:2014-06-20 05:51:26
【问题描述】:

我想实现Linear Scan Register Allocation algorithm proposed by Poletto and Sarkar。它非常简单,可以为每个活动间隔分配一个寄存器或堆栈位置。

仅当已分配寄存器的活动区间数等于寄存器数(即没有更多空闲寄存器)时,才会将堆栈位置分配给区间。

算法:

假设有一条 x86 指令 add a, b,其中 ab 是已被此算法分配堆栈位置(溢出)的变量。没有办法用 两个 内存操作数对这条指令进行编码,因此至少有一个操作数必须驻留在寄存器中。我会在指令前插入一个mov REG, a,但据我了解该算法,此时代码中没有 no 空闲寄存器。这通常是如何解决的?

【问题讨论】:

    标签: compiler-construction register-allocation


    【解决方案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
    

    似乎有一种不需要临时寄存器的替代方法,称为拆分,但我还没有研究过,但上述论文描述了它。

    另一个想法是使用一种不同的算法,该算法使用溢出生成的新指令重新运行自身,并使用溢出启发式算法,该算法将溢出更长的范围,这样由溢出生成的新临时指令不会再次溢出。

    【讨论】:

      猜你喜欢
      • 2020-06-15
      • 2012-04-15
      • 1970-01-01
      • 2011-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-24
      • 2011-09-12
      相关资源
      最近更新 更多