关于c#:JIT编译器的IL优化

IL optimization for JIT compilers

我正在开发一个发出IL代码的编译器。使用Mono和Microsoft.NET JIT编译器将生成的IL实时转换为尽可能快的机器代码是很重要的。

我的问题是:

  • 优化模式是否有意义,比如:

    1
    2
    'stloc.0; ldloc.0; ret' => 'ret'
    'ldc.i4.0; conv.r8' => 'ldc.r8.0'

    这样,或者JIT足够聪明来处理这些问题?

  • 是否有包含由Microsoft/Mono JIT编译器执行的优化列表的规范?

  • 是否有任何良好的阅读和实际建议/最佳实践来优化IL,以便JIT编译器能够反过来生成最佳的机器代码(性能方面)?


  • 冗余的转换和这样的加载/存储是一个非常不可避免的副作用递归体面的解析器。从技术上讲,你可以用窥视孔优化器来消除它们。但这没什么好担心的,C和VB.NET编译器也会生成它们。

    现有的.NET/Mono抖动非常擅长优化它们。他们专注于优化对执行速度至关重要的代码,即机器代码。有一个非常好的优势,即任何编写生成IL的编译器的人都可以自动从这些优化中获益,而无需做任何特殊的事情。

    本文将介绍抖动优化。


  • 你所描述的两个模式是JIT实际上正确的简单的东西(非原始结构除外)。在SSA形式中,常数传播和消除死区值非常容易。
  • 不,您必须测试JIT可以做什么。查看编译器文献以了解期望的标准优化。然后,测试它们。我们现在拥有的两个JIT优化得很少,有时也不能得到最基本的东西。例如,Ryujit不优化MyStruct s; s.x = 1; s.x = 1;s = s;也不是。s.x + s.x从内存中加载x两次。期望渺茫。
  • 您需要了解基本操作映射到什么机器代码。这并不太复杂。尝试一些事情,看看反汇编列表。你很快就会知道输出是什么样子的。