[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