Live data from Hacker News

Jank now has its own custom IR

jank-lang.org

51–57 of 57 posts

Re: Jank now has its own custom IR

#51
post #42
post #4

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.

That's what Julia does. It works pretty well.

Re: Jank now has its own custom IR

#52
post #39
post #27

Earlier 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.

I can't speak for the core team, but from memory invokedynamic took a long time to become performant. So if you still want to support older JVM versions, the performance will be pretty terrible on those older systems if invokedynamic is used for something as integral as var lookups.

Re: Jank now has its own custom IR

#54
post #45
post #8

Earlier 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:…

Thanks for the response. I really like the measured, evidence-based approach you're taking to this work.

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

#55
post #44

Earlier 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.

jank's custom IR is completely separate and unrelated to LLVM IR, aside from both of them being SSA-based IRs. We go from jank's AST into jank's IR into C++, which we then give to Clang compile into the LLVM JIT runtime. So LLVM IR is used in the pipeline, but we don't touch it directly. More info on that, and a diagram, is here: https://book.jank-lang.org/dev/ir.html (which I linked in the post)

Re: Jank now has its own custom IR

#56
You almost always want your own IR that you can use for high level optimisations and then transform it into the LLVM IR.

LLVM 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

#57
post #29

Earlier 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…

That is really interesting, and very clever - thanks for the details! What you describe is indeed what I meant by whole world, I'm not sure if there's a better term of art for it.
Post reply on HN