-
Notifications
You must be signed in to change notification settings - Fork 12.1k
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
[mlir][Transforms][NFC] Dialect conversion: Improve docs for materializations #117847
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-mlir-core Author: Matthias Springer (matthias-springer) ChangesThe terms "legal type" and "illegal type" are ambiguous when talking about materializations. E.g., for target materializations we do not necessarily convert from illegal to legal types. We convert from the most recently mapped value to the type that was produced by converting the original type. Full diff: https://github.com/llvm/llvm-project/pull/117847.diff 2 Files Affected:
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
|
@llvm/pr-subscribers-mlir Author: Matthias Springer (matthias-springer) ChangesThe terms "legal type" and "illegal type" are ambiguous when talking about materializations. E.g., for target materializations we do not necessarily convert from illegal to legal types. We convert from the most recently mapped value to the type that was produced by converting the original type. Full diff: https://github.com/llvm/llvm-project/pull/117847.diff 2 Files Affected:
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
|
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
The terms "legal type" and "illegal type" are ambiguous when talking about materializations. E.g., for target materializations we do not necessarily convert from illegal to legal types. We convert from the most recently mapped value to the type that was produced by converting the original type.