我一直在阅读各种编译器的功能,并且遇到了据报道许多编译器执行的术语“积极优化”。例如,LLVM 引用了以下编译时优化功能:
- 内存/指针特定
- 循环变换
- 数据流
- 算术
- 死码消除
- 内联
这具体是什么意思?假设您有以下代码片段,您如何优化生成的字节码以比编译器生成的代码运行得更快?我对优化 JIT 驱动的运行时(如 C#、Java 和 Flash)的字节码特别感兴趣。这很棘手,因为 JIT 仅支持处理器通常执行的操作码的子集,这限制了您可以执行的优化量。尽管如此,我还是很想知道什么是可能的,以及究竟是什么转换可以推动 VM 的极限。
虚构的代码块:
for (i = 0; i < 100; i++){
in = dataIn[i];
if ((in % 5) == 0){
out = ((in / 2) >> 16) - 10;
}else{
out = ((in << 5) / 2) * 50 + 10;
}
dataOut[i] = out;
}
编译器生成的近似伪代码,用于基于堆栈的 JIT VM,例如 Flash Player:(请原谅我的任何错误,这完全是手写的!)
// i = 0
label: "forInit"
push 0
writeTo "i"
// while i < 100
label: "forStart"
push "i"
push 100
jumpIfMoreThan "forEnd"
// in = dataIn[i];
push "i"
push "dataIn"
readProp
saveTo "in"
// if ((in % 5) == 0)
push "in"
push 5
mod
push 0
jumpIfNotEquals "ifPart2"
label: ifPart1
// out = ((in / 2) >> 16) - 10;
push "in"
push 2
divide
push 16
rightshift
push 10
minus
writeTo "out"
goto "ifEnd"
// else
label: ifPart2
// out = ((in << 5) / 2) * 50 + 10;
push "in"
push 5
leftshift
push 2
divide
push 50
multiply
push 10
add
writeTo "out"
// dataOut[i] = out;
label: ifEnd
push "out"
push "i"
push "dataOut"
writeProp
// i++
push "i"
increment
writeTo "i"
// while i < 100
goto "forStart"
label: "forEnd"