What a fast compiler does¶
Hexir compiles a graph to code that runs. It does not yet compile it to code that runs fast. This section is the catalogue of what would have to change, drawn from the three compilers that have already solved most of it: TVM, IREE and XLA.
It is a reading list and a design space, not a plan. Every entry names the prior art, what it buys, and where it would sit in Hexir. Nothing here is implemented.
The three lineages¶
They disagree about where optimization belongs, and the disagreement is the useful part.
Where the schedule lives |
How a kernel is chosen |
Runtime |
|
|---|---|---|---|
TVM |
explicit, in the IR — a schedule is data you can print and mutate |
searched, per shape, by a cost model |
small graph executor or a VM |
IREE |
in target-specific codegen pipelines, driven by lowering configs |
pattern-matched pipeline plus data tiling and microkernels |
HAL with command buffers and timeline semaphores |
XLA |
implicit — fusion decisions plus an emitter, no user-visible schedule |
fixed emitters, libraries, and autotuned Triton for GEMM |
thunk sequence, optionally captured as a CUDA graph |
Hexir’s hextir dialect already takes TVM’s side: the loop kind attribute
is the schedule, visible in the IR
(see The two IRs). That is the right foundation for most of
the kernel-level entries in this catalogue, and it is why the TVM column is
usually the closest match.
Five levels, and the pages that cover them¶
The levels map onto Hexir’s existing pipeline, so an entry in the catalogue always has an obvious home.
flowchart TB
G["graph level<br/>hexir dialect, tensors"] --> K["kernel level<br/>hextir dialect, loops"]
K --> M["memory<br/>buffers, lifetimes, layout"]
M --> X["execution<br/>command list, streams, HAL"]
L["LLM serving<br/>cuts across all four"]
Graph transforms — fusion, algebraic rewrites, layout, quantization, placement. Whole-tensor reasoning, before any loop exists. Relay/Relax in TVM, Flow in IREE, HLO in XLA.
Kernel transforms — tiling, shared memory, vectorization, tensor cores, and the search that picks their parameters. TIR and MetaSchedule in TVM, LLVMGPU/LLVMCPU codegen in IREE, emitters and the Triton autotuner in XLA.
Memory — allocation planning, liveness, aliasing and in-place update, rematerialization, physical layout.
StorageRewritein TVM, the Stream dialect in IREE,BufferAssignmentin XLA.Execution — asynchrony, launch overhead, command buffers, multi-device transfer. Where a static graph stops paying per-dispatch costs.
LLM serving — paged KV cache, flash attention, weight-only quantization, decode-shaped kernels. Mostly combinations of the above, plus a few things that only make sense for autoregressive models.
Where Hexir stands today¶
Worth stating plainly, because it decides what is worth reading first.
Already present |
Missing entirely |
|---|---|
Placement as an op attribute, pre-lowering |
Any fusion — one op becomes one kernel |
A schedule attribute on every loop ( |
Any use of |
Destination-passing at the kernel boundary |
Shared memory, tiling, tensor cores |
A device image embedded in the artifact |
Buffer reuse; every intermediate is a fresh allocation |
A flat, static command list |
Asynchrony; every dispatch synchronizes |
Constant folding of |
Constant evaluation of subgraphs at compile time |
f32 and f64 |
Anything narrower, and any quantized format |
Reading order, by dependency¶
Most of the catalogue is blocked on a handful of enabling changes. If you are looking for where to start, start with the roots of this graph rather than the leaves.
flowchart LR
F["fusion<br/>graph.md"] --> EP["fused epilogues<br/>bias, activation"]
SM["shared memory<br/>in hextir"] --> T["tiled matmul"]
T --> TC["tensor cores"]
T --> AT["autotuning<br/>kernel.md"]
SM --> FA["flash attention"]
RED["cross-thread<br/>reduction"] --> FA
RED --> GV["split-K GEMV<br/>decode"]
DS["dynamic shapes"] --> CF["control flow<br/>in the VM"]
CF --> KV["paged KV cache"]
DS --> KV
AL["allocation<br/>planning"] --> KV
AS["async + streams"] --> CG["command buffers<br/>CUDA graphs"]
Three of those roots are prerequisites for almost everything on the
LLM page: shared memory in hextir, dynamic shapes in the
artifact format, and control flow in the VM. None of the three is an
optimization by itself, which is exactly why they are easy to defer and
expensive to defer.