Intermediate Representation

The MIND IR is a typed, SSA-based intermediate representation designed for tensor operations and automatic differentiation.

Canonical IR contract: IRModule (control flow included)

mic@1text
  • full IRModule, explicit IDs
  • RFC 0001 fixed-point form
round-trip
mic@3binary
  • magic MIC3, emit with --emit-mic3
  • the trace_hash anchor

Back-compat lineage: Graph dataflow shape (demoted, never the compiled-artifact IR)

mic@2 / mic@2.1text
  • implicit IDs, compact opcodes
  • mic@2.1 adds the MAP (RFC 0014)
lossless
MIC-B v2binary
  • magic MICB, ULEB128 varints
  • Graph shape, binary
mind-model@2model-exchange artifact, byte-preserving renamePending
Solid boxes are the canonical IR contract; dashed boxes are the back-compat lineage. mindc 0.10.x, RFC 0021.

Canonical data shape

IRModule (the SSA structure described below).

Canonical text

mic@1. RFC 0001 fixed-point form; the evidence-chain trace_hash is computed over mic@3 binary (RFC 0016 GAP-1, re-anchored 2026-05-31).

Canonical binary

mic@3 (magic MIC3). Round-trip equivalent to mic@1; carries the evidence MAP epilogue via a 0x4D sentinel.

Legacy dataflow lineage

Back-compat only: mic@2 / mic@2.1 (with MAP). Demoted: never the current or canonical compiled-artifact IR. The rename to mind-model@2, a model-exchange artifact decoupled from the IR contract, is RFC 0021 step 5 (a byte-preserving cross-repo migration, still pending).

Consumer surface

mindc verify <artifact> re-computes the trace_hash over the parsed IR body and reports it; mindc inspect <artifact> decodes a mic@3 binary and pretty-prints the canonical IR body plus a structural summary.

IR Structure

MIND IR uses Static Single Assignment (SSA) form with explicit types:

// Example IR for: y = relu(x @ w)
%0 = mind.const : tensor<2x2xf32> = [[1.0, 2.0], [3.0, 4.0]]
%1 = mind.randn : tensor<2x2xf32>
%2 = mind.matmul(%0, %1) : tensor<2x2xf32>
%3 = mind.relu(%2) : tensor<2x2xf32>
mind.return %3

Core Operations

CategoryOperations
Arithmeticadd, sub, mul, div, neg, pow
Linear Algebramatmul, transpose, dot
Activationsrelu, sigmoid, tanh, softmax, gelu
Reductionssum, mean, max, min, prod
Shapereshape, broadcast, squeeze, unsqueeze
Convolutionconv2d, maxpool2d, avgpool2d

Type Representation

IR types encode both dtype and shape information:

tensor<f32>           // Scalar
tensor<10xf32>        // 1D, static shape
tensor<2x3xf32>       // 2D, static shape
tensor<?x?xf32>       // 2D, dynamic shape
tensor<2x?xf32>       // Mixed static/dynamic

Canonicalization

The IR undergoes canonicalization passes to normalize operations:

  • Dead-code elimination

    Provably dead instructions are pruned.
  • Commutative operand ordering

    add / mul operands are put in a canonical order, so two spellings of the same expression serialise identically.
  • Constant folding, exact-or-skip

    A constant subtree is folded only when the result is representable. On overflow the expression is left unfolded so the runtime wraps it identically; the pass never emits a wrapped or saturated constant. A const-position expression and the identical runtime-position expression therefore always produce the same bytes.

The pass is deliberately conservative and idempotent: it keeps the existing SSA IDs, so running it repeatedly changes nothing. That conservatism is load-bearing: canonicalization output is what trace_hash anchors on.

A further mic@3 → mic@3 middle-end (SCCP-lite const-condition pruning, integer algebraic-identity elimination, region-scoped CSE/GVN) exists but is opt-in and OFF by default, and is a developer flag rather than a shipping profile. With it disabled every emitted byte is byte-identical to the un-optimized IR. Strength reduction, loop-invariant code motion, and register allocation beyond the first deterministic callee-saved slice are not shipped.

OptimizationDefaultShipped status
Canonicalization (DCE, operand ordering, exact-or-skip folding)Always runsShipped
mic@3 → mic@3 middle-end (SCCP-lite, algebraic identities, CSE/GVN)Off; opt-in developer flagOpt-in, not a shipping profile
Strength reduction, loop-invariant code motion, register allocation beyond the first callee-saved sliceNot availableNot shipped

Lowering Pipeline

mindc build lowers through MLIR → LLVM by default (--backend mlir); that path carries floats, tensors and specialty targets (see MLIR Lowering). The opt-in native backend (--backend native) emits native object code directly from the canonical IR (ELF on Linux, Mach-O on macOS, PE/COFF on Windows; x86-64 and ARM64) for the integer and control-flow subset, with no MLIR or LLVM in the loop; it is the normative self-host path. The ladder below is the default MLIR route:

  1. Source (.mind)
    Parse
  2. AST
    Type check
  3. Typed AST
    Lower
  4. MIND IR (High-level)
    Canonicalize
  5. MIND IR (Canonical)what trace_hash anchors on
    Autodiff (if needed)
  6. MIND IR + Gradients
    Lower to MLIR
  7. MLIR Dialects
    Lower to LLVM
  8. LLVM IR
    Codegen
  9. Machine Code
Each arrow names the step that produces the next form. Shaded: the canonical IR and its gradients, before any backend runs.

Learn More

See the full IR specification at mind-spec/ir.md.