Skip to content

[mlir][Transforms][NFC] Dialect conversion: Improve docs for materializations #117847

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

Merged
merged 2 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 42 additions & 34 deletions mlir/docs/DialectConversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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 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:
* When a block argument has been converted to a different type, but
the original argument still has users that will remain live after
Expand All @@ -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
Expand All @@ -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:

Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
27 changes: 14 additions & 13 deletions mlir/include/mlir/Transforms/DialectConversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
Expand Down