Skip to content

Commit d013dd6

Browse files
committed
Add pipeline composition RFC
1 parent c8dde7a commit d013dd6

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

docs/rfcs/PipelineComposition.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# RFC: High Level MLIR Pass Pipeline Composition
2+
3+
Ivan Butygin, Renato Golin
4+
5+
## Motivation
6+
7+
TBD use cases from IREE, TPP
8+
9+
## Proposal
10+
11+
We propose a new API to build a dependencies-based graph of pass pipelines.
12+
This API also allows a dynamic control flow between pipelines in graph, controlled by passes inside said pipelines.
13+
14+
## New APIs
15+
16+
### PipelineGraph
17+
```C++
18+
class PipelineGraph {
19+
public:
20+
void registerPipeline(
21+
StringRef name,
22+
ArrayRef<StringRef> predecessors,
23+
ArrayRef<StringRef> successors,
24+
ArrayRef<StringRef> jumpTargets,
25+
std::function<void(OpPassManager &)> populateFunc);
26+
27+
FailureOr<PipelineSchedule> createPipelineSchedule(raw_ostream &errorStream) const;
28+
};
29+
```
30+
`PipelineGraph` is main entry point for this new API.
31+
User is adding pipelines into graph via `registerPipeline` function, each pipeline have the following properties:
32+
* `name` - Name of thepipeline
33+
* `predecessors` - List of names of pipelines which must be run before current pipeline.
34+
* `successors` - List of the names of pipelines which must be run after current pipeline.
35+
* `jumpTargets` - List of the names of pipelines to which we can dynamically jump after current pipeline.
36+
* `populateFunc` - Callback to populate pipeline with passes.
37+
38+
After user populated the graph object they must call `createPipelineSchedule` metdod to compile the resulted graph into runnable schedule.
39+
`createPipelineSchedule` will build a DAG from pipelines dependencies provided by user, and will try to get linear execution order to satify these dependencies.
40+
41+
If two pipelines doesn't have direct and indirect dependencies, order in which they will be executed is not specified, but stable.
42+
43+
Implicit cycles in graph are not allowed and will result in `createPipelineSchedule` returning error. But cycles via `jumpTargets` are allowed (see later).
44+
45+
Empty pipelines (i.e. pipelines without passes, when `populateFunc` does nothing) are allowed and sometimes desirable.
46+
47+
One usecase is using empty pipelines as anchors for other pipelines. Let's say use wants to split hist entire compiler pipeline into 3 stages: `high`, `middle` and `low`.
48+
They can create a two empty pipelines `high-to-middle` and `midlle-to-low` with appropriate dependencies and the use those as anchors to specify at which compiler stage insert stages which do actual work.
49+
50+
### PipelineSchedule
51+
```C++
52+
class PipelineSchedule {
53+
public:
54+
LogicalResult run(Operation *op);
55+
};
56+
```
57+
`PipelineSchedule` object encapsulates compiled pipeline graph. Main method is `LogicalResult run(Operation *op);` which follows existing MLIR `PassManager::run`.
58+
59+
### Dynamic pipeline control flow
60+
61+
If pipeline has `jumpTargets` populated, it can possibly jump to one of those `jumpTargets` after finishing instead of continuing normally.
62+
63+
Jump is controlled via special MLIR attribute `pipeline.jump_target`, attached to top-level op (usually `builtin.module`).
64+
```
65+
builtin.module {pipeline.jump_target="Foo"} {
66+
...
67+
}
68+
```
69+
70+
Passes inside pipeline can set this attribute to indicate they want compilatin flow to jump to the specific point.
71+
After current pipeline is finished, runtime will check if module object have attribute set and if it does, jump to the selected pipeline and clear the attribute.
72+
73+
Setting attribute to the value, which wasnt in `jumpTargets` for the current pipeline will result in error and abort the compilation flow.

0 commit comments

Comments
 (0)