寄存器分配后的常量传播

时间:2013-03-12 23:23:43

标签: c++ assembly compiler-construction llvm compiler-optimization

我想知道为什么在寄存器分配(RA)之后进行常量传播也是不可取的。经过几次优化过程(后RA),有窥孔优化的范围,如常数传播/死码消除等。 我只能想到两个原因,

  1. 这些优化很容易在SSA表单上进行。
  2. peephole opt。 RA后会导致编译时间增加。
  3. 还有其他原因吗?

    如果可以执行窥视孔选择。然后发布RA应该是什么数据结构/算法(任何论文,参考等都会有所帮助)。

    编辑: 响应500 - 内部服务器错误的评论。 在优化传递之后,如phi-elimination(例如,在llvm-clang中,与寄存器分配合并),全局调度如:将指令提取到父基本块等。

    EDIT2:

    Passes

    在图中所示的示例中: 寄存器分配器指出v1和v2具有相同的值,因此为它们分配相同的寄存器(r1)。寄存器分配后,共同的子表达式消除 pass可以从基本块#4中消除r2 = r1

1 个答案:

答案 0 :(得分:1)

请参阅:Constant folding

给出的例子,

 int x = 14;
 int y = 7 - x / 2;
 return y * (28 / x + 2);

常量折叠后,值x完全未使用。如果首先使用 RA ,它将为x创建寄存器。因此,在运行 RA 阶段之前,有可能进行一些修剪,即使结果相同。如果有更多变量,可以避免溢出。在分配寄存器后,这些很难撤消。

我认为你在考虑strength reduction而不是不断传播?这更符合窥视孔优化的精神;或者我不明白你在窥视孔阶段常规传播的意思,这通常是一个后端部分。

寄存器分配之前应用的任何常量折叠应该是相同的,除非变量已经变为常量或代码被发现死亡;即CFG已更改。 per Mystical

SSA Elimination after Register Allocation描述了LLVM结构。我相信SSA可以使用常量值进行注释,以便在 Phi消除时可以避免不必要的移动。这可能是RA 之后 SSA消除的工件,其他编译器将不会遇到此问题。单独的传递将减慢编译速度,因此解决现有传递中的问题会更好。我认为以下代码说明了这个问题,

 int foo(int a, int b)
 {
    int c;
    if(a > 0)
        c = 7;
    else
        c = a * b + 10;
    return a + c;
 }

phi elimination 代码如下,

 int foo(int a, int b)
 {
    int c;
    if(a > 0) {
        c = 7;
        return a + c;  /* Should reduce to "a+7" */
    } else {
        c = a * b + 10;
        return a + c;
    }
 }