# What Is MLIR and How Does It Relate to LLVM: A Technical Deep Dive

> Discover MLIR, LLVM's flexible compiler infrastructure. Learn how MLIR's modular dialects enable advanced compiler front-ends, optimizers, and code generators. Dive deep into this LLVM sub-project.

- Repository: [LLVM/llvm-project](https://github.com/llvm/llvm-project)
- Tags: deep-dive
- Published: 2026-09-11

---

**MLIR (Multi-Level Intermediate Representation) is a sub-project of the LLVM umbrella that provides a flexible, extensible infrastructure for building compiler front-ends, optimizers, and code generators through a modular dialect system.**

MLIR (Multi-Level Intermediate Representation) is a sub-project of the LLVM umbrella that provides a flexible, extensible infrastructure for building compiler front-ends, optimizers, and code generators. Living inside the `llvm/llvm-project` repository under the `mlir/` directory, MLIR introduces a novel approach to intermediate representation through customizable **dialects** that enable representation of code at multiple abstraction levels before lowering to standard LLVM IR.

## Core Concepts: Understanding MLIR Dialects

### What Are Dialects?

MLIR introduces **dialects** as the fundamental unit of modularity. Each dialect defines its own types, operations, and attributes within a self-contained namespace. Unlike traditional single-level IRs, MLIR allows multiple dialects to coexist within the same module, enabling domain-specific representations for tensors, neural networks, affine loops, or hardware-specific intrinsics.

### Multi-Level Abstraction

Dialects can be **stacked** to represent a program at several abstraction levels simultaneously. A typical compilation pipeline might flow from a high-level tensor dialect through a loop-nest dialect, then to the LLVM dialect, and finally to native LLVM IR. This multi-level approach decouples high-level semantic information from low-level machine details, enabling aggressive domain-specific optimizations before hardware-specific code generation.

## Relationship to LLVM: Integration and Shared Infrastructure

### Repository Structure and Build System

MLIR lives inside the same monorepo as LLVM at `llvm-project/mlir` and shares the same CMake and Bazel build infrastructure. The Bazel rules in `utils/bazel/llvm-project-overlay/mlir/BUILD.bazel` demonstrate how MLIR compilation integrates seamlessly with LLVM's build pipeline, ensuring version compatibility and unified tooling.

### The LLVM Dialect and IR Translation

The **LLVM dialect** inside MLIR mirrors LLVM's own IR constructs, including `llvm::Value`, `llvm::Function`, and LLVM IR instructions. The conversion from MLIR's LLVM dialect to actual LLVM IR is performed by conversion passes in [`mlir/lib/Conversion/LLVM/ConvertToLLVMIR.cpp`](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Conversion/LLVM/ConvertToLLVMIR.cpp). This translation layer maps MLIR operations to their LLVM counterparts, enabling a smooth handoff to LLVM's mature optimization and code-generation pipeline.

### Infrastructure Reuse

MLIR reuses LLVM's **pass manager**, **analysis infrastructure**, and **code-generation back-ends**. The implementation in [`mlir/lib/Pass/PassManager.cpp`](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Pass/PassManager.cpp) shows how MLIR integrates with LLVM's existing pass infrastructure. Conversely, LLVM can invoke MLIR passes as part of an LLVM compilation pipeline, enabling mixed-level optimizations where high-level MLIR transformations inform low-level LLVM optimizations.

## End-to-End Workflow: From High-Level to Native Code

A typical MLIR compilation workflow demonstrates the power of multi-level representation:

1. A front-end emits an MLIR module in a high-level dialect (e.g., TensorFlow's HLO or a custom DSL).
2. Transformation passes optimize the module (e.g., fusion, tiling, loop distribution).
3. A **lowering** pass converts operations through progressively lower dialects until reaching the LLVM dialect.
4. The LLVM dialect module is translated to native LLVM IR.
5. LLVM's existing back-ends generate optimized machine code.

Consider this concrete example using a toy dialect:

```mlir
// toy example: a simple function in the toy dialect
func @add(%arg0: i32, %arg1: i32) -> i32 {
  %c = toy.add %arg0, %arg1 : i32
  return %c : i32
}

```

The following commands demonstrate the complete pipeline from MLIR to executable:

```bash

# 1. Run MLIR's optimizer to lower the toy dialect to the LLVM dialect

mlir-opt toy-example.mlir \
  --convert-ttoy-to-llvm \
  -o lowered.mlir

# 2. Translate the LLVM‑dialect MLIR to real LLVM IR

mlir-translate --mlir-to-llvmir lowered.mlir -o program.ll

# 3. Compile the LLVM IR with clang (or llc) to native code

clang -O2 program.ll -o program

```

## Key Implementation Files in the LLVM Repository

Understanding MLIR's integration with LLVM requires examining these critical source files:

- **[`mlir/README.md`](https://github.com/llvm/llvm-project/blob/main/mlir/README.md)** – Provides the project overview and entry points for documentation.
- **[`mlir/include/mlir/IR/Operation.h`](https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/IR/Operation.h)** – Defines the base class for all operations and the dialect-agnostic IR structure.
- **`mlir/include/mlir/Dialect/`** – Contains header files for creating and extending custom dialects.
- **[`mlir/lib/Conversion/LLVM/ConvertToLLVMIR.cpp`](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Conversion/LLVM/ConvertToLLVMIR.cpp)** – Implements the conversion from the MLIR LLVM dialect to real LLVM IR.
- **[`mlir/lib/Pass/PassManager.cpp`](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Pass/PassManager.cpp)** – Demonstrates MLIR's reuse of LLVM's pass management infrastructure.
- **`mlir/tools/mlir-opt/`** – Source directory for the `mlir-opt` driver used for applying and testing passes.
- **`llvm/lib/Target/LLVMIR/`** – LLVM's native code-generation back-ends that ultimately consume the lowered IR.

## Summary

- **MLIR** is a sub-project of LLVM providing multi-level IR infrastructure through an extensible dialect system.
- **Dialects** enable domain-specific representations that stack from high-level abstractions (tensors, loops) down to hardware-specific details.
- The **LLVM dialect** serves as a bridge to standard LLVM IR through conversion passes implemented in `mlir/lib/Conversion/LLVM/`.
- MLIR reuses LLVM's mature infrastructure including the pass manager, analysis framework, and code-generation back-ends.
- The modular architecture enables rapid development of domain-specific compilers while leveraging LLVM's proven optimization and targeting capabilities.

## Frequently Asked Questions

### Is MLIR a replacement for LLVM IR?

No. MLIR complements LLVM by providing higher-level abstraction capabilities. While LLVM IR operates at a low-level SSA form close to machine code, MLIR supports multiple abstraction levels through dialects. The **LLVM dialect** inside MLIR serves as the bridge, allowing gradual lowering from domain-specific representations to traditional LLVM IR that feeds into existing back-ends.

### How does MLIR's pass manager relate to LLVM's?

MLIR directly reuses LLVM's **pass manager** infrastructure. As implemented in [`mlir/lib/Pass/PassManager.cpp`](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Pass/PassManager.cpp), MLIR integrates with LLVM's analysis framework and pass pipeline, enabling mixed-level optimizations where LLVM passes can invoke MLIR transformations and vice versa. This tight integration allows both systems to share optimization strategies and infrastructure.

### What are the primary use cases for MLIR?

MLIR excels at building **domain-specific compilers** for machine learning frameworks (TensorFlow, PyTorch), hardware accelerators (GPUs, TPUs, custom AI chips), and embedded systems. Its dialect mechanism allows compiler developers to represent high-level tensor operations, affine loops, or hardware-specific intrinsics before systematically lowering them through the LLVM dialect to optimized machine code.

### Where is the LLVM dialect conversion implemented?

The conversion from MLIR's LLVM dialect to actual LLVM IR is implemented in [`mlir/lib/Conversion/LLVM/ConvertToLLVMIR.cpp`](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Conversion/LLVM/ConvertToLLVMIR.cpp). This translation pass maps MLIR operations representing LLVM constructs (such as `llvm::Function` and `llvm::Value`) to their counterparts in the LLVM IR representation, enabling seamless handoff to LLVM's code generation pipeline.