Organisers: Renato Golin, Nicolas Vasilache, Sasha Lopoukhine
At EuroLLVM 2026, Renato, Nicolas, and I (Sasha) organized a roundtable aimed at structuring the assembly and ISA level efforts that are gaining traction in the MLIR ecosystem.
Our objective was to characterize the different IR encodings and their tradeoffs, and to gather input from the community as to the suitability of the different encoding choices across use cases.
The number of assembly-level MLIR projects that we gathered in preparation of this roundtable (see below) and the high attendance of the roundtable itself (40-50 people) suggests a broad interest in the community.
We identified several encoding choices across projects, for example, whether SSA def-use chains are maintained.
During the roundtable, I (Sasha) presented the encoding choices for my work on RISC-V and x86 dialects and also summarized the work of Renato and Nicolas (who were partially absent due to scheduling conflicts).
One particularly interesting tradeoff are encoding differences between my work, the upstream x86 dialect, and Aster.
Over the next few months, Nicolas, Renato, and I plan to iterate on the designs, aiming to eventually submit an RFC to gather community input on ISA-level abstractions and their use in MLIR.
Assembly-level Representations
Here are the projects that I’m aware of that have assembly-level concepts like registers in MLIR:
- MoNaCo
- MLIR to Native Code Generator
- A Multi-level Compiler Backend for Accelerated Micro-kernels Targeting RISC-V ISA Extensions
- My paper that describes the approach we’ve used for codegen
- Talk from previous LLVM Dev meeting
- The current implementation looks a little different now to the one in the presentation and paper:
riscvdialect in xDSL- I’m currently working on something similar in x86/AVX512, all that infrastructure is also in the xDSL repo
- ASTER
: Assembly Tooling and Representations
- Open-source MLIR-based tool for programmable and highly-controllable assembly production on AMD GPUs.
- Scaling Certified Instruction Selection For LLVM IR Through Bitblasting
- Presentation was at this EuroLLVM, recording not yet up
- There are some similar representations in CIRCT, but I haven’t yet looked at them in detail
If you’re aware of other projects with such representations I’d be interesting in hearing about them!
Roundtable discussions
I presented a trivial example of how one could represent assembly-level operations in MLIR, to serve as a reference for the discussion:
// Input
%a = arith.addi %b, %c : index
%d = arith.addi %b, %a : index
// Lowered
%a = riscv.add %b, %c : (!riscv.reg, !riscv.reg) -> !riscv.reg
%d = riscv.add %b, %a : (!riscv.reg, !riscv.reg) -> !riscv.reg
// Allocated
%a = riscv.add %b, %c : (!riscv.reg<a0>, !riscv.reg<a1>) -> !riscv.reg<a1>
%d = riscv.add %b, %a : (!riscv.reg<a0>, !riscv.reg<a1>) -> !riscv.reg<a0>
// asm
add a1, a0, a1
add a0, a0, a1
This is the representation that I have been using in my work over the last few years. Importantly, this is not the same structure as the one used in Aster, where the destination register is passed in, similarly to Destination-Passing Style (DPS) in linalg. Another key distinction is that we keep the SSA relationships for the register-allocated form, whereas Aster destructs the SSA relationships and represents register reads and writes as effects.
I presented the register allocation approach that we currently use in our backend dialects. We discussed the possibility of multiple register allocation approaches, and how the encoding above can is unusual and may lead to some confusion. One of the things we discussed was the ability to verify whether the code above in register allocated form is correct, by looking at the registers stored in the types. We did not reach a consensus on the best register allocation approach, but various people where interested in exploring good register allocation for ISA-level IRs further.
My impression of the discussion was that people generally found ISA abstractions in MLIR weird but interesting, which I’m pretty happy with for this still relatively early stage. Nicolas and I are planning to do more experimentation on the different representations over the next couple of months, and hopefully can come to an agreement and a better understanding of the tradeoffs soon. We’re also planning experiment some more with Renato’s team on the tradeoffs between the existing x86 dialect ops, which operate on vectors, and the ones I’ve been working on, which operate on vector registers. I look forward to writing these up and getting more feedback from the community!