寄存器分配算法
Algorithm for register allocation
我正在尝试为Trees实现一种代码生成/寄存器分配算法,以支持我的旧算法,在旧算法中,我将所有内容都放在堆栈上。现在我正在尝试实现Sethi Ullman算法,但从我在维基百科和一些网页上发现的内容来看,算法的某些部分对我来说仍然不清楚
我想用一些伪代码/C/C++工作代码来解释我缺少的部分。
1( 我应该使用哪种方法来选择免费注册?即将使用的寄存器堆栈。我使用的是我认为非常糟糕的寄存器:交替返回寄存器:如果以前使用的寄存器是R0,则返回R1。如果是R1,则返回R0,依此类推。这对小表达式不起作用。
2( label(left) >= K and label(right) >= K
时我该怎么办?
以下是label
和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,%sn",
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
上面我只提供了主要的算法,但如果需要,我可以为您机器上的测试用例提供完整的代码。
我不太明白为什么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)
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
我不确定,但我认为这很可能是您选择第一条ADD
指令的左/右操作数的方法。
我会在代码后面添加一些打印输出,看看它在不同的情况下会做什么。
相关文章:
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么这个运算符<重载函数对 STL 算法不可见?
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 基于ELO的团队匹配算法
- STL算法和back_inserter可以预分配空间吗?
- 迭代算法之前的高效内存分配
- 并行算法将向量的元素分配到另一个元素的元素
- 为什么这种递归子集和算法会导致指针分配错误
- 标准算法库中的哪些算法进行分配?有没有办法指定这种分配是如何发生的
- 在C/C 中实现实时最佳拟合内存分配算法
- 我应该外包分配算法吗?(raii)
- 好友分配算法 - 起始堆地址
- 算法的复杂性,包括动态分配的数组
- 在从算法stl c++进行排序时访问未分配的内存
- 为遗传算法分配和检索逐位内存值
- 何时删除卡拉苏巴算法中分配的内存?
- 寄存器分配算法