There is a long tradition of type-directed compilation.  Haskell compilation system refers to it as the simplifier or &quot;middle end&quot;.<p>The parsing and type-checking produces a IR known as &#x27;Core&#x27;.  The middle-end optimizes it as a series of source-to-source transformations on Core code.<p>The back end of the compiler transforms Core code into an internal representation of a C dialect called C--, via yet another intermediate language STG (short for &quot;Spineless Tagless G-machine&quot;).<p>Finally, the C-- code output can either be printed as C code for compilation with GCC, converted directly into native binary, or converted to LLVM virtual machine code for compilation with LLVM.  Any output is linked against the Haskell runtime.<p>The innovation would come in creating the optimizations in the middle-end that could not be possible in the LLVM backend.  Proof is in the pudding.  Introducing another layer without any meaningful results is how projects bloat (NIH syndrome).<p>There is a LLVM backend that implements most if not all of the GHC &quot;middle-end&quot; optimizations[0] and should provide you with details&#x2F;context you are seeking.<p>[0] <a href="http:&#x2F;&#x2F;blog.llvm.org&#x2F;2010&#x2F;05&#x2F;glasgow-haskell-compiler-and-llvm.html" rel="nofollow">http:&#x2F;&#x2F;blog.llvm.org&#x2F;2010&#x2F;05&#x2F;glasgow-haskell-compiler-and-ll...</a>