Skip to content

Commit 5cc8c92

Browse files
authored
[NFC][MLIR] Document better linalg morphism (llvm#154313)
1 parent 550dbec commit 5cc8c92

File tree

1 file changed

+82
-54
lines changed

1 file changed

+82
-54
lines changed

mlir/include/mlir/Dialect/Linalg/Passes.td

Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,88 @@
1010
#define MLIR_DIALECT_LINALG_PASSES
1111

1212
include "mlir/Pass/PassBase.td"
13+
include "mlir/IR/Constraints.td"
14+
15+
// ------------------ Begin of "form" conversions
16+
//
17+
// These conversions allow for the transformation of linalg ops between
18+
// different forms. Structured ops can be represented in different forms,
19+
// such as generic ops, category ops, and named ops.
20+
//
21+
// The operation tree is as follows:
22+
// generic category named
23+
// ---------|-------------|----------
24+
// generic ---> contract ----> matmul
25+
// | \-> batch_matmul
26+
// | \-> batch_reduce_matmul
27+
// | \-> ...
28+
// \-> elementwise -> add
29+
// \-> sub
30+
// \-> ...
31+
//
32+
// Morphisms between representations can happen in the following 6 ways:
33+
// generic <---> category <---> named
34+
// \-------------------------/
35+
//
36+
// generic subsumes category which subsumes structured named (not softmax,
37+
// convolutions, etc). The generalization path is guaranteed, the
38+
// specialization path is not.
39+
40+
def LinalgMorphOpsPass : Pass<"linalg-morph-ops"> {
41+
let summary = "Convert linalg ops between forms";
42+
43+
let description = [{
44+
Convert a linalg op from one representation to another equivalent.
45+
For example, a linalg named op `linalg.add` can also be written as an
46+
category op `linalg.elementwise`, and can also be re-written as
47+
a `linalg.generic`, giving the morphism:
48+
49+
named-op <--> category_op (elementwise, contraction, ..) <--> generic
50+
51+
Note that the set of `linalg.generic` subsumes named and category ops
52+
and therefore not all `linalg.genric` can be converted to named or
53+
category op. Similarly, catgory ops subsume named ops.
54+
55+
Note:
56+
Legacy converters:
57+
`--linalg-generalize-named-ops` is the path `named-op --> generic-op`
58+
`--linalg-specialize-generic-ops` is the path `named-op <-- generic-op`
59+
}];
60+
let dependentDialects = ["linalg::LinalgDialect"];
61+
62+
let options = [
63+
// Generalization path is guaranteed.
64+
Option<"namedToCategory", "named-to-category", "bool", /*default=*/"false",
65+
"convert named ops to category op e.g. `linalg.elementwise`">,
66+
Option<"categoryToGeneric", "category-to-generic", "bool", /*default=*/"false",
67+
"convert category ops e.g. `linalg.elementwise` to `linalg.generic`">,
68+
Option<"namedToGeneric", "named-to-generic", "bool", /*default=*/"false",
69+
"convert named ops e.g. `linalg.add` to `linalg.generic`">,
70+
71+
// Specialization path is not guaranteed.
72+
Option<"genericToNamed", "generic-to-named", "bool", /*default=*/"false",
73+
"convert linalg.generic to equivalent named ops"> ];
74+
// TODOs: `generic-to-category`, `category-to-named`
75+
}
76+
77+
def LinalgGeneralizeNamedOpsPass : Pass<"linalg-generalize-named-ops">,
78+
Deprecated<"Use 'linalg-morph-ops' instead."> {
79+
let summary = "Convert named ops into generic ops";
80+
let dependentDialects = ["linalg::LinalgDialect"];
81+
}
82+
83+
def LinalgSpecializeGenericOpsPass : Pass<"linalg-specialize-generic-ops">,
84+
Deprecated<"Use 'linalg-morph-ops' instead."> {
85+
let summary = "Convert generic ops back to named ops";
86+
let dependentDialects = ["linalg::LinalgDialect"];
87+
}
88+
89+
def LinalgNamedOpConversionPass: Pass<"linalg-named-op-conversion"> {
90+
let summary = "Convert from one named linalg op to another.";
91+
let dependentDialects = ["linalg::LinalgDialect", "tensor::TensorDialect"];
92+
}
93+
94+
// ------------------ End of "form" conversions
1395

1496
def ConvertElementwiseToLinalgPass : Pass<"convert-elementwise-to-linalg", ""> {
1597
let summary = "Convert ElementwiseMappable ops to linalg";
@@ -77,67 +159,13 @@ def LinalgElementwiseOpFusionPass : Pass<"linalg-fuse-elementwise-ops"> {
77159
];
78160
}
79161

80-
def LinalgNamedOpConversionPass: Pass<"linalg-named-op-conversion"> {
81-
let summary = "Convert from one named linalg op to another.";
82-
let dependentDialects = ["linalg::LinalgDialect", "tensor::TensorDialect"];
83-
}
84-
85162
def LinalgInlineScalarOperandsPass : Pass<"linalg-inline-scalar-operands"> {
86163
let summary = "Inline scalar operands into linalg generic ops";
87164
let dependentDialects = [
88165
"linalg::LinalgDialect"
89166
];
90167
}
91168

92-
def LinalgMorphOpsPass : Pass<"linalg-morph-ops"> {
93-
let summary = "Convert named op to category ops or generic and vice-versa";
94-
95-
let description = [{
96-
Convert a linalg op from one representation to another equivalent.
97-
For example, a linalg named op `linalg.add` can also be written as an
98-
category op `linalg.elementwise`, and can also be re-written as
99-
a `linalg.generic`, giving the morphism:
100-
101-
named-op <--> category_op (elementwise, contraction, ..) <--> generic
102-
103-
Note that the set of `linalg.generic` subsumes named and category ops
104-
and therefore not all `linalg.genric` can be converted to named or
105-
category op. Similarly, catgory ops subsume named ops.
106-
107-
Note:
108-
Legacy converters:
109-
`--linalg-generalize-named-ops` is the path `named-op --> generic-op`
110-
`--linalg-specialize-generic-ops` is the path `named-op <-- generic-op`
111-
}];
112-
let dependentDialects = ["linalg::LinalgDialect"];
113-
114-
let options = [
115-
// named-op <--> category <--> generic
116-
117-
// Lowering options
118-
Option<"namedToCategory", "named-to-category", "bool", /*default=*/"false",
119-
"convert named ops to category op e.g. `linalg.elementwise`">,
120-
Option<"categoryToGeneric", "category-to-generic", "bool", /*default=*/"false",
121-
"convert category ops e.g. `linalg.elementwise` to `linalg.generic`">,
122-
Option<"namedToGeneric", "named-to-generic", "bool", /*default=*/"false",
123-
"convert named ops e.g. `linalg.add` to `linalg.generic`">,
124-
125-
// Lifting options
126-
// TODOs: `generic-to-category`, `category-to-named`
127-
Option<"genericToNamed", "generic-to-named", "bool", /*default=*/"false",
128-
"convert linalg.generic to equivalent named ops"> ];
129-
}
130-
131-
def LinalgGeneralizeNamedOpsPass : Pass<"linalg-generalize-named-ops"> {
132-
let summary = "Convert named ops into generic ops";
133-
let dependentDialects = ["linalg::LinalgDialect"];
134-
}
135-
136-
def LinalgSpecializeGenericOpsPass : Pass<"linalg-specialize-generic-ops"> {
137-
let summary = "Convert generic ops back to named ops";
138-
let dependentDialects = ["linalg::LinalgDialect"];
139-
}
140-
141169
def LinalgFoldIntoElementwisePass : Pass<"linalg-fold-into-elementwise"> {
142170
let summary = "Fold transform, broadcast and other ops into elementwise";
143171
let dependentDialects = ["linalg::LinalgDialect"];

0 commit comments

Comments
 (0)