Possible alternative compiler backend: Cretonne

I wrote a document comparing Cretonne to LLVM.

I am quite excited about this project. It would be great for Cretonne to have multiple clients because it forces us to define the right abstractions and not let too many client-specific hacks creep in. For Rust, I believe Cretonne can provide debug builds that are both faster and that generate faster code than LLVM’s debug builds.

Debug information

A JIT compiler like IonMonkey does speculative optimizations that sometimes turn out to be incorrect, and a running function needs to be de-optimized. When this happens, the values of local variables are derived from the state of the optimized code and copied into an interpreter stack frame where execution continues.

This means that at certain safe points in the optimized code, it must be possible to compute the value of all local variables that are in scope. This is very similar to the requirements when breaking a debug-compiled Rust program in a debugger. The debugger can display the values of all local variables.

In LLVM, this is achieved with a -O0 build which generates code that keeps all local variables in a designated stack slot at all times. Such code is very slow and very large—register allocation is an important optimization.

A debug build that uses safe-point-preserving optimizations to generate accurate DWARF should run much faster than everything-on-the-stack -O0 code while being just as debuggable.

Schedule

Cretonne is a work in progress, and it can’t do much of anything at the moment. The first goal is to be able to compile WebAssembly as a second-tier compiler in SpiderMonkey. I expect we will get to that point sometime in 2017.

REPL

Cretonne can be used as a JIT for a REPL as can LLVM. I expect Cretonne to provide a better tradeoff between latency and optimizations than LLVM. Of course I have no data to back that up at this time.

Higher-level optimizations

Cretonne does not aim to compete with LLVM in the -O3 optimization space, but it could be a component of a compiler that did. I agree there is an interesting opportunity here, in particular if we can exploit Rust’s explicit aliasing model.

Cretonne’s intermediate representation isolates functions so they can be compiled in parallel. This also means that it can’t really express inter-procedural optimizations like inlining which is essential to optimizing Rust. There’s nothing wrong with inlining one Cretonne function into another, but the process needs to be guided by a call graph representation that is external to Cretonne.

There is an interesting challenge in defining a compiler architecture that permits concurrent inter-procedural optimizations as well as incremental compilation. I hope Cretonne can be a component of such an architecture—it does not attempt to define it.

25 Likes