22  Transformation

A transformation changes MLIR while preserving a stated semantic contract. The word includes local simplification, loop tiling, bufferization, dialect lowering, inlining, outlining, and target legalization. The important question is not whether the printed IR changed; it is what behavior and invariants the new IR must preserve.

22.1 Start With Preconditions And Postconditions

Every transformation needs an input contract and an output contract. A pattern that folds add x, 0 requires an operation whose arithmetic semantics permit the identity. A bufferization pass requires a defined ownership and aliasing model. A lowering pass requires a target dialect and type conversion that can represent the original values.

The postcondition is equally important. A lowering from a high-level dialect may promise that no illegal operations remain. A canonicalization pass may promise a simpler equivalent form but not a globally minimal program. Stating these boundaries prevents a pass from accidentally becoming responsible for unrelated cleanup.

22.2 Preserve More Than Result Values

Correctness includes types, control flow, effects, symbol references, locations, attributes, regions, and any dialect-specific invariants. Replacing a result with an equivalent value is insufficient if the old operation allocated memory, wrote a resource, carried fast-math flags, or owned a region with required terminators.

For a structured loop, changing an iterated value requires synchronized edits to the loop operands, body block arguments, yield operands, and operation results. For a branch, adding a destination argument requires every predecessor to pass one. These are graph transformations with consistency conditions, not line edits.

22.3 Use The Rewriter At The Right Level

Rewrite patterns use PatternRewriter so insertion, replacement, erasure, and listener notifications stay coherent. Larger passes can use IR rewriters and CFG utilities. Direct list manipulation is appropriate only when the pass owns all resulting bookkeeping, including analysis invalidation and dominance.

Build the replacement before erasing the original. Redirect uses through the rewriter, then erase only when no live results or required nested ownership remain. This ordering keeps diagnostics local and avoids transient dangling IR.

22.4 Legality And Profitability Are Different

A legal transformation preserves semantics. A profitable transformation also improves a chosen goal such as runtime, memory traffic, code size, or later lowering opportunity. Many legal rewrites are not universally profitable: unrolling can expose vectorization but increase code size; fusion can reduce memory traffic but raise register pressure.

Keep these decisions separate. A conversion target decides what must be rewritten to reach a dialect boundary. A cost model decides which of several legal forms is preferable. Confusing them makes pipelines brittle and hard to tune.

22.5 Verification Is The Feedback Loop

Verify after new transformations, minimize failing IR, and test both matching and non-matching cases. A transformation test should show the intended before and after form, plus boundary cases where it must decline to rewrite. Tests for incorrect use counts, dynamic shapes, multiple blocks, unknown effects, and symbol visibility are usually more valuable than another happy-path example.