基本块的优化
在编译器的中间代码生成阶段之后,对基本块进行优化。优化是转换程序的过程,通过消耗更少的资源和提供高速来改进代码。在优化中,高级代码被它们等效的高效低级代码所取代。基本块的优化可以与机器相关或与机器无关。
有两种类型的基本块优化:
- 结构保持转换
- 代数变换
结构保持转换:
基本块的结构保持变换包括:
- 死代码消除
- 公共子表达式消除
- 重命名临时变量
- 两个独立相邻语句的交换
死代码消除:
死代码被定义为在程序执行期间从不执行的那部分代码。因此,为了优化,消除了这样的代码或死代码。在程序期间从不执行的代码(死代码)需要时间,因此为了优化和速度,将其从代码中消除。消除死代码会提高程序的速度,因为编译器不必翻译死代码。
例子:
// Program with Dead code
int main()
{
x = 2
if (x > 2)
cout << "code"; // Dead code
else
cout << "Optimization";
return 0;
}
// Optimized Program without dead code
int main()
{
x = 2;
cout << "Optimization"; // Dead Code Eliminated
return 0;
}
通用子表达式消除:
在这种技术中,经常使用的常用子表达式只计算一次,并在需要时重复使用。 DAG(有向无环图)用于消除常见的子表达式。
例子:
临时变量的重命名:
包含临时变量实例的语句可以更改为新临时变量的实例,而无需更改基本块值。
示例:语句 t = a + b 可以更改为 x = a + b,其中 t 是临时变量,x 是新的临时变量,而不更改基本块的值。
两个独立相邻语句的交换:
如果一个块有两个相邻的独立语句可以互换而不影响基本块值。
例子:
t1 = a + b
t2 = c + d
块的这两个独立的语句可以互换而不影响块的值。
代数变换:
基本块的代数变换包括:
- 恒定折叠
- 复制传播
- 强度降低
1. 恒定折叠:
求解连续的常数项,这样编译器就不需要求解这个表达式。
例子:
x = 2 * 3 + y ⇒ x = 6 + y (Optimized code)
2.复制传播:
它有两种类型,可变传播和恒定传播。
变量传播:
x = y ⇒ z = y + 2 (Optimized code)
z = x + 2
不断传播:
x = 3 ⇒ z = 3 + a (Optimized code)
z = x + a
3.强度降低:
用更便宜的语句/指令替换昂贵的语句/指令。
x = 2 * y (costly) ⇒ x = y + y (cheaper)
x = 2 * y (costly) ⇒ x = y << 1 (cheaper)
循环优化:
循环优化包括以下策略:
- 代码运动和频率降低
- 感应变量消除
- 循环合并/组合
- 循环展开
1.代码运动和频率降低
将循环不变代码移到循环之外。
// Program with loop variant inside loop
int main()
{
for (i = 0; i < n; i++) {
x = 10;
y = y + i;
}
return 0;
}
// Program with loop variant outside loop
int main()
{
x = 10;
for (i = 0; i < n; i++)
y = y + i;
return 0;
}
2.归纳变量消除:
消除循环中使用的各种不必要的归纳变量。
// Program with multiple induction variables
int main()
{
i1 = 0;
i2 = 0;
for (i = 0; i < n; i++) {
A[i1++] = B[i2++];
}
return 0;
}
// Program with one induction variable
int main()
{
for (i = 0; i < n; i++) {
A[i++] = B[i++]; // Only one induction variable
}
return 0;
}
3.循环合并/组合:
如果执行的操作可以在单个循环中完成,则合并或组合循环。
// Program with multiple loops
int main()
{
for (i = 0; i < n; i++)
A[i] = i + 1;
for (j = 0; j < n; j++)
B[j] = j - 1;
}
return 0;
}
// Program with one loop when multiple loops are merged
int main()
{
for (i = 0; i < n; i++) {
A[i] = i + 1;
B[i] = i - 1;
}
return 0;
}
4.循环展开:
如果存在可以减少循环执行次数的简单代码,则可以用这些代码替换循环。
// Program with loops
int main()
{
for (i = 0; i < 3; i++)
cout << "Cd";
return 0;
}
// Program with simple code without loops
int main()
{
cout << "Cd";
cout << "Cd";
cout << "Cd";
return 0;
}