我一直在阅读各种编译器的功能,并且我遇到了许多编译器报告执行的“积极优化”一词.例如,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"
解决方法:
以下是编译器可以进行的两个简单优化:
out = ((i / 2) >> 16) - 10;
可以减少到
out = (i >> 17) - 10;
和
out = ((i << 5) / 2) * 50 + 10;
可以减少到
out = (i << 4) * 50 + 10;
回答你的问题“如何优化生成的字节代码以比编译器生成的更快的速度运行?”这是字节码的另一个版本,它有一些优化.
// 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
// optimization: remove unnecessary /2
// out = ((in / 2) >> 16) - 10;
push "in"
push 17
rightshift
push 10
minus
// optimization: don't need out var since value on stack
// dataOut[i] = out;
push "i"
push "dataOut"
writeProp
// optimization: avoid branch to common loop end
// i++
push "i"
increment
writeto "i"
goto "forStart"
// else
label: ifPart2
// optimization: remove unnecessary /2
// out = ((in << 5) / 2) * 50 + 10;
push "in"
push 4
leftshift
push 50
multiply
push 10
add
// optimization: don't need out var since value on stack
// dataOut[i] = out;
push "i"
push "dataOut"
writeProp
// optimization: avoid branch to common loop end
// i++
push "i"
increment
writeto "i"
goto "forStart"
label: "forEnd"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。