Great article, as always. There is one thing that I think is important to bear in mind when discussing inlining, especially in the context of Clojure. This is that once a function has been inlined, you can no longer update the definition of that function in the REPL and have that update the behaviour of functions which use it, unless you recompile those as well. This is not a criticism of course, it’s just part of th…
Is that really true? Can't you track invalidations via a dependency graph? Right, as you said, you'd have to recompile dependents.
Jank now has its own custom IR
51–57 of 57 posts
Re: Jank now has its own custom IR
#52Earlier quoted context omitted.
Clojure (AFAIK) does not use invokedynamic, except perhaps in the latest version for some of the new interop stuff. It still officially supports JVM 1.8 bytecode. It’s a language which greatly values stability and backwards compatibility, so it’s been very slow to adopt newer JVM features.
Though there may be other reasons not to use it, invokedynamic is not a new feature of the JVM. If they're targeting 1.8 binary compatibility, they certainly have it at their disposal, since it landed in 1.7.
Re: Jank now has its own custom IR
#53Re: Jank now has its own custom IR
#54Earlier quoted context omitted.
The article talks about inlining a two-arity call to clojure.core/max to instead be an explicit call to cpp/jank.runtime.max, eliminating the unnecessary argument count matching and recursion portions of the Clojure function. It also mentions that in Clang the runtime max function will itself be inlined, so that's something LLVM ("the LLVM project", anyway) is still doing - and beyond that, as written this IR is like…
The first three paragraphs here are on point! jank's IR passes will not worry much about things like load/store optimization, register allocation, inlining C++ functions, etc. These are in LLVM's domain. We just worry about the Clojure side of things. Polymorphic math is intense, but we do our best to avoid the extra work by unboxing whenever possible. > A future optimisation might be to specialise for unboxed types:…
I have the wrong CPU architectures for pre-built jank packages (x86 mac, aarch64 linux, the exact opposite of 'normal') so I haven't actually looked at what it produces, so my last paragraph was pure speculation. I appreciate the detail you gave!
Re: Jank now has its own custom IR
#55Earlier quoted context omitted.
I spoke with a couple Clang and LLVM devs about MLIR when I was doing the original design for jank's IR. The general consensus was that MLIR added a great deal of complexity on top of designing/implementing an IR and nobody was confident it was actually worth the effort. Since I knew exactly what I wanted, I just built that.
Your custom IR is above LLVM’s IR, correct? Is it like SwiftIR then? Maybe you could add a paragraph or two going through that design decision.
Re: Jank now has its own custom IR
#56LLVM at the IR level has no understanding of the semantics of your language and therefore can't do the kind of optimisations that will really make a big speed difference.
I ended up having two custom IR's for a very high performance compiler I maintain at work. It made a big difference.
Re: Jank now has its own custom IR
#57Earlier quoted context omitted.
That is very cool indeed. Are there limitations that this imposes? Is Julia a whole world compiler or does it support partial compilation?
There's two main limitations: 1. If you try and re-define a global constant or add new methods inside a running program using `eval` or whatever, then your running program won't see those changes until it advances the world-age (i.e. either by using `invokelatest`, or by returning to the top-level scope). Note though that things like closures and defining functions within functions is fine, you just can't do an arbit…