Julia performance has has little to do with LLVM. If performance was that easy, you could just slap LLVM in the back of any dynamic language and poff by magic you have super performance.
Most dynamic languages that have reached decent performance have done so using trace-JIT compilers. These are complex and require a lot of man hours to make.
PyPy is a similar approach. It is hard problem to solve.
Yet Julia spending considerably less man hours than either project and with smaller and simpler code base has managed to run circles around these two projects in terms of performance.
Why? Because of smart language design. The pervasive multiple-dispatch design tailored towards JIT code generation has been key.
It allowed Julia to get great performance with a very simple method-JIT compiler. These are much easier to make than trace-JIT compilers.
But Julia is not alone. Go is another example of a language which kicks above its weight. It is a relatively simple implementation, yet has good performance and is enjoyable for most people to work with. Except those who really hate Go of course ;-)
My bottom line is: LANGUAGE DESIGN MATTERS!!! You you design a smart and simple language you can get away with simple implementations and still get good performance.
Sure LLVM is an important piece of the puzzle, but it serves no more important role than C does as the backend for Haskell IMHO.
Once this choice has been made, Julia compiles the method, specialised for the exact types of the arguments.
So, the dispatch process and the JIT compiler are linked - both are reliant on type information every time a function is called.
This specialisation is the only way the Julia JIT uses runtime type information. Unlike JavaScript JITs, Julia does not track things like the types of local variables during execution (although it may do some static inference). Therefore type annotations for local variables can improve performance.
So, if not on local variables, where are explicit types necessary (other than function parameters)?
I believe Julia is the only programming language where multiple dispatch is the way all function calls work. There are no exceptions. It is also the only language where it was used to aid a JIT compiler.
Once you dig into multiple dispatch and see how it affects everything from performance to Julia package design and how packages integrate with each other, you will just be blown away.
It is hard to convey how ingenious this solution is. Even the creators themselves have admitted they did not realize how clever this would end up being. They only realized after people started actively using Julia what a gold mine they had hit.