Live data from Hacker News

Jank now has its own custom IR

jank-lang.org

21–30 of 57 posts

Re: Jank now has its own custom IR

#21
post #18
post #12

The natural evolution of compiler toolchains that live long enough on top of LLVM, eventually every one matures into having their own IR. Even clang is now in the process of doing the same. > We're going to use Clojure JVM to get our baseline benchmark numbers and then we'll aim to beat those numbers with jank. > Note that all numbers in this post are measured on my five year old x86_64 desktop with an AMD Ryzen Thre…

Isn't the main benefit of LLVM that you get tons of backends for free? What does having your own IR give you that's worth this tradeoff?

I suppose you can always translate your own IR to the one supported by LLVM. That would be the first backend I'd write, if I was making my own IR.

Re: Jank now has its own custom IR

#22
post #18

Earlier quoted context omitted.

Isn't the main benefit of LLVM that you get tons of backends for free? What does having your own IR give you that's worth this tradeoff?

These compilers aren't replacing LLVM, they are adding a compilation step with its own IR where they do certain optimizations and translations *before* handing things off to LLVM. Basically, the idea is to do as much 'high level' optimization and transformation stuff as you can in your own IR, and then let LLVM handle the low-level stuff and the targeting of specific hardware vendors.

That makes sense, thanks. Is this IR at a level where the optimisations can't just be added to LLVM then?

Re: Jank now has its own custom IR

#23
post #11
post #7

The natural question is why doesn't Jank use MLIR?

No language using MLIR uses it directly out of the box, in that sense the right question is why did Jank not create their MLIR dialect.

MLIR dialects have to be lowered into the basic LLVM one eventually, don't they? Does MLIR add anything over a custom IR for host languages that aren't deficient at manipulating data structures?

Re: Jank now has its own custom IR

#24
post #22

Earlier quoted context omitted.

These compilers aren't replacing LLVM, they are adding a compilation step with its own IR where they do certain optimizations and translations *before* handing things off to LLVM. Basically, the idea is to do as much 'high level' optimization and transformation stuff as you can in your own IR, and then let LLVM handle the low-level stuff and the targeting of specific hardware vendors.

That makes sense, thanks. Is this IR at a level where the optimisations can't just be added to LLVM then?

I don't know much about Jank's implementation, but I can speak to how it's done in Julia (dynamic, high performance language with lispy semantics but matlaby syntax, JIT compiled to LLVM).

I think the big thing is just that LLVM can't really be made to closely model everyone's different weird langauge semantics. In practice, the less C-like your language is, the more hoops you will likely need to jump through in order to prepare your code to be handed off to LLVM if you want to get a good result out of it, otherwise it just wont understand your code well enough to make good optimizations, or may not have the proper optimizations implemented.

Trying to modify LLVM to fit your purposes is a bit of an uphill battle too. You either have to try and convince all the stakeholders that each one of your proposed modifications are worth it (when they're typically just not needed by C-like languages), or you need to maintain a fork which is a nightmare.

Like, just to take one example, Julia has a world-age system I describe here: https://news.ycombinator.com/item?id=48151251#48177215 which most other LLVM users would have no use for, and would just add complexity and overhead for them so I don't think any julia people ever even thought about trying to upstream that.

Julia is a somewhat extreme example. It actually has like 2.5 different IRs internally because it just does a lot of compiler transforms before handing things off to LLVM. We've generally just been on a trajectory of moving more and more stuff over to the Julia side because it gives us maximal control.

Re: Jank now has its own custom IR

#25
post #22

Earlier quoted context omitted.

These compilers aren't replacing LLVM, they are adding a compilation step with its own IR where they do certain optimizations and translations *before* handing things off to LLVM. Basically, the idea is to do as much 'high level' optimization and transformation stuff as you can in your own IR, and then let LLVM handle the low-level stuff and the targeting of specific hardware vendors.

That makes sense, thanks. Is this IR at a level where the optimisations can't just be added to LLVM then?

[dead]

Re: Jank now has its own custom IR

#26
post #11

Earlier quoted context omitted.

No language using MLIR uses it directly out of the box, in that sense the right question is why did Jank not create their MLIR dialect.

MLIR dialects have to be lowered into the basic LLVM one eventually, don't they? Does MLIR add anything over a custom IR for host languages that aren't deficient at manipulating data structures?

'MLIR dialects' is just a term for teaching MLIR how to manipulate and understand your own custom IR.

MLIR is just very good at producing good vectorized code in the presence of stuff like nested loops compared to LLVM or even some of the most carefully crafted custom compilers. It's not about whether your custom compiler is 'deficient' at handling data structures, MLIR is just genuinely very good at some of this stuff compared to basically anyone else.

For most projects it's just more trouble than it's worth though, because maintaining and using an MLIR dialect definition is hard.

Re: Jank now has its own custom IR

#27
post #19
post #9

Earlier quoted context omitted.

No, it doesn't. In JVM Clojure's case, the vars are usually compiled to the moral equivalent of a global variable holding a pointer to a function. This allows you to update the function if the developer redefines it in the REPL, but it comes at a performance cost (the JVM can't inline it or otherwise optimise it). Clojure also allows you to compile with "direct linking", e.g. for production deployments, where you kno…

> the vars are usually compiled to the moral equivalent of a global variable holding a pointer to a function. This allows you to update the function if the developer redefines it in the REPL, but it comes at a performance cost (the JVM can't inline it or otherwise optimise it) might be out of my depth but I find it surprising; I thought compilation through invokedynamic should be able to handle redefinition while sti…

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.

Re: Jank now has its own custom IR

#29
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…

Julia actually has some really cool machinery for handling this that I would encourage other JIT languages to copy. Whenever you call a function, that function and any calls in that call stack occur in a 'fixed world age'. Within a given world-age, method tables and global constants are all fixed, and the langauge can be analyzed like it's statically typed (there are escape hatches like `invoke_in_world`, and `invoke…

That is very cool indeed. Are there limitations that this imposes? Is Julia a whole world compiler or does it support partial compilation?

Re: Jank now has its own custom IR

#30

Probably a stupid question, but is LLVM better at optimising its IR than C compilers are at optimising C? Asked another way, why not use C as an IR, if it's compatible with your language semantics?

LLVM is essentially what you get when you say "I want to use C as an IR", and then try and do it for a bit and say "hmm, okay I'd like to put some restrictions on this IR... and maybe some customization hooks... and maybe this feature..."
Post reply on HN