JLIR: A Julia-Native MLIR-Inspired Intermediate Representation with Automatic JACC Kernel Extraction
Organizations: Oak Ridge National Laboratory, Oak Ridge, 37830, USA
Abstract
The Multi-Level Intermediate Representation (MLIR) has made reusable compiler infrastructure practical for domain-specific computation. However, MLIR's strong compile-time type requirements and low-level (C++) extension model can be a poor match for high-level, dynamically specialized languages such as Julia. MLIR has several drawbacks for dynamic programming languages in terms of the type system and level of abstraction. It is thus extremely challenging for non-compiler or scientific computing users to introduce new programming abstractions and express algorithm implementations in a form that remains both natural and optimizable. As a result, library interfaces for linear algebra, mesh processing, partial differential equations, and related domains often sit outside the compiler optimization path. We present JLIR (Julia-native Level Intermediate Representation), a Julia-native intermediate representation framework that brings the main benefits of MLIR-style multi-level, dialect-oriented compilation into the Julia ecosystem while remaining usable as ordinary Julia code. JLIR represents Julia programs before low-level lowering, supports extensible operations and transformation passes through Julia's language mechanisms, and allows partially typed programs to remain transformable until concrete types are known. The framework includes built-in dialects for arithmetic, control flow, functions, structured loops, and memory operations, and it also includes a lightweight mechanism for adding new domain operations without modifying the core system. To demonstrate JLIR's capabilities, we applied it to automatic Julia for Accelerators (JACC) kernel generation.
Figures & tables
| MLIR concept | MLIR mechanism | JLIR (Julia-native) |
| Operation type | C ++ struct + TableGen | Julia struct + @op DSL |
| Dialect definition | TableGen .td file | @dialect macro |
| Op dispatch | Virtual method table | Julia multiple dispatch |
| Pass interface | C ++ CRTP † abstract base class | Julia AbstractPass + dispatch |
| Front-end parser | Custom MLIR parser / C ++ | Meta.parse + Expr walk |
| Type system | Strictly typed at IR build time | AnyType for JIT-resolved types |
| Pattern | Kernel | Julia Source | JLIR | Generated JACC |
|---|---|---|---|---|
| 1D Parallel-for | rms_norm_scale | Listing 5 | Listing 6 | Listing 13 |
| 2D Parallel-for | jacobi2d | Listing 7 | Listing 8 | Listing 14 |
| 2D Parallel-for | gemm | Listing 9 | Listing 10 | Listing 15 |
| (Mixed 2D+Sequential) | ||||
| 1D Parallel-reduce | rms_norm_reduce | Listing 11 | Listing 12 | Listing 16 |
| Benchmark | Source LOC | Pipeline Time |
|---|---|---|
| GEMM | 10 | ms |
| Jacobi 2D stencil | 8 | ms |
| Black–Scholes | 12 | ms |
| LLaMA-3 (3 kernels) | 52 | ms |
| N | JACC CPU | cuBLAS | JACC GPU | Julia+CUDA |
|---|---|---|---|---|
| [GF/s] | [TF/s] | [TF/s] | [TF/s] | |
| 256 | 0.8 | 0.818 | 0.54 | 0.91 |
| 512 | 5.9 | 4.265 | 1.35 | 1.65 |
| 1,024 | 22.0 | 13.17 | 1.89 | 2.16 |
| 2,048 | 24.0 | 16.83 | 1.28 | 1.96 |
| 4,096 | — | 17.27 | 1.20 | 1.88 |
| N | Serial | CPU thr. | Julia+CUDA | JACC GPU |
|---|---|---|---|---|
| 512 | 17.4 | 0.2 | 758.3 | 499.8 |
| 1024 | 16.2 | 0.9 | 2226.9 | 1353.2 |
| 2048 | 6.0 | 4.5 | 3227.9 | 2401.7 |
| 4096 | — | 17.7 | 3814.0 | 3023.4 |
| N | Serial | CPU thr. | Julia+CUDA | JACC GPU |
|---|---|---|---|---|
| 100 K | 0.4 | 0.04 | 118.1 | 77.0 |
| 1 M | 0.4 | 0.40 | 434.6 | 351.0 |
| 10 M | — | 4.93 | 581.3 | 555.5 |
| Kernel | Serial | JACC CPU | JACC GPU | GPU |
|---|---|---|---|---|
| [ms] | [ms] | [ms] | Speedup | |
| embed_lookup | 0.028 | 38.8 | 0.020 | |
| rms_norm_reduce | 0.003 | 43.3 | 0.069 | |
| rms_norm_scale | 0.0009 | 45.5 | 0.020 | |
| matmul_vec | 96.7 | 38.0 | 1.137 | |
| rope_rotate_q | 0.044 | 52.9 | 0.048 |
| Metric | Before fusion | After fusion |
|---|---|---|
| Ops in loop body | 4 BinOp | 2 ScaleAddOp |
| Arithmetic / iter | ||
| Memory reads / iter |
| Kernel | Ref. | JLIR | Ratio |
|---|---|---|---|
| axpy_dot | 0.40 s | 0.04 s | faster |
| activation_sum | 14.8 s | 13.5 s |
| Component | JLIR | C ++ MLIR |
|---|---|---|
| Dialect op definitions | 26 (.jld) | 41 (.td + header + glue) |
| ScaleAddFusionPass | 24 | 60 |
| DotElemFusionPass | 17 | 40 |
| Lowering + registration | auto | 67 |
| Build system | none (Julia pkg) | CMake + mlir-tblgen + ninja |
| Total (code lines) | 67 | 243 |
| Phase ( 2 kernels) | JLIR ( s) | C ++ MLIR ( s) |
|---|---|---|
| Parse / Build IR | 0 25 | 50 |
| Fusion passes | 10–50 | 520 |
| Lower to arith | 160 | 100 |
| Total | 185 | 620 |
| N | JACC GPU | Reactant GPU | cuBLAS |
|---|---|---|---|
| 256 | 0.58 | 0.37 | 0.82 |
| 512 | 1.38 | 2.81 | 4.27 |
| 1,024 | 1.89 | 9.43 | 13.17 |
| 2,048 | 1.29 | 14.76 | 16.83 |
| 4,096 | 1.20 | 17.31 | 17.27 |
| n | JACC GPU | Reactant GPU | JACC/React. |
|---|---|---|---|
| 100 K | 87 | 25 | |
| 1 M | 371 | 160 | |
| 10 M | 557 | 489 |
| Benchmark | JACC GPU peak | Julia+CUDA peak | cuBLAS peak | JACC/Julia+CUDA |
|---|---|---|---|---|
| Jacobi 2D (eff. BW ‡ ) | 3,023 GB/s | 3,814 GB/s | — | 79% |
| Black–Scholes | 556 GF/s | 581 GF/s | — | 96% |
| GEMM ( ) † | 1,889 GF/s | 2,158 GF/s | 13,168 GF/s | 87% |
| matmul_vec (LLaMA-3) | over serial | — | — | — |
Appendix figures & tables4 assets
Supplementary material from the paper’s appendix.