I guess "IR" is "intermediate representation" while "MLIR" [1] ("Multi-Level Intermediate Representation") is an IR from Chris Lattner/LLVM that is designed to be modular and extensible. For the uninitiated, I think [2] shows how the current Julia IR is generated and used in the Julia JIT compilation process
Yes, except these are the devdocs for the current IR: https://docs.julialang.org/en/v1/devdocs/ssair/. I wrote that system about 10 years ago, but it was a bit of a rush job in the lead up to Julia 1.0 in order to be able to do some optimizations that we desperately needed to do. It's held up reasonably well, but it's definitely hit its limitations as Julia's popularity has continued to grow. There've been multiple downstream attempts to use it to do compiler-y things and they've all had middling success (including my own). I think the jankiness of the IR API played a role in that, so this is my attempt to try to start cleaning that up.
Uh, hi guys. This is my PR, but you should probably know that this is an AI generated prototype based on some of my design documents, but nowhere near ready for prime time. I do want to do something like this, but whether it'll take this shape or another is still up in the air.
Very cool work Keno! Any place to find information about the Julia-specific concepts / features compared to MLIR?
Wondering if there are modeling or analysis modalities that don’t fit cleanly into MLIR concepts (understand that abstract interpretation on the IR comes with a unique set of concerns)
I don't think there's anything we need to do here that couldn't be expressed in MLIR representationally. That said, I also haven't studied MLIR's representation in too much detail myself, so it's possible there's subtle corner cases. For example, in LLVM you end up getting quadratic processing times even for linear time passes, because it needs to restore the ordering count for instructions (I think the trick in this PR may be backportable to LLVM to improve that, but I haven't looked into it yet). We ran into that badly with larger functions, so it's possible there'd be similar corner cases in MLIR if we used it e.g. for the tree structuring that's proposed in this PR.
Not using MLIR here is more about other considerations:
1. It'd probably be more of a pain to write high performance bindings than just to write the data structure in julia itself.
2. We will be targeting WasmGC in the near future, so we need our core runtime and compiler data structures to be compilable without the assumption of necessarily having linear memory available.
3. It's designed to be used by downstream julia users, so it's easier for them to not have to deal with another system in another language.
4. It's experimental and we need to be able to make changes quickly without having to necessarily have a big upstream discussion.
That said, like I mentioned in the other comment, easy interop with MLIR is an explicit design goal.
> 2. We will be targeting WasmGC in the near future, so we need our core runtime and compiler data structures to be compilable without the assumption of necessarily having linear memory available.
Big if true. Does that mean we'll get a no-alloc iOS backend?
The WasmGC and the lack of good support in LLVM is a pain, but having yet another IR may be worse decision in the long run compared with just using MLIR and submitting changes to have it work for you
I was unaware of alternative IRs for julia (albeit I started learning much more about compilers once I left the julia ecosystem). What other IRs is this supposed to replace? And why not just go with MLIR directly?
Julia has roughly 2 different IRs that live pre LLVM (one for type inference, one for Julia level optimization). This is a proposed replacement to both of these. The reason not to go MLIR is that writing Julia is a lot nicer than writing C++.
MLIR pulls in a lot of interface complexity that we don't want or need for pure-julia end-users. That said, it is obviously and deliberately close to MLIR as a representation since people do want to be able to interface with MLIR (e.g. in Enzyme), so I'd like to facilitate easy conversion back and forth.
I guess "IR" is "intermediate representation" while "MLIR" [1] ("Multi-Level Intermediate Representation") is an IR from Chris Lattner/LLVM that is designed to be modular and extensible. For the uninitiated, I think [2] shows how the current Julia IR is generated and used in the Julia JIT compilation process
[1] https://en.wikipedia.org/wiki/MLIR_(software)
[2] https://docs.julialang.org/en/v1/devdocs/jit/
Yes, except these are the devdocs for the current IR: https://docs.julialang.org/en/v1/devdocs/ssair/. I wrote that system about 10 years ago, but it was a bit of a rush job in the lead up to Julia 1.0 in order to be able to do some optimizations that we desperately needed to do. It's held up reasonably well, but it's definitely hit its limitations as Julia's popularity has continued to grow. There've been multiple downstream attempts to use it to do compiler-y things and they've all had middling success (including my own). I think the jankiness of the IR API played a role in that, so this is my attempt to try to start cleaning that up.
Uh, hi guys. This is my PR, but you should probably know that this is an AI generated prototype based on some of my design documents, but nowhere near ready for prime time. I do want to do something like this, but whether it'll take this shape or another is still up in the air.
Very cool work Keno! Any place to find information about the Julia-specific concepts / features compared to MLIR?
Wondering if there are modeling or analysis modalities that don’t fit cleanly into MLIR concepts (understand that abstract interpretation on the IR comes with a unique set of concerns)
I don't think there's anything we need to do here that couldn't be expressed in MLIR representationally. That said, I also haven't studied MLIR's representation in too much detail myself, so it's possible there's subtle corner cases. For example, in LLVM you end up getting quadratic processing times even for linear time passes, because it needs to restore the ordering count for instructions (I think the trick in this PR may be backportable to LLVM to improve that, but I haven't looked into it yet). We ran into that badly with larger functions, so it's possible there'd be similar corner cases in MLIR if we used it e.g. for the tree structuring that's proposed in this PR.
Not using MLIR here is more about other considerations:
1. It'd probably be more of a pain to write high performance bindings than just to write the data structure in julia itself.
2. We will be targeting WasmGC in the near future, so we need our core runtime and compiler data structures to be compilable without the assumption of necessarily having linear memory available.
3. It's designed to be used by downstream julia users, so it's easier for them to not have to deal with another system in another language.
4. It's experimental and we need to be able to make changes quickly without having to necessarily have a big upstream discussion.
That said, like I mentioned in the other comment, easy interop with MLIR is an explicit design goal.
> 2. We will be targeting WasmGC in the near future, so we need our core runtime and compiler data structures to be compilable without the assumption of necessarily having linear memory available.
Big if true. Does that mean we'll get a no-alloc iOS backend?
I'm not sure I understand the connection, but I also know basically nothing about iOS.
The WasmGC and the lack of good support in LLVM is a pain, but having yet another IR may be worse decision in the long run compared with just using MLIR and submitting changes to have it work for you
Not sure the MLIR folks would appreciate a vibe-rewrite PR from C++ into Julia, but guess we could give it a go ;).
I was unaware of alternative IRs for julia (albeit I started learning much more about compilers once I left the julia ecosystem). What other IRs is this supposed to replace? And why not just go with MLIR directly?
Julia has roughly 2 different IRs that live pre LLVM (one for type inference, one for Julia level optimization). This is a proposed replacement to both of these. The reason not to go MLIR is that writing Julia is a lot nicer than writing C++.
MLIR pulls in a lot of interface complexity that we don't want or need for pure-julia end-users. That said, it is obviously and deliberately close to MLIR as a representation since people do want to be able to interface with MLIR (e.g. in Enzyme), so I'd like to facilitate easy conversion back and forth.
So, does this mean faster rendering in notebooks, better debugging, fewer NVIDIA troubles?
Probably not. It's mostly about making it less of a pain for downstream packages that need to do compiler-y things.
Probably not directly but eventually I could see it having some benefits for what you listed.