[Mlir-commits] [mlir] [MLIR][Linalg][Docs] Add forms to Linalg rationale docs (PR #156859)
Renato Golin
llvmlistbot at llvm.org
Tue Oct 7 03:38:15 PDT 2025
https://github.com/rengolin updated https://github.com/llvm/llvm-project/pull/156859
>From ea798446f28d6fbff73e2d5b0f408b63c6efd8e5 Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Wed, 3 Sep 2025 11:27:25 +0100
Subject: [PATCH 1/8] [MLIR][Linalg][Docs] Add forms to Linalg rationale docs
As discussed in:
* https://discourse.llvm.org/t/rfc-linalg-forms/87994/
* https://discourse.llvm.org/t/rfc-extend-linalg-elemwise-named-ops-semantics/83927
* https://discourse.llvm.org/t/rfc-op-explosion-in-linalg/82863/1
* https://discourse.llvm.org/t/rfc-mlir-linalg-operation-tree/83586
---
mlir/docs/Rationale/RationaleLinalgDialect.md | 87 ++++++++++++++++---
1 file changed, 73 insertions(+), 14 deletions(-)
diff --git a/mlir/docs/Rationale/RationaleLinalgDialect.md b/mlir/docs/Rationale/RationaleLinalgDialect.md
index 8975b0a7d515e..4426d3fb9b3c2 100644
--- a/mlir/docs/Rationale/RationaleLinalgDialect.md
+++ b/mlir/docs/Rationale/RationaleLinalgDialect.md
@@ -411,6 +411,20 @@ and is used as a lowering target for Linalg, enabling further transformations
and combination of semantically-loaded and lower-level inputs. As such, Linalg
is intended to complement Affine rather than replace it.
+### Summary of Existing Alternatives a Picture<a name="observationssummary"></a>
+Lastly, we summarize our observations of lessons from [Prior
+Art](#prior-art)---when viewed under the lense of our [Core Guiding
+Principles](#guiding_principles)---with the following picture.
+
+<img width="1200" alt="MLIR Codegen Flow"
+src="https://user-images.githubusercontent.com/10148468/73613904-2f720a00-45c8-11ea-8265-1c856c02525b.png">
+
+This figure is not meant to be perfectly accurate but a rough map of how we view
+the distribution of structural information in existing systems, from a
+codegen-friendly angle. Unsurprisingly, the
+[Linalg Dialect](../Dialects/Linalg/_index.md) and its future evolutions aspire
+to a position in the top-right of this map.
+
## Core Guiding Principles<a name="guiding_principles"></a>
### Transformations and Simplicity First<a name="transformations_first"></a>
@@ -506,6 +520,65 @@ potential by introducing lower-level IR ops and *smaller* Linalg ops.
This gradually reduces the potential, all the way to Loops + VectorOps
and LLVMIR.
+### Interchangeability of Forms<a name="forms"></a>
+
+Linalg's various forms (named, generic) also carry information, and that
+information should be preserved as much as possible during the progressive
+lowering. A `matmul` operation is a special case of a `contract` operation,
+which in turn is a special case of `generic` operation. Transformations on
+the more special forms should not be converted to the more generic ones
+unnecessarily, in the same way that they should not be broken down into
+loops + arithmetic if they can still be represented as a Linalg op.
+
+#### Generic, Category, Named<a name="generic_category_named"></a>
+
+The core Linalg operation tree has three forms:
+* **Generic:** Represented by `linalg.generic` and can encode all perfectly-nested
+loop operations.
+* **Category:** Represented by `linalg.contract` and `linalg.elementwise`,
+which are special (einsum) forms of the `generic` operation.
+* **Named:** All _named_ forms that can lower to either _category_ or
+_generic_ forms. For example, `linalg.matmul`, `linalg.add`, etc.
+
+Unlike lowering to loops, the different Linalg forms that are derived from
+`linalg.generic` are *equivalent*. It should always be possible to convert
+a named operation into a generic and back to named, if the semantics is
+preserved. The various forms in the Linalg dialect are meant to facilitate
+pattern matching (single operations or DAGs) and to be able to consider
+different forms as *canonical* for different transforms.
+
+#### Special Operations<a name="special_ops"></a>
+
+Not all Linalg operations represent perfectly nested loops, and therefore
+cannot be represented as a `linalg.generic`. There are two kinds of Linalg
+operations that fall into this category:
+* **Composite:** Operations that compose multiple Linalg operations, for
+example `linalg.softmax`. These can be converted to a DAG of Linalg operations
+(in any form).
+* **Special Named:** Operations that are usually matched against library calls
+or special lowering, but can only be lowered to a combination of Linalg and
+non-Linalg operations, for example `linalg.*conv*`, `linalg.winograd*`,
+`linalg.pooling*`, etc.
+
+#### Canonical Forms<a name="canonical_forms"></a>
+
+With multiple (often exchangeable) forms, and with transformation simplicity
+in mind, compilers should aim for reducing matching and replacing complexity
+as much as possible. When matching a single operation with a complex pattern,
+having all the information from a `generic` is useful to iteratively match
+different patterns in turn. However, when assembling a DAG of operations to
+form a pattern, it's much simpler to match against named operations (like
+`max` + `div` + `reduce` + `broadcast`) than their generic counterparts.
+
+This is where the interchangeability of forms comes in handy. Linalg has the
+ability to specialize and generalize in order to convert the IR to a form that
+is easier for a particular type of transform. With forms being semantically
+equivalent, one can convert back-and-forth throughout the various transforms
+to match the needs of each transform. For that particular transform, such
+form can be considered _canonical_ and therefore "expected" for the pattern
+to _match_. This reduces complexity of pattern matchers and simplifies compiler
+pipelines.
+
### Composable and Declarative Transformations<a name="declarative_transformations"></a>
Complex and impactful transformations need not be hard to manipulate, write or
maintain. Mixing XLA-style high-level op semantics knowledge with generic
@@ -606,17 +679,3 @@ Considering the *potential* described during the discussion on
transformation would dictate that the potential remains constant.
In contrast, Linalg advocates for ***monotonicity*** under
transformations.
-
-### Summary of Existing Alternatives a Picture<a name="observationssummary"></a>
-Lastly, we summarize our observations of lessons from [Prior
-Art](#prior-art)---when viewed under the lense of our [Core Guiding
-Principles](#guiding_principles)---with the following picture.
-
-<img width="1200" alt="MLIR Codegen Flow"
-src="https://user-images.githubusercontent.com/10148468/73613904-2f720a00-45c8-11ea-8265-1c856c02525b.png">
-
-This figure is not meant to be perfectly accurate but a rough map of how we view
-the distribution of structural information in existing systems, from a
-codegen-friendly angle. Unsurprisingly, the
-[Linalg Dialect](../Dialects/Linalg/_index.md) and its future evolutions aspire
-to a position in the top-right of this map.
>From 7ea9ca0617e09090cfc3f07b99cc1ccc1646b3d6 Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Thu, 4 Sep 2025 16:31:29 +0100
Subject: [PATCH 2/8] revert unrelated change
---
mlir/docs/Rationale/RationaleLinalgDialect.md | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/mlir/docs/Rationale/RationaleLinalgDialect.md b/mlir/docs/Rationale/RationaleLinalgDialect.md
index 4426d3fb9b3c2..9f85921c43b81 100644
--- a/mlir/docs/Rationale/RationaleLinalgDialect.md
+++ b/mlir/docs/Rationale/RationaleLinalgDialect.md
@@ -411,20 +411,6 @@ and is used as a lowering target for Linalg, enabling further transformations
and combination of semantically-loaded and lower-level inputs. As such, Linalg
is intended to complement Affine rather than replace it.
-### Summary of Existing Alternatives a Picture<a name="observationssummary"></a>
-Lastly, we summarize our observations of lessons from [Prior
-Art](#prior-art)---when viewed under the lense of our [Core Guiding
-Principles](#guiding_principles)---with the following picture.
-
-<img width="1200" alt="MLIR Codegen Flow"
-src="https://user-images.githubusercontent.com/10148468/73613904-2f720a00-45c8-11ea-8265-1c856c02525b.png">
-
-This figure is not meant to be perfectly accurate but a rough map of how we view
-the distribution of structural information in existing systems, from a
-codegen-friendly angle. Unsurprisingly, the
-[Linalg Dialect](../Dialects/Linalg/_index.md) and its future evolutions aspire
-to a position in the top-right of this map.
-
## Core Guiding Principles<a name="guiding_principles"></a>
### Transformations and Simplicity First<a name="transformations_first"></a>
@@ -679,3 +665,17 @@ Considering the *potential* described during the discussion on
transformation would dictate that the potential remains constant.
In contrast, Linalg advocates for ***monotonicity*** under
transformations.
+
+### Summary of Existing Alternatives a Picture<a name="observationssummary"></a>
+Lastly, we summarize our observations of lessons from [Prior
+Art](#prior-art)---when viewed under the lense of our [Core Guiding
+Principles](#guiding_principles)---with the following picture.
+
+<img width="1200" alt="MLIR Codegen Flow"
+src="https://user-images.githubusercontent.com/10148468/73613904-2f720a00-45c8-11ea-8265-1c856c02525b.png">
+
+This figure is not meant to be perfectly accurate but a rough map of how we view
+the distribution of structural information in existing systems, from a
+codegen-friendly angle. Unsurprisingly, the
+[Linalg Dialect](../Dialects/Linalg/_index.md) and its future evolutions aspire
+to a position in the top-right of this map.
>From e57ef2e0fb15d21197e63a1a1220a13cc46aaff0 Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Fri, 5 Sep 2025 14:44:41 +0100
Subject: [PATCH 3/8] in a generic
---
mlir/docs/Rationale/RationaleLinalgDialect.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/docs/Rationale/RationaleLinalgDialect.md b/mlir/docs/Rationale/RationaleLinalgDialect.md
index 9f85921c43b81..c337bc82193b9 100644
--- a/mlir/docs/Rationale/RationaleLinalgDialect.md
+++ b/mlir/docs/Rationale/RationaleLinalgDialect.md
@@ -551,7 +551,7 @@ non-Linalg operations, for example `linalg.*conv*`, `linalg.winograd*`,
With multiple (often exchangeable) forms, and with transformation simplicity
in mind, compilers should aim for reducing matching and replacing complexity
as much as possible. When matching a single operation with a complex pattern,
-having all the information from a `generic` is useful to iteratively match
+having all the information in a `generic` is useful to iteratively match
different patterns in turn. However, when assembling a DAG of operations to
form a pattern, it's much simpler to match against named operations (like
`max` + `div` + `reduce` + `broadcast`) than their generic counterparts.
>From 6f161cd002135936fc26edb81632ac887a40999d Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Mon, 8 Sep 2025 14:42:44 +0100
Subject: [PATCH 4/8] Apply suggestions from code review
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Andrzej Warzyński <andrzej.warzynski at gmail.com>
---
mlir/docs/Rationale/RationaleLinalgDialect.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mlir/docs/Rationale/RationaleLinalgDialect.md b/mlir/docs/Rationale/RationaleLinalgDialect.md
index c337bc82193b9..c573085acc339 100644
--- a/mlir/docs/Rationale/RationaleLinalgDialect.md
+++ b/mlir/docs/Rationale/RationaleLinalgDialect.md
@@ -516,7 +516,7 @@ the more special forms should not be converted to the more generic ones
unnecessarily, in the same way that they should not be broken down into
loops + arithmetic if they can still be represented as a Linalg op.
-#### Generic, Category, Named<a name="generic_category_named"></a>
+#### The Linalg Forms
The core Linalg operation tree has three forms:
* **Generic:** Represented by `linalg.generic` and can encode all perfectly-nested
@@ -528,7 +528,7 @@ _generic_ forms. For example, `linalg.matmul`, `linalg.add`, etc.
Unlike lowering to loops, the different Linalg forms that are derived from
`linalg.generic` are *equivalent*. It should always be possible to convert
-a named operation into a generic and back to named, if the semantics is
+a named operation into a generic and back to named, if the semantics are
preserved. The various forms in the Linalg dialect are meant to facilitate
pattern matching (single operations or DAGs) and to be able to consider
different forms as *canonical* for different transforms.
>From e746daa3f538ec468f9a2cf5fa526d1b0026ffc9 Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Sun, 14 Sep 2025 21:36:30 +0100
Subject: [PATCH 5/8] Addressed forms discussion, simplified whole section
---
mlir/docs/Rationale/RationaleLinalgDialect.md | 35 ++++++++-----------
1 file changed, 14 insertions(+), 21 deletions(-)
diff --git a/mlir/docs/Rationale/RationaleLinalgDialect.md b/mlir/docs/Rationale/RationaleLinalgDialect.md
index c573085acc339..fe75474e6f5d3 100644
--- a/mlir/docs/Rationale/RationaleLinalgDialect.md
+++ b/mlir/docs/Rationale/RationaleLinalgDialect.md
@@ -508,21 +508,14 @@ and LLVMIR.
### Interchangeability of Forms<a name="forms"></a>
-Linalg's various forms (named, generic) also carry information, and that
-information should be preserved as much as possible during the progressive
-lowering. A `matmul` operation is a special case of a `contract` operation,
-which in turn is a special case of `generic` operation. Transformations on
-the more special forms should not be converted to the more generic ones
-unnecessarily, in the same way that they should not be broken down into
-loops + arithmetic if they can still be represented as a Linalg op.
-
#### The Linalg Forms
The core Linalg operation tree has three forms:
* **Generic:** Represented by `linalg.generic` and can encode all perfectly-nested
loop operations.
* **Category:** Represented by `linalg.contract` and `linalg.elementwise`,
-which are special (einsum) forms of the `generic` operation.
+which are special (einsum) forms of the `generic` operation. In the future, other
+category operations are planned (e.g.: `linalg.convolution` and `linalg.pooling`).
* **Named:** All _named_ forms that can lower to either _category_ or
_generic_ forms. For example, `linalg.matmul`, `linalg.add`, etc.
@@ -533,18 +526,18 @@ preserved. The various forms in the Linalg dialect are meant to facilitate
pattern matching (single operations or DAGs) and to be able to consider
different forms as *canonical* for different transforms.
-#### Special Operations<a name="special_ops"></a>
-
-Not all Linalg operations represent perfectly nested loops, and therefore
-cannot be represented as a `linalg.generic`. There are two kinds of Linalg
-operations that fall into this category:
-* **Composite:** Operations that compose multiple Linalg operations, for
-example `linalg.softmax`. These can be converted to a DAG of Linalg operations
-(in any form).
-* **Special Named:** Operations that are usually matched against library calls
-or special lowering, but can only be lowered to a combination of Linalg and
-non-Linalg operations, for example `linalg.*conv*`, `linalg.winograd*`,
-`linalg.pooling*`, etc.
+In addition to the three forms above, there's a separate class that does not
+belong to the tree, as it does not generalize. These are **composite:** operations
+that compose multiple Linalg operations, for example `linalg.softmax` and
+`linalg.winograd*`. These can be converted to a DAG of Linalg operations.
+
+Linalg's various forms (named, generic) also carry information, and that
+information should be preserved as much as possible during the progressive
+lowering. A `matmul` operation is a special case of a `contract` operation,
+which in turn is a special case of `generic` operation. Transformations on
+the more special forms should not be converted to the more generic ones
+unnecessarily, in the same way that they should not be broken down into
+loops + arithmetic if they can still be represented as a Linalg op.
#### Canonical Forms<a name="canonical_forms"></a>
>From 31f352fc6ca5db07a882d1471f20d6340021919b Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Wed, 1 Oct 2025 13:44:07 +0100
Subject: [PATCH 6/8] rewriting the forms sub-section
---
mlir/docs/Rationale/RationaleLinalgDialect.md | 38 +++++++++++--------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/mlir/docs/Rationale/RationaleLinalgDialect.md b/mlir/docs/Rationale/RationaleLinalgDialect.md
index fe75474e6f5d3..1f0fff3a2a01f 100644
--- a/mlir/docs/Rationale/RationaleLinalgDialect.md
+++ b/mlir/docs/Rationale/RationaleLinalgDialect.md
@@ -513,25 +513,31 @@ and LLVMIR.
The core Linalg operation tree has three forms:
* **Generic:** Represented by `linalg.generic` and can encode all perfectly-nested
loop operations.
-* **Category:** Represented by `linalg.contract` and `linalg.elementwise`,
-which are special (einsum) forms of the `generic` operation. In the future, other
-category operations are planned (e.g.: `linalg.convolution` and `linalg.pooling`).
-* **Named:** All _named_ forms that can lower to either _category_ or
-_generic_ forms. For example, `linalg.matmul`, `linalg.add`, etc.
-
-Unlike lowering to loops, the different Linalg forms that are derived from
-`linalg.generic` are *equivalent*. It should always be possible to convert
-a named operation into a generic and back to named, if the semantics are
-preserved. The various forms in the Linalg dialect are meant to facilitate
+* **Category:** For example, `linalg.contract` and `linalg.elementwise`, that encode
+higher-level semantics of a `linalg.generic` while still representing multiple _named_
+operations via attributes and syntax. In the future, other category operations are
+planned (e.g.: `linalg.convolution` and `linalg.pooling`).
+* **Named:** For example, `linalg.matmul`, `linalg.add`, etc. All _named_ forms that
+can be converted to either a single _category_ or _generic_ forms, ie. are _perfectly nested_.
+* **Composite:** For example `linalg.softmax` and the `winograd` variations. These
+operations are not perfectly nested, and are converted to a list of other operations
+(of various dialects).
+
+The different Linalg forms that are derived from `linalg.generic` are *equivalent*.
+It should always be possible to convert a **named** operation into a **category** and that
+into a **generic** and back to **named**. However, it may not be possible to convert a
+**generic** into a **named** if there is no such named form.
+
+**Composite** operations cannot be converted to the other three classes and forms a
+sub-set on its own. But they can use other Linalg forms when expanding. There can be
+a pattern-matching transform to detect a graph of operations and convert into a
+**composite** operation.
+
+The various forms in the Linalg dialect are meant to facilitate
pattern matching (single operations or DAGs) and to be able to consider
different forms as *canonical* for different transforms.
-In addition to the three forms above, there's a separate class that does not
-belong to the tree, as it does not generalize. These are **composite:** operations
-that compose multiple Linalg operations, for example `linalg.softmax` and
-`linalg.winograd*`. These can be converted to a DAG of Linalg operations.
-
-Linalg's various forms (named, generic) also carry information, and that
+Linalg's various forms also carry information, and that
information should be preserved as much as possible during the progressive
lowering. A `matmul` operation is a special case of a `contract` operation,
which in turn is a special case of `generic` operation. Transformations on
>From 1d4933dbf79fa767ad6bcf62e59cdda1dd4fb362 Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Wed, 1 Oct 2025 15:34:02 +0100
Subject: [PATCH 7/8] Fixed outdated line, add the op tree for clarification.
---
mlir/docs/Rationale/RationaleLinalgDialect.md | 22 +++++++++++++------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/mlir/docs/Rationale/RationaleLinalgDialect.md b/mlir/docs/Rationale/RationaleLinalgDialect.md
index 1f0fff3a2a01f..fcef0b4ed788d 100644
--- a/mlir/docs/Rationale/RationaleLinalgDialect.md
+++ b/mlir/docs/Rationale/RationaleLinalgDialect.md
@@ -510,7 +510,7 @@ and LLVMIR.
#### The Linalg Forms
-The core Linalg operation tree has three forms:
+The core Linalg operation set has four forms:
* **Generic:** Represented by `linalg.generic` and can encode all perfectly-nested
loop operations.
* **Category:** For example, `linalg.contract` and `linalg.elementwise`, that encode
@@ -523,15 +523,23 @@ can be converted to either a single _category_ or _generic_ forms, ie. are _perf
operations are not perfectly nested, and are converted to a list of other operations
(of various dialects).
-The different Linalg forms that are derived from `linalg.generic` are *equivalent*.
-It should always be possible to convert a **named** operation into a **category** and that
-into a **generic** and back to **named**. However, it may not be possible to convert a
-**generic** into a **named** if there is no such named form.
+The forms correlate in the following manner:
+```
++ generic
+ \__ + category
+ \__ + named
++ composite
+```
-**Composite** operations cannot be converted to the other three classes and forms a
+The `category` and `named` forms are derived from `linalg.generic` and are *equivalent*.
+It should always be possible to convert a `named` operation into a `category` and that
+into a `generic` and back to `named`. However, it may not be possible to convert a
+`generic` into a `named` if there is no such `named` form.
+
+`Composite` operations cannot be converted to the other three classes and forms a
sub-set on its own. But they can use other Linalg forms when expanding. There can be
a pattern-matching transform to detect a graph of operations and convert into a
-**composite** operation.
+`composite` operation.
The various forms in the Linalg dialect are meant to facilitate
pattern matching (single operations or DAGs) and to be able to consider
>From c80f526ff715796261bc03c7818ad7c43a588cea Mon Sep 17 00:00:00 2001
From: Renato Golin <rengolin at systemcall.eu>
Date: Tue, 7 Oct 2025 11:38:03 +0100
Subject: [PATCH 8/8] Apply suggestions from code review
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Andrzej Warzyński <andrzej.warzynski at gmail.com>
---
mlir/docs/Rationale/RationaleLinalgDialect.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mlir/docs/Rationale/RationaleLinalgDialect.md b/mlir/docs/Rationale/RationaleLinalgDialect.md
index fcef0b4ed788d..cce71f3471421 100644
--- a/mlir/docs/Rationale/RationaleLinalgDialect.md
+++ b/mlir/docs/Rationale/RationaleLinalgDialect.md
@@ -548,7 +548,7 @@ different forms as *canonical* for different transforms.
Linalg's various forms also carry information, and that
information should be preserved as much as possible during the progressive
lowering. A `matmul` operation is a special case of a `contract` operation,
-which in turn is a special case of `generic` operation. Transformations on
+which in turn is a special case of a `generic` operation. Transformations on
the more special forms should not be converted to the more generic ones
unnecessarily, in the same way that they should not be broken down into
loops + arithmetic if they can still be represented as a Linalg op.
@@ -558,7 +558,7 @@ loops + arithmetic if they can still be represented as a Linalg op.
With multiple (often exchangeable) forms, and with transformation simplicity
in mind, compilers should aim for reducing matching and replacing complexity
as much as possible. When matching a single operation with a complex pattern,
-having all the information in a `generic` is useful to iteratively match
+having all the information in a `generic` Op is useful to iteratively match
different patterns in turn. However, when assembling a DAG of operations to
form a pattern, it's much simpler to match against named operations (like
`max` + `div` + `reduce` + `broadcast`) than their generic counterparts.
More information about the Mlir-commits
mailing list