微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 具体来说,编译器如何积极优化生成的字节码?

我一直在阅读各种编译器的功能,并且我遇到了许多编译器报告执行的“积极优化”一词.例如,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] 举报,一经查实,本站将立刻删除。

相关推荐