Welcome to the tutorial series that teaches how to write a tiny optimising compiler in haskell!
Start from:
I've wanted to write this for a while: a tiny optimising compiler for a small imperative ish language.
I want to show off modern compiler ideas, such as:
I currently have a parser for the source language, conversion to IR, then to SSA, and a semi-broken MIPS backend.
Shows the correct way of doing a lot of things, in the sense of "engineering". I might pick the slower algorithm to compute a dominator tree, because I wish to emphasize the idea of the dominator tree. When a trade off is presented between simplicity and performance, I will pick simplicity.
[x]
Parse[x]
Generate non-SSA IR[x]
Convert non-SSA to SSA (Mem2Reg
is the pass where this happens.)[x]
generate MIPS assembly from SSA IR (half-done)[ ]
(Optional) generate LLVM for SSA IR (Can be pulled from simplexhc)At this point, we have a "functioning" compiler. Now, we can extend the compiler or the language. I want to show off optimisations, so I will spend more time implementing optimisations
[ ]
Loop detection.[ ]
Scalar evolution.[ ]
Global value numbering.[ ]
Dead code elimination.[ ]
Loop unrolling.[ ]
invariant load hoisting.Note that we do not yet have functions in the language! let's add that.
[ ]
extend language with functions.[ ]
generate MIPS for functions.[ ]
Inlining.If we get here, we can then add polyhedral abilities to the compiler. For this though, we would need to integrate with isl
. Someone will need to write haskell bindings :)
.