用于C / C ++的JIT优化器

我正在阅读有关JIT优于预编译的优点,其中之一是JIT可以根据实际运行时数据调整分支预测。 现在我在大学写一个编译器已经很久了,但在我看来,在大多数情况下(没有明确的getos),预编译代码也可以实现类似的东西。

请考虑以下代码:

test x jne L2: L1: ... jmp L3: L2: ... L3: 

如果我们有一些运行时检测可以看到’jne L2’为真的次数,它可以物理地交换L1:block和L2:block中的所有指令。 当然,它必须知道交换期间任何一个块都没有线程,但这些都是细节……

  test x jeq L1: L2: ... jmp L3: L1: ... L3: 

我知道程序代码加载到只读内存等时也存在问题,但这是一个想法。

所以我的问题是,这样的JIT优化是否适用于C / C ++,还是我错过了一些无法做到这一点的根本原因? 那里有C / C ++的JIT优化器吗?

最现代的CPU支持分支预测。 它们具有一个小缓存,允许CPU在概念上为您提供在运行时重新排序的好处。 此缓存的大小相当有限,但可能意味着您没有获得您想象的那么多的好处。 有些CPU甚至可以开始执行两个分支并丢弃未采用的分支上完成的工作。


编辑:使用JIT编译器的最大优势来自这样的代码。

 if (debug) { // do something } 

JIT非常擅长检测和优化无法执行任何操作的代码。 (如果你有一个微基准测试表明Java比C快得多,那么JIT很可能检测到你的测试没有做任何C编译器没有做的事情)

你可能会问,为什么C不会有这样的东西? 因为它有“更好”的东西

 #if DEBUG // do something #endif 

这是最佳的,只要DEBUG很少更改,并且您只有很少的这些标志,因此您可以编译每个有用的组合。

这种方法的问题是可扩展性。 您添加的每个标志都可以使预编译的二进制文件数量增加一倍。

如果你有许多这样的标志,并且编译每个组合是不切实际的,你需要依靠分支预测来动态优化你的代码。

我不知道C ++没有JIT编译器; 然而,GCC确实支持反馈定向优化(FDO),其可以使用运行时分析来优化分支预测等。

请参阅以“-fprofile”开头的GCC选项 (提示:“ – fprofile-use”使用生成的运行时配置文件执行优化,而“-fprofile-generate”用于生成运行时配置文件)。

您正在引用跟踪或重新优化JIT,而不仅仅是任何旧的JIT,没有为C或C ++做过这样的事情(至少不是公开的)。 但是,您可能想要检查LLVM是否使用Clang或GCC前端的分支(考虑它的编译器和JIT)不是那种方式,因为我似乎有些主题表明它可能已实现。

HP Dynamo二进制重新编译器certificate,对于C ++编译器生成的优化代码,可以实现高达20%的加速。 Dynamo并不完全是JIT编译器,因为它以任意机器代码而不是某些更高级别的表示forms(如JVM字节码或.NET CIL)开始,但原则上,C ++的JIT只能比Dynamo更有效。 请参阅: http : //citeseerx.ist.psu.edu/viewdoc/summary?doi = 10.1.1.12.7138&rank=1

Dynamo是为HP PA-RISC架构而创建的,从未作为商业产品提供,因此它在当前由x86变体主导的世界中没有多大用处。 我想知道VMware,Connectix或Parallels是否曾经为他们的重新编译器添加优化传递,或者他们已经摆脱了二进制转换,转而支持最新x86 CPU中的虚拟化function。