numbacc: a Numba/MLIR backend for SPy
What it is¶
numba/numbacc is a next-generation AOT compiler
project from the Numba team that uses SPy directly as its frontend — not a hypothetical
integration, a working one. Its Makefile vendors spylang/spy as a pinned dependency,
and nbcc/frontend/frontend.py reads SPy’s own typed AST objects (W_ASTFunc, SPyVM,
FQN) straight out of the SPy VM, in-memory — no text serialization or re-parsing
involved.
The pipeline¶
SPy (typed AST) → sealir (RVSDG representation) → egglog-based e-graph optimization → MLIR → LLVM → native code,
plus a separate cutile_backend targeting NVIDIA’s real cuda-tile MLIR dialect for
GPU.
A few notable pieces:
sealir/RVSDG is a separatenumba-org repo — a structured dataflow IR purpose-built for this project. It’s unrelated to the classicnumba.core.irused by Numba’s JIT.egglog-based equality saturation runs before MLIR lowering — a genuinely current compiler technique (e-graph rewriting), not something either SPy’s C backend or a hand-rolled Codon backend would get.MLIR’s
linalg+transformdialects handle tensor/array tiling and fusion — mature, widely-adopted infrastructure across the ML compiler ecosystem (IREE, torch-mlir, and others), a stronger foundation than a bespoke fusion pass would be.
Not just a backend¶
numbacc also ships its own SPy-source library, mlir_tensor_lib.spy, defining a
TensorType that splices literal MLIR ops (linalg.add, tensor.dim) directly into
compiled output, using @blue-phase metaprogramming rather than compiler changes. This
is separate from NumSPy’s existing array[DTYPE, NDIM] — a second, MLIR-native array
abstraction, not (yet) unified with NumSPy’s.
Separately, examples/e2e/*.spy (loops, @struct classes, if/else) show a genuine
general-purpose backend for SPy’s core language — no MLIR-specific syntax, ordinary SPy
compiled straight through.
Caveats¶
Early-stage: sparse README, few stars/watchers — a research prototype, not a supported product.
Pinned to an old SPy commit rather than tracking
main.A heavy toolchain: custom conda recipes for cross-compiled MLIR Python bindings, two separate MLIR version environments (LLVM 20/21), plus
egglog,sealir, andcuda-tileas further dependencies.Whether NumSPy and
mlir_tensor_lib’sTensorTypeare meant to converge eventually, or stay separate long-term, isn’t answered by the code.