---
# System prepended metadata

title: 'IRDL: An IR Definition Language for SSA Compilers'
tags: [' Talk', Templates]

---

---
title: "IRDL: An IR Definition Language for SSA Compilers"
tags: Templates, Talk
description: View the slide with "Slide Mode".
---

# IRDL

![](https://i.imgur.com/lXr8EDg.png)

[paper (PDF)](https://dl.acm.org/doi/pdf/10.1145/3519939.3523700), [talk (youtube)](https://www.youtube.com/watch?v=uKXv1Cc_Pgs)

---

### Why?

Too many IRs!

```plaintext

  Swift ----> SIL-IR --------+
                             |
  C/C++ ---------------------+-----> LLVM ----> machine code
                             |
  Rust  ----> HIR ---> MIR --+

```

---

### (You are like little baby, watch this)

```plaintext

  Swift ----> SIL-IR --------+
                             |
  C/C++ ---------------------+-----> LLVM ----> machine code
                             |         ^           ^
  Rust  ----> HIR ---> MIR --+         |           |
                                       |           |
                                       |           |
  Haskell --> Core --> STG ---> Cmm ---+--> NCG ---+

```

---

### On a smaller scale

```plaintext
  LQC ---> Burn Semantics ---> Burn Assembly ---> TAC --+
                                                        |
                                                        |
                                                        |
         Interpreted by Burninator <--- Burn Config <---+
```

---

### Usual Cost of Adding a New IR

* Custom IR
* Parser
* Printer
* Pass manager
* Dead code elimination
* Peephole optimizations

---

### Cost of Adding a New IR (for us)

* Custom IR
* ~~Parser~~
* Printer (probably, debugging)
* ~~Pass manager~~
* Dead code elimination _sometimes_
* Peephole optimizations _sometimes_

---

### Recent development: MLIR

_Multi-Level Intermediate Representation_

<img src="https://i.imgur.com/Ztwh8xX.png" width="600px" />

---

_Only problem you can't solve with more languages is too many languages_

---

### What MLIR Solves

* Custom IR
* ~~Parser~~
* ~~Printer~~
* ~~Pass manager~~
* ~~Dead code elim~~
* ~~Peephole optimizations~~

---

### Problem?

_gotta use C++_

<img src="https://i.imgur.com/U6xhwxN.png" width="400px" />

---

### Existing Solutions

* TableGen - legacy LLVM framework <!-- generic boilerplate, mostly backend -->
* ODS - Operator Definition Specification, used by MLIR, built on TableGen, incomplete

---

### (Proposed) Solution: IRDL

_IRDL: An IR Definition Language for SSA Compilers_

---

### Designed, Principled

* Everything is a Constraint or an Operation
* Types, Aliases => Constraints
* Instructions, Regions, Literals => Operations

---

_A collection of Constraints and Operations is a Dialect_

---

### Example: Complex Math

```c++
Dialect cmath {
  Alias !FloatType = !AnyOf<!f32, !f64>
  Type complex {
    Parameters (elementType: !FloatType)
    Summary "A complex number"
  }
  Operation mul {
    ConstraintVar (!T: !complex<FloatType>)
    Operands (lhs: !T, rhs: !T)
    Results (res: !T)
    Format "$lhs, $rhs : $T.elementType"
    Summary "Multiply two complex numbers"
  }
}
```

---

### Constraint Composition

Usual logical AND/OR/NOT

```c++
Alias NonZero = !And<int32_t, !Not<0 : int32_t>>
Alias Integer = !AnyOf<int32_t, int64_t>
Alias Float = !AnyOf<f32, f64>
Alias Number = !AnyOf<!Integer, !Float>
```

---

### Literals in Constraints

Limited use of literals and enums in constraints

```c++
Enum signedness { Signless, Signed, Unsigned }

Type integer {
  Parameters (bitwidth: uint32_t, signed: signedness)
}

Alias signed_integer = !integer<uint32_t, signedness.Signed>
```

Dependent types, plz

---

### Control Flow

```c++
Operation range_loop_done {}
Operation range_loop {
  Operands (start: !i32, stop: !i32, step: !i32)
  Region body {
    Arguments (i: !i32)
    Terminator range_loop_done
  }
}
```

`Terminator` means body must be a single BB

---

### Control Flow

```c++
Operation conditional_branch {
  Operands (condition: !i1) // 1 bit bools are cute
  Successors (true_branch, false_branch) // basic blocks
}
```

---

### C++ Escape Hatch

```c++
Constraint Size : uint32_t {
  Summary "integer value between 0 and 32"
  CppConstraint "$_self <= 32"
}
Type SizedVec {
  Parameters (typ: !AnyType, size: Size)
}
Operation append_vec {
  ConstraintVars (T: !AnyType)
  Operands (lhs: SizedVec<T, Size>, rhs: SizedVec<T, Size>)
  Results (res: SizedVec<T, Size>)
  CppConstraint "$_self.lhs().size() + 
    $_self.rhs().size() == $_self.res().size()"
}
```

---

### Big Punchline

LLVM MLIR: 942 ops over 28 IR dialects

IRDL can represent 97% of them directly

The remainder require minimal C++

---

### Cool How Do I Use It

_Bad news_: [it's currently a branch in a fork of LLVM](https://github.com/opencompl/llvm-project/pull/1) :cry: 

---

### Links

* [IRDL Paper](https://dl.acm.org/doi/pdf/10.1145/3519939.3523700)
* [PLDI Talk](https://www.youtube.com/watch?v=uKXv1Cc_Pgs), ~16 mins
* [IRDL @ MLIR Open Developer Meeting](https://www.youtube.com/watch?v=SlCXx5IFV40), ~1 hour
* [Older MLIR Paper](https://arxiv.org/pdf/2002.11054.pdf)

---

---

### Different Ways I've Typed IRDL Today

* IRDL
* IDRL
* IDLR
* IRBL