寄存器分配算法

问题描述 投票:4回答:2

我正在尝试为Trees实现一个代码生成register分配算法,而不是我以前的算法,我把所有的东西都放在堆栈上。现在我想实现 Sethi-Ullman算法 但从我在维基百科和一些网页上找到的唯一内容来看,算法的一些部分对我来说仍然不清楚。

我想用一些伪代码CC++工作代码来解释我所缺少的部分。

1)我应该用哪种方法来选择自由寄存器? 即,寄存器的堆栈求用。我现在用的是我认为很差的一种方法。交替返回寄存器:如果之前使用的寄存器是R0,返回R1。如果是R1,返回R0,以此类推。对小的表达式不起作用。

2)当 label(left) >= K and label(right) >= K ?

这里是 labelsethi-ullman 职能

REG reg()
{
    static REG r = REG_NONE;

    switch(r) {
        case REG_NONE:
            r = REG_r0;
            break;
        case REG_r0:
            r = REG_r1;
            break;
        case REG_r1:
            r = REG_r0;
            break;
        default:
            assert(0);
            break;
    }
    return r;
}

void SethiUllman(AST *node)
{
    static const int K = 2;

    if(node->left != NULL && node->right != NULL) {
            int l = node->left->n;
            int r = node->right->n;

            if(l >= K && r >= K) {
                SethiUllman(node->right);
                node->n = node->n - 1;
                //emit(node->right, REG_r0);
                SethiUllman(node->left);
                //emit(node->left, REG_r1);
            }
            else if(l >= r) {
                SethiUllman(node->left);
                SethiUllman(node->right);
                node->n = node->n - 1;
            }
            else if(l < r) {
                SethiUllman(node->right);
                SethiUllman(node->left);
                node->n = node->n - 1;
            }

            node->reg = reg();

            printf("%s %s,%s\n", 
                         op_string(node->type),
                         reg_string(node->left->reg),
                         reg_string(node->right->reg));

        }
    else if(node->type == TYPE::id) {
        node->n = node->n + 1;
        node->reg = reg();
        emit(node);
    }
    else {
        node->reg = reg();
        emit(node);
    }
}

void label(AST *node)
{
    if(node == NULL)
        return;

    label(node->left);
    label(node->right);

    if(node->left != NULL && node->right != NULL) {
        int l = node->left->n;
        int r = node->right->n;
        if(l == r)
            node->n = 1 + l;
        else
            node->n = max(1, l, r);
    }
    else if(node->type == TYPE::id) {
        node->n = 1;
    } else if(node->type == TYPE::number) {
        node->n = 0;
    }
}

对于这样一个exp的树。

2+b*3

它确实会生成。

LOAD R0,[b]
LOAD R1,3
MUL R0,R1
LOAD R1,2
ADD R1,R0

而从这样的树中:

8+(2+b*3)

它也会生成:

LOAD R0,[b]
LOAD R1,3
MUL R0,R1
LOAD R1,2
ADD R1,R0
LOAD R1,8 < R1 is not preserved. I don't know how it should be done.
ADD R0,R1

上面我只提供了主要的算法,但如果需要的话,我可以在你的机器上提供完整的测试用例代码。

c++ c algorithm compiler-construction register-allocation
2个回答
2
投票

我不太明白为什么 8+(2+b*3) 表达式不只是 "工作",因为在我看来,表达式在计算中不应该需要超过两个寄存器。但是,如果你不能在两个寄存器中执行整个计算,那么你需要做 "溢出"--将寄存器存储在一个临时(堆栈)位置,当你再次需要时,再从这个临时位置恢复值。

这就是你发布的代码。

LOAD R0,[b]
LOAD R1,3
MUL R0,R1     ; R0 = b*3
LOAD R1,2     
ADD R1,R0     ; R1 = 2+(b*3)
LOAD R1,8 < R1 is not preserved. I don't know how it should be done.
ADD R0,R1

我们可以重写一下,用 "溢出 "的方式。

LOAD R0,[b]
LOAD R1,3
MUL R0,R1     ; R0 = b*3
LOAD R1,2     
ADD R1,R0     ; R1 = 2+(b*3)
STORE R1, [tmp]
LOAD R1,8 < R1 is not preserved. I don't know how it should be done.
LOAD R0, [tmp]
ADD R0,R1

但是,不使用溢出也是可以的 这说明你使用的实际算法是错误的。

LOAD R0,[b]
LOAD R1,3
MUL R0,R1     ; R0 = b*3
LOAD R1,2     
ADD R0,R1     ; R0 = 2+(b*3)
LOAD R1,8     ; Use R0 above -> R1 is now free.
ADD R0,R1

或者,同样的,我不确定

LOAD R0,[b]
LOAD R1,3
MUL R0,R1     ; R0 = b*3
LOAD R1,2     
ADD R1,R0     ; R1 = 2+(b*3)
LOAD R0,8     ; Store in R1 above -> R0 is now free.
ADD R0,R1

我不确定,但我认为很可能是你选择了第一个操作数的leftright的方法 ADD 指令。

我会按照代码添加一些打印的内容,看看它在不同情况下的作用。

© www.soinside.com 2019 - 2024. All rights reserved.