Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Compiler construction x86的寄存器分配_Compiler Construction_X86_Code Generation_Register Allocation - Fatal编程技术网

Compiler construction x86的寄存器分配

Compiler construction x86的寄存器分配,compiler-construction,x86,code-generation,register-allocation,Compiler Construction,X86,Code Generation,Register Allocation,我正在尝试使用x86进行简单的寄存器分配。我正在使用线性寄存器分配器,但我对一些简单的事情有一些问题,我没有找到相关信息 int main() { int a, b, c; a = 10; b = 20; c = 2; a = a + b; b = b * 5; c = c * b + a; return c; } 对于这个简单的代码,忽略常量传播,g++&msvc生成类似的代码,将所有临时数据推送到堆栈上,然后仅对ALU操作使用

我正在尝试使用x86进行简单的寄存器分配。我正在使用线性寄存器分配器,但我对一些简单的事情有一些问题,我没有找到相关信息

int main()
{
    int a, b, c;
    a = 10;
    b = 20;
    c = 2;
    a = a + b;
    b = b * 5;
    c = c * b + a;
    return c;
}
对于这个简单的代码,忽略常量传播,g++&msvc生成类似的代码,将所有临时数据推送到堆栈上,然后仅对ALU操作使用eax、ebx等。Clang使用O0生成以下代码

main:                                   # @main
    movl    $0, -4(%rsp)
    movl    $10, -8(%rsp)
    movl    $20, -12(%rsp)
    movl    $2, -16(%rsp)
    movl    -8(%rsp), %eax
    addl    -12(%rsp), %eax
    movl    %eax, -8(%rsp)
    imull   $5, -12(%rsp), %eax
    movl    %eax, -12(%rsp)
    movl    -16(%rsp), %eax
    imull   -12(%rsp), %eax
    addl    -8(%rsp), %eax
    movl    %eax, -16(%rsp)
    movl    -16(%rsp), %eax
    ret
很明显,所有临时表都在堆栈上。所以我的问题是基于同样的事情在任何时候,如果eax/ebx等中用于add/mul/div等操作的任何指令的生命周期超过1条指令,则。也就是说,任何有效范围间隔的值是存储在这些寄存器中,还是在寄存器分配完成并将其值推送到临时寄存器后立即将其逐出?


或者我们可以使用其中的一些寄存器,直到遇到下一条ALU指令,并在必要时执行延迟推式堆栈吗?

只要保留
esp
和被调用方保存寄存器,您几乎可以做任何您想做的事。编译器在没有优化的情况下把所有东西都推到堆栈上的原因是这样更容易。(完全没有寄存器分配)谢谢你。我明白。我的问题更倾向于当这无法优化时。例如,a、b、c的值不是常数,而是来自参数。在这种情况下,对于寄存器分配器来说,它会在寄存器中存储任何内容,还是仍然在堆栈中。例如,即使在MSVC上,我也看到当它无法优化时,它只对alu使用eax等。不用于存储任何中间值。这是一个复杂得多的过程。MSVC喜欢使用eax,因为它是“第一”寄存器。编译器中真正发生的事情(通过优化)是,它生成一个以节点为值的图,然后解决一个图着色问题。每种颜色都是不同的寄存器。在简单函数中,图形很简单,只需要1或2种颜色。MSVC显然喜欢使用eax作为第一种颜色。我想你误解了我的问题。我理解图着色在这种情况下的作用。我想问的是,既然eax在say mul/div指令中使用,这就是为什么它们没有被用于任何活动范围?似乎只有alu操作使用通用寄存器,所有临时寄存器都位于堆栈上。所以,如果临时代码可以存储在GPR中,或者由于它们必须溢出,每当ALU发生时,编译器会倾向于将它们预着色并将其放在堆栈上,而不是将它们存储在堆栈上,那么这可以进行更多的优化吗?您是在问优化的代码还是未优化的代码?答案非常不同。上面显示的示例没有经过优化。编译器不进行寄存器分配,只是将堆栈位置分配给所有变量和临时变量。它使用寄存器的唯一原因是指令本身对寄存器进行操作。在这种情况下,它只使用
eax
,因为它只需要使用一个寄存器。