我想知道为什么不建议在寄存器分配 (RA) 之后进行持续传播。在几次优化通过后(RA 后),存在窥孔优化的空间,例如恒定传播/死代码消除等。 我只能想到两个原因,
- 这些优化很容易在 SSA 表单上进行。
- 窥视孔选项。后 RA 将导致编译时间增加。
还有其他原因吗?
如果可以执行窥孔opt。发布 RA 那么数据结构/算法应该是什么(任何论文、引用资料等都会有所帮助)。
编辑: 回应 500 - Internal Server Error 的评论。 在像 phi-elimination 这样的优化通过之后(例如,在 llvm-clang 中,与寄存器分配合并),全局调度像:将指令拉到父基本 block 等。
编辑2:
如图所示的例子:
寄存器分配器计算出 v1 和 v2 具有相同的值,因此将相同的寄存器 (r1) 分配给它们。寄存器分配后公共(public)子表达式消除
pass 可以从基本 block #4 中消除 r2 = r1
。
最佳答案
给出的例子,
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/