c++ - 寄存器分配后的持续传播

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

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

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

还有其他原因吗?

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

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

编辑2:

Passes

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

最佳答案

参见: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 消除的产物,其他编译器不会遇到此问题。单独的 channel 会减慢编译速度,因此在现有 channel 中解决该问题会更好。我认为以下代码说明了这个问题,

 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;
    }
 }

关于c++ - 寄存器分配后的持续传播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15374207/

相关文章:

c++ - 一个类没有检测到另一个类的对象

assembly - ARM 汇编程序指令 "ADDS Rn, #1"与 "ADDS Rd, Rn, #1"

c - 我应该禁用 C 编译器签名/未签名不匹配警告吗?

assembly - 从寄存器中减去变量?错误 A2022 : instruction operands must be the same size

c - 跳转到数据段

c++ - 如何向 Borland C++ Builder 2010 项目添加一些外部可执行文件?

来自 USB 的 C++ 和 Lua

c++ - OpenCV "referenced from: _main in main.o"构建错误

c++ - 用于切换 .h 和相应 .cpp 的 Visual Studio 2017 按钮

c++ - 两个线程之间是否有内存泄漏(缓冲,清空)