3

我想知道为什么不建议在寄存器分配(RA)之后进行持续传播。经过几次优化(后 RA)之后,就有了窥视孔优化的空间,比如不断传播/死代码消除等。我只能想到两个原因,

  1. 这些优化很容易在 SSA 表单上进行。
  2. 窥视孔选择。post RA 将导致编译时间增加。

还有其他原因吗?

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

编辑:响应 500 - Internal Server Error 的评论。在 phi 消除(例如,在 llvm-clang 中,与寄存器分配合并)等优化通过之后,全局调度如:将指令拉到父基本块等。

编辑2:

通行证

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

4

1 回答 1

1

请参阅:恒定折叠

给出的例子,

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

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

我认为您正在考虑降低强度而不是不断传播?这更符合窥视孔优化的精神;或者我不明白你在窥视孔阶段持续传播是什么意思,这通常是后端部分。

在寄存器分配之前应用的任何常量折叠都应该是相同的,除非变量已被设为常量或代码被发现死了;即CFG已经改变。每个神秘主义者

寄存器分配后的 SSA 消除描​​述了 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 消除后,代码看起来像,

 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;
    }
 }
于 2013-03-21T16:51:23.667 回答