编译器优化和实例
编译器优化 C 代码时,通常从多个层面进行优化,以提高程序的执行效率、减小代码体积,或者降低能耗。以下是主要的优化方向和技术分类:
一、代码层级优化(源代码级)
这些优化通常是在编程时就能看到效果的。
1. 常量传播(Constant Propagation)
将程序中不变的值直接替代使用它的变量。
int a = 5; int b = a + 3; // 优化后:int b = 8;
2. 常量折叠(Constant Folding)
编译期间计算常量表达式结果。
int c = 3 * 4 + 5; // 优化为 int c = 17;
3. 死代码消除(Dead Code Elimination)
去掉永远不会被执行或没有影响的代码。
if (0) { do_something(); // 会被删掉 }
4. 代码内联(Function Inlining)
将小函数直接展开,消除函数调用开销。
inline int add(int x, int y) { return x + y; } // 调用 add(a, b) -> 替换为 a + b
5. 循环展开(Loop Unrolling)
减少循环控制带来的开销,提高流水线效率。
for (int i = 0; i < 4; ++i) arr[i] = 0; // 优化为 arr[0]=0; arr[1]=0; arr[2]=0; arr[3]=0;
6. 循环不变代码外提(Loop-Invariant Code Motion)
把循环中不变的计算移出循环。
for (int i = 0; i < n; ++i) { x = a * b; // 如果 a 和 b 不变,这一行会被移出循环 }
二、中间表示(IR)层优化
这是编译器内部的优化过程,源代码看不到,但生成的汇编更高效。
1. 中间代码优化(如 SSA)
将变量转为“静态单赋值”(SSA)形式,便于分析依赖与优化。
2. 寄存器分配(Register Allocation)
尽可能将变量保存在 CPU 寄存器中,而不是内存里。
3. 指令选择和调度(Instruction Scheduling)
选择适合目标平台的汇编指令,并调整顺序减少数据冲突和流水线停顿。