Skip to content

Commit

Permalink
[mlir][Transforms] Dialect conversion: Simplify handling of dropped a…
Browse files Browse the repository at this point in the history
…rguments (llvm#96207)

This commit simplifies the handling of dropped arguments and updates
some dialect conversion documentation that is outdated.

When converting a block signature, a `BlockTypeConversionRewrite` object
and potentially multiple `ReplaceBlockArgRewrite` are created. During
the "commit" phase, uses of the old block arguments are replaced with
the new block arguments, but the old implementation was written in an
inconsistent way: some block arguments were replaced in
`BlockTypeConversionRewrite::commit` and some were replaced in
`ReplaceBlockArgRewrite::commit`. The new
`BlockTypeConversionRewrite::commit` implementation is much simpler and
no longer modifies any IR; that is done only in `ReplaceBlockArgRewrite`
now. The `ConvertedArgInfo` data structure is no longer needed.

To that end, materializations of dropped arguments are now built in
`applySignatureConversion` instead of `materializeLiveConversions`; the
latter function no longer has to deal with dropped arguments.

Other minor improvements:
- Improve variable name: `origOutputType` -> `origArgType`. Add an
assertion to check that this field is only used for argument
materializations.
- Add more comments to `applySignatureConversion`.

Note: Error messages around failed materializations for dropped basic
block arguments changed slightly. That is because those materializations
are now built in `legalizeUnresolvedMaterialization` instead of
`legalizeConvertedArgumentTypes`.

This commit is in preparation of decoupling argument/source/target
materializations from the dialect conversion.
  • Loading branch information
matthias-springer authored Jun 25, 2024
1 parent 62d44fb commit f1e0657
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 156 deletions.
44 changes: 29 additions & 15 deletions mlir/docs/DialectConversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ depending on the situation.
- An argument materialization is used when converting the type of a block
argument during a [signature conversion](#region-signature-conversion).
The new block argument types are specified in a `SignatureConversion`
object. An original block argument can be converted into multiple
block arguments, which is not supported everywhere in the dialect
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.
* Source Materialization
Expand All @@ -259,6 +266,9 @@ depending on the situation.
* When a block argument has been converted to a different type, but
the original argument still has users that will remain live after
the conversion process has finished.
* When a block argument has been dropped, but the argument still has
users that will remain live after the conversion process has
finished.
* When the result type of an operation has been converted to a
different type, but the original result still has users that will
remain live after the conversion process is finished.
Expand Down Expand Up @@ -328,36 +338,40 @@ class TypeConverter {
registerConversion(wrapCallback<T>(std::forward<FnT>(callback)));
}
/// Register a materialization function, which must be convertible to the
/// following form:
/// `Optional<Value> (OpBuilder &, T, ValueRange, Location)`,
/// where `T` is any subclass of `Type`.
/// This function is responsible for creating an operation, using the
/// OpBuilder and Location provided, that "converts" a range of values into a
/// single value of the given type `T`. It must return a Value of the
/// converted type on success, an `std::nullopt` if it failed but other
/// materialization can be attempted, and `nullptr` on unrecoverable failure.
/// It will only be called for (sub)types of `T`.
///
/// All of the following materializations require function objects that are
/// convertible to the following form:
/// `std::optional<Value>(OpBuilder &, T, ValueRange, Location)`,
/// where `T` is any subclass of `Type`. This function is responsible for
/// creating an operation, using the OpBuilder and Location provided, that
/// "casts" a range of values into a single value of the given type `T`. It
/// must return a Value of the converted type on success, an `std::nullopt` if
/// it failed but other materialization can be attempted, and `nullptr` on
/// unrecoverable failure. It will only be called for (sub)types of `T`.
/// Materialization functions must be provided when a type conversion may
/// persist after the conversion has finished.
/// This method registers a materialization that will be called when
/// converting an illegal block argument type, to a legal type.
/// converting (potentially multiple) block arguments that were the result of
/// a signature conversion of a single block argument, to a single SSA value
/// of a legal type.
template <typename FnT,
typename T = typename llvm::function_traits<FnT>::template arg_t<1>>
void addArgumentMaterialization(FnT &&callback) {
argumentMaterializations.emplace_back(
wrapMaterialization<T>(std::forward<FnT>(callback)));
}
/// This method registers a materialization that will be called when
/// converting a legal type to an illegal source type. This is used when
/// conversions to an illegal type must persist beyond the main conversion.
/// 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.
template <typename FnT,
typename T = typename llvm::function_traits<FnT>::template arg_t<1>>
void addSourceMaterialization(FnT &&callback) {
sourceMaterializations.emplace_back(
wrapMaterialization<T>(std::forward<FnT>(callback)));
}
/// This method registers a materialization that will be called when
/// converting type from an illegal, or source, type to a legal type.
/// converting an illegal (source) value to a legal (target) type.
template <typename FnT,
typename T = typename llvm::function_traits<FnT>::template arg_t<1>>
void addTargetMaterialization(FnT &&callback) {
Expand Down
17 changes: 10 additions & 7 deletions mlir/include/mlir/Transforms/DialectConversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ class TypeConverter {
registerConversion(wrapCallback<T>(std::forward<FnT>(callback)));
}

/// Register a materialization function, which must be convertible to the
/// following form:
/// All of the following materializations require function objects that are
/// convertible to the following form:
/// `std::optional<Value>(OpBuilder &, T, ValueRange, Location)`,
/// where `T` is any subclass of `Type`. This function is responsible for
/// creating an operation, using the OpBuilder and Location provided, that
Expand All @@ -179,26 +179,29 @@ class TypeConverter {
/// unrecoverable failure. It will only be called for (sub)types of `T`.
/// Materialization functions must be provided when a type conversion may
/// persist after the conversion has finished.
///

/// This method registers a materialization that will be called when
/// converting an illegal block argument type, to a legal type.
/// converting (potentially multiple) block arguments that were the result of
/// a signature conversion of a single block argument, to a single SSA value
/// of a legal type.
template <typename FnT, typename T = typename llvm::function_traits<
std::decay_t<FnT>>::template arg_t<1>>
void addArgumentMaterialization(FnT &&callback) {
argumentMaterializations.emplace_back(
wrapMaterialization<T>(std::forward<FnT>(callback)));
}
/// This method registers a materialization that will be called when
/// converting a legal type to an illegal source type. This is used when
/// conversions to an illegal type must persist beyond the main conversion.
/// 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.
template <typename FnT, typename T = typename llvm::function_traits<
std::decay_t<FnT>>::template arg_t<1>>
void addSourceMaterialization(FnT &&callback) {
sourceMaterializations.emplace_back(
wrapMaterialization<T>(std::forward<FnT>(callback)));
}
/// This method registers a materialization that will be called when
/// converting type from an illegal, or source, type to a legal type.
/// converting an illegal (source) value to a legal (target) type.
template <typename FnT, typename T = typename llvm::function_traits<
std::decay_t<FnT>>::template arg_t<1>>
void addTargetMaterialization(FnT &&callback) {
Expand Down
Loading

0 comments on commit f1e0657

Please sign in to comment.