Xilinx/mlir-air

Python

151

2,974 commits

updated Oct 18, 2026

See the code

README

MLIR-AIR

An MLIR-based compiler for spatial accelerators. One architecture-independent representation of hierarchical compute and asynchronous data movement, lowered to AMD™ NPUs and GPUs.

Build License Contributors

MLIR logo

📖 Documentation  ·  🚀 Programming Guide  ·  🧩 Compute Model  ·  💡 Examples

The AIR dialect represents a design as a hierarchy of compute regions (air.launch, air.segment, air.herd) over an explicit memory hierarchy (L3, L2, L1). Data movement between levels is an explicit operation rather than a side effect. Designs are written as imperative behavioral programs; the compiler infers the dependencies between operations, represents them as asynchronous tokens, and uses that graph to distribute computation across hardware regions and overlap data movement with compute. The representation is architecture-independent: air-to-aie lowers it to MLIR-AIE for Ryzen™ AI NPUs, and air-to-rocdl lowers it to gpu.launch for AMD™ GPUs.

from air import api as air
from air.api.types import dtype_of
import numpy as np

N, TILE, CORES = 4096, 512, 2
dt = dtype_of(np.float32)

A, B, C = air.tensor([N], dt), air.tensor([N], dt), air.tensor([N], dt)

with air.launch(name="eltwise_add") as launch:

    @launch.body
    def _():
        with air.segment(name="segment_0") as seg:

            @seg.body
            def _():
                l2_a = air.alloc([N], dt, scope=seg.private())     # L2
                l2_b = air.alloc([N], dt, scope=seg.private())
                l2_c = air.alloc([N], dt, scope=seg.private())

                air.ops.load(l2_a, A)                              # L3 -> L2
                air.ops.load(l2_b, B)

                with air.herd([range(0, N, TILE)], name="herd_0", shape=(CORES,)) as h:

                    @h.body
                    def _(tx):
                        i0 = tx * TILE
                        a = air.alloc([TILE], dt, scope=h.private())   # L1
                        b = air.alloc([TILE], dt, scope=h.private())
                        c = air.alloc([TILE], dt, scope=h.private())

                        air.ops.load(a, l2_a[i0 : i0 + TILE])          # L2 -> L1
                        air.ops.load(b, l2_b[i0 : i0 + TILE])
                        c[:] = a[:] + b[:]
                        air.ops.store(c, l2_c[i0 : i0 + TILE])

                air.ops.store(l2_c, C)                             # L2 -> L3

module = launch.build(target="npu2")

Two cores each add four 512-element tiles. aircc lowers the design through MLIR-AIE and the Peano compiler to an xclbin and instruction stream that XRT runs on the NPU.

More about the compiler

air-opt drives the pass pipeline and is the main tool for inspecting a design between stages. aircc is the end-to-end compiler driver. air-runner simulates a design and emits a Chrome trace, so a schedule can be evaluated before hardware is involved.

MLIR-AIR is described in the following paper:

E. Wang, S. Bayliss, A. Bisca, Z. Blair, S. Chowdhary, K. Denolf, J. Fifield, B. Freiberger, E. Hunhoff, P. James-Roxby, J. Lo, J. Melber, S. Neuendorffer, E. Richter, A. Rosti, J. Setoain, G. Singh, E. Taka, P. Vasireddy, Z. Yu, N. Zhang, J. Zhuang. "From Loop Nests to Silicon: Mapping AI Workloads onto AMD NPUs with MLIR-AIR". arXiv:2510.14871, October 2025.

Install

Prebuilt wheels are the recommended path. Each guide also covers a source build.

HostStart here
Ryzen™ AI on LinuxRyzen AI (Linux)
Ryzen™ AI on Windows 11Ryzen AI (Windows)
GPU on LinuxGPU (Linux)

Learn more


Copyright© 2018-2022 Xilinx, Inc.
Copyright© 2022-2026 Advanced Micro Devices, Inc.

Xilinx/mlir-air

Python

151

2,974 commits

updated Oct 18, 2026

See the code

README

MLIR-AIR

An MLIR-based compiler for spatial accelerators. One architecture-independent representation of hierarchical compute and asynchronous data movement, lowered to AMD™ NPUs and GPUs.

Build License Contributors

MLIR logo

📖 Documentation  ·  🚀 Programming Guide  ·  🧩 Compute Model  ·  💡 Examples

The AIR dialect represents a design as a hierarchy of compute regions (air.launch, air.segment, air.herd) over an explicit memory hierarchy (L3, L2, L1). Data movement between levels is an explicit operation rather than a side effect. Designs are written as imperative behavioral programs; the compiler infers the dependencies between operations, represents them as asynchronous tokens, and uses that graph to distribute computation across hardware regions and overlap data movement with compute. The representation is architecture-independent: air-to-aie lowers it to MLIR-AIE for Ryzen™ AI NPUs, and air-to-rocdl lowers it to gpu.launch for AMD™ GPUs.

from air import api as air
from air.api.types import dtype_of
import numpy as np

N, TILE, CORES = 4096, 512, 2
dt = dtype_of(np.float32)

A, B, C = air.tensor([N], dt), air.tensor([N], dt), air.tensor([N], dt)

with air.launch(name="eltwise_add") as launch:

    @launch.body
    def _():
        with air.segment(name="segment_0") as seg:

            @seg.body
            def _():
                l2_a = air.alloc([N], dt, scope=seg.private())     # L2
                l2_b = air.alloc([N], dt, scope=seg.private())
                l2_c = air.alloc([N], dt, scope=seg.private())

                air.ops.load(l2_a, A)                              # L3 -> L2
                air.ops.load(l2_b, B)

                with air.herd([range(0, N, TILE)], name="herd_0", shape=(CORES,)) as h:

                    @h.body
                    def _(tx):
                        i0 = tx * TILE
                        a = air.alloc([TILE], dt, scope=h.private())   # L1
                        b = air.alloc([TILE], dt, scope=h.private())
                        c = air.alloc([TILE], dt, scope=h.private())

                        air.ops.load(a, l2_a[i0 : i0 + TILE])          # L2 -> L1
                        air.ops.load(b, l2_b[i0 : i0 + TILE])
                        c[:] = a[:] + b[:]
                        air.ops.store(c, l2_c[i0 : i0 + TILE])

                air.ops.store(l2_c, C)                             # L2 -> L3

module = launch.build(target="npu2")

Two cores each add four 512-element tiles. aircc lowers the design through MLIR-AIE and the Peano compiler to an xclbin and instruction stream that XRT runs on the NPU.

More about the compiler

air-opt drives the pass pipeline and is the main tool for inspecting a design between stages. aircc is the end-to-end compiler driver. air-runner simulates a design and emits a Chrome trace, so a schedule can be evaluated before hardware is involved.

MLIR-AIR is described in the following paper:

E. Wang, S. Bayliss, A. Bisca, Z. Blair, S. Chowdhary, K. Denolf, J. Fifield, B. Freiberger, E. Hunhoff, P. James-Roxby, J. Lo, J. Melber, S. Neuendorffer, E. Richter, A. Rosti, J. Setoain, G. Singh, E. Taka, P. Vasireddy, Z. Yu, N. Zhang, J. Zhuang. "From Loop Nests to Silicon: Mapping AI Workloads onto AMD NPUs with MLIR-AIR". arXiv:2510.14871, October 2025.

Install

Prebuilt wheels are the recommended path. Each guide also covers a source build.

HostStart here
Ryzen™ AI on LinuxRyzen AI (Linux)
Ryzen™ AI on Windows 11Ryzen AI (Windows)
GPU on LinuxGPU (Linux)

Learn more


Copyright© 2018-2022 Xilinx, Inc.
Copyright© 2022-2026 Advanced Micro Devices, Inc.

Significant stargazers

Jiuyang Liu

1,046 followers · starred Jul 2023

Shouyu

13 followers · starred Feb 2025

Kai Sasaki

408 followers · starred Feb 2024

scturtle

90 followers · starred May 2023