[Mlir-commits] [mlir] [NFC][MLIR] Document better linalg morphism (PR #154313)
Renato Golin
llvmlistbot at llvm.org
Tue Aug 19 08:53:45 PDT 2025
https://github.com/rengolin updated https://github.com/llvm/llvm-project/pull/154313
>From 8225a8abe0e3b8e02ef5ad30cb526d14e41b1f36 Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Tue, 19 Aug 2025 12:52:50 +0100
Subject: [PATCH 1/2] [NFC][MLIR] Document better linalg morphism
---
mlir/include/mlir/Dialect/Linalg/Passes.td | 132 ++++++++++++---------
1 file changed, 78 insertions(+), 54 deletions(-)
diff --git a/mlir/include/mlir/Dialect/Linalg/Passes.td b/mlir/include/mlir/Dialect/Linalg/Passes.td
index f23662930accc..7eb4daf00a04e 100644
--- a/mlir/include/mlir/Dialect/Linalg/Passes.td
+++ b/mlir/include/mlir/Dialect/Linalg/Passes.td
@@ -10,6 +10,84 @@
#define MLIR_DIALECT_LINALG_PASSES
include "mlir/Pass/PassBase.td"
+include "mlir/IR/Constraints.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"];
+}
+
+def LinalgNamedOpConversionPass: Pass<"linalg-named-op-conversion"> {
+ let summary = "Convert from one named linalg op to another.";
+ let dependentDialects = ["linalg::LinalgDialect", "tensor::TensorDialect"];
+}
+
+// ------------------ End of "form" conversions
def ConvertElementwiseToLinalgPass : Pass<"convert-elementwise-to-linalg", ""> {
let summary = "Convert ElementwiseMappable ops to linalg";
@@ -77,11 +155,6 @@ def LinalgElementwiseOpFusionPass : Pass<"linalg-fuse-elementwise-ops"> {
];
}
-def LinalgNamedOpConversionPass: Pass<"linalg-named-op-conversion"> {
- let summary = "Convert from one named linalg op to another.";
- let dependentDialects = ["linalg::LinalgDialect", "tensor::TensorDialect"];
-}
-
def LinalgInlineScalarOperandsPass : Pass<"linalg-inline-scalar-operands"> {
let summary = "Inline scalar operands into linalg generic ops";
let dependentDialects = [
@@ -89,55 +162,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"];
>From 57977cedc3e10c5d942eab54f365063a12dd378b Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Tue, 19 Aug 2025 16:53:32 +0100
Subject: [PATCH 2/2] address comments
---
mlir/include/mlir/Dialect/Linalg/Passes.td | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/mlir/include/mlir/Dialect/Linalg/Passes.td b/mlir/include/mlir/Dialect/Linalg/Passes.td
index 7eb4daf00a04e..0b2c9c94dc73d 100644
--- a/mlir/include/mlir/Dialect/Linalg/Passes.td
+++ b/mlir/include/mlir/Dialect/Linalg/Passes.td
@@ -14,8 +14,9 @@ include "mlir/IR/Constraints.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.
+// These conversions allow for the transformation of linalg ops between
+// different forms. Structured ops can be represented in different forms,
+// such as generic ops, category ops, and named ops.
//
// The operation tree is as follows:
// generic category named
@@ -32,8 +33,9 @@ include "mlir/IR/Constraints.td"
// generic <---> category <---> named
// \-------------------------/
//
-// generic subsumes category which subsumes named.
-// The generalization path is guaranteed, the specialization path is not.
+// generic subsumes category which subsumes structured named (not softmax,
+// convolutions, etc). The generalization path is guaranteed, the
+// specialization path is not.
def LinalgMorphOpsPass : Pass<"linalg-morph-ops"> {
let summary = "Convert linalg ops between forms";
@@ -72,12 +74,14 @@ def LinalgMorphOpsPass : Pass<"linalg-morph-ops"> {
// TODOs: `generic-to-category`, `category-to-named`
}
-def LinalgGeneralizeNamedOpsPass : Pass<"linalg-generalize-named-ops">, Deprecated<"Use 'linalg-morph-ops' instead."> {
+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."> {
+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"];
}
More information about the Mlir-commits
mailing list