Skip to content

Pipeline

Renato Golin edited this page Mar 16, 2026 · 6 revisions

The Driver class helps users (direct or via Workload) to run passes and schedules on on or more payload modules. It owns the module and the pipeline and provides some guarantees (no interference on module, consistent pipeline stage application). This way, the only errors will be due to pass ordering, and not infrastructure mess up.

Pipeline Testing

One can already use --stage option to pass multiple stages to a pipeline, as seen here. This is good for testing, but not so much building complex pipelines.

Upstream Passes

You can use an upstream pass syntax as a stage, for example:

  • "canonicalize"
  • "builtin.module(affine-loop-fusion)"
  • "func.func(llvm-request-c-wrappers)"

Bundles

The lighthouse.pipeline module has some bundles defined.

You can just pass their names as a stage:

  • "BufferizationBundle"
  • "CleanupBundle"
  • etc.

It's unclear how generic those bundles will be and how to properly define and use them. In the future, it'd be better if those bundles are defined outside of the pipeline module, so that users can easily override. See below for such a proposal.

Transforms

Passing a filename as a stage triggers a TransformStage creation, for example: --stage=my-transform.mlir. This is helpful for testing but quite limited. A file that does not yield a schedule will emit an error, so it's not unsafe, just unhelpful.

In the future, it'd be nice to accept two types of files, mlir and py, and build the schedule accordingly. See the TODO in the code.

There are two ways of passing multiple schedules to the pipeline:

  1. Each schedule as a separate stage: --stage=sched1.mlir --stage=sched2.mlir. This works if the schedules are independent and expecting to be executed in that order (with potentially other stages in between). But it does not allow composition or decision making (if GPU go left, if CPU go right).
  2. One mega-schedule as a single stage: --stage=mega-sched.mlir. Such "mega schedule" would include other schedules and allow decision making, trial-and-error, multi-versioning and other approaches. Transform schedules are not yet that powerful, and building such infrastructure can be quite complex with today's level of support.

Pipeline Descriptors

Using a YAML file as a description of a pipeline could allow for more complex pipeline building.

For example:

main-pipeline.yaml:
  Pipeline:
    # Include other YAML files, intermixed with calling other stage types
    # This would deprecate the need for bundles.
    include: high-level.yaml
    pass: canoncalize
    include: mid-level.yaml
    pass: canoncalize
    include: lower-to-llvm.yaml
    pass: canoncalize

high-level.yaml:
  Pipeline:
    # Stages can have arguments, needs user input when loading yaml
    pass: linalg-generalize-named-ops
    pass: linalg-tile-and-fuse-tensor-ops{tile-sizes=$tile_sizes} # This goes as plain text
    transform: linalg-reorder-loops.mlir{access_pattern=$order} # This can go into transform.tune.knob
    pass: eliminate-empty-tensors

mid-level.yaml:
  Pipeline:
    # A mega-schedule (that includes other schedules)
    transform: my-cpu-mega-sched.py{target=$target l1cache=$l1d ext=$list}
    pass: canonicalize

lower-to-llvm.yaml:
  Pipeline:
    pass: convert-scf-to-cf
    pass: convert-to-llvm
    pass: reconcile-unrealized-casts

Clone this wiki locally