C#编译器和JIT都做哪些优化?

14

我在为我的编译器课程中编写C#编译器并继续进行工作。目前,我已经完成了教科书上关于编译器优化的大部分章节。

就大部分而言,当教科书编写时,并没有考虑到即时编译(Just-In-Time compilation),我很好奇C#编译器执行的静态预编译优化和JIT过程中执行的优化有什么不同?

当我与人们谈论针对CLR的编译时,我通常会听到:“大多数优化都是由JIT完成的”。

像循环展开、常量折叠/传播、指令交错这样的事情是由C#编译器在预-Jit时处理还是由Jitter处理?如果jitter没有处理它们,那么即时编译器独有的JIT优化是什么样的?


12
你提到的大多数优化都是由JIT编译器完成的。C#编译器执行常量折叠是因为语言语义要求如此。使用/o运行的C#编译器只会进行简单的IL控制流优化,例如消除“跳转到下一条指令”的操作。这是一个好的话题;我将尝试在博客上撰写一篇关于我们在IL级别上进行哪些优化的文章。请在接下来的一个月左右关注我的博客获取详细信息。 - Eric Lippert
@Eric Lippert,太棒了!没想到会收到微软编译器团队的高级开发人员回复!如果您记得的话,在发表博客文章时,请务必从这里链接过来。无论如何,我都会关注的。谢谢Eric。 - mmcdole
3
不用谢。这篇文章将于6月11日发布。 - Eric Lippert
8
博客文章已发布:http://blogs.msdn.com/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx该文章讨论了C#编译器的“-optimize”选项对代码生成的影响。它解释了在何种情况下启用此选项可以提高代码执行效率,以及何时这可能会导致不良结果。该文章还提供了一些实际示例,展示了应如何使用此选项以及何时避免使用它。 - jerryjvl
3个回答

3
我可以想象到许多仅适用于JIT的优化,特别是任何依赖应用程序运行环境/上下文的优化。(请注意,以下所有内容均为假设,我不确定是否会执行这些操作或其中哪些操作)。
最无聊的:JIT可以根据32位/64位底层操作系统进行优化,甚至可能取决于确切的处理器架构。
不适用的内容:更有趣的是,当应用程序未在调试上下文中运行时(例如某些条件代码),JIT可以优化掉仅在调试模式下运行的任何内容。
最有趣的:JIT可以优化掉仅取决于只读字段的类中的条件分支,因为理论上该值在类的执行期间永远不会改变。
基本上,我认为将优化推迟到JIT通常是正确的选择,因为在JIT时间,关于代码实际运行的上下文可用的信息最多,从而使更有意义的优化成为可能。

9
只有在调试期间使用的代码会被C#编译器删除,而不是JIT编译器。 - Eric Lippert

0
David Notario在他的博客上有一些文章(你可以从这里开始,然后往前看),但它们相当简略。

-5

我认为C#编译器不会进行任何优化。JIT完成所有工作。


由于调试版和发布版在IL级别上是不同的,编译器会进行一些优化。 - Brian Rasmussen
我认为这种推理是错误的(例如,在“调试”中,编译器可能会插入无操作、其他序列点调试信息等),但这并不意味着“发布”会进行任何优化。 - Brian
1
调试版本可能会进行一些悲观优化,以提高调试效果。 - peterchen
我想这归结于什么算作优化。不插入NOP可能不算作优化,但编译器在发布版本中实际上会删除未使用的变量,我认为这是一种优化。 - Brian Rasmussen
5
C#编译器确实进行优化,这就是/o标志的作用。但它们并不是非常复杂的优化。 - Eric Lippert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接