-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
114 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
# 常量传播 | ||
|
||
常量传播的目的在于发掘代码中可能存在的常量,尽量用对常量的引用替代对虚拟寄存器的引用(虚拟寄存器和变量是同一个概念,以下都使用变量),并尽量计算出可以计算的常量表达式。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,42 @@ | ||
# 死代码消除 | ||
|
||
死代码消除即无用代码消除,死代码和不可达代码是两个概念。前者指的是执行之后没有任何作用的代码(例如:多余的计算),后者指的是永远无法被执行到的代码。 | ||
死代码消除(Dead code elimination, DCE)即无用代码消除,死代码和不可达代码是两个概念。前者指的是执行之后没有任何作用的代码(例如:多余的计算),后者指的是永远无法被执行到的代码。 | ||
|
||
活跃变量分析为每个程序点计算出所有变量的集合的子集,用于表示该点处活跃的变量,所以数据流分析的值集为所有变量的集合的幂集。"活跃"的含义是在程序执行过这一点**之后**,这个变量**当前的值**会被使用到,所以数据流分析是后向的。对于单个语句$S$,传递函数要根据$S$之后活跃的变量计算$S$之前活跃的变量,计算方法为:所有$S$用到的变量在$S$之前都是活跃的,所有$S$之后活跃的变量,如果没有在$S$中被定值,证明未来的那次使用用的还是$S$之前的值,所以也是活跃的。 | ||
死代码消除通常依赖于Use-Def和Def-Use数据流分析([这里](https://people.cs.vt.edu/ryder/415/lectures/machIndepOpts.pdf)有一个参考资料),这个数据流分析可以帮我们找到每个指令用到的变量是在哪里定义的。 | ||
|
||
这里讲一下几个常见的需要注意的点: | ||
这里介绍一种 DCE 的方法(来源于《高级编译器设计与实现》(鲸书)): | ||
|
||
进行死代码删除的时候,如果一条语句**没有副作用**,而且它的赋值目标(如果有的话)不在$out_S$中,那么这条语句就可以删去 | ||
- 所谓的副作用,其实就是除了"改变赋值目标变量"之外,其他所有的作用。显然,tac中没有既没有副作用,同时也没有赋值目标的语句 | ||
- 你在实现的时候可以认为除了`a = call b`之外的所有有赋值目标的语句都是没有副作用的,对于`a = call b`,如果$a \notin out_S$,要求将它优化为`call b` | ||
- 首先,标识所有计算**必要值**的指令。比如在函数中要返回(`return`)或输出(`print`)的值,或者它可能会对从函数外访问的存储单元有影响(全局内存访问,对函数外定义的数组访问)。 | ||
- 然后,以迭代的方式逐步标记对这种对计算**必要值**有贡献的指令。假如一个指令的结果是另一个**必要值**计算指令的输入,那么这个指令也是必要的。 | ||
- 当以上迭代函数稳定不变时,所有未标记的指令都可以认为是Dead Code,可以删除。 | ||
|
||
其实还有一些语句的"副作用"不是很明确,比如除0,有符号整数溢出等(依平台而定),可能会导致程序崩溃,但是**优化的时候可以不把这当成是副作用**:按照c/c++常用的说法这叫未定义行为,这可以减轻编译器作者的负担,编译器可以假定程序永远没有未定义行为,并以此为依据来优化。 | ||
具体实现上,可以借助du/ud链来实现: | ||
|
||
我们的测试样例中不会出现未定义行为,所以可以放心地忽略掉这些副作用。 | ||
- 维护一个set,存储所有必要值的定义指令。 | ||
- 找出函数所有的**必要值**,标记这些值的定义指令。 | ||
- 对于set中的每个指令,顺着ud链找到所有使用这个指令的指令,将这些指令加入set。 | ||
- 对于上一步中新加入的指令,继续顺着ud链找到所有使用这个指令的指令,将这些指令加入set。 | ||
- 重复上一步,直到set不再变化。 | ||
- 函数中的指令,如果不在set中,就可以认为是Dead Code。 | ||
|
||
此处举个例子: | ||
```asm | ||
_main: | ||
_T0 = 1 | ||
_T1 = 2 | ||
_T2 = _T1 + 5 | ||
_T3 = _T0 + 2 | ||
_T4 = _T3 * 5 | ||
return _T4 # _T4 是必要值 | ||
``` | ||
|
||
顺着ud链,可以找到 `_T4 = _T3 * 5`,因此 `_T3` 也是必要值。继续找到 `_T3 = _T0 + 2`,因此 `_T0` 也是必要值。最终 `_T0`、`_T3`、`_T4` 都是必要值,而 `_T1`、`_T2` 的定义指令都可以认为是Dead Code。 | ||
|
||
因此可以优化为: | ||
```asm | ||
_main: | ||
_T0 = 1 | ||
_T3 = _T0 + 2 | ||
_T4 = _T3 * 5 | ||
return _T4 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters