C++ 寄存器分配算法

C++ 寄存器分配算法,c++,c,algorithm,compiler-construction,register-allocation,C++,C,Algorithm,Compiler Construction,Register Allocation,我正在尝试为树实现一个代码生成/寄存器分配算法,以支持我的旧算法,在旧算法中,我将所有内容都放在堆栈上。现在我正在尝试实现,但仅从我在维基百科和一些网页上找到的内容来看,算法的某些部分对我来说仍然不清楚 我正在寻找一些伪代码/C/C++工作代码对我缺少的部分的解释 1) 我应该使用哪种方法选择免费注册?即,开始使用的寄存器堆栈。我使用的是我认为很差的一个:交替返回寄存器:如果以前使用的登记器是R0,返回R1。如果为R1,则返回R0,以此类推。它不适用于小表达式 2) 当标签(左)>=K和标签(右

我正在尝试为树实现一个代码生成/寄存器分配算法,以支持我的旧算法,在旧算法中,我将所有内容都放在堆栈上。现在我正在尝试实现,但仅从我在维基百科和一些网页上找到的内容来看,算法的某些部分对我来说仍然不清楚

我正在寻找一些伪代码/C/C++工作代码对我缺少的部分的解释

1) 我应该使用哪种方法选择免费注册?即,开始使用的寄存器堆栈。我使用的是我认为很差的一个:交替返回寄存器:如果以前使用的登记器是R0,返回R1。如果为R1,则返回R0,以此类推。它不适用于小表达式

2) 当
标签(左)>=K和标签(右)>=K
时,我应该怎么做

下面是
标签
sethi-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;
    }
}
它确实产生:

LOAD R0,[b]
LOAD R1,3
MUL R0,R1
LOAD R1,2
ADD R1,R0
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
从这样一个例子:

2+b*3
8+(2+b*3)
它确实产生:

LOAD R0,[b]
LOAD R1,3
MUL R0,R1
LOAD R1,2
ADD R1,R0
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
加载R0[b]
荷载R1,3
MUL R0,R1
荷载R1,2
加上R1,R0
未保留荷载R1,8

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

我不太明白为什么
8+(2+b*3)
表达式不只是“工作”,因为对我来说,表达式在计算中不应该需要超过2个寄存器。但是,如果不能在两个寄存器中执行整个计算,则需要执行“溢出”——将寄存器存储在临时(堆栈)位置,然后在再次需要时从该临时位置恢复值

这是您发布的代码:

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)
LOAD R0,8     ; Store in R1 above -> R0 is now free.
ADD R0,R1
我不确定,但我认为这可能是您选择第一条
ADD
指令的左/右操作数的方式


我将添加一些打印输出以遵循代码,并查看它在不同情况下的功能

我知道我的问题可能是我的实现算法有什么问题。不幸的是,没有实际调试您的代码本身(这需要完整的代码,我不确定我在任何情况下都想这样做)。我建议你自己遵循逻辑,找出哪里出了问题。我看不出你错在哪里。