[Mlir-commits] [mlir] [mlir][Transforms][NFC] Dialect conversion: Improve docs for materializations (PR #117847)
Matthias Springer
llvmlistbot at llvm.org
Wed Nov 27 19:30:46 PST 2024
https://github.com/matthias-springer updated https://github.com/llvm/llvm-project/pull/117847
>From a82df149a67a781b4a4f24410244f11fb3f2ec6a Mon Sep 17 00:00:00 2001
From: Matthias Springer <mspringer at nvidia.com>
Date: Wed, 27 Nov 2024 05:51:04 +0100
Subject: [PATCH 1/2] [mlir][Transforms][NFC] Dialect conversion: Clarify type
legality
---
mlir/docs/DialectConversion.md | 76 ++++++++++---------
.../mlir/Transforms/DialectConversion.h | 27 +++----
2 files changed, 56 insertions(+), 47 deletions(-)
diff --git a/mlir/docs/DialectConversion.md b/mlir/docs/DialectConversion.md
index 4f6cb1dec66a63..12276f88e42b7a 100644
--- a/mlir/docs/DialectConversion.md
+++ b/mlir/docs/DialectConversion.md
@@ -230,17 +230,17 @@ The `TypeConverter` contains several hooks for detailing how to convert types,
and how to materialize conversions between types in various situations. The two
main aspects of the `TypeConverter` are conversion and materialization.
-A `conversion` describes how a given illegal source `Type` should be converted
-to N target types. If the source type is already "legal", it should convert to
-itself. Type conversions are specified via the `addConversion` method described
+A `conversion` describes how a given source `Type` should be converted to N
+target types. If the source type is converted to itself, we say it is a "legal"
+type. Type conversions are specified via the `addConversion` method described
below.
-A `materialization` describes how a set of values should be converted to a
-single value of a desired type. An important distinction with a `conversion` is
-that a `materialization` can produce IR, whereas a `conversion` cannot. These
-materializations are used by the conversion framework to ensure type safety
-during the conversion process. There are several types of materializations
-depending on the situation.
+A `materialization` describes how a list of values should be converted to a
+list of values with specific types. An important distinction from a
+`conversion` is that a `materialization` can produce IR, whereas a `conversion`
+cannot. These materializations are used by the conversion framework to ensure
+type safety during the conversion process. There are several types of
+materializations depending on the situation.
* Argument Materialization
@@ -252,16 +252,15 @@ depending on the situation.
conversion. (E.g., adaptors support only a single replacement value for
each original value.) Therefore, an argument materialization is used to
convert potentially multiple new block arguments back into a single SSA
- value.
+ value. An argument materialization is also used when replacing an op
+ result with multiple values.
* Source Materialization
- - A source materialization converts from a value with a "legal" target
- type, back to a specific source type. This is used when an operation is
- "legal" during the conversion process, but contains a use of an illegal
- type. This may happen during a conversion where some operations are
- converted to those with different resultant types, but still retain
- users of the original type system.
+ - A source materialization is used when a value was replaced with a value
+ of different type, but there are still users that expects the original
+ ("source") type at the end of the conversion process. A source
+ materialization converts the replacement value back to the source type.
- This materialization is used in the following situations:
* When a block argument has been converted to a different type, but
the original argument still has users that will remain live after
@@ -275,16 +274,12 @@ depending on the situation.
* Target Materialization
- - A target materialization converts from a value with an "illegal" source
- type, to a value of a "legal" type. This is used when a pattern expects
- the remapped operands to be of a certain set of types, but the original
- input operands have not been converted. This may happen during a
- conversion where some operations are converted to those with different
- resultant types, but still retain uses of the original type system.
- - This materialization is used in the following situations:
- * When the remapped operands of a
- [conversion pattern](#conversion-patterns) are not legal for the
- type conversion provided by the pattern.
+ - A target materialization converts a value to the type that is expected
+ by a conversion pattern according to its type converter.
+ - A target materialization is used when a pattern expects the remapped
+ operands to be of a certain set of types, but the original input
+ operands have either not been replaced or been replaced with values of
+ a different type.
If a converted value is used by an operation that isn't converted, it needs a
conversion back to the `source` type, hence source materialization; if an
@@ -297,10 +292,8 @@ will not implicitly change during the conversion process. When the type of a
value definition, either block argument or operation result, is being changed,
the users of that definition must also be updated during the conversion process.
If they aren't, a type conversion must be materialized to ensure that a value of
-the expected type is still present within the IR. If a target materialization is
-required, but cannot be performed, the pattern application fails. If a source
-materialization is required, but cannot be performed, the entire conversion
-process fails.
+the expected type is still present within the IR. If a materialization is
+required, but cannot be performed, the entire conversion process fails.
Several of the available hooks are detailed below:
@@ -362,9 +355,9 @@ class TypeConverter {
}
/// This method registers a materialization that will be called when
- /// converting a legal replacement value back to an illegal source type.
- /// This is used when some uses of the original, illegal value must persist
- /// beyond the main conversion.
+ /// converting a replacement value back to its original source type.
+ /// This is used when some uses of the original value persist beyond the main
+ /// conversion.
template <typename FnT,
typename T = typename llvm::function_traits<FnT>::template arg_t<1>>
void addSourceMaterialization(FnT &&callback) {
@@ -373,7 +366,22 @@ class TypeConverter {
}
/// This method registers a materialization that will be called when
- /// converting an illegal (source) value to a legal (target) type.
+ /// converting a value to a target type according to a pattern's type
+ /// converter.
+ ///
+ /// Note: Target materializations can optionally inspect the "original"
+ /// type. This type may be different from the type of the input value.
+ /// For example, let's assume that a conversion pattern "P1" replaced an SSA
+ /// value "v1" (type "t1") with "v2" (type "t2"). Then a different conversion
+ /// pattern "P2" matches an op that has "v1" as an operand. Let's furthermore
+ /// assume that "P2" determines that the converted target type of "t1" is
+ /// "t3", which may be different from "t2". In this example, the target
+ /// materialization will be invoked with: outputType = "t3", inputs = "v2",
+ /// originalType = "t1". Note that the original type "t1" cannot be recovered
+ /// from just "t3" and "v2"; that's why the originalType parameter exists.
+ ///
+ /// Note: During a 1:N conversion, the result types can be a TypeRange. In
+ /// that case the materialization produces a SmallVector<Value>.
template <typename FnT,
typename T = typename llvm::function_traits<FnT>::template arg_t<1>>
void addTargetMaterialization(FnT &&callback) {
diff --git a/mlir/include/mlir/Transforms/DialectConversion.h b/mlir/include/mlir/Transforms/DialectConversion.h
index de47765006f81e..aac6b7c03548a9 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -189,9 +189,9 @@ class TypeConverter {
}
/// This method registers a materialization that will be called when
- /// converting a legal replacement value back to an illegal source type.
- /// This is used when some uses of the original, illegal value must persist
- /// beyond the main conversion.
+ /// converting a replacement value back to its original source type.
+ /// This is used when some uses of the original value persist beyond the main
+ /// conversion.
template <typename FnT, typename T = typename llvm::function_traits<
std::decay_t<FnT>>::template arg_t<1>>
void addSourceMaterialization(FnT &&callback) {
@@ -200,17 +200,18 @@ class TypeConverter {
}
/// This method registers a materialization that will be called when
- /// converting an illegal (source) value to a legal (target) type.
+ /// converting a value to a target type according to a pattern's type
+ /// converter.
///
- /// Note: For target materializations, users can optionally take the original
- /// type. This type may be different from the type of the input. For example,
- /// let's assume that a conversion pattern "P1" replaced an SSA value "v1"
- /// (type "t1") with "v2" (type "t2"). Then a different conversion pattern
- /// "P2" matches an op that has "v1" as an operand. Let's furthermore assume
- /// that "P2" determines that the legalized type of "t1" is "t3", which may
- /// be different from "t2". In this example, the target materialization
- /// will be invoked with: outputType = "t3", inputs = "v2",
- // originalType = "t1". Note that the original type "t1" cannot be recovered
+ /// Note: Target materializations can optionally inspect the "original"
+ /// type. This type may be different from the type of the input value.
+ /// For example, let's assume that a conversion pattern "P1" replaced an SSA
+ /// value "v1" (type "t1") with "v2" (type "t2"). Then a different conversion
+ /// pattern "P2" matches an op that has "v1" as an operand. Let's furthermore
+ /// assume that "P2" determines that the converted target type of "t1" is
+ /// "t3", which may be different from "t2". In this example, the target
+ /// materialization will be invoked with: outputType = "t3", inputs = "v2",
+ /// originalType = "t1". Note that the original type "t1" cannot be recovered
/// from just "t3" and "v2"; that's why the originalType parameter exists.
///
/// Note: During a 1:N conversion, the result types can be a TypeRange. In
>From 30b20859f838ebb5c8c939fde2ad9ababe70fe87 Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Thu, 28 Nov 2024 12:30:38 +0900
Subject: [PATCH 2/2] Update mlir/docs/DialectConversion.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Markus Böck <markus.boeck02 at gmail.com>
---
mlir/docs/DialectConversion.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/docs/DialectConversion.md b/mlir/docs/DialectConversion.md
index 12276f88e42b7a..3168f5e13c7515 100644
--- a/mlir/docs/DialectConversion.md
+++ b/mlir/docs/DialectConversion.md
@@ -258,7 +258,7 @@ materializations depending on the situation.
* Source Materialization
- A source materialization is used when a value was replaced with a value
- of different type, but there are still users that expects the original
+ of a different type, but there are still users that expects the original
("source") type at the end of the conversion process. A source
materialization converts the replacement value back to the source type.
- This materialization is used in the following situations:
More information about the Mlir-commits
mailing list