Powered by SourceForge   Home | About | Partners | Contact Us

Incremental recompilation with LLVM

I have run into an interesting issue with LLVM when I enabled global optimizations in XLR. It looks like the link-time optimization passes (LTO) in LLVM are not too friendly to incremental recompilation.

Generating code for a program while it runs is generally referred to as just-in-time compilation (JIT). LLVM supports JIT in a number of ways. In LLVM, you create Function instances that you populate with instructions. Then, you can run a number of optimization passes on this internal representation of the code before generating actual machine code. You can then run that machine code directly. In XLR, this generation of machine code happens in CompiledUnit::Finalize.

There are various optimization passes. Some of them are designed to run on a Function. There are, however, optimizations that involve multiple functions. For example, LLVM can automatically inline a function in another one if it's small enough. Doing this kind of optimization happens only once you have all the functions and are ready to link them together, hence the LTO name. Sometimes, people also refer to this as "whole program optimization" (WPO).

So what happens if you decide that the program source is allowed to change while the program runs? Well, when that happens, you may need to create additional Function objects in case some code was added. Then, you clearly need to re-run any global optimization phase.

This is where I noticed a rather peculiar behavior of the LTO phases of LLVM. They are rather heavy-handed when it comes to memory management. Once you run LTO, any Function or GlobalValue that has not been used this time around is simply deleted! This is implemented by a particular phase called GlobalDCE.

That behavior makes it rather difficult to perform incremental re-compilation of the whole program. It forces you to re-generate the entire set of Function objects, even if 99% of them didn't change. Most notably for XLR, it means that I can't keep around the prototypes for the XLR runtime functions. Alternatively, I can try to disable LTO in a way that still gets me inlining and other goodies. Stay tuned.

I raised the point on the LLVM mailing list. I doubt I'm the only one running into the problem...