-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[NFC][MLIR] Document better linalg morphism #154313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-mlir-linalg Author: Renato Golin (rengolin) ChangesFull diff: https://github.com/llvm/llvm-project/pull/154313.diff 1 Files Affected:
diff --git a/mlir/include/mlir/Dialect/Linalg/Passes.td b/mlir/include/mlir/Dialect/Linalg/Passes.td
index f23662930accc..5204ee146a412 100644
--- a/mlir/include/mlir/Dialect/Linalg/Passes.td
+++ b/mlir/include/mlir/Dialect/Linalg/Passes.td
@@ -11,6 +11,78 @@
include "mlir/Pass/PassBase.td"
+// ------------------ Begin of "form" conversions
+//
+// These conversions allow for the transformation of linalg ops between different forms.
+// Structured ops can be represented in different forms, such as named ops, category ops, and generic ops.
+//
+// The operation tree is as follows:
+// generic category named
+// ---------|-------------|----------
+// generic ---> contract ----> matmul
+// | \-> batch_matmul
+// | \-> batch_reduce_matmul
+// | \-> ...
+// \-> elementwise -> add
+// \-> sub
+// \-> ...
+//
+// Morphisms between representations can happen in the following 6 ways:
+// generic <---> category <---> named
+// \-------------------------/
+//
+// generic subsumes category which subsumes named.
+// The generalization path is guaranteed, the specialization path is not.
+
+def LinalgMorphOpsPass : Pass<"linalg-morph-ops"> {
+ let summary = "Convert linalg ops between forms";
+
+ let description = [{
+ Convert a linalg op from one representation to another equivalent.
+ For example, a linalg named op `linalg.add` can also be written as an
+ category op `linalg.elementwise`, and can also be re-written as
+ a `linalg.generic`, giving the morphism:
+
+ named-op <--> category_op (elementwise, contraction, ..) <--> generic
+
+ Note that the set of `linalg.generic` subsumes named and category ops
+ and therefore not all `linalg.genric` can be converted to named or
+ category op. Similarly, catgory ops subsume named ops.
+
+ Note:
+ Legacy converters:
+ `--linalg-generalize-named-ops` is the path `named-op --> generic-op`
+ `--linalg-specialize-generic-ops` is the path `named-op <-- generic-op`
+ }];
+ let dependentDialects = ["linalg::LinalgDialect"];
+
+ let options = [
+ // Generalization path is guaranteed.
+ Option<"namedToCategory", "named-to-category", "bool", /*default=*/"false",
+ "convert named ops to category op e.g. `linalg.elementwise`">,
+ Option<"categoryToGeneric", "category-to-generic", "bool", /*default=*/"false",
+ "convert category ops e.g. `linalg.elementwise` to `linalg.generic`">,
+ Option<"namedToGeneric", "named-to-generic", "bool", /*default=*/"false",
+ "convert named ops e.g. `linalg.add` to `linalg.generic`">,
+
+ // Specialization path is not guaranteed.
+ Option<"genericToNamed", "generic-to-named", "bool", /*default=*/"false",
+ "convert linalg.generic to equivalent named ops"> ];
+ // TODOs: `generic-to-category`, `category-to-named`
+}
+
+def LinalgGeneralizeNamedOpsPass : Pass<"linalg-generalize-named-ops">, Deprecated<"Use 'linalg-morph-ops' instead."> {
+ let summary = "Convert named ops into generic ops";
+ let dependentDialects = ["linalg::LinalgDialect"];
+}
+
+def LinalgSpecializeGenericOpsPass : Pass<"linalg-specialize-generic-ops">, Deprecated<"Use 'linalg-morph-ops' instead."> {
+ let summary = "Convert generic ops back to named ops";
+ let dependentDialects = ["linalg::LinalgDialect"];
+}
+
+// ------------------ End of "form" conversions
+
def ConvertElementwiseToLinalgPass : Pass<"convert-elementwise-to-linalg", ""> {
let summary = "Convert ElementwiseMappable ops to linalg";
let description = [{
@@ -89,55 +161,6 @@ def LinalgInlineScalarOperandsPass : Pass<"linalg-inline-scalar-operands"> {
];
}
-def LinalgMorphOpsPass : Pass<"linalg-morph-ops"> {
- let summary = "Convert named op to category ops or generic and vice-versa";
-
- let description = [{
- Convert a linalg op from one representation to another equivalent.
- For example, a linalg named op `linalg.add` can also be written as an
- category op `linalg.elementwise`, and can also be re-written as
- a `linalg.generic`, giving the morphism:
-
- named-op <--> category_op (elementwise, contraction, ..) <--> generic
-
- Note that the set of `linalg.generic` subsumes named and category ops
- and therefore not all `linalg.genric` can be converted to named or
- category op. Similarly, catgory ops subsume named ops.
-
- Note:
- Legacy converters:
- `--linalg-generalize-named-ops` is the path `named-op --> generic-op`
- `--linalg-specialize-generic-ops` is the path `named-op <-- generic-op`
- }];
- let dependentDialects = ["linalg::LinalgDialect"];
-
- let options = [
- // named-op <--> category <--> generic
-
- // Lowering options
- Option<"namedToCategory", "named-to-category", "bool", /*default=*/"false",
- "convert named ops to category op e.g. `linalg.elementwise`">,
- Option<"categoryToGeneric", "category-to-generic", "bool", /*default=*/"false",
- "convert category ops e.g. `linalg.elementwise` to `linalg.generic`">,
- Option<"namedToGeneric", "named-to-generic", "bool", /*default=*/"false",
- "convert named ops e.g. `linalg.add` to `linalg.generic`">,
-
- // Lifting options
- // TODOs: `generic-to-category`, `category-to-named`
- Option<"genericToNamed", "generic-to-named", "bool", /*default=*/"false",
- "convert linalg.generic to equivalent named ops"> ];
-}
-
-def LinalgGeneralizeNamedOpsPass : Pass<"linalg-generalize-named-ops"> {
- let summary = "Convert named ops into generic ops";
- let dependentDialects = ["linalg::LinalgDialect"];
-}
-
-def LinalgSpecializeGenericOpsPass : Pass<"linalg-specialize-generic-ops"> {
- let summary = "Convert generic ops back to named ops";
- let dependentDialects = ["linalg::LinalgDialect"];
-}
-
def LinalgFoldIntoElementwisePass : Pass<"linalg-fold-into-elementwise"> {
let summary = "Fold transform, broadcast and other ops into elementwise";
let dependentDialects = ["linalg::LinalgDialect"];
|
|
@llvm/pr-subscribers-mlir Author: Renato Golin (rengolin) ChangesFull diff: https://github.com/llvm/llvm-project/pull/154313.diff 1 Files Affected:
diff --git a/mlir/include/mlir/Dialect/Linalg/Passes.td b/mlir/include/mlir/Dialect/Linalg/Passes.td
index f23662930accc..5204ee146a412 100644
--- a/mlir/include/mlir/Dialect/Linalg/Passes.td
+++ b/mlir/include/mlir/Dialect/Linalg/Passes.td
@@ -11,6 +11,78 @@
include "mlir/Pass/PassBase.td"
+// ------------------ Begin of "form" conversions
+//
+// These conversions allow for the transformation of linalg ops between different forms.
+// Structured ops can be represented in different forms, such as named ops, category ops, and generic ops.
+//
+// The operation tree is as follows:
+// generic category named
+// ---------|-------------|----------
+// generic ---> contract ----> matmul
+// | \-> batch_matmul
+// | \-> batch_reduce_matmul
+// | \-> ...
+// \-> elementwise -> add
+// \-> sub
+// \-> ...
+//
+// Morphisms between representations can happen in the following 6 ways:
+// generic <---> category <---> named
+// \-------------------------/
+//
+// generic subsumes category which subsumes named.
+// The generalization path is guaranteed, the specialization path is not.
+
+def LinalgMorphOpsPass : Pass<"linalg-morph-ops"> {
+ let summary = "Convert linalg ops between forms";
+
+ let description = [{
+ Convert a linalg op from one representation to another equivalent.
+ For example, a linalg named op `linalg.add` can also be written as an
+ category op `linalg.elementwise`, and can also be re-written as
+ a `linalg.generic`, giving the morphism:
+
+ named-op <--> category_op (elementwise, contraction, ..) <--> generic
+
+ Note that the set of `linalg.generic` subsumes named and category ops
+ and therefore not all `linalg.genric` can be converted to named or
+ category op. Similarly, catgory ops subsume named ops.
+
+ Note:
+ Legacy converters:
+ `--linalg-generalize-named-ops` is the path `named-op --> generic-op`
+ `--linalg-specialize-generic-ops` is the path `named-op <-- generic-op`
+ }];
+ let dependentDialects = ["linalg::LinalgDialect"];
+
+ let options = [
+ // Generalization path is guaranteed.
+ Option<"namedToCategory", "named-to-category", "bool", /*default=*/"false",
+ "convert named ops to category op e.g. `linalg.elementwise`">,
+ Option<"categoryToGeneric", "category-to-generic", "bool", /*default=*/"false",
+ "convert category ops e.g. `linalg.elementwise` to `linalg.generic`">,
+ Option<"namedToGeneric", "named-to-generic", "bool", /*default=*/"false",
+ "convert named ops e.g. `linalg.add` to `linalg.generic`">,
+
+ // Specialization path is not guaranteed.
+ Option<"genericToNamed", "generic-to-named", "bool", /*default=*/"false",
+ "convert linalg.generic to equivalent named ops"> ];
+ // TODOs: `generic-to-category`, `category-to-named`
+}
+
+def LinalgGeneralizeNamedOpsPass : Pass<"linalg-generalize-named-ops">, Deprecated<"Use 'linalg-morph-ops' instead."> {
+ let summary = "Convert named ops into generic ops";
+ let dependentDialects = ["linalg::LinalgDialect"];
+}
+
+def LinalgSpecializeGenericOpsPass : Pass<"linalg-specialize-generic-ops">, Deprecated<"Use 'linalg-morph-ops' instead."> {
+ let summary = "Convert generic ops back to named ops";
+ let dependentDialects = ["linalg::LinalgDialect"];
+}
+
+// ------------------ End of "form" conversions
+
def ConvertElementwiseToLinalgPass : Pass<"convert-elementwise-to-linalg", ""> {
let summary = "Convert ElementwiseMappable ops to linalg";
let description = [{
@@ -89,55 +161,6 @@ def LinalgInlineScalarOperandsPass : Pass<"linalg-inline-scalar-operands"> {
];
}
-def LinalgMorphOpsPass : Pass<"linalg-morph-ops"> {
- let summary = "Convert named op to category ops or generic and vice-versa";
-
- let description = [{
- Convert a linalg op from one representation to another equivalent.
- For example, a linalg named op `linalg.add` can also be written as an
- category op `linalg.elementwise`, and can also be re-written as
- a `linalg.generic`, giving the morphism:
-
- named-op <--> category_op (elementwise, contraction, ..) <--> generic
-
- Note that the set of `linalg.generic` subsumes named and category ops
- and therefore not all `linalg.genric` can be converted to named or
- category op. Similarly, catgory ops subsume named ops.
-
- Note:
- Legacy converters:
- `--linalg-generalize-named-ops` is the path `named-op --> generic-op`
- `--linalg-specialize-generic-ops` is the path `named-op <-- generic-op`
- }];
- let dependentDialects = ["linalg::LinalgDialect"];
-
- let options = [
- // named-op <--> category <--> generic
-
- // Lowering options
- Option<"namedToCategory", "named-to-category", "bool", /*default=*/"false",
- "convert named ops to category op e.g. `linalg.elementwise`">,
- Option<"categoryToGeneric", "category-to-generic", "bool", /*default=*/"false",
- "convert category ops e.g. `linalg.elementwise` to `linalg.generic`">,
- Option<"namedToGeneric", "named-to-generic", "bool", /*default=*/"false",
- "convert named ops e.g. `linalg.add` to `linalg.generic`">,
-
- // Lifting options
- // TODOs: `generic-to-category`, `category-to-named`
- Option<"genericToNamed", "generic-to-named", "bool", /*default=*/"false",
- "convert linalg.generic to equivalent named ops"> ];
-}
-
-def LinalgGeneralizeNamedOpsPass : Pass<"linalg-generalize-named-ops"> {
- let summary = "Convert named ops into generic ops";
- let dependentDialects = ["linalg::LinalgDialect"];
-}
-
-def LinalgSpecializeGenericOpsPass : Pass<"linalg-specialize-generic-ops"> {
- let summary = "Convert generic ops back to named ops";
- let dependentDialects = ["linalg::LinalgDialect"];
-}
-
def LinalgFoldIntoElementwisePass : Pass<"linalg-fold-into-elementwise"> {
let summary = "Fold transform, broadcast and other ops into elementwise";
let dependentDialects = ["linalg::LinalgDialect"];
|
|
I will just point out that in the context of just linalg's structured ops, the term "category" could/should be "einsum" - that's the kind of operation modelled by The term "category" seems more helpful in the context of there being a "category" (i.e. a tree) of structured ops and there being a distinct "category" (i.e. tree, though potentially a trivial one) for convolution ops. Wouldn't want to be missing the forest due to thinking we are seeing just a single tree 😉 |
|
Let's see what people think about this in the RFC, and we can rename things accordingly. |
|
I don't mind the definition: "Category" is the name for the ops that have "children" and are themselves a sub-tree. As far as I can tell though, non of the other groups of ops will have |
Documentation, amirite? 🤷 😆 Let's decide nomenclature after we agree on semantics. (then fix the docs) |
No description provided.