[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-28 Thread Matthias Springer via llvm-branch-commits


@@ -321,15 +323,15 @@ class RandomizedWorklist : public Worklist {
 /// to the worklist in the beginning.
 class GreedyPatternRewriteDriver : public RewriterBase::Listener {
 protected:
-  explicit GreedyPatternRewriteDriver(MLIRContext *ctx,
+  explicit GreedyPatternRewriteDriver(PatternRewriter &rewriter,
   const FrozenRewritePatternSet &patterns,
   const GreedyRewriteConfig &config);
 
   /// Add the given operation to the worklist.
   void addSingleOpToWorklist(Operation *op);
 
   /// Add the given operation and its ancestors to the worklist.
-  void addToWorklist(Operation *op);
+  virtual void addToWorklist(Operation *op);

matthias-springer wrote:

We can avoid this virtual function call by templatizing the driver class.

https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-28 Thread Matthias Springer via llvm-branch-commits


@@ -1053,3 +1055,241 @@ LogicalResult mlir::applyOpPatternsAndFold(
   });
   return converged;
 }
+
+//===--===//
+// One-Shot Dialect Conversion Infrastructure
+//===--===//
+
+namespace {
+/// A conversion rewriter for the One-Shot Dialect Conversion. This rewriter
+/// immediately materializes all IR changes. It derives from
+/// `ConversionPatternRewriter` so that the existing conversion patterns can
+/// be used with the One-Shot Dialect Conversion.
+class OneShotConversionPatternRewriter : public ConversionPatternRewriter {
+public:
+  OneShotConversionPatternRewriter(MLIRContext *ctx)
+  : ConversionPatternRewriter(ctx) {}
+
+  bool canRecoverFromRewriteFailure() const override { return false; }
+
+  void replaceOp(Operation *op, ValueRange newValues) override;
+
+  void replaceOp(Operation *op, Operation *newOp) override {
+replaceOp(op, newOp->getResults());
+  }
+
+  void eraseOp(Operation *op) override { PatternRewriter::eraseOp(op); }
+
+  void eraseBlock(Block *block) override { PatternRewriter::eraseBlock(block); 
}
+
+  void inlineBlockBefore(Block *source, Block *dest, Block::iterator before,
+ ValueRange argValues = std::nullopt) override {
+PatternRewriter::inlineBlockBefore(source, dest, before, argValues);
+  }
+  using PatternRewriter::inlineBlockBefore;
+
+  void startOpModification(Operation *op) override {
+PatternRewriter::startOpModification(op);
+  }
+
+  void finalizeOpModification(Operation *op) override {
+PatternRewriter::finalizeOpModification(op);
+  }
+
+  void cancelOpModification(Operation *op) override {
+PatternRewriter::cancelOpModification(op);
+  }

matthias-springer wrote:

The only one that would still be necessary is `replaceOp` because it must 
insert unrealized_conversion_casts. All the others could be removed (because 
the intermediate `ConversionPatternRewriter` class would be gone).

https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-28 Thread Matthias Springer via llvm-branch-commits


@@ -1053,3 +1055,241 @@ LogicalResult mlir::applyOpPatternsAndFold(
   });
   return converged;
 }
+
+//===--===//
+// One-Shot Dialect Conversion Infrastructure
+//===--===//
+
+namespace {
+/// A conversion rewriter for the One-Shot Dialect Conversion. This rewriter
+/// immediately materializes all IR changes. It derives from
+/// `ConversionPatternRewriter` so that the existing conversion patterns can
+/// be used with the One-Shot Dialect Conversion.
+class OneShotConversionPatternRewriter : public ConversionPatternRewriter {
+public:
+  OneShotConversionPatternRewriter(MLIRContext *ctx)
+  : ConversionPatternRewriter(ctx) {}
+
+  bool canRecoverFromRewriteFailure() const override { return false; }
+
+  void replaceOp(Operation *op, ValueRange newValues) override;
+
+  void replaceOp(Operation *op, Operation *newOp) override {
+replaceOp(op, newOp->getResults());
+  }
+
+  void eraseOp(Operation *op) override { PatternRewriter::eraseOp(op); }
+
+  void eraseBlock(Block *block) override { PatternRewriter::eraseBlock(block); 
}
+
+  void inlineBlockBefore(Block *source, Block *dest, Block::iterator before,
+ ValueRange argValues = std::nullopt) override {
+PatternRewriter::inlineBlockBefore(source, dest, before, argValues);
+  }
+  using PatternRewriter::inlineBlockBefore;
+
+  void startOpModification(Operation *op) override {
+PatternRewriter::startOpModification(op);
+  }
+
+  void finalizeOpModification(Operation *op) override {
+PatternRewriter::finalizeOpModification(op);
+  }
+
+  void cancelOpModification(Operation *op) override {
+PatternRewriter::cancelOpModification(op);
+  }
+
+  void setCurrentTypeConverter(const TypeConverter *converter) override {
+typeConverter = converter;
+  }
+
+  const TypeConverter *getCurrentTypeConverter() const override {
+return typeConverter;
+  }
+
+  LogicalResult getAdapterOperands(StringRef valueDiagTag,
+   std::optional inputLoc,
+   ValueRange values,
+   SmallVector &remapped) override;
+
+private:
+  /// Build an unrealized_conversion_cast op or look it up in the cache.
+  Value buildUnrealizedConversionCast(Location loc, Type type, Value value);
+
+  /// The current type converter.
+  const TypeConverter *typeConverter;
+
+  /// A cache for unrealized_conversion_casts. To ensure that identical casts
+  /// are not built multiple times.
+  DenseMap, Value> castCache;

matthias-springer wrote:

I think this can happen during `getAdapterOperands`. Each conversion pattern 
can have its own type converter. (That's why there is `currentTypeConverter` 
etc.)

```
func.func @foo(%arg0: i1) {
  "op1"(%arg0)
  "op2"(%arg0)
}
```

Let's assume that there is no conversion pattern for `func.func`. I.e., the 
block argument is not converted. We could have two different patterns for "op1" 
and "op2" with different type converters that convert `i1` to different types. 
Now we have to insert two unrealized_conversion_casts with different result 
types.

(This probably does not happen very often.)


https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-29 Thread Matthias Springer via llvm-branch-commits


@@ -1053,3 +1055,241 @@ LogicalResult mlir::applyOpPatternsAndFold(
   });
   return converged;
 }
+
+//===--===//
+// One-Shot Dialect Conversion Infrastructure
+//===--===//
+
+namespace {
+/// A conversion rewriter for the One-Shot Dialect Conversion. This rewriter
+/// immediately materializes all IR changes. It derives from
+/// `ConversionPatternRewriter` so that the existing conversion patterns can
+/// be used with the One-Shot Dialect Conversion.
+class OneShotConversionPatternRewriter : public ConversionPatternRewriter {
+public:
+  OneShotConversionPatternRewriter(MLIRContext *ctx)
+  : ConversionPatternRewriter(ctx) {}
+
+  bool canRecoverFromRewriteFailure() const override { return false; }
+
+  void replaceOp(Operation *op, ValueRange newValues) override;
+
+  void replaceOp(Operation *op, Operation *newOp) override {
+replaceOp(op, newOp->getResults());
+  }
+
+  void eraseOp(Operation *op) override { PatternRewriter::eraseOp(op); }
+
+  void eraseBlock(Block *block) override { PatternRewriter::eraseBlock(block); 
}
+
+  void inlineBlockBefore(Block *source, Block *dest, Block::iterator before,
+ ValueRange argValues = std::nullopt) override {
+PatternRewriter::inlineBlockBefore(source, dest, before, argValues);
+  }
+  using PatternRewriter::inlineBlockBefore;
+
+  void startOpModification(Operation *op) override {
+PatternRewriter::startOpModification(op);
+  }
+
+  void finalizeOpModification(Operation *op) override {
+PatternRewriter::finalizeOpModification(op);
+  }
+
+  void cancelOpModification(Operation *op) override {
+PatternRewriter::cancelOpModification(op);
+  }
+
+  void setCurrentTypeConverter(const TypeConverter *converter) override {
+typeConverter = converter;
+  }
+
+  const TypeConverter *getCurrentTypeConverter() const override {
+return typeConverter;
+  }
+
+  LogicalResult getAdapterOperands(StringRef valueDiagTag,
+   std::optional inputLoc,
+   ValueRange values,
+   SmallVector &remapped) override;
+
+private:
+  /// Build an unrealized_conversion_cast op or look it up in the cache.
+  Value buildUnrealizedConversionCast(Location loc, Type type, Value value);
+
+  /// The current type converter.
+  const TypeConverter *typeConverter;
+
+  /// A cache for unrealized_conversion_casts. To ensure that identical casts
+  /// are not built multiple times.
+  DenseMap, Value> castCache;
+};
+
+void OneShotConversionPatternRewriter::replaceOp(Operation *op,
+ ValueRange newValues) {
+  assert(op->getNumResults() == newValues.size());
+  for (auto [orig, repl] : llvm::zip_equal(op->getResults(), newValues)) {
+if (orig.getType() != repl.getType()) {
+  // Type mismatch: insert unrealized_conversion cast.
+  replaceAllUsesWith(orig, buildUnrealizedConversionCast(
+   op->getLoc(), orig.getType(), repl));
+} else {
+  // Same type: use replacement value directly.
+  replaceAllUsesWith(orig, repl);
+}
+  }
+  eraseOp(op);
+}
+
+Value OneShotConversionPatternRewriter::buildUnrealizedConversionCast(
+Location loc, Type type, Value value) {
+  auto it = castCache.find(std::make_pair(value, type));
+  if (it != castCache.end())
+return it->second;
+
+  // Insert cast at the beginning of the block (for block arguments) or right
+  // after the defining op.
+  OpBuilder::InsertionGuard g(*this);
+  Block *insertBlock = value.getParentBlock();
+  Block::iterator insertPt = insertBlock->begin();
+  if (OpResult inputRes = dyn_cast(value))
+insertPt = ++inputRes.getOwner()->getIterator();
+  setInsertionPoint(insertBlock, insertPt);
+  auto castOp = create(loc, type, value);
+  castCache[std::make_pair(value, type)] = castOp.getOutputs()[0];
+  return castOp.getOutputs()[0];
+}
+
+class ConversionPatternRewriteDriver : public GreedyPatternRewriteDriver {

matthias-springer wrote:

"One Shot" may be a misnomer. I really meant "no rollback".

I am reluctant to build something that is not compatible with the large number 
of existing conversion patterns. I would rather gradually improve the situation 
in way where users have a painless way to migrate to the new driver. Otherwise, 
is anybody going to use the new infrastructure?


https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-29 Thread Matthias Springer via llvm-branch-commits


@@ -1053,3 +1055,241 @@ LogicalResult mlir::applyOpPatternsAndFold(
   });
   return converged;
 }
+
+//===--===//
+// One-Shot Dialect Conversion Infrastructure
+//===--===//
+
+namespace {
+/// A conversion rewriter for the One-Shot Dialect Conversion. This rewriter
+/// immediately materializes all IR changes. It derives from
+/// `ConversionPatternRewriter` so that the existing conversion patterns can
+/// be used with the One-Shot Dialect Conversion.
+class OneShotConversionPatternRewriter : public ConversionPatternRewriter {
+public:
+  OneShotConversionPatternRewriter(MLIRContext *ctx)
+  : ConversionPatternRewriter(ctx) {}
+
+  bool canRecoverFromRewriteFailure() const override { return false; }
+
+  void replaceOp(Operation *op, ValueRange newValues) override;
+
+  void replaceOp(Operation *op, Operation *newOp) override {
+replaceOp(op, newOp->getResults());
+  }
+
+  void eraseOp(Operation *op) override { PatternRewriter::eraseOp(op); }
+
+  void eraseBlock(Block *block) override { PatternRewriter::eraseBlock(block); 
}
+
+  void inlineBlockBefore(Block *source, Block *dest, Block::iterator before,
+ ValueRange argValues = std::nullopt) override {
+PatternRewriter::inlineBlockBefore(source, dest, before, argValues);
+  }
+  using PatternRewriter::inlineBlockBefore;
+
+  void startOpModification(Operation *op) override {
+PatternRewriter::startOpModification(op);
+  }
+
+  void finalizeOpModification(Operation *op) override {
+PatternRewriter::finalizeOpModification(op);
+  }
+
+  void cancelOpModification(Operation *op) override {
+PatternRewriter::cancelOpModification(op);
+  }
+
+  void setCurrentTypeConverter(const TypeConverter *converter) override {
+typeConverter = converter;
+  }
+
+  const TypeConverter *getCurrentTypeConverter() const override {
+return typeConverter;
+  }
+
+  LogicalResult getAdapterOperands(StringRef valueDiagTag,
+   std::optional inputLoc,
+   ValueRange values,
+   SmallVector &remapped) override;
+
+private:
+  /// Build an unrealized_conversion_cast op or look it up in the cache.
+  Value buildUnrealizedConversionCast(Location loc, Type type, Value value);
+
+  /// The current type converter.
+  const TypeConverter *typeConverter;
+
+  /// A cache for unrealized_conversion_casts. To ensure that identical casts
+  /// are not built multiple times.
+  DenseMap, Value> castCache;
+};
+
+void OneShotConversionPatternRewriter::replaceOp(Operation *op,
+ ValueRange newValues) {
+  assert(op->getNumResults() == newValues.size());
+  for (auto [orig, repl] : llvm::zip_equal(op->getResults(), newValues)) {
+if (orig.getType() != repl.getType()) {
+  // Type mismatch: insert unrealized_conversion cast.
+  replaceAllUsesWith(orig, buildUnrealizedConversionCast(
+   op->getLoc(), orig.getType(), repl));
+} else {
+  // Same type: use replacement value directly.
+  replaceAllUsesWith(orig, repl);
+}
+  }
+  eraseOp(op);
+}
+
+Value OneShotConversionPatternRewriter::buildUnrealizedConversionCast(
+Location loc, Type type, Value value) {
+  auto it = castCache.find(std::make_pair(value, type));
+  if (it != castCache.end())
+return it->second;
+
+  // Insert cast at the beginning of the block (for block arguments) or right
+  // after the defining op.
+  OpBuilder::InsertionGuard g(*this);
+  Block *insertBlock = value.getParentBlock();
+  Block::iterator insertPt = insertBlock->begin();
+  if (OpResult inputRes = dyn_cast(value))
+insertPt = ++inputRes.getOwner()->getIterator();
+  setInsertionPoint(insertBlock, insertPt);
+  auto castOp = create(loc, type, value);
+  castCache[std::make_pair(value, type)] = castOp.getOutputs()[0];
+  return castOp.getOutputs()[0];
+}
+
+class ConversionPatternRewriteDriver : public GreedyPatternRewriteDriver {

matthias-springer wrote:

What's the main issue that you see with a worklist-based approach? Imo, the 
main complexity of the dialect conversion is because of rollback and late 
materialization. I never had issues issues debugging a greedy pattern rewrite 
with `-debug` so far.

https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-29 Thread Matthias Springer via llvm-branch-commits


@@ -1053,3 +1055,241 @@ LogicalResult mlir::applyOpPatternsAndFold(
   });
   return converged;
 }
+
+//===--===//
+// One-Shot Dialect Conversion Infrastructure
+//===--===//
+
+namespace {
+/// A conversion rewriter for the One-Shot Dialect Conversion. This rewriter
+/// immediately materializes all IR changes. It derives from
+/// `ConversionPatternRewriter` so that the existing conversion patterns can
+/// be used with the One-Shot Dialect Conversion.
+class OneShotConversionPatternRewriter : public ConversionPatternRewriter {
+public:
+  OneShotConversionPatternRewriter(MLIRContext *ctx)
+  : ConversionPatternRewriter(ctx) {}
+
+  bool canRecoverFromRewriteFailure() const override { return false; }
+
+  void replaceOp(Operation *op, ValueRange newValues) override;
+
+  void replaceOp(Operation *op, Operation *newOp) override {
+replaceOp(op, newOp->getResults());
+  }
+
+  void eraseOp(Operation *op) override { PatternRewriter::eraseOp(op); }
+
+  void eraseBlock(Block *block) override { PatternRewriter::eraseBlock(block); 
}
+
+  void inlineBlockBefore(Block *source, Block *dest, Block::iterator before,
+ ValueRange argValues = std::nullopt) override {
+PatternRewriter::inlineBlockBefore(source, dest, before, argValues);
+  }
+  using PatternRewriter::inlineBlockBefore;
+
+  void startOpModification(Operation *op) override {
+PatternRewriter::startOpModification(op);
+  }
+
+  void finalizeOpModification(Operation *op) override {
+PatternRewriter::finalizeOpModification(op);
+  }
+
+  void cancelOpModification(Operation *op) override {
+PatternRewriter::cancelOpModification(op);
+  }
+
+  void setCurrentTypeConverter(const TypeConverter *converter) override {
+typeConverter = converter;
+  }
+
+  const TypeConverter *getCurrentTypeConverter() const override {
+return typeConverter;
+  }
+
+  LogicalResult getAdapterOperands(StringRef valueDiagTag,
+   std::optional inputLoc,
+   ValueRange values,
+   SmallVector &remapped) override;
+
+private:
+  /// Build an unrealized_conversion_cast op or look it up in the cache.
+  Value buildUnrealizedConversionCast(Location loc, Type type, Value value);
+
+  /// The current type converter.
+  const TypeConverter *typeConverter;
+
+  /// A cache for unrealized_conversion_casts. To ensure that identical casts
+  /// are not built multiple times.
+  DenseMap, Value> castCache;
+};
+
+void OneShotConversionPatternRewriter::replaceOp(Operation *op,
+ ValueRange newValues) {
+  assert(op->getNumResults() == newValues.size());
+  for (auto [orig, repl] : llvm::zip_equal(op->getResults(), newValues)) {
+if (orig.getType() != repl.getType()) {
+  // Type mismatch: insert unrealized_conversion cast.
+  replaceAllUsesWith(orig, buildUnrealizedConversionCast(
+   op->getLoc(), orig.getType(), repl));
+} else {
+  // Same type: use replacement value directly.
+  replaceAllUsesWith(orig, repl);
+}
+  }
+  eraseOp(op);
+}
+
+Value OneShotConversionPatternRewriter::buildUnrealizedConversionCast(
+Location loc, Type type, Value value) {
+  auto it = castCache.find(std::make_pair(value, type));
+  if (it != castCache.end())
+return it->second;
+
+  // Insert cast at the beginning of the block (for block arguments) or right
+  // after the defining op.
+  OpBuilder::InsertionGuard g(*this);
+  Block *insertBlock = value.getParentBlock();
+  Block::iterator insertPt = insertBlock->begin();
+  if (OpResult inputRes = dyn_cast(value))
+insertPt = ++inputRes.getOwner()->getIterator();
+  setInsertionPoint(insertBlock, insertPt);
+  auto castOp = create(loc, type, value);
+  castCache[std::make_pair(value, type)] = castOp.getOutputs()[0];
+  return castOp.getOutputs()[0];
+}
+
+class ConversionPatternRewriteDriver : public GreedyPatternRewriteDriver {

matthias-springer wrote:

> I don't have problem with dialect conversion complexity actually, other than 
> replaceAllUsesWith not doing what it says it does

I tried to fix that [here](https://github.com/llvm/llvm-project/pull/84725). It 
sounded like the rollback logic was getting too complex. (I would agree with 
that.)

> Without rollback you're incompatible anyway, people can't "just adopt it".

I expect that most dialect conversions do not actually need the rollback. I am 
not aware of any passes in MLIR that require it. (But users may have their own 
passes that rely on it, that's why I asked in the RFC.) So my hope is that the 
existing patterns just work with the new driver. I only tried it with 
`NVGPUToNVVM.cpp` and `ComplexToStandard.cpp` so far, and have to try migrating 
a few more passe

[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-29 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-29 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Simplify handling of dropped arguments (PR #96207)

2024-06-20 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/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.


>From ed7bb706dc8eaec2f45a8f63c98d9b9b7fac23a8 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 20 Jun 2024 11:18:44 +0200
Subject: [PATCH] [mlir][Transforms] Dialect conversion: Simplify handling of
 dropped arguments

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`.
---
 mlir/docs/DialectConversion.md|  37 +++-
 .../mlir/Transforms/DialectConversion.h   |  10 +-
 .../Transforms/Utils/DialectConversion.cpp| 208 +++---
 .../test-legalize-type-conversion.mlir|   6 +-
 4 files changed, 111 insertions(+), 150 deletions(-)

diff --git a/mlir/docs/DialectConversion.md b/mlir/docs/DialectConversion.md
index 69781bb868bbf..f722974a9a1e5 100644
--- a/mlir/docs/DialectConversion.md
+++ b/mlir/docs/DialectConversion.md
@@ -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
 
@@ -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 pro

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Dialect Conversion: Move argument materialization logic (PR #96329)

2024-06-21 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/96329

This commit moves the argument materialization logic from 
`legalizeConvertedArgumentTypes` to `legalizeUnresolvedMaterializations`.

Before this change:
- Argument materializations were created in `legalizeConvertedArgumentTypes` 
(which used to call `materializeLiveConversions`).

After this change:
- `legalizeConvertedArgumentTypes` creates a "placeholder" 
`unrealized_conversion_cast`.
- The placeholder `unrealized_conversion_cast` is replaced with an argument 
materialization (using the type converter) in 
`legalizeUnresolvedMaterializations`.
- All argument and target materializations now take place in the same location 
(`legalizeUnresolvedMaterializations`).

This commit brings us closer towards creating all source/target/argument 
materializations in one central step, which can then be made optional (and 
delegated to the user) in the future. (There is one more source materialization 
step that has not been moved yet.)

This commit also consolidates all `build*UnresolvedMaterialization` functions 
into a single `buildUnresolvedMaterialization` function.



>From d2b0b9ef97c626fc48b0c00ce2ec8e5573599f2b Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 20 Jun 2024 17:40:07 +0200
Subject: [PATCH] remove materializeLiveConversions

---
 .../Transforms/Utils/DialectConversion.cpp| 133 +++---
 1 file changed, 52 insertions(+), 81 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 07ebd687ee2b3..47e03383304af 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -53,6 +53,16 @@ static void logFailure(llvm::ScopedPrinter &os, StringRef 
fmt, Args &&...args) {
   });
 }
 
+/// Helper function that computes an insertion point where the given value is
+/// defined and can be used without a dominance violation.
+static OpBuilder::InsertPoint computeInsertPoint(Value value) {
+  Block *insertBlock = value.getParentBlock();
+  Block::iterator insertPt = insertBlock->begin();
+  if (OpResult inputRes = dyn_cast(value))
+insertPt = ++inputRes.getOwner()->getIterator();
+  return OpBuilder::InsertPoint(insertBlock, insertPt);
+}
+
 
//===--===//
 // ConversionValueMapping
 
//===--===//
@@ -445,11 +455,9 @@ class BlockTypeConversionRewrite : public BlockRewrite {
 return rewrite->getKind() == Kind::BlockTypeConversion;
   }
 
-  /// Materialize any necessary conversions for converted arguments that have
-  /// live users, using the provided `findLiveUser` to search for a user that
-  /// survives the conversion process.
-  LogicalResult
-  materializeLiveConversions(function_ref findLiveUser);
+  Block *getOrigBlock() const { return origBlock; }
+
+  const TypeConverter *getConverter() const { return converter; }
 
   void commit(RewriterBase &rewriter) override;
 
@@ -841,14 +849,10 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// Build an unresolved materialization operation given an output type and 
set
   /// of input operands.
   Value buildUnresolvedMaterialization(MaterializationKind kind,
-   Block *insertBlock,
-   Block::iterator insertPt, Location loc,
+   OpBuilder::InsertPoint ip, Location loc,
ValueRange inputs, Type outputType,
Type origOutputType,
const TypeConverter *converter);
-  Value buildUnresolvedTargetMaterialization(Location loc, Value input,
- Type outputType,
- const TypeConverter *converter);
 
   
//======//
   // Rewriter Notification Hooks
@@ -981,49 +985,6 @@ void BlockTypeConversionRewrite::rollback() {
   block->replaceAllUsesWith(origBlock);
 }
 
-LogicalResult BlockTypeConversionRewrite::materializeLiveConversions(
-function_ref findLiveUser) {
-  // Process the remapping for each of the original arguments.
-  for (auto it : llvm::enumerate(origBlock->getArguments())) {
-BlockArgument origArg = it.value();
-// Note: `block` may be detached, so OpBuilder::atBlockBegin cannot be 
used.
-OpBuilder builder(it.value().getContext(), /*listener=*/&rewriterImpl);
-builder.setInsertionPointToStart(block);
-
-// If the type of this argument changed and the argument is still live, we
-// need to materialize a conversion.
-if (rewriterImpl.mapping.lookupOrNull(origArg, origArg.getType()))
-  continue;
-Operation *liveUser = findLiveUser(

[llvm-branch-commits] [mlir] [mlir][Conversion] `FuncToLLVM`: Simplify bare-pointer handling (PR #96393)

2024-06-22 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/96393

Before this commit, there used to be a workaround in the `func.func`/`gpu.func` 
op lowering when the bare-pointer calling convention is enabled. This 
workaround "patched up" the argument materializations for memref arguments. 
This can be done directly in the argument materialization functions (as the 
TODOs in the code base indicate).

This commit effectively reverts back to the old implementation 
(a664c14001fa2359604527084c91d0864aa131a4) and adds additional checks to make 
sure that bare pointers are used only for function entry block arguments.


>From f65911a2b08c538d24a9b2044123390ceae5b4b5 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Sat, 22 Jun 2024 14:54:21 +0200
Subject: [PATCH] [mlir][Conversion] `FuncToLLVM`: Simplify bare-pointer
 handling

Before this commit, there used to be a workaround in the `func.func`/`gpu.func` 
op lowering when the bare-pointer calling convention was enabled. This 
workaround "patched up" the argument materializations for memref arguments. 
This can be done directly in the argument materialization functions (as the 
TODOs in the code base indicate).
---
 mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp |  53 
 .../Conversion/GPUCommon/GPUOpsLowering.cpp   | 128 +++---
 .../Conversion/LLVMCommon/TypeConverter.cpp   |  22 ++-
 3 files changed, 66 insertions(+), 137 deletions(-)

diff --git a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp 
b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
index 744236692fbb6..efb80467369a2 100644
--- a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
+++ b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
@@ -268,55 +268,6 @@ static void wrapExternalFunction(OpBuilder &builder, 
Location loc,
   }
 }
 
-/// Modifies the body of the function to construct the `MemRefDescriptor` from
-/// the bare pointer calling convention lowering of `memref` types.
-static void modifyFuncOpToUseBarePtrCallingConv(
-ConversionPatternRewriter &rewriter, Location loc,
-const LLVMTypeConverter &typeConverter, LLVM::LLVMFuncOp funcOp,
-TypeRange oldArgTypes) {
-  if (funcOp.getBody().empty())
-return;
-
-  // Promote bare pointers from memref arguments to memref descriptors at the
-  // beginning of the function so that all the memrefs in the function have a
-  // uniform representation.
-  Block *entryBlock = &funcOp.getBody().front();
-  auto blockArgs = entryBlock->getArguments();
-  assert(blockArgs.size() == oldArgTypes.size() &&
- "The number of arguments and types doesn't match");
-
-  OpBuilder::InsertionGuard guard(rewriter);
-  rewriter.setInsertionPointToStart(entryBlock);
-  for (auto it : llvm::zip(blockArgs, oldArgTypes)) {
-BlockArgument arg = std::get<0>(it);
-Type argTy = std::get<1>(it);
-
-// Unranked memrefs are not supported in the bare pointer calling
-// convention. We should have bailed out before in the presence of
-// unranked memrefs.
-assert(!isa(argTy) &&
-   "Unranked memref is not supported");
-auto memrefTy = dyn_cast(argTy);
-if (!memrefTy)
-  continue;
-
-// Replace barePtr with a placeholder (undef), promote barePtr to a ranked
-// or unranked memref descriptor and replace placeholder with the last
-// instruction of the memref descriptor.
-// TODO: The placeholder is needed to avoid replacing barePtr uses in the
-// MemRef descriptor instructions. We may want to have a utility in the
-// rewriter to properly handle this use case.
-Location loc = funcOp.getLoc();
-auto placeholder = rewriter.create(
-loc, typeConverter.convertType(memrefTy));
-rewriter.replaceUsesOfBlockArgument(arg, placeholder);
-
-Value desc = MemRefDescriptor::fromStaticShape(rewriter, loc, 
typeConverter,
-   memrefTy, arg);
-rewriter.replaceOp(placeholder, {desc});
-  }
-}
-
 FailureOr
 mlir::convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp,
 ConversionPatternRewriter &rewriter,
@@ -462,10 +413,6 @@ mlir::convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp,
 wrapForExternalCallers(rewriter, funcOp->getLoc(), converter, funcOp,
newFuncOp);
 }
-  } else {
-modifyFuncOpToUseBarePtrCallingConv(
-rewriter, funcOp->getLoc(), converter, newFuncOp,
-llvm::cast(funcOp.getFunctionType()).getInputs());
   }
 
   return newFuncOp;
diff --git a/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp 
b/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp
index 7ea05b7e7f6c1..6053e34f30a41 100644
--- a/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp
+++ b/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp
@@ -182,35 +182,6 @@ GPUFuncOpLowering::matchAndRewrite(gpu::GPUFuncOp 
gpuFuncOp, OpAdaptor adaptor,
  &signatureConversion)))
 return failure();
 
-  /

[llvm-branch-commits] [mlir] [mlir][Conversion] `FuncToLLVM`: Simplify bare-pointer handling (PR #96393)

2024-06-22 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/96393

>From 2d838580bf8c17ea7a17d73415b3c64c1775b37d Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Sat, 22 Jun 2024 14:54:21 +0200
Subject: [PATCH] [mlir][Conversion] `FuncToLLVM`: Simplify bare-pointer
 handling

Before this commit, there used to be a workaround in the `func.func`/`gpu.func` 
op lowering when the bare-pointer calling convention was enabled. This 
workaround "patched up" the argument materializations for memref arguments. 
This can be done directly in the argument materialization functions (as the 
TODOs in the code base indicate).
---
 mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp | 53 ---
 .../Conversion/GPUCommon/GPUOpsLowering.cpp   | 29 --
 .../Conversion/LLVMCommon/TypeConverter.cpp   | 22 ++--
 3 files changed, 17 insertions(+), 87 deletions(-)

diff --git a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp 
b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
index 744236692fbb6..efb80467369a2 100644
--- a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
+++ b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
@@ -268,55 +268,6 @@ static void wrapExternalFunction(OpBuilder &builder, 
Location loc,
   }
 }
 
-/// Modifies the body of the function to construct the `MemRefDescriptor` from
-/// the bare pointer calling convention lowering of `memref` types.
-static void modifyFuncOpToUseBarePtrCallingConv(
-ConversionPatternRewriter &rewriter, Location loc,
-const LLVMTypeConverter &typeConverter, LLVM::LLVMFuncOp funcOp,
-TypeRange oldArgTypes) {
-  if (funcOp.getBody().empty())
-return;
-
-  // Promote bare pointers from memref arguments to memref descriptors at the
-  // beginning of the function so that all the memrefs in the function have a
-  // uniform representation.
-  Block *entryBlock = &funcOp.getBody().front();
-  auto blockArgs = entryBlock->getArguments();
-  assert(blockArgs.size() == oldArgTypes.size() &&
- "The number of arguments and types doesn't match");
-
-  OpBuilder::InsertionGuard guard(rewriter);
-  rewriter.setInsertionPointToStart(entryBlock);
-  for (auto it : llvm::zip(blockArgs, oldArgTypes)) {
-BlockArgument arg = std::get<0>(it);
-Type argTy = std::get<1>(it);
-
-// Unranked memrefs are not supported in the bare pointer calling
-// convention. We should have bailed out before in the presence of
-// unranked memrefs.
-assert(!isa(argTy) &&
-   "Unranked memref is not supported");
-auto memrefTy = dyn_cast(argTy);
-if (!memrefTy)
-  continue;
-
-// Replace barePtr with a placeholder (undef), promote barePtr to a ranked
-// or unranked memref descriptor and replace placeholder with the last
-// instruction of the memref descriptor.
-// TODO: The placeholder is needed to avoid replacing barePtr uses in the
-// MemRef descriptor instructions. We may want to have a utility in the
-// rewriter to properly handle this use case.
-Location loc = funcOp.getLoc();
-auto placeholder = rewriter.create(
-loc, typeConverter.convertType(memrefTy));
-rewriter.replaceUsesOfBlockArgument(arg, placeholder);
-
-Value desc = MemRefDescriptor::fromStaticShape(rewriter, loc, 
typeConverter,
-   memrefTy, arg);
-rewriter.replaceOp(placeholder, {desc});
-  }
-}
-
 FailureOr
 mlir::convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp,
 ConversionPatternRewriter &rewriter,
@@ -462,10 +413,6 @@ mlir::convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp,
 wrapForExternalCallers(rewriter, funcOp->getLoc(), converter, funcOp,
newFuncOp);
 }
-  } else {
-modifyFuncOpToUseBarePtrCallingConv(
-rewriter, funcOp->getLoc(), converter, newFuncOp,
-llvm::cast(funcOp.getFunctionType()).getInputs());
   }
 
   return newFuncOp;
diff --git a/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp 
b/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp
index 3e6fcc076fb4d..6053e34f30a41 100644
--- a/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp
+++ b/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp
@@ -182,35 +182,6 @@ GPUFuncOpLowering::matchAndRewrite(gpu::GPUFuncOp 
gpuFuncOp, OpAdaptor adaptor,
  &signatureConversion)))
 return failure();
 
-  // If bare memref pointers are being used, remap them back to memref
-  // descriptors This must be done after signature conversion to get rid of the
-  // unrealized casts.
-  if (getTypeConverter()->getOptions().useBarePtrCallConv) {
-OpBuilder::InsertionGuard guard(rewriter);
-rewriter.setInsertionPointToStart(&llvmFuncOp.getBody().front());
-for (const auto [idx, argTy] :
- llvm::enumerate(gpuFuncOp.getArgumentTypes())) {
-  auto memrefTy = dyn_cast(argTy);
-  if (!memrefTy)
-continue;
-  assert(memrefTy.has

[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Fix missing source materialization (PR #97903)

2024-07-13 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/97903
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Fix missing source materialization (PR #97903)

2024-07-13 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/97903
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Simplify handling of dropped arguments (PR #97213)

2024-07-13 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/97213
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Simplify handling of dropped arguments (PR #97213)

2024-07-13 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/97213
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Fix missing source materialization (PR #97903)

2024-07-13 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/97903

>From 577317640c0f5800650157f5c4c6fbe6220eba38 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Sat, 6 Jul 2024 14:28:41 +0200
Subject: [PATCH] fix test

---
 mlir/docs/DialectConversion.md|  3 +-
 .../SCF/TransformOps/SCFTransformOps.td   | 11 +++
 .../mlir/Transforms/DialectConversion.h   | 10 +--
 .../Conversion/LLVMCommon/TypeConverter.cpp   | 28 --
 .../Dialect/SCF/TransformOps/CMakeLists.txt   |  1 +
 .../SCF/TransformOps/SCFTransformOps.cpp  | 13 ++-
 .../Transforms/Utils/DialectConversion.cpp| 87 ++-
 .../FuncToLLVM/func-memref-return.mlir|  4 +-
 .../Transforms/test-block-legalization.mlir   | 44 ++
 9 files changed, 141 insertions(+), 60 deletions(-)
 create mode 100644 mlir/test/Transforms/test-block-legalization.mlir

diff --git a/mlir/docs/DialectConversion.md b/mlir/docs/DialectConversion.md
index db26e6477d5fc..23e74470a835f 100644
--- a/mlir/docs/DialectConversion.md
+++ b/mlir/docs/DialectConversion.md
@@ -352,7 +352,8 @@ class TypeConverter {
 
   /// This method registers a materialization that will be called when
   /// converting (potentially multiple) block arguments that were the result of
-  /// a signature conversion of a single block argument, to a single SSA value.
+  /// a signature conversion of a single block argument, to a single SSA value
+  /// with the old argument type.
   template ::template 
arg_t<1>>
   void addArgumentMaterialization(FnT &&callback) {
diff --git a/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td 
b/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td
index 7bf914f6456ce..20880d94a83ca 100644
--- a/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td
+++ b/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td
@@ -38,6 +38,17 @@ def ApplySCFStructuralConversionPatternsOp : 
Op]> {
+  let description = [{
+Collects patterns that lower structured control flow ops to unstructured
+control flow.
+  }];
+
+  let assemblyFormat = "attr-dict";
+}
+
 def Transform_ScfForOp : Transform_ConcreteOpType<"scf.for">;
 
 def ForallToForOp : Op>::template arg_t<1>>
   void addArgumentMaterialization(FnT &&callback) {
diff --git a/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp 
b/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp
index f5620a6a7cd91..32d02d5e438bd 100644
--- a/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp
+++ b/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp
@@ -153,9 +153,11 @@ LLVMTypeConverter::LLVMTypeConverter(MLIRContext *ctx,
type.isVarArg());
   });
 
-  // Materialization for memrefs creates descriptor structs from individual
-  // values constituting them, when descriptors are used, i.e. more than one
-  // value represents a memref.
+  // Argument materializations convert from the new block argument types
+  // (multiple SSA values that make up a memref descriptor) back to the
+  // original block argument type. The dialect conversion framework will then
+  // insert a target materialization from the original block argument type to
+  // a legal type.
   addArgumentMaterialization(
   [&](OpBuilder &builder, UnrankedMemRefType resultType, ValueRange inputs,
   Location loc) -> std::optional {
@@ -164,12 +166,18 @@ LLVMTypeConverter::LLVMTypeConverter(MLIRContext *ctx,
   // memref descriptor cannot be built just from a bare pointer.
   return std::nullopt;
 }
-return UnrankedMemRefDescriptor::pack(builder, loc, *this, resultType,
-  inputs);
+Value desc = UnrankedMemRefDescriptor::pack(builder, loc, *this,
+resultType, inputs);
+// An argument materialization must return a value of type
+// `resultType`, so insert a cast from the memref descriptor type
+// (!llvm.struct) to the original memref type.
+return builder.create(loc, resultType, 
desc)
+.getResult(0);
   });
   addArgumentMaterialization([&](OpBuilder &builder, MemRefType resultType,
  ValueRange inputs,
  Location loc) -> std::optional {
+Value desc;
 if (inputs.size() == 1) {
   // This is a bare pointer. We allow bare pointers only for function entry
   // blocks.
@@ -180,10 +188,16 @@ LLVMTypeConverter::LLVMTypeConverter(MLIRContext *ctx,
   if (!block->isEntryBlock() ||
   !isa(block->getParentOp()))
 return std::nullopt;
-  return MemRefDescriptor::fromStaticShape(builder, loc, *this, resultType,
+  desc = MemRefDescriptor::fromStaticShape(builder, loc, *this, resultType,
inputs[0]);
+} else {
+  desc = MemRefDescriptor::pack(builder, loc, *this, resultType, inputs);

[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Simplify handling of dropped arguments (PR #97213)

2024-07-13 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/97213

>From b0b781318e5f76f28b9340efbdcc3f91c2c1cf31 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Sat, 13 Jul 2024 17:36:37 +0200
Subject: [PATCH] [mlir][Transforms] Dialect conversion: Simplify handling of
 dropped arguments

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.

This is a re-upload of #96207.
---
 .../Transforms/Utils/DialectConversion.cpp| 173 ++
 .../test-legalize-type-conversion.mlir|   6 +-
 2 files changed, 57 insertions(+), 122 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 1e0afee2373a9..0b552a7e1ca3b 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -432,34 +432,14 @@ class MoveBlockRewrite : public BlockRewrite {
   Block *insertBeforeBlock;
 };
 
-/// This structure contains the information pertaining to an argument that has
-/// been converted.
-struct ConvertedArgInfo {
-  ConvertedArgInfo(unsigned newArgIdx, unsigned newArgSize,
-   Value castValue = nullptr)
-  : newArgIdx(newArgIdx), newArgSize(newArgSize), castValue(castValue) {}
-
-  /// The start index of in the new argument list that contains arguments that
-  /// replace the original.
-  unsigned newArgIdx;
-
-  /// The number of arguments that replaced the original argument.
-  unsigned newArgSize;
-
-  /// The cast value that was created to cast from the new arguments to the
-  /// old. This only used if 'newArgSize' > 1.
-  Value castValue;
-};
-
 /// Block type conversion. This rewrite is partially reflected in the IR.
 class BlockTypeConversionRewrite : public BlockRewrite {
 public:
-  BlockTypeConversionRewrite(
-  ConversionPatternRewriterImpl &rewriterImpl, Block *block,
-  Block *origBlock, SmallVector, 1> 
argInfo,
-  const TypeConverter *converter)
+  BlockTypeConversionRewrite(ConversionPatternRewriterImpl &rewriterImpl,
+ Block *block, Block *origBlock,
+ const TypeConverter *converter)
   : BlockRewrite(Kind::BlockTypeConversion, rewriterImpl, block),
-origBlock(origBlock), argInfo(argInfo), converter(converter) {}
+origBlock(origBlock), converter(converter) {}
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() == Kind::BlockTypeConversion;
@@ -479,10 +459,6 @@ class BlockTypeConversionRewrite : public BlockRewrite {
   /// The original block that was requested to have its signature converted.
   Block *origBlock;
 
-  /// The conversion information for each of the arguments. The information is
-  /// std::nullopt if the argument was dropped during conversion.
-  SmallVector, 1> argInfo;
-
   /// The type converter used to convert the arguments.
   const TypeConverter *converter;
 };
@@ -691,12 +667,16 @@ class CreateOperationRewrite : public OperationRewrite {
 /// The type of materialization.
 enum MaterializationKind {
   /// This materialization materializes a conversion for an illegal block
-  /// argument type, to a legal one.
+  /// argument type, to the original one.
   Argument,
 
   /// This materialization materializes a conversion from an illegal type to a
   /// legal one.
-  Target
+  Target,
+
+  /// This materialization materializes a conversion from a legal type back to
+  /// an illegal one.
+  Source
 };
 
 

[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Simplify handling of dropped arguments (PR #97213)

2024-07-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer ready_for_review 
https://github.com/llvm/llvm-project/pull/97213
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Dialect Conversion: Move argument materialization logic (PR #98805)

2024-07-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/98805

This commit moves the argument materialization logic from 
`legalizeConvertedArgumentTypes` to `legalizeUnresolvedMaterializations`.

Before this change:
- Argument materializations were created in `legalizeConvertedArgumentTypes` 
(which used to call `materializeLiveConversions`).

After this change:
- `legalizeConvertedArgumentTypes` creates a "placeholder" 
`unrealized_conversion_cast`.
- The placeholder `unrealized_conversion_cast` is replaced with an argument 
materialization (using the type converter) in 
`legalizeUnresolvedMaterializations`.
- All argument and target materializations now take place in the same location 
(`legalizeUnresolvedMaterializations`).

This commit brings us closer towards creating all source/target/argument 
materializations in one central step, which can then be made optional (and 
delegated to the user) in the future. (There is one more source materialization 
step that has not been moved yet.)

This commit also consolidates all `build*UnresolvedMaterialization` functions 
into a single `buildUnresolvedMaterialization` function.

This is a re-upload of #96329.

>From dac43d6ee0b2231aa64d49650f9b052ced49d3e4 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 20 Jun 2024 17:40:07 +0200
Subject: [PATCH] [mlir][Transforms][NFC] Dialect Conversion: Move argument
 materialization logic

This commit moves the argument materialization logic from 
`legalizeConvertedArgumentTypes` to `legalizeUnresolvedMaterializations`.

Before this change:
- Argument materializations were created in `legalizeConvertedArgumentTypes` 
(which used to call `materializeLiveConversions`).

After this change:
- `legalizeConvertedArgumentTypes` creates a "placeholder" 
`unrealized_conversion_cast`.
- The placeholder `unrealized_conversion_cast` is replaced with an argument 
materialization (using the type converter) in 
`legalizeUnresolvedMaterializations`.
- All argument and target materializations now take place in the same location 
(`legalizeUnresolvedMaterializations`).

This commit brings us closer towards creating all source/target/argument 
materializations in one central step, which can then be made optional (and 
delegated to the user) in the future. (There is one more source materialization 
step that has not been moved yet.)

This commit also consolidates all `build*UnresolvedMaterialization` functions 
into a single `buildUnresolvedMaterialization` function.

This is a re-upload of #96329.
---
 .../Transforms/Utils/DialectConversion.cpp| 138 +++---
 1 file changed, 54 insertions(+), 84 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 0b552a7e1ca3b..a2e7570380351 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -53,6 +53,16 @@ static void logFailure(llvm::ScopedPrinter &os, StringRef 
fmt, Args &&...args) {
   });
 }
 
+/// Helper function that computes an insertion point where the given value is
+/// defined and can be used without a dominance violation.
+static OpBuilder::InsertPoint computeInsertPoint(Value value) {
+  Block *insertBlock = value.getParentBlock();
+  Block::iterator insertPt = insertBlock->begin();
+  if (OpResult inputRes = dyn_cast(value))
+insertPt = ++inputRes.getOwner()->getIterator();
+  return OpBuilder::InsertPoint(insertBlock, insertPt);
+}
+
 
//===--===//
 // ConversionValueMapping
 
//===--===//
@@ -445,11 +455,9 @@ class BlockTypeConversionRewrite : public BlockRewrite {
 return rewrite->getKind() == Kind::BlockTypeConversion;
   }
 
-  /// Materialize any necessary conversions for converted arguments that have
-  /// live users, using the provided `findLiveUser` to search for a user that
-  /// survives the conversion process.
-  LogicalResult
-  materializeLiveConversions(function_ref findLiveUser);
+  Block *getOrigBlock() const { return origBlock; }
+
+  const TypeConverter *getConverter() const { return converter; }
 
   void commit(RewriterBase &rewriter) override;
 
@@ -830,15 +838,10 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// Build an unresolved materialization operation given an output type and 
set
   /// of input operands.
   Value buildUnresolvedMaterialization(MaterializationKind kind,
-   Block *insertBlock,
-   Block::iterator insertPt, Location loc,
+   OpBuilder::InsertPoint ip, Location loc,
ValueRange inputs, Type outputType,
const TypeConverter *converter);
 
-  Value buildUnresolvedTargetMaterialization(Locat

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Dialect conversion: Eagerly build reverse mapping (PR #101476)

2024-08-01 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/101476
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Build unresolved materialization for replaced ops (PR #101514)

2024-08-01 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/101514

When inserting an argument/source/target materialization, the dialect 
conversion framework first inserts a "dummy" `unrealized_conversion_cast` op 
(during the rewrite process) and then (in the "finialize" phase) replaces these 
cast ops with the IR generated by the type converter callback.

This is the case for all materializations, except when ops are being replaced 
with values that have a different type. In that case, the dialect conversion 
currently directly emits a source materialization. This commit changes the 
implementation, such that a temporary `unrealized_conversion_cast` is also 
inserted in that case.

This commit simplifies the code base: all materializations now happen in 
`legalizeUnresolvedMaterialization`. This commit makes it possible to decouple 
source/target/argument materializations from the dialect conversion (to reduce 
the complexity of the code base). Such materializations can then also be 
optional. This will be implemented in a follow-up commit.

Depends on #101476.


>From 6f771c12fdc1459da867a89bf89c32a38251a4a1 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 1 Aug 2024 18:24:56 +0200
Subject: [PATCH] [mlir][Transforms] Dialect conversion: Build unresolved
 materialization for replaced ops

When inserting an argument/source/target materialization, the dialect 
conversion framework first inserts a "dummy" `unrealized_conversion_cast` op 
(during the rewrite process) and then (in the "finialize" phase) replaces these 
cast ops with the IR generated by the type converter callback.

This is the case for all materializations, except when ops are being replaced 
with values that have a different type. In that case, the dialect conversion 
currently directly emits a source materialization. This commit changes the 
implementation, such that a temporary `unrealized_conversion_cast` is also 
inserted in this case.

This commit simplifies the code base: all materializations now happen in 
`legalizeUnresolvedMaterialization`. This commit makes it possible to decouple 
source/target/argument materializations from the dialect conversion (to reduce 
the complexity of the code base). Such materializations can then also be 
optional. This will be implemented in a follow-up commit.
---
 .../Transforms/Utils/DialectConversion.cpp| 126 +++---
 .../VectorToSPIRV/vector-to-spirv.mlir|   4 +-
 .../Transforms/finalizing-bufferize.mlir  |   3 +-
 .../test-legalize-type-conversion.mlir|  11 +-
 4 files changed, 57 insertions(+), 87 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 8f9b21b7ee1e5..b0b5a8247b53f 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -2348,6 +2348,12 @@ struct OperationConverter {
   legalizeConvertedArgumentTypes(ConversionPatternRewriter &rewriter,
  ConversionPatternRewriterImpl &rewriterImpl);
 
+  /// Legalize the types of converted op results.
+  LogicalResult legalizeConvertedOpResultTypes(
+  ConversionPatternRewriter &rewriter,
+  ConversionPatternRewriterImpl &rewriterImpl,
+  DenseMap> &inverseMapping);
+
   /// Legalize any unresolved type materializations.
   LogicalResult legalizeUnresolvedMaterializations(
   ConversionPatternRewriter &rewriter,
@@ -2359,14 +2365,6 @@ struct OperationConverter {
   legalizeErasedResult(Operation *op, OpResult result,
ConversionPatternRewriterImpl &rewriterImpl);
 
-  /// Legalize an operation result that was replaced with a value of a 
different
-  /// type.
-  LogicalResult legalizeChangedResultType(
-  Operation *op, OpResult result, Value newValue,
-  const TypeConverter *replConverter, ConversionPatternRewriter &rewriter,
-  ConversionPatternRewriterImpl &rewriterImpl,
-  const DenseMap> &inverseMapping);
-
   /// Dialect conversion configuration.
   ConversionConfig config;
 
@@ -2459,10 +2457,42 @@ OperationConverter::finalize(ConversionPatternRewriter 
&rewriter) {
 return failure();
   DenseMap> inverseMapping =
   rewriterImpl.mapping.getInverse();
+  if (failed(legalizeConvertedOpResultTypes(rewriter, rewriterImpl,
+inverseMapping)))
+return failure();
   if (failed(legalizeUnresolvedMaterializations(rewriter, rewriterImpl,
 inverseMapping)))
 return failure();
+  return success();
+}
 
+/// Finds a user of the given value, or of any other value that the given value
+/// replaced, that was not replaced in the conversion process.
+static Operation *findLiveUserOfReplaced(
+Value initialValue, ConversionPatternRewriterImpl &rewriterImpl,
+const DenseMap> &inverseMapping) {
+  SmallVector worklist(1, initialValue);
+  while (!w

[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Build unresolved materialization for replaced ops (PR #101514)

2024-08-03 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/101514

>From 2d9d1281db99061b212259a60a8bffdfdc800447 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 1 Aug 2024 18:24:56 +0200
Subject: [PATCH] [mlir][Transforms] Dialect conversion: Build unresolved
 materialization for replaced ops

When inserting an argument/source/target materialization, the dialect 
conversion framework first inserts a "dummy" `unrealized_conversion_cast` op 
(during the rewrite process) and then (in the "finialize" phase) replaces these 
cast ops with the IR generated by the type converter callback.

This is the case for all materializations, except when ops are being replaced 
with values that have a different type. In that case, the dialect conversion 
currently directly emits a source materialization. This commit changes the 
implementation, such that a temporary `unrealized_conversion_cast` is also 
inserted in this case.

This commit simplifies the code base: all materializations now happen in 
`legalizeUnresolvedMaterialization`. This commit makes it possible to decouple 
source/target/argument materializations from the dialect conversion (to reduce 
the complexity of the code base). Such materializations can then also be 
optional. This will be implemented in a follow-up commit.
---
 .../Transforms/Utils/DialectConversion.cpp| 126 +++---
 .../VectorToSPIRV/vector-to-spirv.mlir|   4 +-
 .../Transforms/finalizing-bufferize.mlir  |   3 +-
 .../test-legalize-type-conversion.mlir|  11 +-
 4 files changed, 57 insertions(+), 87 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 8f9b21b7ee1e5..b0b5a8247b53f 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -2348,6 +2348,12 @@ struct OperationConverter {
   legalizeConvertedArgumentTypes(ConversionPatternRewriter &rewriter,
  ConversionPatternRewriterImpl &rewriterImpl);
 
+  /// Legalize the types of converted op results.
+  LogicalResult legalizeConvertedOpResultTypes(
+  ConversionPatternRewriter &rewriter,
+  ConversionPatternRewriterImpl &rewriterImpl,
+  DenseMap> &inverseMapping);
+
   /// Legalize any unresolved type materializations.
   LogicalResult legalizeUnresolvedMaterializations(
   ConversionPatternRewriter &rewriter,
@@ -2359,14 +2365,6 @@ struct OperationConverter {
   legalizeErasedResult(Operation *op, OpResult result,
ConversionPatternRewriterImpl &rewriterImpl);
 
-  /// Legalize an operation result that was replaced with a value of a 
different
-  /// type.
-  LogicalResult legalizeChangedResultType(
-  Operation *op, OpResult result, Value newValue,
-  const TypeConverter *replConverter, ConversionPatternRewriter &rewriter,
-  ConversionPatternRewriterImpl &rewriterImpl,
-  const DenseMap> &inverseMapping);
-
   /// Dialect conversion configuration.
   ConversionConfig config;
 
@@ -2459,10 +2457,42 @@ OperationConverter::finalize(ConversionPatternRewriter 
&rewriter) {
 return failure();
   DenseMap> inverseMapping =
   rewriterImpl.mapping.getInverse();
+  if (failed(legalizeConvertedOpResultTypes(rewriter, rewriterImpl,
+inverseMapping)))
+return failure();
   if (failed(legalizeUnresolvedMaterializations(rewriter, rewriterImpl,
 inverseMapping)))
 return failure();
+  return success();
+}
 
+/// Finds a user of the given value, or of any other value that the given value
+/// replaced, that was not replaced in the conversion process.
+static Operation *findLiveUserOfReplaced(
+Value initialValue, ConversionPatternRewriterImpl &rewriterImpl,
+const DenseMap> &inverseMapping) {
+  SmallVector worklist(1, initialValue);
+  while (!worklist.empty()) {
+Value value = worklist.pop_back_val();
+
+// Walk the users of this value to see if there are any live users that
+// weren't replaced during conversion.
+auto liveUserIt = llvm::find_if_not(value.getUsers(), [&](Operation *user) 
{
+  return rewriterImpl.isOpIgnored(user);
+});
+if (liveUserIt != value.user_end())
+  return *liveUserIt;
+auto mapIt = inverseMapping.find(value);
+if (mapIt != inverseMapping.end())
+  worklist.append(mapIt->second);
+  }
+  return nullptr;
+}
+
+LogicalResult OperationConverter::legalizeConvertedOpResultTypes(
+ConversionPatternRewriter &rewriter,
+ConversionPatternRewriterImpl &rewriterImpl,
+DenseMap> &inverseMapping) {
   // Process requested operation replacements.
   for (unsigned i = 0; i < rewriterImpl.rewrites.size(); ++i) {
 auto *opReplacement =
@@ -2485,14 +2515,21 @@ OperationConverter::finalize(ConversionPatternRewriter 
&rewriter) {
   if (result.getType() == newValue.getT

[llvm-branch-commits] [mlir] [mlir][IR] Auto-generate element type verification for VectorType (PR #102449)

2024-08-08 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/102449

#102326 enables verification of type parameters that are type constraints. The 
element type verification for `VectorType` (and maybe other builtin types in 
the future) can now be auto-generated.

Also remove redundant error checking in the vector type parser: element type 
and dimensions are already checked by the verifier (which is called from 
`getChecked`).

Depends on #102326.


>From 73980b05339b57ff770d3b9aa5e82a569d84f91d Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 8 Aug 2024 12:28:23 +0200
Subject: [PATCH] [mlir][IR] Auto-generate element type verification for
 VectorType

---
 mlir/include/mlir/IR/BuiltinTypes.td|  4 +++-
 mlir/lib/AsmParser/TypeParser.cpp   | 13 +++--
 mlir/test/IR/invalid-builtin-types.mlir |  6 +++---
 3 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/mlir/include/mlir/IR/BuiltinTypes.td 
b/mlir/include/mlir/IR/BuiltinTypes.td
index 365edcf68d8b94..4b3add2035263c 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -17,6 +17,7 @@
 include "mlir/IR/AttrTypeBase.td"
 include "mlir/IR/BuiltinDialect.td"
 include "mlir/IR/BuiltinTypeInterfaces.td"
+include "mlir/IR/CommonTypeConstraints.td"
 
 // TODO: Currently the types defined in this file are prefixed with `Builtin_`.
 // This is to differentiate the types here with the ones in OpBase.td. We 
should
@@ -1146,7 +1147,7 @@ def Builtin_Vector : Builtin_Type<"Vector", "vector",
   }];
   let parameters = (ins
 ArrayRefParameter<"int64_t">:$shape,
-"Type":$elementType,
+AnyTypeOf<[AnyInteger, Index, AnyFloat]>:$elementType,
 ArrayRefParameter<"bool">:$scalableDims
   );
   let builders = [
@@ -1173,6 +1174,7 @@ def Builtin_Vector : Builtin_Type<"Vector", "vector",
 /// type. In particular, vectors can consist of integer, index, or float
 /// primitives.
 static bool isValidElementType(Type t) {
+  // TODO: Auto-generate this function from $elementType.
   return ::llvm::isa(t);
 }
 
diff --git a/mlir/lib/AsmParser/TypeParser.cpp 
b/mlir/lib/AsmParser/TypeParser.cpp
index 542eaeefe57f12..f070c072c43296 100644
--- a/mlir/lib/AsmParser/TypeParser.cpp
+++ b/mlir/lib/AsmParser/TypeParser.cpp
@@ -458,31 +458,24 @@ Type Parser::parseTupleType() {
 /// static-dim-list ::= decimal-literal (`x` decimal-literal)*
 ///
 VectorType Parser::parseVectorType() {
+  SMLoc loc = getToken().getLoc();
   consumeToken(Token::kw_vector);
 
   if (parseToken(Token::less, "expected '<' in vector type"))
 return nullptr;
 
+  // Parse the dimensions.
   SmallVector dimensions;
   SmallVector scalableDims;
   if (parseVectorDimensionList(dimensions, scalableDims))
 return nullptr;
-  if (any_of(dimensions, [](int64_t i) { return i <= 0; }))
-return emitError(getToken().getLoc(),
- "vector types must have positive constant sizes"),
-   nullptr;
 
   // Parse the element type.
-  auto typeLoc = getToken().getLoc();
   auto elementType = parseType();
   if (!elementType || parseToken(Token::greater, "expected '>' in vector 
type"))
 return nullptr;
 
-  if (!VectorType::isValidElementType(elementType))
-return emitError(typeLoc, "vector elements must be int/index/float type"),
-   nullptr;
-
-  return VectorType::get(dimensions, elementType, scalableDims);
+  return getChecked(loc, dimensions, elementType, scalableDims);
 }
 
 /// Parse a dimension list in a vector type. This populates the dimension list.
diff --git a/mlir/test/IR/invalid-builtin-types.mlir 
b/mlir/test/IR/invalid-builtin-types.mlir
index 9884212e916c1f..07854a25000feb 100644
--- a/mlir/test/IR/invalid-builtin-types.mlir
+++ b/mlir/test/IR/invalid-builtin-types.mlir
@@ -120,17 +120,17 @@ func.func @illegaltype(i21312312323120) // expected-error 
{{invalid integer widt
 // -
 
 // Test no nested vector.
-// expected-error@+1 {{vector elements must be int/index/float type}}
+// expected-error@+1 {{failed to verify 'elementType': integer or index or 
floating-point}}
 func.func @vectors(vector<1 x vector<1xi32>>, vector<2x4xf32>)
 
 // -
 
-// expected-error @+1 {{vector types must have positive constant sizes}}
+// expected-error @+1 {{vector types must have positive constant sizes but got 
0}}
 func.func @zero_vector_type() -> vector<0xi32>
 
 // -
 
-// expected-error @+1 {{vector types must have positive constant sizes}}
+// expected-error @+1 {{vector types must have positive constant sizes but got 
1, 0}}
 func.func @zero_in_vector_type() -> vector<1x0xi32>
 
 // -

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][IR] Auto-generate element type verification for VectorType (PR #102449)

2024-08-08 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/102449

>From 1e3c58ae8903d58c2a10c634e859c8f1e4df9812 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 8 Aug 2024 12:28:23 +0200
Subject: [PATCH] [mlir][IR] Auto-generate element type verification for
 VectorType

---
 mlir/include/mlir/IR/BuiltinTypes.td|  4 +++-
 mlir/lib/AsmParser/TypeParser.cpp   | 13 +++--
 mlir/test/IR/invalid-builtin-types.mlir |  6 +++---
 mlir/test/python/ir/builtin_types.py|  2 +-
 4 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/mlir/include/mlir/IR/BuiltinTypes.td 
b/mlir/include/mlir/IR/BuiltinTypes.td
index 365edcf68d8b9..4b3add2035263 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -17,6 +17,7 @@
 include "mlir/IR/AttrTypeBase.td"
 include "mlir/IR/BuiltinDialect.td"
 include "mlir/IR/BuiltinTypeInterfaces.td"
+include "mlir/IR/CommonTypeConstraints.td"
 
 // TODO: Currently the types defined in this file are prefixed with `Builtin_`.
 // This is to differentiate the types here with the ones in OpBase.td. We 
should
@@ -1146,7 +1147,7 @@ def Builtin_Vector : Builtin_Type<"Vector", "vector",
   }];
   let parameters = (ins
 ArrayRefParameter<"int64_t">:$shape,
-"Type":$elementType,
+AnyTypeOf<[AnyInteger, Index, AnyFloat]>:$elementType,
 ArrayRefParameter<"bool">:$scalableDims
   );
   let builders = [
@@ -1173,6 +1174,7 @@ def Builtin_Vector : Builtin_Type<"Vector", "vector",
 /// type. In particular, vectors can consist of integer, index, or float
 /// primitives.
 static bool isValidElementType(Type t) {
+  // TODO: Auto-generate this function from $elementType.
   return ::llvm::isa(t);
 }
 
diff --git a/mlir/lib/AsmParser/TypeParser.cpp 
b/mlir/lib/AsmParser/TypeParser.cpp
index 542eaeefe57f1..f070c072c4329 100644
--- a/mlir/lib/AsmParser/TypeParser.cpp
+++ b/mlir/lib/AsmParser/TypeParser.cpp
@@ -458,31 +458,24 @@ Type Parser::parseTupleType() {
 /// static-dim-list ::= decimal-literal (`x` decimal-literal)*
 ///
 VectorType Parser::parseVectorType() {
+  SMLoc loc = getToken().getLoc();
   consumeToken(Token::kw_vector);
 
   if (parseToken(Token::less, "expected '<' in vector type"))
 return nullptr;
 
+  // Parse the dimensions.
   SmallVector dimensions;
   SmallVector scalableDims;
   if (parseVectorDimensionList(dimensions, scalableDims))
 return nullptr;
-  if (any_of(dimensions, [](int64_t i) { return i <= 0; }))
-return emitError(getToken().getLoc(),
- "vector types must have positive constant sizes"),
-   nullptr;
 
   // Parse the element type.
-  auto typeLoc = getToken().getLoc();
   auto elementType = parseType();
   if (!elementType || parseToken(Token::greater, "expected '>' in vector 
type"))
 return nullptr;
 
-  if (!VectorType::isValidElementType(elementType))
-return emitError(typeLoc, "vector elements must be int/index/float type"),
-   nullptr;
-
-  return VectorType::get(dimensions, elementType, scalableDims);
+  return getChecked(loc, dimensions, elementType, scalableDims);
 }
 
 /// Parse a dimension list in a vector type. This populates the dimension list.
diff --git a/mlir/test/IR/invalid-builtin-types.mlir 
b/mlir/test/IR/invalid-builtin-types.mlir
index 9884212e916c1..07854a25000fe 100644
--- a/mlir/test/IR/invalid-builtin-types.mlir
+++ b/mlir/test/IR/invalid-builtin-types.mlir
@@ -120,17 +120,17 @@ func.func @illegaltype(i21312312323120) // expected-error 
{{invalid integer widt
 // -
 
 // Test no nested vector.
-// expected-error@+1 {{vector elements must be int/index/float type}}
+// expected-error@+1 {{failed to verify 'elementType': integer or index or 
floating-point}}
 func.func @vectors(vector<1 x vector<1xi32>>, vector<2x4xf32>)
 
 // -
 
-// expected-error @+1 {{vector types must have positive constant sizes}}
+// expected-error @+1 {{vector types must have positive constant sizes but got 
0}}
 func.func @zero_vector_type() -> vector<0xi32>
 
 // -
 
-// expected-error @+1 {{vector types must have positive constant sizes}}
+// expected-error @+1 {{vector types must have positive constant sizes but got 
1, 0}}
 func.func @zero_in_vector_type() -> vector<1x0xi32>
 
 // -
diff --git a/mlir/test/python/ir/builtin_types.py 
b/mlir/test/python/ir/builtin_types.py
index 2161f110ac31e..f9554105e 100644
--- a/mlir/test/python/ir/builtin_types.py
+++ b/mlir/test/python/ir/builtin_types.py
@@ -345,7 +345,7 @@ def testVectorType():
 VectorType.get(shape, none)
 except MLIRError as e:
 # CHECK: Invalid type:
-# CHECK: error: unknown: vector elements must be int/index/float 
type but got 'none'
+# CHECK: error: unknown: failed to verify 'elementType': integer 
or index or floating-point
 print(e)
 else:
 print("Exception not produced")


[llvm-branch-commits] [mlir] [mlir][ODS] Verify type constraints in Types and Attributes (PR #102326)

2024-08-09 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/102326
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][ODS] Verify type constraints in Types and Attributes (PR #102326)

2024-08-09 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/102326
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][ODS] Verify type constraints in Types and Attributes (PR #102326)

2024-08-09 Thread Matthias Springer via llvm-branch-commits


@@ -153,6 +153,9 @@ class TypeConstraint {
   // The name of the C++ Type class if known, or Type if not.
   string cppClassName = cppClassNameParam;
+  // TODO: This field is sometimes called `cppClassName` and sometimes

matthias-springer wrote:

Fixed in #102657.

https://github.com/llvm/llvm-project/pull/102326
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][IR] Auto-generate element type verification for VectorType (PR #102449)

2024-08-09 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/102449

>From c399a1c6e82afcfcc2ad531cb49d53683f294f91 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 8 Aug 2024 12:28:23 +0200
Subject: [PATCH] [mlir][IR] Auto-generate element type verification for
 VectorType

---
 mlir/include/mlir/IR/BuiltinTypes.td|  4 +++-
 mlir/lib/AsmParser/TypeParser.cpp   | 13 +++--
 mlir/test/IR/invalid-builtin-types.mlir |  6 +++---
 mlir/test/python/ir/builtin_types.py|  2 +-
 4 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/mlir/include/mlir/IR/BuiltinTypes.td 
b/mlir/include/mlir/IR/BuiltinTypes.td
index 365edcf68d8b94..4b3add2035263c 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -17,6 +17,7 @@
 include "mlir/IR/AttrTypeBase.td"
 include "mlir/IR/BuiltinDialect.td"
 include "mlir/IR/BuiltinTypeInterfaces.td"
+include "mlir/IR/CommonTypeConstraints.td"
 
 // TODO: Currently the types defined in this file are prefixed with `Builtin_`.
 // This is to differentiate the types here with the ones in OpBase.td. We 
should
@@ -1146,7 +1147,7 @@ def Builtin_Vector : Builtin_Type<"Vector", "vector",
   }];
   let parameters = (ins
 ArrayRefParameter<"int64_t">:$shape,
-"Type":$elementType,
+AnyTypeOf<[AnyInteger, Index, AnyFloat]>:$elementType,
 ArrayRefParameter<"bool">:$scalableDims
   );
   let builders = [
@@ -1173,6 +1174,7 @@ def Builtin_Vector : Builtin_Type<"Vector", "vector",
 /// type. In particular, vectors can consist of integer, index, or float
 /// primitives.
 static bool isValidElementType(Type t) {
+  // TODO: Auto-generate this function from $elementType.
   return ::llvm::isa(t);
 }
 
diff --git a/mlir/lib/AsmParser/TypeParser.cpp 
b/mlir/lib/AsmParser/TypeParser.cpp
index 542eaeefe57f12..f070c072c43296 100644
--- a/mlir/lib/AsmParser/TypeParser.cpp
+++ b/mlir/lib/AsmParser/TypeParser.cpp
@@ -458,31 +458,24 @@ Type Parser::parseTupleType() {
 /// static-dim-list ::= decimal-literal (`x` decimal-literal)*
 ///
 VectorType Parser::parseVectorType() {
+  SMLoc loc = getToken().getLoc();
   consumeToken(Token::kw_vector);
 
   if (parseToken(Token::less, "expected '<' in vector type"))
 return nullptr;
 
+  // Parse the dimensions.
   SmallVector dimensions;
   SmallVector scalableDims;
   if (parseVectorDimensionList(dimensions, scalableDims))
 return nullptr;
-  if (any_of(dimensions, [](int64_t i) { return i <= 0; }))
-return emitError(getToken().getLoc(),
- "vector types must have positive constant sizes"),
-   nullptr;
 
   // Parse the element type.
-  auto typeLoc = getToken().getLoc();
   auto elementType = parseType();
   if (!elementType || parseToken(Token::greater, "expected '>' in vector 
type"))
 return nullptr;
 
-  if (!VectorType::isValidElementType(elementType))
-return emitError(typeLoc, "vector elements must be int/index/float type"),
-   nullptr;
-
-  return VectorType::get(dimensions, elementType, scalableDims);
+  return getChecked(loc, dimensions, elementType, scalableDims);
 }
 
 /// Parse a dimension list in a vector type. This populates the dimension list.
diff --git a/mlir/test/IR/invalid-builtin-types.mlir 
b/mlir/test/IR/invalid-builtin-types.mlir
index 9884212e916c1f..07854a25000feb 100644
--- a/mlir/test/IR/invalid-builtin-types.mlir
+++ b/mlir/test/IR/invalid-builtin-types.mlir
@@ -120,17 +120,17 @@ func.func @illegaltype(i21312312323120) // expected-error 
{{invalid integer widt
 // -
 
 // Test no nested vector.
-// expected-error@+1 {{vector elements must be int/index/float type}}
+// expected-error@+1 {{failed to verify 'elementType': integer or index or 
floating-point}}
 func.func @vectors(vector<1 x vector<1xi32>>, vector<2x4xf32>)
 
 // -
 
-// expected-error @+1 {{vector types must have positive constant sizes}}
+// expected-error @+1 {{vector types must have positive constant sizes but got 
0}}
 func.func @zero_vector_type() -> vector<0xi32>
 
 // -
 
-// expected-error @+1 {{vector types must have positive constant sizes}}
+// expected-error @+1 {{vector types must have positive constant sizes but got 
1, 0}}
 func.func @zero_in_vector_type() -> vector<1x0xi32>
 
 // -
diff --git a/mlir/test/python/ir/builtin_types.py 
b/mlir/test/python/ir/builtin_types.py
index 2161f110ac31e2..f9554105ed 100644
--- a/mlir/test/python/ir/builtin_types.py
+++ b/mlir/test/python/ir/builtin_types.py
@@ -345,7 +345,7 @@ def testVectorType():
 VectorType.get(shape, none)
 except MLIRError as e:
 # CHECK: Invalid type:
-# CHECK: error: unknown: vector elements must be int/index/float 
type but got 'none'
+# CHECK: error: unknown: failed to verify 'elementType': integer 
or index or floating-point
 print(e)
 else:
 print("Exception not produced")


[llvm-branch-commits] [mlir] [mlir][Transforms][WIP] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/104668
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][WIP] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/104668

>From ca2db3fa01051a6e9b74e22efc3adbbff585f8f4 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Sat, 17 Aug 2024 11:38:40 +0200
Subject: [PATCH] [mlir][Transforms][WIP] Dialect conversion: Make
 materializations optional

Build all source/target/argument materializations after the conversion has 
succeeded. Provide a new configuration option for users to opt out of all 
automatic materializations. In that case, the resulting IR will have 
`builtin.unrealized_conversion_cast` ops.
---
 .../Transforms/Utils/DialectConversion.cpp| 382 --
 .../Conversion/NVGPUToNVVM/nvgpu-to-nvvm.mlir |   5 +-
 .../Transforms/finalizing-bufferize.mlir  |   1 +
 .../test-legalize-type-conversion.mlir|   6 +-
 4 files changed, 94 insertions(+), 300 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 6238a257b2ffda..1f9b78963403a8 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -702,14 +702,8 @@ class UnresolvedMaterializationRewrite : public 
OperationRewrite {
 return rewrite->getKind() == Kind::UnresolvedMaterialization;
   }
 
-  UnrealizedConversionCastOp getOperation() const {
-return cast(op);
-  }
-
   void rollback() override;
 
-  void cleanup(RewriterBase &rewriter) override;
-
   /// Return the type converter of this materialization (which may be null).
   const TypeConverter *getConverter() const {
 return converterAndKind.getPointer();
@@ -766,7 +760,7 @@ namespace detail {
 struct ConversionPatternRewriterImpl : public RewriterBase::Listener {
   explicit ConversionPatternRewriterImpl(MLIRContext *ctx,
  const ConversionConfig &config)
-  : context(ctx), config(config) {}
+  : context(ctx), eraseRewriter(ctx), config(config) {}
 
   
//======//
   // State Management
@@ -834,6 +828,7 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   
//======//
   // Materializations
   
//======//
+
   /// Build an unresolved materialization operation given an output type and 
set
   /// of input operands.
   Value buildUnresolvedMaterialization(MaterializationKind kind,
@@ -877,8 +872,8 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// no new IR is created between calls to `eraseOp`/`eraseBlock`.
   struct SingleEraseRewriter : public RewriterBase, RewriterBase::Listener {
   public:
-SingleEraseRewriter(MLIRContext *context)
-: RewriterBase(context, /*listener=*/this) {}
+SingleEraseRewriter(MLIRContext *ctx)
+: RewriterBase(ctx, /*listener=*/this) {}
 
 /// Erase the given op (unless it was already erased).
 void eraseOp(Operation *op) override {
@@ -912,6 +907,8 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// MLIR context.
   MLIRContext *context;
 
+  SingleEraseRewriter eraseRewriter;
+
   // Mapping between replaced values that differ in type. This happens when
   // replacing a value with one of a different type.
   ConversionValueMapping mapping;
@@ -1058,10 +1055,6 @@ void UnresolvedMaterializationRewrite::rollback() {
   op->erase();
 }
 
-void UnresolvedMaterializationRewrite::cleanup(RewriterBase &rewriter) {
-  rewriter.eraseOp(op);
-}
-
 void ConversionPatternRewriterImpl::applyRewrites() {
   // Commit all rewrites.
   IRRewriter rewriter(context, config.listener);
@@ -1069,7 +1062,6 @@ void ConversionPatternRewriterImpl::applyRewrites() {
 rewrite->commit(rewriter);
 
   // Clean up all rewrites.
-  SingleEraseRewriter eraseRewriter(context);
   for (auto &rewrite : rewrites)
 rewrite->cleanup(eraseRewriter);
 }
@@ -2354,12 +2346,6 @@ struct OperationConverter {
   ConversionPatternRewriterImpl &rewriterImpl,
   DenseMap> &inverseMapping);
 
-  /// Legalize any unresolved type materializations.
-  LogicalResult legalizeUnresolvedMaterializations(
-  ConversionPatternRewriter &rewriter,
-  ConversionPatternRewriterImpl &rewriterImpl,
-  DenseMap> &inverseMapping);
-
   /// Legalize an operation result that was marked as "erased".
   LogicalResult
   legalizeErasedResult(Operation *op, OpResult result,
@@ -2406,6 +2392,57 @@ LogicalResult 
OperationConverter::convert(ConversionPatternRewriter &rewriter,
   return success();
 }
 
+static LogicalResult
+legalizeUnresolvedMaterialization(RewriterBase &rewriter,
+  UnresolvedMaterializationRewrite *rewrite) {
+  UnrealizedConversionCastOp op =
+  cast(rewrite->getOperation());
+  assert(!op.use_empty() &&
+ "expected that dead materiali

[llvm-branch-commits] [mlir] [mlir][Transforms][WIP] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/104668

>From 26c00f29b320e95f314372cae557cc0294796863 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Sat, 17 Aug 2024 11:38:40 +0200
Subject: [PATCH] [mlir][Transforms][WIP] Dialect conversion: Make
 materializations optional

Build all source/target/argument materializations after the conversion has 
succeeded. Provide a new configuration option for users to opt out of all 
automatic materializations. In that case, the resulting IR will have 
`builtin.unrealized_conversion_cast` ops.
---
 .../Transforms/Utils/DialectConversion.cpp| 382 --
 .../Conversion/NVGPUToNVVM/nvgpu-to-nvvm.mlir |   5 +-
 .../Transforms/finalizing-bufferize.mlir  |   1 +
 .../test-legalize-type-conversion.mlir|   6 +-
 4 files changed, 94 insertions(+), 300 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 6238a257b2ffda..1f9b78963403a8 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -702,14 +702,8 @@ class UnresolvedMaterializationRewrite : public 
OperationRewrite {
 return rewrite->getKind() == Kind::UnresolvedMaterialization;
   }
 
-  UnrealizedConversionCastOp getOperation() const {
-return cast(op);
-  }
-
   void rollback() override;
 
-  void cleanup(RewriterBase &rewriter) override;
-
   /// Return the type converter of this materialization (which may be null).
   const TypeConverter *getConverter() const {
 return converterAndKind.getPointer();
@@ -766,7 +760,7 @@ namespace detail {
 struct ConversionPatternRewriterImpl : public RewriterBase::Listener {
   explicit ConversionPatternRewriterImpl(MLIRContext *ctx,
  const ConversionConfig &config)
-  : context(ctx), config(config) {}
+  : context(ctx), eraseRewriter(ctx), config(config) {}
 
   
//======//
   // State Management
@@ -834,6 +828,7 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   
//======//
   // Materializations
   
//======//
+
   /// Build an unresolved materialization operation given an output type and 
set
   /// of input operands.
   Value buildUnresolvedMaterialization(MaterializationKind kind,
@@ -877,8 +872,8 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// no new IR is created between calls to `eraseOp`/`eraseBlock`.
   struct SingleEraseRewriter : public RewriterBase, RewriterBase::Listener {
   public:
-SingleEraseRewriter(MLIRContext *context)
-: RewriterBase(context, /*listener=*/this) {}
+SingleEraseRewriter(MLIRContext *ctx)
+: RewriterBase(ctx, /*listener=*/this) {}
 
 /// Erase the given op (unless it was already erased).
 void eraseOp(Operation *op) override {
@@ -912,6 +907,8 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// MLIR context.
   MLIRContext *context;
 
+  SingleEraseRewriter eraseRewriter;
+
   // Mapping between replaced values that differ in type. This happens when
   // replacing a value with one of a different type.
   ConversionValueMapping mapping;
@@ -1058,10 +1055,6 @@ void UnresolvedMaterializationRewrite::rollback() {
   op->erase();
 }
 
-void UnresolvedMaterializationRewrite::cleanup(RewriterBase &rewriter) {
-  rewriter.eraseOp(op);
-}
-
 void ConversionPatternRewriterImpl::applyRewrites() {
   // Commit all rewrites.
   IRRewriter rewriter(context, config.listener);
@@ -1069,7 +1062,6 @@ void ConversionPatternRewriterImpl::applyRewrites() {
 rewrite->commit(rewriter);
 
   // Clean up all rewrites.
-  SingleEraseRewriter eraseRewriter(context);
   for (auto &rewrite : rewrites)
 rewrite->cleanup(eraseRewriter);
 }
@@ -2354,12 +2346,6 @@ struct OperationConverter {
   ConversionPatternRewriterImpl &rewriterImpl,
   DenseMap> &inverseMapping);
 
-  /// Legalize any unresolved type materializations.
-  LogicalResult legalizeUnresolvedMaterializations(
-  ConversionPatternRewriter &rewriter,
-  ConversionPatternRewriterImpl &rewriterImpl,
-  DenseMap> &inverseMapping);
-
   /// Legalize an operation result that was marked as "erased".
   LogicalResult
   legalizeErasedResult(Operation *op, OpResult result,
@@ -2406,6 +2392,57 @@ LogicalResult 
OperationConverter::convert(ConversionPatternRewriter &rewriter,
   return success();
 }
 
+static LogicalResult
+legalizeUnresolvedMaterialization(RewriterBase &rewriter,
+  UnresolvedMaterializationRewrite *rewrite) {
+  UnrealizedConversionCastOp op =
+  cast(rewrite->getOperation());
+  assert(!op.use_empty() &&
+ "expected that dead materiali

[llvm-branch-commits] [mlir] [mlir][Transforms][WIP] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/104668

>From 2658d44d5c8aab38f39c34dc99a8e874c6794b75 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Sat, 17 Aug 2024 11:38:40 +0200
Subject: [PATCH] [mlir][Transforms][WIP] Dialect conversion: Make
 materializations optional

Build all source/target/argument materializations after the conversion has 
succeeded. Provide a new configuration option for users to opt out of all 
automatic materializations. In that case, the resulting IR will have 
`builtin.unrealized_conversion_cast` ops.
---
 .../mlir/Transforms/DialectConversion.h   |  11 +
 .../Transforms/Utils/DialectConversion.cpp| 380 --
 .../Conversion/NVGPUToNVVM/nvgpu-to-nvvm.mlir |   5 +-
 .../Transforms/finalizing-bufferize.mlir  |   1 +
 .../test-legalize-type-conversion.mlir|   6 +-
 5 files changed, 105 insertions(+), 298 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 60113bdef16a23..5f680e8eca7559 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -1124,6 +1124,17 @@ struct ConversionConfig {
   // already been modified) and iterators into past IR state cannot be
   // represented at the moment.
   RewriterBase::Listener *listener = nullptr;
+
+  /// If set to "true", the dialect conversion attempts to build source/target/
+  /// argument materializations through the type converter API in lieu of
+  /// builtin.unrealized_conversion_cast ops. The conversion process fails if
+  /// at least one materialization could not be built.
+  ///
+  /// If set to "false", the dialect conversion does not does not build any
+  /// custom materializations and instead inserts
+  /// builtin.unrealized_conversion_cast ops to ensure that the resulting IR
+  /// is valid.
+  bool buildMaterializations = true;
 };
 
 
//===--===//
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 6238a257b2ffda..dd6109c9fe6cfc 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -702,14 +702,8 @@ class UnresolvedMaterializationRewrite : public 
OperationRewrite {
 return rewrite->getKind() == Kind::UnresolvedMaterialization;
   }
 
-  UnrealizedConversionCastOp getOperation() const {
-return cast(op);
-  }
-
   void rollback() override;
 
-  void cleanup(RewriterBase &rewriter) override;
-
   /// Return the type converter of this materialization (which may be null).
   const TypeConverter *getConverter() const {
 return converterAndKind.getPointer();
@@ -766,7 +760,7 @@ namespace detail {
 struct ConversionPatternRewriterImpl : public RewriterBase::Listener {
   explicit ConversionPatternRewriterImpl(MLIRContext *ctx,
  const ConversionConfig &config)
-  : context(ctx), config(config) {}
+  : context(ctx), eraseRewriter(ctx), config(config) {}
 
   
//======//
   // State Management
@@ -834,6 +828,7 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   
//======//
   // Materializations
   
//======//
+
   /// Build an unresolved materialization operation given an output type and 
set
   /// of input operands.
   Value buildUnresolvedMaterialization(MaterializationKind kind,
@@ -912,6 +907,8 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// MLIR context.
   MLIRContext *context;
 
+  SingleEraseRewriter eraseRewriter;
+
   // Mapping between replaced values that differ in type. This happens when
   // replacing a value with one of a different type.
   ConversionValueMapping mapping;
@@ -1058,10 +1055,6 @@ void UnresolvedMaterializationRewrite::rollback() {
   op->erase();
 }
 
-void UnresolvedMaterializationRewrite::cleanup(RewriterBase &rewriter) {
-  rewriter.eraseOp(op);
-}
-
 void ConversionPatternRewriterImpl::applyRewrites() {
   // Commit all rewrites.
   IRRewriter rewriter(context, config.listener);
@@ -1069,7 +1062,6 @@ void ConversionPatternRewriterImpl::applyRewrites() {
 rewrite->commit(rewriter);
 
   // Clean up all rewrites.
-  SingleEraseRewriter eraseRewriter(context);
   for (auto &rewrite : rewrites)
 rewrite->cleanup(eraseRewriter);
 }
@@ -2354,12 +2346,6 @@ struct OperationConverter {
   ConversionPatternRewriterImpl &rewriterImpl,
   DenseMap> &inverseMapping);
 
-  /// Legalize any unresolved type materializations.
-  LogicalResult legalizeUnresolvedMaterializations(
-  ConversionPatternRewriter &rewriter,
-  ConversionPatternRewriterImp

[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/104668
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/104668
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/104668
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/104668
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/104668

>From f72f6427871531a135e6621c520b05570dfa3bcb Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Sat, 17 Aug 2024 11:38:40 +0200
Subject: [PATCH] [mlir][Transforms][WIP] Dialect conversion: Make
 materializations optional

Build all source/target/argument materializations after the conversion has 
succeeded. Provide a new configuration option for users to opt out of all 
automatic materializations. In that case, the resulting IR will have 
`builtin.unrealized_conversion_cast` ops.
---
 .../mlir/Transforms/DialectConversion.h   |  11 +
 .../Transforms/Utils/DialectConversion.cpp| 383 --
 .../Conversion/NVGPUToNVVM/nvgpu-to-nvvm.mlir |   5 +-
 .../Transforms/finalizing-bufferize.mlir  |   1 +
 .../test-legalize-type-conversion.mlir|   6 +-
 5 files changed, 108 insertions(+), 298 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 60113bdef16a23..5f680e8eca7559 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -1124,6 +1124,17 @@ struct ConversionConfig {
   // already been modified) and iterators into past IR state cannot be
   // represented at the moment.
   RewriterBase::Listener *listener = nullptr;
+
+  /// If set to "true", the dialect conversion attempts to build source/target/
+  /// argument materializations through the type converter API in lieu of
+  /// builtin.unrealized_conversion_cast ops. The conversion process fails if
+  /// at least one materialization could not be built.
+  ///
+  /// If set to "false", the dialect conversion does not does not build any
+  /// custom materializations and instead inserts
+  /// builtin.unrealized_conversion_cast ops to ensure that the resulting IR
+  /// is valid.
+  bool buildMaterializations = true;
 };
 
 
//===--===//
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 6238a257b2ffda..f710116186e741 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -702,14 +702,8 @@ class UnresolvedMaterializationRewrite : public 
OperationRewrite {
 return rewrite->getKind() == Kind::UnresolvedMaterialization;
   }
 
-  UnrealizedConversionCastOp getOperation() const {
-return cast(op);
-  }
-
   void rollback() override;
 
-  void cleanup(RewriterBase &rewriter) override;
-
   /// Return the type converter of this materialization (which may be null).
   const TypeConverter *getConverter() const {
 return converterAndKind.getPointer();
@@ -766,7 +760,7 @@ namespace detail {
 struct ConversionPatternRewriterImpl : public RewriterBase::Listener {
   explicit ConversionPatternRewriterImpl(MLIRContext *ctx,
  const ConversionConfig &config)
-  : context(ctx), config(config) {}
+  : context(ctx), eraseRewriter(ctx), config(config) {}
 
   
//======//
   // State Management
@@ -834,6 +828,7 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   
//======//
   // Materializations
   
//======//
+
   /// Build an unresolved materialization operation given an output type and 
set
   /// of input operands.
   Value buildUnresolvedMaterialization(MaterializationKind kind,
@@ -912,6 +907,11 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// MLIR context.
   MLIRContext *context;
 
+  /// A rewriter that keeps track of ops/block that were already erased and
+  /// skips duplicate op/block erasures. This rewriter is used during the
+  /// "cleanup" phase.
+  SingleEraseRewriter eraseRewriter;
+
   // Mapping between replaced values that differ in type. This happens when
   // replacing a value with one of a different type.
   ConversionValueMapping mapping;
@@ -1058,10 +1058,6 @@ void UnresolvedMaterializationRewrite::rollback() {
   op->erase();
 }
 
-void UnresolvedMaterializationRewrite::cleanup(RewriterBase &rewriter) {
-  rewriter.eraseOp(op);
-}
-
 void ConversionPatternRewriterImpl::applyRewrites() {
   // Commit all rewrites.
   IRRewriter rewriter(context, config.listener);
@@ -1069,7 +1065,6 @@ void ConversionPatternRewriterImpl::applyRewrites() {
 rewrite->commit(rewriter);
 
   // Clean up all rewrites.
-  SingleEraseRewriter eraseRewriter(context);
   for (auto &rewrite : rewrites)
 rewrite->cleanup(eraseRewriter);
 }
@@ -2354,12 +2349,6 @@ struct OperationConverter {
   ConversionPatternRewriterImpl &rewriterImpl,
   DenseMap> &inverseMapping);
 
-  /// Le

[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Make materializations optional (PR #104668)

2024-08-17 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer ready_for_review 
https://github.com/llvm/llvm-project/pull/104668
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Modularize block actions (PR #81237)

2024-02-09 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81237

Throughout the rewrite process, the dialect conversion maintains a list of 
"block actions" that can be rolled back upon failure. This commit encapsulates 
the existing block actions into separate classes, making it easier to add 
additional actions in the future.

This commit also renames "block actions" to "rewrite actions". In a subsequent 
commit, an "operation action" that allows rolling back movements of single 
operations is added. This is to support `moveOpBefore` in the dialect 
conversion.

Rewrite actions have two methods: `commit()` commits an action. It can no 
longer be rolled back afterwards. `rollback()` undoes an action. It can no 
longer be committed afterwards.

>From 956717ee48940279edfbe84794d6f9575c14d075 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 9 Feb 2024 09:29:10 +
Subject: [PATCH] [mlir][Transforms][NFC] Modularize block actions

Throughout the rewrite process, the dialect conversion maintains a list
of "block actions" that can be rolled back upon failure. This commit
encapsulates the existing block actions into separate classes, making it
easier to add additional actions in the future.

This commit also renames "block actions" to "rewrite actions". In a
subsequent commit, an "operation action" that allows rolling back
movements of single operations is added. This is to support
`moveOpBefore` in the dialect conversion.

Rewrite actions have two methods: `commit()` commits an action. It can
no longer be rolled back afterwards. `rollback()` undoes an action. It
can no longer be committed afterwards.
---
 .../Transforms/Utils/DialectConversion.cpp| 466 +++---
 1 file changed, 283 insertions(+), 183 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index e41231d7cbd390..44c107c8733f3d 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,13 +154,13 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numBlockActions, unsigned numIgnoredOperations,
+unsigned numRewriteActions, unsigned numIgnoredOperations,
 unsigned numRootUpdates)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
 numArgReplacements(numArgReplacements),
-numBlockActions(numBlockActions),
+numRewriteActions(numRewriteActions),
 numIgnoredOperations(numIgnoredOperations),
 numRootUpdates(numRootUpdates) {}
 
@@ -176,8 +176,8 @@ struct RewriterState {
   /// The current number of argument replacements queued.
   unsigned numArgReplacements;
 
-  /// The current number of block actions performed.
-  unsigned numBlockActions;
+  /// The current number of rewrite actions performed.
+  unsigned numRewriteActions;
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
@@ -235,86 +235,6 @@ struct OpReplacement {
   const TypeConverter *converter;
 };
 
-//===--===//
-// BlockAction
-
-/// The kind of the block action performed during the rewrite.  Actions can be
-/// undone if the conversion fails.
-enum class BlockActionKind {
-  Create,
-  Erase,
-  Inline,
-  Move,
-  Split,
-  TypeConversion
-};
-
-/// Original position of the given block in its parent region. During undo
-/// actions, the block needs to be placed before `insertBeforeBlock`.
-struct BlockPosition {
-  Region *region;
-  Block *insertBeforeBlock;
-};
-
-/// Information needed to undo inlining actions.
-/// - the source block
-/// - the first inlined operation (could be null if the source block was empty)
-/// - the last inlined operation (could be null if the source block was empty)
-struct InlineInfo {
-  Block *sourceBlock;
-  Operation *firstInlinedInst;
-  Operation *lastInlinedInst;
-};
-
-/// The storage class for an undoable block action (one of BlockActionKind),
-/// contains the information necessary to undo this action.
-struct BlockAction {
-  static BlockAction getCreate(Block *block) {
-return {BlockActionKind::Create, block, {}};
-  }
-  static BlockAction getErase(Block *block, BlockPosition originalPosition) {
-return {BlockActionKind::Erase, block, {originalPosition}};
-  }
-  static BlockAction getInline(Block *block, Block *srcBlock,
-   Block::iterator before) {
-BlockAction action{BlockActionKind::Inline, block, {}};
-action.inlineInfo = {srcBlock,
- srcBlock->empty() ? nullptr : &srcBlock->front(),
- srcBlock->empty() ? nullptr : &srcBlock-

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Modularize block actions (PR #81237)

2024-02-09 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81237

>From ae9dcbbcf4a23cd9f5a28195ceb3687957fa730f Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 9 Feb 2024 09:29:10 +
Subject: [PATCH] [mlir][Transforms][NFC] Modularize block actions

Throughout the rewrite process, the dialect conversion maintains a list
of "block actions" that can be rolled back upon failure. This commit
encapsulates the existing block actions into separate classes, making it
easier to add additional actions in the future.

This commit also renames "block actions" to "rewrite actions". In a
subsequent commit, an "operation action" that allows rolling back
movements of single operations is added. This is to support
`moveOpBefore` in the dialect conversion.

Rewrite actions have two methods: `commit()` commits an action. It can
no longer be rolled back afterwards. `rollback()` undoes an action. It
can no longer be committed afterwards.
---
 .../Transforms/Utils/DialectConversion.cpp| 466 +++---
 1 file changed, 283 insertions(+), 183 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index e41231d7cbd390..44c107c8733f3d 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,13 +154,13 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numBlockActions, unsigned numIgnoredOperations,
+unsigned numRewriteActions, unsigned numIgnoredOperations,
 unsigned numRootUpdates)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
 numArgReplacements(numArgReplacements),
-numBlockActions(numBlockActions),
+numRewriteActions(numRewriteActions),
 numIgnoredOperations(numIgnoredOperations),
 numRootUpdates(numRootUpdates) {}
 
@@ -176,8 +176,8 @@ struct RewriterState {
   /// The current number of argument replacements queued.
   unsigned numArgReplacements;
 
-  /// The current number of block actions performed.
-  unsigned numBlockActions;
+  /// The current number of rewrite actions performed.
+  unsigned numRewriteActions;
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
@@ -235,86 +235,6 @@ struct OpReplacement {
   const TypeConverter *converter;
 };
 
-//===--===//
-// BlockAction
-
-/// The kind of the block action performed during the rewrite.  Actions can be
-/// undone if the conversion fails.
-enum class BlockActionKind {
-  Create,
-  Erase,
-  Inline,
-  Move,
-  Split,
-  TypeConversion
-};
-
-/// Original position of the given block in its parent region. During undo
-/// actions, the block needs to be placed before `insertBeforeBlock`.
-struct BlockPosition {
-  Region *region;
-  Block *insertBeforeBlock;
-};
-
-/// Information needed to undo inlining actions.
-/// - the source block
-/// - the first inlined operation (could be null if the source block was empty)
-/// - the last inlined operation (could be null if the source block was empty)
-struct InlineInfo {
-  Block *sourceBlock;
-  Operation *firstInlinedInst;
-  Operation *lastInlinedInst;
-};
-
-/// The storage class for an undoable block action (one of BlockActionKind),
-/// contains the information necessary to undo this action.
-struct BlockAction {
-  static BlockAction getCreate(Block *block) {
-return {BlockActionKind::Create, block, {}};
-  }
-  static BlockAction getErase(Block *block, BlockPosition originalPosition) {
-return {BlockActionKind::Erase, block, {originalPosition}};
-  }
-  static BlockAction getInline(Block *block, Block *srcBlock,
-   Block::iterator before) {
-BlockAction action{BlockActionKind::Inline, block, {}};
-action.inlineInfo = {srcBlock,
- srcBlock->empty() ? nullptr : &srcBlock->front(),
- srcBlock->empty() ? nullptr : &srcBlock->back()};
-return action;
-  }
-  static BlockAction getMove(Block *block, BlockPosition originalPosition) {
-return {BlockActionKind::Move, block, {originalPosition}};
-  }
-  static BlockAction getSplit(Block *block, Block *originalBlock) {
-BlockAction action{BlockActionKind::Split, block, {}};
-action.originalBlock = originalBlock;
-return action;
-  }
-  static BlockAction getTypeConversion(Block *block) {
-return BlockAction{BlockActionKind::TypeConversion, block, {}};
-  }
-
-  // The action kind.
-  BlockActionKind kind;
-
-  // A pointer to the block that was created by the action.
-  Block *block;
-
-  union {
-// In use if kind == BlockActionK

[llvm-branch-commits] [mlir] [mlir][Transforms] Support `moveOpBefore`/`After` in dialect conversion (PR #81240)

2024-02-09 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81240

Add a new rewrite action for "operation movements". This action can roll back 
`moveOpBefore` and `moveOpAfter`.

`RewriterBase::moveOpBefore` and `RewriterBase::moveOpAfter` is no longer 
virtual. (The dialect conversion can gather all required information for 
rollbacks from listener notifications.)


>From 7503c0cb484c54249ff66c5780197d46937c660d Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 9 Feb 2024 09:58:46 +
Subject: [PATCH] [mlir][Transforms] Support `moveOpBefore`/`After` in dialect
 conversion

Add a new rewrite action for "operation movements". This action can roll back 
`moveOpBefore` and `moveOpAfter`.

`RewriterBase::moveOpBefore` and `RewriterBase::moveOpAfter` is no longer 
virtual. (The dialect conversion can gather all required information for 
rollbacks from listener notifications.)
---
 mlir/include/mlir/IR/PatternMatch.h   |  6 +-
 .../mlir/Transforms/DialectConversion.h   |  5 --
 .../Transforms/Utils/DialectConversion.cpp| 74 +++
 mlir/test/Transforms/test-legalizer.mlir  | 14 
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   | 20 -
 5 files changed, 93 insertions(+), 26 deletions(-)

diff --git a/mlir/include/mlir/IR/PatternMatch.h 
b/mlir/include/mlir/IR/PatternMatch.h
index 78dcfe7f6fc3d2..b8aeea0d23475b 100644
--- a/mlir/include/mlir/IR/PatternMatch.h
+++ b/mlir/include/mlir/IR/PatternMatch.h
@@ -588,8 +588,7 @@ class RewriterBase : public OpBuilder {
 
   /// Unlink this operation from its current block and insert it right before
   /// `iterator` in the specified block.
-  virtual void moveOpBefore(Operation *op, Block *block,
-Block::iterator iterator);
+  void moveOpBefore(Operation *op, Block *block, Block::iterator iterator);
 
   /// Unlink this operation from its current block and insert it right after
   /// `existingOp` which may be in the same or another block in the same
@@ -598,8 +597,7 @@ class RewriterBase : public OpBuilder {
 
   /// Unlink this operation from its current block and insert it right after
   /// `iterator` in the specified block.
-  virtual void moveOpAfter(Operation *op, Block *block,
-   Block::iterator iterator);
+  void moveOpAfter(Operation *op, Block *block, Block::iterator iterator);
 
   /// Unlink this block and insert it right before `existingBlock`.
   void moveBlockBefore(Block *block, Block *anotherBlock);
diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index f061d761ecefbb..c0c702a7d34821 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -738,11 +738,6 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
   // Hide unsupported pattern rewriter API.
   using OpBuilder::setListener;
 
-  void moveOpBefore(Operation *op, Block *block,
-Block::iterator iterator) override;
-  void moveOpAfter(Operation *op, Block *block,
-   Block::iterator iterator) override;
-
   std::unique_ptr impl;
 };
 
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 44c107c8733f3d..ffdb069f6e9b81 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -757,7 +757,8 @@ class RewriteAction {
 InlineBlock,
 MoveBlock,
 SplitBlock,
-BlockTypeConversion
+BlockTypeConversion,
+MoveOperation
   };
 
   virtual ~RewriteAction() = default;
@@ -970,6 +971,54 @@ class BlockTypeConversionAction : public BlockAction {
 
   void rollback() override;
 };
+
+/// An operation rewrite.
+class OperationAction : public RewriteAction {
+public:
+  /// Return the operation that this action operates on.
+  Operation *getOperation() const { return op; }
+
+  static bool classof(const RewriteAction *action) {
+return action->getKind() >= Kind::MoveOperation &&
+   action->getKind() <= Kind::MoveOperation;
+  }
+
+protected:
+  OperationAction(Kind kind, ConversionPatternRewriterImpl &rewriterImpl,
+  Operation *op)
+  : RewriteAction(kind, rewriterImpl), op(op) {}
+
+  // The operation that this action operates on.
+  Operation *op;
+};
+
+/// Rewrite action that represent the moving of a block.
+class MoveOperationAction : public OperationAction {
+public:
+  MoveOperationAction(ConversionPatternRewriterImpl &rewriterImpl,
+  Operation *op, Block *block, Operation *insertBeforeOp)
+  : OperationAction(Kind::MoveOperation, rewriterImpl, op), block(block),
+insertBeforeOp(insertBeforeOp) {}
+
+  static bool classof(const RewriteAction *action) {
+return action->getKind() == Kind::MoveOperation;
+  }
+
+  void rollback() override {
+// Move the operation back to its original pos

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn in-place op modifications into `RewriteAction`s (PR #81245)

2024-02-09 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81245

This commit simplifies the internal state of the dialect conversion. A separate 
field for the previous state of in-place op modifications is no longer needed.

>From cdbd92786887ba8f801cb0c4299f708f0a410465 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 9 Feb 2024 11:36:59 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn in-place op modifications into
 `RewriteAction`s

This commit simplifies the internal state of the dialect conversion. A separate 
field for the previous state of in-place op modifications is no longer needed.
---
 .../Transforms/Utils/DialectConversion.cpp| 128 --
 1 file changed, 58 insertions(+), 70 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index ffdb069f6e9b81..d0114a148cd374 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,15 +154,13 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numRewriteActions, unsigned numIgnoredOperations,
-unsigned numRootUpdates)
+unsigned numRewriteActions, unsigned numIgnoredOperations)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
 numArgReplacements(numArgReplacements),
 numRewriteActions(numRewriteActions),
-numIgnoredOperations(numIgnoredOperations),
-numRootUpdates(numRootUpdates) {}
+numIgnoredOperations(numIgnoredOperations) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -181,44 +179,6 @@ struct RewriterState {
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
-
-  /// The current number of operations that were updated in place.
-  unsigned numRootUpdates;
-};
-
-//===--===//
-// OperationTransactionState
-
-/// The state of an operation that was updated by a pattern in-place. This
-/// contains all of the necessary information to reconstruct an operation that
-/// was updated in place.
-class OperationTransactionState {
-public:
-  OperationTransactionState() = default;
-  OperationTransactionState(Operation *op)
-  : op(op), loc(op->getLoc()), attrs(op->getAttrDictionary()),
-operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
-
-  /// Discard the transaction state and reset the state of the original
-  /// operation.
-  void resetOperation() const {
-op->setLoc(loc);
-op->setAttrs(attrs);
-op->setOperands(operands);
-for (const auto &it : llvm::enumerate(successors))
-  op->setSuccessor(it.value(), it.index());
-  }
-
-  /// Return the original operation of this state.
-  Operation *getOperation() const { return op; }
-
-private:
-  Operation *op;
-  LocationAttr loc;
-  DictionaryAttr attrs;
-  SmallVector operands;
-  SmallVector successors;
 };
 
 
//===--===//
@@ -758,7 +718,8 @@ class RewriteAction {
 MoveBlock,
 SplitBlock,
 BlockTypeConversion,
-MoveOperation
+MoveOperation,
+ModifyOperation
   };
 
   virtual ~RewriteAction() = default;
@@ -980,7 +941,7 @@ class OperationAction : public RewriteAction {
 
   static bool classof(const RewriteAction *action) {
 return action->getKind() >= Kind::MoveOperation &&
-   action->getKind() <= Kind::MoveOperation;
+   action->getKind() <= Kind::ModifyOperation;
   }
 
 protected:
@@ -1019,6 +980,34 @@ class MoveOperationAction : public OperationAction {
   // this operation was the only operation in the region.
   Operation *insertBeforeOp;
 };
+
+/// Rewrite action that represents the in-place modification of an operation.
+/// The previous state of the operation is stored in this action.
+class ModifyOperationAction : public OperationAction {
+public:
+  ModifyOperationAction(ConversionPatternRewriterImpl &rewriterImpl,
+Operation *op)
+  : OperationAction(Kind::ModifyOperation, rewriterImpl, op),
+loc(op->getLoc()), attrs(op->getAttrDictionary()),
+operands(op->operand_begin(), op->operand_end()),
+successors(op->successor_begin(), op->successor_end()) {}
+
+  /// Discard the transaction state and reset the state of the original
+  /// operation.
+  void rollback() override {
+op->setLoc(loc);
+op->setAttrs(attrs);
+op->setOperands(operands);
+for (const auto &it : llvm::enumerate(successors))
+  op->setSuccessor(it.value(), it.index());
+  }
+
+private:
+

[llvm-branch-commits] [mlir] [mlir][Transforms] Support `moveOpBefore`/`After` in dialect conversion (PR #81240)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81240

>From c60c43bcd2296715ceca83a3f9666433883ec303 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 12 Feb 2024 09:05:50 +
Subject: [PATCH 1/2] [mlir][Transforms][WIP] RewriteAction

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../Transforms/Utils/DialectConversion.cpp| 504 +++---
 1 file changed, 306 insertions(+), 198 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index e41231d7cbd390..edca84e5a73f04 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,13 +154,12 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numBlockActions, unsigned numIgnoredOperations,
+unsigned numRewrites, unsigned numIgnoredOperations,
 unsigned numRootUpdates)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
-numArgReplacements(numArgReplacements),
-numBlockActions(numBlockActions),
+numArgReplacements(numArgReplacements), numRewrites(numRewrites),
 numIgnoredOperations(numIgnoredOperations),
 numRootUpdates(numRootUpdates) {}
 
@@ -176,8 +175,8 @@ struct RewriterState {
   /// The current number of argument replacements queued.
   unsigned numArgReplacements;
 
-  /// The current number of block actions performed.
-  unsigned numBlockActions;
+  /// The current number of rewrites performed.
+  unsigned numRewrites;
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
@@ -235,86 +234,6 @@ struct OpReplacement {
   const TypeConverter *converter;
 };
 
-//===--===//
-// BlockAction
-
-/// The kind of the block action performed during the rewrite.  Actions can be
-/// undone if the conversion fails.
-enum class BlockActionKind {
-  Create,
-  Erase,
-  Inline,
-  Move,
-  Split,
-  TypeConversion
-};
-
-/// Original position of the given block in its parent region. During undo
-/// actions, the block needs to be placed before `insertBeforeBlock`.
-struct BlockPosition {
-  Region *region;
-  Block *insertBeforeBlock;
-};
-
-/// Information needed to undo inlining actions.
-/// - the source block
-/// - the first inlined operation (could be null if the source block was empty)
-/// - the last inlined operation (could be null if the source block was empty)
-struct InlineInfo {
-  Block *sourceBlock;
-  Operation *firstInlinedInst;
-  Operation *lastInlinedInst;
-};
-
-/// The storage class for an undoable block action (one of BlockActionKind),
-/// contains the information necessary to undo this action.
-struct BlockAction {
-  static BlockAction getCreate(Block *block) {
-return {BlockActionKind::Create, block, {}};
-  }
-  static BlockAction getErase(Block *block, BlockPosition originalPosition) {
-return {BlockActionKind::Erase, block, {originalPosition}};
-  }
-  static BlockAction getInline(Block *block, Block *srcBlock,
-   Block::iterator before) {
-BlockAction action{BlockActionKind::Inline, block, {}};
-action.inlineInfo = {srcBlock,
- srcBlock->empty() ? nullptr : &srcBlock->front(),
- srcBlock->empty() ? nullptr : &srcBlock->back()};
-return action;
-  }
-  static BlockAction getMove(Block *block, BlockPosition originalPosition) {
-return {BlockActionKind::Move, block, {originalPosition}};
-  }
-  static BlockAction getSplit(Block *block, Block *originalBlock) {
-BlockAction action{BlockActionKind::Split, block, {}};
-action.originalBlock = originalBlock;
-return action;
-  }
-  static BlockAction getTypeConversion(Block *block) {
-return BlockAction{BlockActionKind::TypeConversion, block, {}};
-  }
-
-  // The action kind.
-  BlockActionKind kind;
-
-  // A pointer to the block that was created by the action.
-  Block *block;
-
-  union {
-// In use if kind == BlockActionKind::Inline or BlockActionKind::Erase, and
-// contains a pointer to the region that originally contained the block as
-// well as the position of the block in that region.
-BlockPosition originalPosition;
-// In use if kind == BlockActionKind::Split and contains a pointer to the
-// block that was split into two parts.
-Block *originalBlock;
-// In use if kind == BlockActionKind::Inline, and contains the information
-// needed to undo the inlining.
-InlineInfo inlineInfo;
-  };
-};
-
 
//===--===/

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Modularize block actions (PR #81237)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81237

>From c60c43bcd2296715ceca83a3f9666433883ec303 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 12 Feb 2024 09:05:50 +
Subject: [PATCH] [mlir][Transforms][WIP] RewriteAction

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../Transforms/Utils/DialectConversion.cpp| 504 +++---
 1 file changed, 306 insertions(+), 198 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index e41231d7cbd390..edca84e5a73f04 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,13 +154,12 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numBlockActions, unsigned numIgnoredOperations,
+unsigned numRewrites, unsigned numIgnoredOperations,
 unsigned numRootUpdates)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
-numArgReplacements(numArgReplacements),
-numBlockActions(numBlockActions),
+numArgReplacements(numArgReplacements), numRewrites(numRewrites),
 numIgnoredOperations(numIgnoredOperations),
 numRootUpdates(numRootUpdates) {}
 
@@ -176,8 +175,8 @@ struct RewriterState {
   /// The current number of argument replacements queued.
   unsigned numArgReplacements;
 
-  /// The current number of block actions performed.
-  unsigned numBlockActions;
+  /// The current number of rewrites performed.
+  unsigned numRewrites;
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
@@ -235,86 +234,6 @@ struct OpReplacement {
   const TypeConverter *converter;
 };
 
-//===--===//
-// BlockAction
-
-/// The kind of the block action performed during the rewrite.  Actions can be
-/// undone if the conversion fails.
-enum class BlockActionKind {
-  Create,
-  Erase,
-  Inline,
-  Move,
-  Split,
-  TypeConversion
-};
-
-/// Original position of the given block in its parent region. During undo
-/// actions, the block needs to be placed before `insertBeforeBlock`.
-struct BlockPosition {
-  Region *region;
-  Block *insertBeforeBlock;
-};
-
-/// Information needed to undo inlining actions.
-/// - the source block
-/// - the first inlined operation (could be null if the source block was empty)
-/// - the last inlined operation (could be null if the source block was empty)
-struct InlineInfo {
-  Block *sourceBlock;
-  Operation *firstInlinedInst;
-  Operation *lastInlinedInst;
-};
-
-/// The storage class for an undoable block action (one of BlockActionKind),
-/// contains the information necessary to undo this action.
-struct BlockAction {
-  static BlockAction getCreate(Block *block) {
-return {BlockActionKind::Create, block, {}};
-  }
-  static BlockAction getErase(Block *block, BlockPosition originalPosition) {
-return {BlockActionKind::Erase, block, {originalPosition}};
-  }
-  static BlockAction getInline(Block *block, Block *srcBlock,
-   Block::iterator before) {
-BlockAction action{BlockActionKind::Inline, block, {}};
-action.inlineInfo = {srcBlock,
- srcBlock->empty() ? nullptr : &srcBlock->front(),
- srcBlock->empty() ? nullptr : &srcBlock->back()};
-return action;
-  }
-  static BlockAction getMove(Block *block, BlockPosition originalPosition) {
-return {BlockActionKind::Move, block, {originalPosition}};
-  }
-  static BlockAction getSplit(Block *block, Block *originalBlock) {
-BlockAction action{BlockActionKind::Split, block, {}};
-action.originalBlock = originalBlock;
-return action;
-  }
-  static BlockAction getTypeConversion(Block *block) {
-return BlockAction{BlockActionKind::TypeConversion, block, {}};
-  }
-
-  // The action kind.
-  BlockActionKind kind;
-
-  // A pointer to the block that was created by the action.
-  Block *block;
-
-  union {
-// In use if kind == BlockActionKind::Inline or BlockActionKind::Erase, and
-// contains a pointer to the region that originally contained the block as
-// well as the position of the block in that region.
-BlockPosition originalPosition;
-// In use if kind == BlockActionKind::Split and contains a pointer to the
-// block that was split into two parts.
-Block *originalBlock;
-// In use if kind == BlockActionKind::Inline, and contains the information
-// needed to undo the inlining.
-InlineInfo inlineInfo;
-  };
-};
-
 
//===--===//
 /

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn in-place op modifications into `RewriteAction`s (PR #81245)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81245

>From f7010ea9f363c011f4171a6329ad6de30880c3e7 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 12 Feb 2024 09:11:47 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn in-place op modifications into
 `RewriteAction`s

This commit simplifies the internal state of the dialect conversion. A separate 
field for the previous state of in-place op modifications is no longer needed.

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../mlir/Transforms/DialectConversion.h   |   4 +-
 .../Transforms/Utils/DialectConversion.cpp| 123 --
 2 files changed, 56 insertions(+), 71 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index b028d2b71b3762..c0c702a7d34821 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -721,8 +721,8 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
 
   /// PatternRewriter hook for updating the given operation in-place.
   /// Note: These methods only track updates to the given operation itself,
-  /// and not nested regions. Updates to regions will still require
-  /// notification through other more specific hooks above.
+  /// and not nested regions. Updates to regions will still require 
notification
+  /// through other more specific hooks above.
   void startOpModification(Operation *op) override;
 
   /// PatternRewriter hook for updating the given operation in-place.
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 85b67bb834de7c..489ccd0139c7f2 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,14 +154,12 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numRewrites, unsigned numIgnoredOperations,
-unsigned numRootUpdates)
+unsigned numRewrites, unsigned numIgnoredOperations)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
 numArgReplacements(numArgReplacements), numRewrites(numRewrites),
-numIgnoredOperations(numIgnoredOperations),
-numRootUpdates(numRootUpdates) {}
+numIgnoredOperations(numIgnoredOperations) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -180,44 +178,6 @@ struct RewriterState {
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
-
-  /// The current number of operations that were updated in place.
-  unsigned numRootUpdates;
-};
-
-//===--===//
-// OperationTransactionState
-
-/// The state of an operation that was updated by a pattern in-place. This
-/// contains all of the necessary information to reconstruct an operation that
-/// was updated in place.
-class OperationTransactionState {
-public:
-  OperationTransactionState() = default;
-  OperationTransactionState(Operation *op)
-  : op(op), loc(op->getLoc()), attrs(op->getAttrDictionary()),
-operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
-
-  /// Discard the transaction state and reset the state of the original
-  /// operation.
-  void resetOperation() const {
-op->setLoc(loc);
-op->setAttrs(attrs);
-op->setOperands(operands);
-for (const auto &it : llvm::enumerate(successors))
-  op->setSuccessor(it.value(), it.index());
-  }
-
-  /// Return the original operation of this state.
-  Operation *getOperation() const { return op; }
-
-private:
-  Operation *op;
-  LocationAttr loc;
-  DictionaryAttr attrs;
-  SmallVector operands;
-  SmallVector successors;
 };
 
 
//===--===//
@@ -761,7 +721,8 @@ class IRRewrite {
 MoveBlock,
 SplitBlock,
 BlockTypeConversion,
-MoveOperation
+MoveOperation,
+ModifyOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -992,7 +953,7 @@ class OperationRewrite : public IRRewrite {
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() >= Kind::MoveOperation &&
-   rewrite->getKind() <= Kind::MoveOperation;
+   rewrite->getKind() <= Kind::ModifyOperation;
   }
 
 protected:
@@ -1031,6 +992,34 @@ class MoveOperationRewrite : public OperationRewrite {
   // this operation was the only operation in the region.
   Operation *insertBeforeOp;
 };
+
+/// In-place modification of an op. This rewrite is immediately reflected in
+///

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Modularize block actions (PR #81237)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/81237
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Modularize block actions (PR #81237)

2024-02-12 Thread Matthias Springer via llvm-branch-commits


@@ -820,6 +740,238 @@ void ArgConverter::insertConversion(Block *newBlock,
   conversionInfo.insert({newBlock, std::move(info)});
 }
 
+//===--===//
+// RewriteAction

matthias-springer wrote:

I renamed `RewriteAction` to `IRRewrite`.


https://github.com/llvm/llvm-project/pull/81237
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Support `moveOpBefore`/`After` in dialect conversion (PR #81240)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/81240
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Support `moveOpBefore`/`After` in dialect conversion (PR #81240)

2024-02-12 Thread Matthias Springer via llvm-branch-commits


@@ -970,6 +971,54 @@ class BlockTypeConversionAction : public BlockAction {
 
   void rollback() override;
 };
+
+/// An operation rewrite.

matthias-springer wrote:

I renamed the class to `OperationRewrite`. I added more documentation to the 
superclass `IRRewrite` in the dependent PR.


https://github.com/llvm/llvm-project/pull/81240
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn in-place op modification into `IRRewrite` (PR #81245)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/81245
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `ArgConverter` state (PR #81462)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81462

* When converting a block signature, `ArgConverter` creates a new block with 
the new signature and moves all operation from the old block to the new block. 
The new block is temporarily inserted into a region that is stored in 
`regionMapping`. The old block is not yet deleted, so that the conversion can 
be rolled back. `regionMapping` is not needed. Instead of moving the old block 
to a temporary region, it can just be unlinked. Block erasures are handles in 
the same way in the dialect conversion.
* `regionToConverter` is a mapping from regions to type converter. That field 
is never accessed within `ArgConverter`. It should be stored in 
`ConversionPatternRewriterImpl` instead.


>From 5af1476c5d439c14122ffb50d24923e522a61b32 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 12 Feb 2024 10:53:59 +
Subject: [PATCH] [mlir][Transforms][NFC] Simplify `ArgConverter` state

* When converting a block signature, `ArgConverter` creates a new block with 
the new signature and moves all operation from the old block to the new block. 
The new block is temporarily inserted into a region that is stored in 
`regionMapping`. The old block is not yet deleted, so that the conversion can 
be rolled back. `regionMapping` is not needed. Instead of moving the old block 
to a temporary region, it can just be unlinked. Block erasures are handles in 
the same way in the dialect conversion.
* `regionToConverter` is a mapping from regions to type converter. That field 
is never accessed within `ArgConverter`. It should be stored in 
`ConversionPatternRewriterImpl` instead.
---
 .../Transforms/Utils/DialectConversion.cpp| 63 ++-
 1 file changed, 18 insertions(+), 45 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 489ccd0139c7f..53717f632621d 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -348,18 +348,6 @@ struct ArgConverter {
 return conversionInfo.count(block) || convertedBlocks.count(block);
   }
 
-  /// Set the type converter to use for the given region.
-  void setConverter(Region *region, const TypeConverter *typeConverter) {
-assert(typeConverter && "expected valid type converter");
-regionToConverter[region] = typeConverter;
-  }
-
-  /// Return the type converter to use for the given region, or null if there
-  /// isn't one.
-  const TypeConverter *getConverter(Region *region) {
-return regionToConverter.lookup(region);
-  }
-
   
//======//
   // Rewrite Application
   
//======//
@@ -409,9 +397,6 @@ struct ArgConverter {
   ConversionValueMapping &mapping,
   SmallVectorImpl &argReplacements);
 
-  /// Insert a new conversion into the cache.
-  void insertConversion(Block *newBlock, ConvertedBlockInfo &&info);
-
   /// A collection of blocks that have had their arguments converted. This is a
   /// map from the new replacement block, back to the original block.
   llvm::MapVector conversionInfo;
@@ -419,14 +404,6 @@ struct ArgConverter {
   /// The set of original blocks that were converted.
   DenseSet convertedBlocks;
 
-  /// A mapping from valid regions, to those containing the original blocks of 
a
-  /// conversion.
-  DenseMap> regionMapping;
-
-  /// A mapping of regions to type converters that should be used when
-  /// converting the arguments of blocks within that region.
-  DenseMap regionToConverter;
-
   /// The pattern rewriter to use when materializing conversions.
   PatternRewriter &rewriter;
 
@@ -474,9 +451,10 @@ void ArgConverter::discardRewrites(Block *block) {
 block->getArgument(i).dropAllUses();
   block->replaceAllUsesWith(origBlock);
 
-  // Move the operations back the original block and the delete the new block.
+  // Move the operations back the original block, move the original block back
+  // into its original location and the delete the new block.
   origBlock->getOperations().splice(origBlock->end(), block->getOperations());
-  origBlock->moveBefore(block);
+  block->getParent()->getBlocks().insert(Region::iterator(block), origBlock);
   block->erase();
 
   convertedBlocks.erase(origBlock);
@@ -510,6 +488,9 @@ void ArgConverter::applyRewrites(ConversionValueMapping 
&mapping) {
 mapping.lookupOrDefault(castValue, origArg.getType()));
   }
 }
+
+delete origBlock;
+blockInfo.origBlock = nullptr;
   }
 }
 
@@ -603,6 +584,9 @@ Block *ArgConverter::applySignatureConversion(
   // signature.
   Block *newBlock = block->splitBlock(block->begin());
   block->replaceAllUsesWith(newBlock);
+  // Unlink the block, but do not erase it yet, so that the change can be 
rolled
+  // back.
+  block->getParent()->getBlocks().remo

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `ArgConverter` state (PR #81462)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81462

>From ba1a8085ab576b56a7d1780d9a3f01cb6769df65 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 12 Feb 2024 11:24:52 +
Subject: [PATCH] [mlir][Transforms][NFC] Simplify `ArgConverter` state

* When converting a block signature, `ArgConverter` creates a new block with 
the new signature and moves all operation from the old block to the new block. 
The new block is temporarily inserted into a region that is stored in 
`regionMapping`. The old block is not yet deleted, so that the conversion can 
be rolled back. `regionMapping` is not needed. Instead of moving the old block 
to a temporary region, it can just be unlinked. Block erasures are handles in 
the same way in the dialect conversion.
* `regionToConverter` is a mapping from regions to type converter. That field 
is never accessed within `ArgConverter`. It should be stored in 
`ConversionPatternRewriterImpl` instead.
---
 .../Transforms/Utils/DialectConversion.cpp| 79 ++-
 1 file changed, 22 insertions(+), 57 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 489ccd0139c7f2..e1c838ea1e43a4 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -343,23 +343,6 @@ struct ArgConverter {
 const TypeConverter *converter;
   };
 
-  /// Return if the signature of the given block has already been converted.
-  bool hasBeenConverted(Block *block) const {
-return conversionInfo.count(block) || convertedBlocks.count(block);
-  }
-
-  /// Set the type converter to use for the given region.
-  void setConverter(Region *region, const TypeConverter *typeConverter) {
-assert(typeConverter && "expected valid type converter");
-regionToConverter[region] = typeConverter;
-  }
-
-  /// Return the type converter to use for the given region, or null if there
-  /// isn't one.
-  const TypeConverter *getConverter(Region *region) {
-return regionToConverter.lookup(region);
-  }
-
   
//======//
   // Rewrite Application
   
//======//
@@ -409,24 +392,10 @@ struct ArgConverter {
   ConversionValueMapping &mapping,
   SmallVectorImpl &argReplacements);
 
-  /// Insert a new conversion into the cache.
-  void insertConversion(Block *newBlock, ConvertedBlockInfo &&info);
-
   /// A collection of blocks that have had their arguments converted. This is a
   /// map from the new replacement block, back to the original block.
   llvm::MapVector conversionInfo;
 
-  /// The set of original blocks that were converted.
-  DenseSet convertedBlocks;
-
-  /// A mapping from valid regions, to those containing the original blocks of 
a
-  /// conversion.
-  DenseMap> regionMapping;
-
-  /// A mapping of regions to type converters that should be used when
-  /// converting the arguments of blocks within that region.
-  DenseMap regionToConverter;
-
   /// The pattern rewriter to use when materializing conversions.
   PatternRewriter &rewriter;
 
@@ -474,12 +443,12 @@ void ArgConverter::discardRewrites(Block *block) {
 block->getArgument(i).dropAllUses();
   block->replaceAllUsesWith(origBlock);
 
-  // Move the operations back the original block and the delete the new block.
+  // Move the operations back the original block, move the original block back
+  // into its original location and the delete the new block.
   origBlock->getOperations().splice(origBlock->end(), block->getOperations());
-  origBlock->moveBefore(block);
+  block->getParent()->getBlocks().insert(Region::iterator(block), origBlock);
   block->erase();
 
-  convertedBlocks.erase(origBlock);
   conversionInfo.erase(it);
 }
 
@@ -510,6 +479,9 @@ void ArgConverter::applyRewrites(ConversionValueMapping 
&mapping) {
 mapping.lookupOrDefault(castValue, origArg.getType()));
   }
 }
+
+delete origBlock;
+blockInfo.origBlock = nullptr;
   }
 }
 
@@ -572,9 +544,11 @@ FailureOr ArgConverter::convertSignature(
 Block *block, const TypeConverter *converter,
 ConversionValueMapping &mapping,
 SmallVectorImpl &argReplacements) {
-  // Check if the block was already converted. If the block is detached,
-  // conservatively assume it is going to be deleted.
-  if (hasBeenConverted(block) || !block->getParent())
+  // Check if the block was already converted.
+  // * If the block is mapped in `conversionInfo`, it is a converted block.
+  // * If the block is detached, conservatively assume that it is going to be
+  //   deleted; it is likely the old block (before it was converted).
+  if (conversionInfo.count(block) || !block->getParent())
 return block;
   // If a converter wasn't provided, and the block wasn't already converted,
   // there is nothing we can do

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `ArgConverter` state (PR #81462)

2024-02-12 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/81462
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Support `moveOpBefore`/`After` in dialect conversion (PR #81240)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81240

>From 1d17c768c1588850ceb331e3dd85930deec5728c Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:08:38 +
Subject: [PATCH] [mlir][Transforms] Support `moveOpBefore`/`After` in dialect
 conversion

Add a new rewrite action for "operation movements". This action can roll back 
`moveOpBefore` and `moveOpAfter`.

`RewriterBase::moveOpBefore` and `RewriterBase::moveOpAfter` is no longer 
virtual. (The dialect conversion can gather all required information for 
rollbacks from listener notifications.)

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 mlir/include/mlir/IR/PatternMatch.h   |  6 +-
 .../mlir/Transforms/DialectConversion.h   |  9 +--
 .../Transforms/Utils/DialectConversion.cpp| 74 +++
 mlir/test/Transforms/test-legalizer.mlir  | 14 
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   | 20 -
 5 files changed, 95 insertions(+), 28 deletions(-)

diff --git a/mlir/include/mlir/IR/PatternMatch.h 
b/mlir/include/mlir/IR/PatternMatch.h
index 78dcfe7f6fc3d2..b8aeea0d23475b 100644
--- a/mlir/include/mlir/IR/PatternMatch.h
+++ b/mlir/include/mlir/IR/PatternMatch.h
@@ -588,8 +588,7 @@ class RewriterBase : public OpBuilder {
 
   /// Unlink this operation from its current block and insert it right before
   /// `iterator` in the specified block.
-  virtual void moveOpBefore(Operation *op, Block *block,
-Block::iterator iterator);
+  void moveOpBefore(Operation *op, Block *block, Block::iterator iterator);
 
   /// Unlink this operation from its current block and insert it right after
   /// `existingOp` which may be in the same or another block in the same
@@ -598,8 +597,7 @@ class RewriterBase : public OpBuilder {
 
   /// Unlink this operation from its current block and insert it right after
   /// `iterator` in the specified block.
-  virtual void moveOpAfter(Operation *op, Block *block,
-   Block::iterator iterator);
+  void moveOpAfter(Operation *op, Block *block, Block::iterator iterator);
 
   /// Unlink this block and insert it right before `existingBlock`.
   void moveBlockBefore(Block *block, Block *anotherBlock);
diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 851d639ae68a77..15fa39bde104b9 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -744,8 +744,8 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
 
   /// PatternRewriter hook for updating the given operation in-place.
   /// Note: These methods only track updates to the given operation itself,
-  /// and not nested regions. Updates to regions will still require 
notification
-  /// through other more specific hooks above.
+  /// and not nested regions. Updates to regions will still require
+  /// notification through other more specific hooks above.
   void startOpModification(Operation *op) override;
 
   /// PatternRewriter hook for updating the given operation in-place.
@@ -761,11 +761,6 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
   // Hide unsupported pattern rewriter API.
   using OpBuilder::setListener;
 
-  void moveOpBefore(Operation *op, Block *block,
-Block::iterator iterator) override;
-  void moveOpAfter(Operation *op, Block *block,
-   Block::iterator iterator) override;
-
   std::unique_ptr impl;
 };
 
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 9875f8668b65a8..84597fb7986b07 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -760,7 +760,8 @@ class IRRewrite {
 InlineBlock,
 MoveBlock,
 SplitBlock,
-BlockTypeConversion
+BlockTypeConversion,
+MoveOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -982,6 +983,54 @@ class BlockTypeConversionRewrite : public BlockRewrite {
   // `ArgConverter::applyRewrites`. This should be done in the "commit" method.
   void rollback() override;
 };
+
+/// An operation rewrite.
+class OperationRewrite : public IRRewrite {
+public:
+  /// Return the operation that this rewrite operates on.
+  Operation *getOperation() const { return op; }
+
+  static bool classof(const IRRewrite *rewrite) {
+return rewrite->getKind() >= Kind::MoveOperation &&
+   rewrite->getKind() <= Kind::MoveOperation;
+  }
+
+protected:
+  OperationRewrite(Kind kind, ConversionPatternRewriterImpl &rewriterImpl,
+   Operation *op)
+  : IRRewrite(kind, rewriterImpl), op(op) {}
+
+  // The operation that this rewrite operates on.
+  Operation *op;
+};
+
+/// Moving of an operation. This rewrite is immediately reflected in the IR.
+class MoveOperationRewrite : public OperationRew

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn in-place op modification into `IRRewrite` (PR #81245)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81245

>From 4bb65218698f0104775f3eea05817c6d5228a9e7 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:17:03 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn in-place op modifications into
 `RewriteAction`s

This commit simplifies the internal state of the dialect conversion. A separate 
field for the previous state of in-place op modifications is no longer needed.

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../mlir/Transforms/DialectConversion.h   |   4 +-
 .../Transforms/Utils/DialectConversion.cpp| 139 +-
 2 files changed, 68 insertions(+), 75 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 15fa39bde104b9..0d7722aa07ee38 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -744,8 +744,8 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
 
   /// PatternRewriter hook for updating the given operation in-place.
   /// Note: These methods only track updates to the given operation itself,
-  /// and not nested regions. Updates to regions will still require
-  /// notification through other more specific hooks above.
+  /// and not nested regions. Updates to regions will still require 
notification
+  /// through other more specific hooks above.
   void startOpModification(Operation *op) override;
 
   /// PatternRewriter hook for updating the given operation in-place.
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 84597fb7986b07..5206a65608ba14 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,14 +154,12 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numRewrites, unsigned numIgnoredOperations,
-unsigned numRootUpdates)
+unsigned numRewrites, unsigned numIgnoredOperations)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
 numArgReplacements(numArgReplacements), numRewrites(numRewrites),
-numIgnoredOperations(numIgnoredOperations),
-numRootUpdates(numRootUpdates) {}
+numIgnoredOperations(numIgnoredOperations) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -180,44 +178,6 @@ struct RewriterState {
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
-
-  /// The current number of operations that were updated in place.
-  unsigned numRootUpdates;
-};
-
-//===--===//
-// OperationTransactionState
-
-/// The state of an operation that was updated by a pattern in-place. This
-/// contains all of the necessary information to reconstruct an operation that
-/// was updated in place.
-class OperationTransactionState {
-public:
-  OperationTransactionState() = default;
-  OperationTransactionState(Operation *op)
-  : op(op), loc(op->getLoc()), attrs(op->getAttrDictionary()),
-operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
-
-  /// Discard the transaction state and reset the state of the original
-  /// operation.
-  void resetOperation() const {
-op->setLoc(loc);
-op->setAttrs(attrs);
-op->setOperands(operands);
-for (const auto &it : llvm::enumerate(successors))
-  op->setSuccessor(it.value(), it.index());
-  }
-
-  /// Return the original operation of this state.
-  Operation *getOperation() const { return op; }
-
-private:
-  Operation *op;
-  LocationAttr loc;
-  DictionaryAttr attrs;
-  SmallVector operands;
-  SmallVector successors;
 };
 
 
//===--===//
@@ -761,7 +721,8 @@ class IRRewrite {
 MoveBlock,
 SplitBlock,
 BlockTypeConversion,
-MoveOperation
+MoveOperation,
+ModifyOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -992,7 +953,7 @@ class OperationRewrite : public IRRewrite {
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() >= Kind::MoveOperation &&
-   rewrite->getKind() <= Kind::MoveOperation;
+   rewrite->getKind() <= Kind::ModifyOperation;
   }
 
 protected:
@@ -1031,8 +992,50 @@ class MoveOperationRewrite : public OperationRewrite {
   // this operation was the only operation in the region.
   Operation *insertBeforeOp;
 };
+
+/// In-place modification of an op. This rewrite is immediately reflected in
+///

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `ArgConverter` state (PR #81462)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81462

>From c7afdb221528ad0aa76b2ba50a6db47eefd71bb2 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:20:30 +
Subject: [PATCH] [mlir][Transforms][NFC] Simplify `ArgConverter` state

* When converting a block signature, `ArgConverter` creates a new block with 
the new signature and moves all operation from the old block to the new block. 
The new block is temporarily inserted into a region that is stored in 
`regionMapping`. The old block is not yet deleted, so that the conversion can 
be rolled back. `regionMapping` is not needed. Instead of moving the old block 
to a temporary region, it can just be unlinked. Block erasures are handles in 
the same way in the dialect conversion.
* `regionToConverter` is a mapping from regions to type converter. That field 
is never accessed within `ArgConverter`. It should be stored in 
`ConversionPatternRewriterImpl` instead.
---
 .../Transforms/Utils/DialectConversion.cpp| 79 ++-
 1 file changed, 22 insertions(+), 57 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 5206a65608ba14..67b076b295eae8 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -343,23 +343,6 @@ struct ArgConverter {
 const TypeConverter *converter;
   };
 
-  /// Return if the signature of the given block has already been converted.
-  bool hasBeenConverted(Block *block) const {
-return conversionInfo.count(block) || convertedBlocks.count(block);
-  }
-
-  /// Set the type converter to use for the given region.
-  void setConverter(Region *region, const TypeConverter *typeConverter) {
-assert(typeConverter && "expected valid type converter");
-regionToConverter[region] = typeConverter;
-  }
-
-  /// Return the type converter to use for the given region, or null if there
-  /// isn't one.
-  const TypeConverter *getConverter(Region *region) {
-return regionToConverter.lookup(region);
-  }
-
   
//======//
   // Rewrite Application
   
//======//
@@ -409,24 +392,10 @@ struct ArgConverter {
   ConversionValueMapping &mapping,
   SmallVectorImpl &argReplacements);
 
-  /// Insert a new conversion into the cache.
-  void insertConversion(Block *newBlock, ConvertedBlockInfo &&info);
-
   /// A collection of blocks that have had their arguments converted. This is a
   /// map from the new replacement block, back to the original block.
   llvm::MapVector conversionInfo;
 
-  /// The set of original blocks that were converted.
-  DenseSet convertedBlocks;
-
-  /// A mapping from valid regions, to those containing the original blocks of 
a
-  /// conversion.
-  DenseMap> regionMapping;
-
-  /// A mapping of regions to type converters that should be used when
-  /// converting the arguments of blocks within that region.
-  DenseMap regionToConverter;
-
   /// The pattern rewriter to use when materializing conversions.
   PatternRewriter &rewriter;
 
@@ -474,12 +443,12 @@ void ArgConverter::discardRewrites(Block *block) {
 block->getArgument(i).dropAllUses();
   block->replaceAllUsesWith(origBlock);
 
-  // Move the operations back the original block and the delete the new block.
+  // Move the operations back the original block, move the original block back
+  // into its original location and the delete the new block.
   origBlock->getOperations().splice(origBlock->end(), block->getOperations());
-  origBlock->moveBefore(block);
+  block->getParent()->getBlocks().insert(Region::iterator(block), origBlock);
   block->erase();
 
-  convertedBlocks.erase(origBlock);
   conversionInfo.erase(it);
 }
 
@@ -510,6 +479,9 @@ void ArgConverter::applyRewrites(ConversionValueMapping 
&mapping) {
 mapping.lookupOrDefault(castValue, origArg.getType()));
   }
 }
+
+delete origBlock;
+blockInfo.origBlock = nullptr;
   }
 }
 
@@ -572,9 +544,11 @@ FailureOr ArgConverter::convertSignature(
 Block *block, const TypeConverter *converter,
 ConversionValueMapping &mapping,
 SmallVectorImpl &argReplacements) {
-  // Check if the block was already converted. If the block is detached,
-  // conservatively assume it is going to be deleted.
-  if (hasBeenConverted(block) || !block->getParent())
+  // Check if the block was already converted.
+  // * If the block is mapped in `conversionInfo`, it is a converted block.
+  // * If the block is detached, conservatively assume that it is going to be
+  //   deleted; it is likely the old block (before it was converted).
+  if (conversionInfo.count(block) || !block->getParent())
 return block;
   // If a converter wasn't provided, and the block wasn't already converted,
   // there is nothing we can do

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn block type conversion into `IRRewrite` (PR #81756)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81756

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, the signature conversion of a block was only a "partial" IR rewrite. 
Rollbacks were triggered via `BlockTypeConversionRewrite::rollback`, but there 
was no `BlockTypeConversionRewrite::commit` equivalent.

Overview of changes:
* Remove `ArgConverter`, an internal helper class that kept track of all block 
type conversions. There is now a separate `BlockTypeConversionRewrite` for each 
block type conversion.
* No more special handling for block type conversions. They are now normal "IR 
rewrites", just like "block creation" or "block movement". In particular, 
trigger "commits" of block type conversion via 
`BlockTypeConversionRewrite::commit`.
* Remove `ArgConverter::notifyOpRemoved`. This function was used to inform the 
`ArgConverter` that an operation was erased, to prevent a double-free of 
operations in certain situations. It would be unpractical to add a 
`notifyOpRemoved` API to `IRRewrite`. Instead, erasing ops/block should go 
through a new `SingleEraseRewriter` (that is owned by the 
`ConversionPatternRewriterImpl`) if there is chance of double-free. This 
rewriter ignores `eraseOp`/`eraseBlock` if the op/block was already freed.


>From ae08e916df9fcee362a813b89c126716376e462f Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:23:29 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn block type convertion into
 `IRRewrite`

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, the signature conversion of a block was only a "partial" IR rewrite. 
Rollbacks were triggered via `BlockTypeConversionRewrite::rollback`, but there 
was no `BlockTypeConversionRewrite::commit` equivalent.

Overview of changes:
* Remove `ArgConverter`, an internal helper class that kept track of all block 
type conversions. There is now a separate `BlockTypeConversionRewrite` for each 
block type conversion.
* No more special handling for block type conversions. They are now normal "IR 
rewrites", just like "block creation" or "block movement". In particular, 
trigger "commits" of block type conversion via 
`BlockTypeConversionRewrite::commit`.
* Remove `ArgConverter::notifyOpRemoved`. This function was used to inform the 
`ArgConverter` that an operation was erased, to prevent a double-free of 
operations in certain situations. It would be unpractical to add a 
`notifyOpRemoved` API to `IRRewrite`. Instead, erasing ops/block should go 
through a new `SingleEraseRewriter` (that is owned by the 
`ConversionPatternRewriterImpl`) if there is chance of double-free. This 
rewriter ignores `eraseOp`/`eraseBlock` if the op/block was already freed.
---
 .../Transforms/Utils/DialectConversion.cpp| 810 --
 1 file changed, 376 insertions(+), 434 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 67b076b295eae8..b2baa88879b6e9 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,12 +154,13 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numRewrites, unsigned numIgnoredOperations)
+unsigned numRewrites, unsigned numIgnoredOperations,
+unsigned numErased)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
 numArgReplacements(numArgReplacements), numRewrites(numRewrites),
-numIgnoredOperations(numIgnoredOperations) {}
+numIgnoredOperations(numIgnoredOperations), numErased(numErased) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -178,6 +179,9 @@ struct RewriterState {
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
+
+  /// The current number of erased operations/blocks.
+  unsigned numErased;
 };
 
 
//===--===//
@@ -292,374 +296,6 @@ static Value buildUnresolvedTargetMaterialization(
   outputType, outputType, converter, unresolvedMaterializations);
 }
 
-//===--===//
-// ArgConverter
-//===--===//
-namespace {
-/// This class provides a simple interface for converting the types of block
-/// arguments. This is done by cre

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn op/block arg replacements into `IRRewrite`s (PR #81757)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81757

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be committed (upon success) or 
rolled back (upon failure).

Until now, op replacements and block argument replacements were kept track in 
separate data structures inside the dialect conversion. This commit turns them 
into `IRRewrite`s, so that they can be committed or rolled back just like any 
other rewrite. This simplifies the internal state of the dialect conversion.

Overview of changes:
* Add two new rewrite classes: `ReplaceBlockArgRewrite` and 
`ReplaceOperationRewrite`. Remove the `OpReplacement` helper class; it is now 
part of `ReplaceOperationRewrite`.
* Simplify `RewriterState`: `numReplacements` and `numArgReplacements` are no 
longer needed. (Now being kept track of by `numRewrites`.)
* Add `IRRewrite::cleanup`. Operations should not be erased in `commit` because 
they may still be referenced in other internal state of the dialect conversion 
(`mapping`). Detaching operations is fine.
* `trackedOps` are now updated during the "commit" phase instead of after 
applying all rewrites.


>From 8405efca0845d39d01534505fde3c376ffb21fc5 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:27:53 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn op/block arg replacements into
 `IRRewrite`s

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, op replacements and block argument replacements were kept track in 
separate data structures inside the dialect conversion. This commit turns them 
into `IRRewrite`s, so that they can be committed or rolled back just like any 
other rewrite. This simplifies the internal state of the dialect conversion.

Overview of changes:
* Add two new rewrite classes: `ReplaceBlockArgRewrite` and 
`ReplaceOperationRewrite`. Remove the `OpReplacement` helper class; it is now 
part of `ReplaceOperationRewrite`.
* Simplify `RewriterState`: `numReplacements` and `numArgReplacements` are no 
longer needed. (Now being kept track of by `numRewrites`.)
* Add `IRRewrite::cleanup`. Operations should not be erased in `commit` because 
they may still be referenced in other internal state of the dialect conversion 
(`mapping`). Detaching operations is fine.
---
 .../Transforms/Utils/DialectConversion.cpp| 297 ++
 1 file changed, 159 insertions(+), 138 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index b2baa88879b6e9..a07c8a56822de5 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -153,14 +153,12 @@ namespace {
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
-unsigned numReplacements, unsigned numArgReplacements,
 unsigned numRewrites, unsigned numIgnoredOperations,
 unsigned numErased)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
-numReplacements(numReplacements),
-numArgReplacements(numArgReplacements), numRewrites(numRewrites),
-numIgnoredOperations(numIgnoredOperations), numErased(numErased) {}
+numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
+numErased(numErased) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -168,12 +166,6 @@ struct RewriterState {
   /// The current number of unresolved materializations.
   unsigned numUnresolvedMaterializations;
 
-  /// The current number of replacements queued.
-  unsigned numReplacements;
-
-  /// The current number of argument replacements queued.
-  unsigned numArgReplacements;
-
   /// The current number of rewrites performed.
   unsigned numRewrites;
 
@@ -184,20 +176,6 @@ struct RewriterState {
   unsigned numErased;
 };
 
-//===--===//
-// OpReplacement
-
-/// This class represents one requested operation replacement via 'replaceOp' 
or
-/// 'eraseOp`.
-struct OpReplacement {
-  OpReplacement(const TypeConverter *converter = nullptr)
-  : converter(converter) {}
-
-  /// An optional type converter that can be used to materialize conversions
-  /// between the new and old values if necessary.
-  const TypeConverter *converter;
-};
-
 
//===--===//
 // UnresolvedMaterialization
 
@@ -318,8 +296,10 @@ class IRRewrite {
 MoveBlock,
 SplitBlock,
 BlockTypeConversion,
+ReplaceBlockArg,
 MoveOperation,
-ModifyOpera

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn op creation into `IRRewrite` (PR #81759)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81759

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be committed (upon success) or 
rolled back (upon failure).

Until now, the dialect conversion kept track of "op creation" in separate 
internal data structures. This commit turns "op creation" into an `IRRewrite` 
that can be committed and rolled back just like any other rewrite. This commit 
simplifies the internal state of the dialect conversion.

>From 572d77c023455993be4861f5207bfd87b94124a3 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:32:28 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn op creation into `IRRewrite`

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, the dialect conversion kept track of "op creation" in separate 
internal data structures. This commit turns "op creation" into an `IRRewrite` 
that can be committed and rolled back just like any other rewrite. This commit 
simplifies the internal state of the dialect conversion.
---
 .../Transforms/Utils/DialectConversion.cpp| 104 +++---
 1 file changed, 66 insertions(+), 38 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index a07c8a56822de5..2bb56d5df1ebd3 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -152,17 +152,12 @@ namespace {
 /// This class contains a snapshot of the current conversion rewriter state.
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
-  RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
-unsigned numRewrites, unsigned numIgnoredOperations,
-unsigned numErased)
-  : numCreatedOps(numCreatedOps),
-numUnresolvedMaterializations(numUnresolvedMaterializations),
+  RewriterState(unsigned numUnresolvedMaterializations, unsigned numRewrites,
+unsigned numIgnoredOperations, unsigned numErased)
+  : numUnresolvedMaterializations(numUnresolvedMaterializations),
 numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
 numErased(numErased) {}
 
-  /// The current number of created operations.
-  unsigned numCreatedOps;
-
   /// The current number of unresolved materializations.
   unsigned numUnresolvedMaterializations;
 
@@ -299,7 +294,8 @@ class IRRewrite {
 ReplaceBlockArg,
 MoveOperation,
 ModifyOperation,
-ReplaceOperation
+ReplaceOperation,
+CreateOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -372,7 +368,11 @@ class CreateBlockRewrite : public BlockRewrite {
 auto &blockOps = block->getOperations();
 while (!blockOps.empty())
   blockOps.remove(blockOps.begin());
-eraseBlock(block);
+if (block->getParent()) {
+  eraseBlock(block);
+} else {
+  delete block;
+}
   }
 };
 
@@ -602,7 +602,7 @@ class OperationRewrite : public IRRewrite {
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() >= Kind::MoveOperation &&
-   rewrite->getKind() <= Kind::ReplaceOperation;
+   rewrite->getKind() <= Kind::CreateOperation;
   }
 
 protected:
@@ -708,6 +708,19 @@ class ReplaceOperationRewrite : public OperationRewrite {
   /// 1->N conversion of some kind.
   bool changedResults;
 };
+
+class CreateOperationRewrite : public OperationRewrite {
+public:
+  CreateOperationRewrite(ConversionPatternRewriterImpl &rewriterImpl,
+ Operation *op)
+  : OperationRewrite(Kind::CreateOperation, rewriterImpl, op) {}
+
+  static bool classof(const IRRewrite *rewrite) {
+return rewrite->getKind() == Kind::CreateOperation;
+  }
+
+  void rollback() override;
+};
 } // namespace
 
 /// Return "true" if there is an operation rewrite that matches the specified
@@ -925,9 +938,6 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   // replacing a value with one of a different type.
   ConversionValueMapping mapping;
 
-  /// Ordered vector of all of the newly created operations during conversion.
-  SmallVector createdOps;
-
   /// Ordered vector of all unresolved type conversion materializations during
   /// conversion.
   SmallVector unresolvedMaterializations;
@@ -1110,7 +1120,18 @@ void ReplaceOperationRewrite::rollback() {
 
 void ReplaceOperationRewrite::cleanup() { eraseOp(op); }
 
+void CreateOperationRewrite::rollback() {
+  for (Region ®ion : op->getRegions()) {
+while (!region.getBlocks().empty())
+  region.getBlocks().remove(region.getBlocks().begin());
+  }
+  op->dropAllUses();
+  eraseOp(op);
+}
+
 void ConversionPatternRewriterImpl::detachNestedAndErase(

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `ArgConverter` state (PR #81462)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81462

>From a79501ebced4a3410c3a28c6555973bb45156e76 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:20:30 +
Subject: [PATCH] [mlir][Transforms][NFC] Simplify `ArgConverter` state

* When converting a block signature, `ArgConverter` creates a new block with 
the new signature and moves all operation from the old block to the new block. 
The new block is temporarily inserted into a region that is stored in 
`regionMapping`. The old block is not yet deleted, so that the conversion can 
be rolled back. `regionMapping` is not needed. Instead of moving the old block 
to a temporary region, it can just be unlinked. Block erasures are handles in 
the same way in the dialect conversion.
* `regionToConverter` is a mapping from regions to type converter. That field 
is never accessed within `ArgConverter`. It should be stored in 
`ConversionPatternRewriterImpl` instead.
---
 .../Transforms/Utils/DialectConversion.cpp| 79 ++-
 1 file changed, 22 insertions(+), 57 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 5206a65608ba14..67b076b295eae8 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -343,23 +343,6 @@ struct ArgConverter {
 const TypeConverter *converter;
   };
 
-  /// Return if the signature of the given block has already been converted.
-  bool hasBeenConverted(Block *block) const {
-return conversionInfo.count(block) || convertedBlocks.count(block);
-  }
-
-  /// Set the type converter to use for the given region.
-  void setConverter(Region *region, const TypeConverter *typeConverter) {
-assert(typeConverter && "expected valid type converter");
-regionToConverter[region] = typeConverter;
-  }
-
-  /// Return the type converter to use for the given region, or null if there
-  /// isn't one.
-  const TypeConverter *getConverter(Region *region) {
-return regionToConverter.lookup(region);
-  }
-
   
//======//
   // Rewrite Application
   
//======//
@@ -409,24 +392,10 @@ struct ArgConverter {
   ConversionValueMapping &mapping,
   SmallVectorImpl &argReplacements);
 
-  /// Insert a new conversion into the cache.
-  void insertConversion(Block *newBlock, ConvertedBlockInfo &&info);
-
   /// A collection of blocks that have had their arguments converted. This is a
   /// map from the new replacement block, back to the original block.
   llvm::MapVector conversionInfo;
 
-  /// The set of original blocks that were converted.
-  DenseSet convertedBlocks;
-
-  /// A mapping from valid regions, to those containing the original blocks of 
a
-  /// conversion.
-  DenseMap> regionMapping;
-
-  /// A mapping of regions to type converters that should be used when
-  /// converting the arguments of blocks within that region.
-  DenseMap regionToConverter;
-
   /// The pattern rewriter to use when materializing conversions.
   PatternRewriter &rewriter;
 
@@ -474,12 +443,12 @@ void ArgConverter::discardRewrites(Block *block) {
 block->getArgument(i).dropAllUses();
   block->replaceAllUsesWith(origBlock);
 
-  // Move the operations back the original block and the delete the new block.
+  // Move the operations back the original block, move the original block back
+  // into its original location and the delete the new block.
   origBlock->getOperations().splice(origBlock->end(), block->getOperations());
-  origBlock->moveBefore(block);
+  block->getParent()->getBlocks().insert(Region::iterator(block), origBlock);
   block->erase();
 
-  convertedBlocks.erase(origBlock);
   conversionInfo.erase(it);
 }
 
@@ -510,6 +479,9 @@ void ArgConverter::applyRewrites(ConversionValueMapping 
&mapping) {
 mapping.lookupOrDefault(castValue, origArg.getType()));
   }
 }
+
+delete origBlock;
+blockInfo.origBlock = nullptr;
   }
 }
 
@@ -572,9 +544,11 @@ FailureOr ArgConverter::convertSignature(
 Block *block, const TypeConverter *converter,
 ConversionValueMapping &mapping,
 SmallVectorImpl &argReplacements) {
-  // Check if the block was already converted. If the block is detached,
-  // conservatively assume it is going to be deleted.
-  if (hasBeenConverted(block) || !block->getParent())
+  // Check if the block was already converted.
+  // * If the block is mapped in `conversionInfo`, it is a converted block.
+  // * If the block is detached, conservatively assume that it is going to be
+  //   deleted; it is likely the old block (before it was converted).
+  if (conversionInfo.count(block) || !block->getParent())
 return block;
   // If a converter wasn't provided, and the block wasn't already converted,
   // there is nothing we can do

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn block type conversion into `IRRewrite` (PR #81756)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81756

>From dcd13b85b50846d84850388e2bbed74c0aa54e62 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:23:29 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn block type convertion into
 `IRRewrite`

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, the signature conversion of a block was only a "partial" IR rewrite. 
Rollbacks were triggered via `BlockTypeConversionRewrite::rollback`, but there 
was no `BlockTypeConversionRewrite::commit` equivalent.

Overview of changes:
* Remove `ArgConverter`, an internal helper class that kept track of all block 
type conversions. There is now a separate `BlockTypeConversionRewrite` for each 
block type conversion.
* No more special handling for block type conversions. They are now normal "IR 
rewrites", just like "block creation" or "block movement". In particular, 
trigger "commits" of block type conversion via 
`BlockTypeConversionRewrite::commit`.
* Remove `ArgConverter::notifyOpRemoved`. This function was used to inform the 
`ArgConverter` that an operation was erased, to prevent a double-free of 
operations in certain situations. It would be unpractical to add a 
`notifyOpRemoved` API to `IRRewrite`. Instead, erasing ops/block should go 
through a new `SingleEraseRewriter` (that is owned by the 
`ConversionPatternRewriterImpl`) if there is chance of double-free. This 
rewriter ignores `eraseOp`/`eraseBlock` if the op/block was already freed.
---
 .../Transforms/Utils/DialectConversion.cpp| 810 --
 1 file changed, 376 insertions(+), 434 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 67b076b295eae8..b2baa88879b6e9 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,12 +154,13 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numRewrites, unsigned numIgnoredOperations)
+unsigned numRewrites, unsigned numIgnoredOperations,
+unsigned numErased)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
 numArgReplacements(numArgReplacements), numRewrites(numRewrites),
-numIgnoredOperations(numIgnoredOperations) {}
+numIgnoredOperations(numIgnoredOperations), numErased(numErased) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -178,6 +179,9 @@ struct RewriterState {
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
+
+  /// The current number of erased operations/blocks.
+  unsigned numErased;
 };
 
 
//===--===//
@@ -292,374 +296,6 @@ static Value buildUnresolvedTargetMaterialization(
   outputType, outputType, converter, unresolvedMaterializations);
 }
 
-//===--===//
-// ArgConverter
-//===--===//
-namespace {
-/// This class provides a simple interface for converting the types of block
-/// arguments. This is done by creating a new block that contains the new legal
-/// types and extracting the block that contains the old illegal types to allow
-/// for undoing pending rewrites in the case of failure.
-struct ArgConverter {
-  ArgConverter(
-  PatternRewriter &rewriter,
-  SmallVectorImpl &unresolvedMaterializations)
-  : rewriter(rewriter),
-unresolvedMaterializations(unresolvedMaterializations) {}
-
-  /// This structure contains the information pertaining to an argument that 
has
-  /// been converted.
-  struct ConvertedArgInfo {
-ConvertedArgInfo(unsigned newArgIdx, unsigned newArgSize,
- Value castValue = nullptr)
-: newArgIdx(newArgIdx), newArgSize(newArgSize), castValue(castValue) {}
-
-/// The start index of in the new argument list that contains arguments 
that
-/// replace the original.
-unsigned newArgIdx;
-
-/// The number of arguments that replaced the original argument.
-unsigned newArgSize;
-
-/// The cast value that was created to cast from the new arguments to the
-/// old. This only used if 'newArgSize' > 1.
-Value castValue;
-  };
-
-  /// This structure contains information pertaining to a block that has had 
its
-  /// signature converted.
-  struct ConvertedBlockInfo {
-ConvertedBlockInfo(Block *origBlock, const TypeConverter *converter)
- 

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn op/block arg replacements into `IRRewrite`s (PR #81757)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81757

>From 613a6162af4ac07066dbcf87b580a085eca5a47a Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:27:53 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn op/block arg replacements into
 `IRRewrite`s

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, op replacements and block argument replacements were kept track in 
separate data structures inside the dialect conversion. This commit turns them 
into `IRRewrite`s, so that they can be committed or rolled back just like any 
other rewrite. This simplifies the internal state of the dialect conversion.

Overview of changes:
* Add two new rewrite classes: `ReplaceBlockArgRewrite` and 
`ReplaceOperationRewrite`. Remove the `OpReplacement` helper class; it is now 
part of `ReplaceOperationRewrite`.
* Simplify `RewriterState`: `numReplacements` and `numArgReplacements` are no 
longer needed. (Now being kept track of by `numRewrites`.)
* Add `IRRewrite::cleanup`. Operations should not be erased in `commit` because 
they may still be referenced in other internal state of the dialect conversion 
(`mapping`). Detaching operations is fine.
---
 .../Transforms/Utils/DialectConversion.cpp| 297 ++
 1 file changed, 159 insertions(+), 138 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index b2baa88879b6e9..a07c8a56822de5 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -153,14 +153,12 @@ namespace {
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
-unsigned numReplacements, unsigned numArgReplacements,
 unsigned numRewrites, unsigned numIgnoredOperations,
 unsigned numErased)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
-numReplacements(numReplacements),
-numArgReplacements(numArgReplacements), numRewrites(numRewrites),
-numIgnoredOperations(numIgnoredOperations), numErased(numErased) {}
+numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
+numErased(numErased) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -168,12 +166,6 @@ struct RewriterState {
   /// The current number of unresolved materializations.
   unsigned numUnresolvedMaterializations;
 
-  /// The current number of replacements queued.
-  unsigned numReplacements;
-
-  /// The current number of argument replacements queued.
-  unsigned numArgReplacements;
-
   /// The current number of rewrites performed.
   unsigned numRewrites;
 
@@ -184,20 +176,6 @@ struct RewriterState {
   unsigned numErased;
 };
 
-//===--===//
-// OpReplacement
-
-/// This class represents one requested operation replacement via 'replaceOp' 
or
-/// 'eraseOp`.
-struct OpReplacement {
-  OpReplacement(const TypeConverter *converter = nullptr)
-  : converter(converter) {}
-
-  /// An optional type converter that can be used to materialize conversions
-  /// between the new and old values if necessary.
-  const TypeConverter *converter;
-};
-
 
//===--===//
 // UnresolvedMaterialization
 
@@ -318,8 +296,10 @@ class IRRewrite {
 MoveBlock,
 SplitBlock,
 BlockTypeConversion,
+ReplaceBlockArg,
 MoveOperation,
-ModifyOperation
+ModifyOperation,
+ReplaceOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -330,6 +310,12 @@ class IRRewrite {
   /// Commit the rewrite.
   virtual void commit() {}
 
+  /// Cleanup operations. Operations may be unlinked from their blocks during
+  /// the commit/rollback phase, but they must not be erased yet. This is
+  /// because internal dialect conversion state (such as `mapping`) may still
+  /// be using them. Operations must be erased during cleanup.
+  virtual void cleanup() {}
+
   /// Erase the given op (unless it was already erased).
   void eraseOp(Operation *op);
 
@@ -356,7 +342,7 @@ class BlockRewrite : public IRRewrite {
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() >= Kind::CreateBlock &&
-   rewrite->getKind() <= Kind::BlockTypeConversion;
+   rewrite->getKind() <= Kind::ReplaceBlockArg;
   }
 
 protected:
@@ -424,6 +410,8 @@ class EraseBlockRewrite : public BlockRewrite {
   void commit() override {
 // Erase the block.
 assert(block && "expected block");
+assert(block->empty() && "expected empty block");
+bloc

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn op creation into `IRRewrite` (PR #81759)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81759

>From 3873a3e96d0582c0ecf24335dad01560b61e8d90 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:32:28 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn op creation into `IRRewrite`

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, the dialect conversion kept track of "op creation" in separate 
internal data structures. This commit turns "op creation" into an `IRRewrite` 
that can be committed and rolled back just like any other rewrite. This commit 
simplifies the internal state of the dialect conversion.
---
 .../Transforms/Utils/DialectConversion.cpp| 104 +++---
 1 file changed, 66 insertions(+), 38 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index a07c8a56822de5..2bb56d5df1ebd3 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -152,17 +152,12 @@ namespace {
 /// This class contains a snapshot of the current conversion rewriter state.
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
-  RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
-unsigned numRewrites, unsigned numIgnoredOperations,
-unsigned numErased)
-  : numCreatedOps(numCreatedOps),
-numUnresolvedMaterializations(numUnresolvedMaterializations),
+  RewriterState(unsigned numUnresolvedMaterializations, unsigned numRewrites,
+unsigned numIgnoredOperations, unsigned numErased)
+  : numUnresolvedMaterializations(numUnresolvedMaterializations),
 numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
 numErased(numErased) {}
 
-  /// The current number of created operations.
-  unsigned numCreatedOps;
-
   /// The current number of unresolved materializations.
   unsigned numUnresolvedMaterializations;
 
@@ -299,7 +294,8 @@ class IRRewrite {
 ReplaceBlockArg,
 MoveOperation,
 ModifyOperation,
-ReplaceOperation
+ReplaceOperation,
+CreateOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -372,7 +368,11 @@ class CreateBlockRewrite : public BlockRewrite {
 auto &blockOps = block->getOperations();
 while (!blockOps.empty())
   blockOps.remove(blockOps.begin());
-eraseBlock(block);
+if (block->getParent()) {
+  eraseBlock(block);
+} else {
+  delete block;
+}
   }
 };
 
@@ -602,7 +602,7 @@ class OperationRewrite : public IRRewrite {
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() >= Kind::MoveOperation &&
-   rewrite->getKind() <= Kind::ReplaceOperation;
+   rewrite->getKind() <= Kind::CreateOperation;
   }
 
 protected:
@@ -708,6 +708,19 @@ class ReplaceOperationRewrite : public OperationRewrite {
   /// 1->N conversion of some kind.
   bool changedResults;
 };
+
+class CreateOperationRewrite : public OperationRewrite {
+public:
+  CreateOperationRewrite(ConversionPatternRewriterImpl &rewriterImpl,
+ Operation *op)
+  : OperationRewrite(Kind::CreateOperation, rewriterImpl, op) {}
+
+  static bool classof(const IRRewrite *rewrite) {
+return rewrite->getKind() == Kind::CreateOperation;
+  }
+
+  void rollback() override;
+};
 } // namespace
 
 /// Return "true" if there is an operation rewrite that matches the specified
@@ -925,9 +938,6 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   // replacing a value with one of a different type.
   ConversionValueMapping mapping;
 
-  /// Ordered vector of all of the newly created operations during conversion.
-  SmallVector createdOps;
-
   /// Ordered vector of all unresolved type conversion materializations during
   /// conversion.
   SmallVector unresolvedMaterializations;
@@ -1110,7 +1120,18 @@ void ReplaceOperationRewrite::rollback() {
 
 void ReplaceOperationRewrite::cleanup() { eraseOp(op); }
 
+void CreateOperationRewrite::rollback() {
+  for (Region ®ion : op->getRegions()) {
+while (!region.getBlocks().empty())
+  region.getBlocks().remove(region.getBlocks().begin());
+  }
+  op->dropAllUses();
+  eraseOp(op);
+}
+
 void ConversionPatternRewriterImpl::detachNestedAndErase(Operation *op) {
+  // if (erasedIR.erasedOps.contains(op)) return;
+
   for (Region ®ion : op->getRegions()) {
 for (Block &block : region.getBlocks()) {
   while (!block.getOperations().empty())
@@ -1127,8 +1148,6 @@ void ConversionPatternRewriterImpl::discardRewrites() {
   // Remove any newly created ops.
   for (UnresolvedMaterialization &materialization : unresolvedMaterializations)
 detachNestedAndErase(materialization.getOp());
-  for (auto *op : llvm:

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC][WIP] Turn unresolved materializations into `IRRewrite`s (PR #81761)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81761

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be committed (upon success) or 
rolled back (upon failure).

This commit turns the creation of unresolved materializations 
(`unrealized_conversion_cast`) into `IRRewrite` objects. After this commit, all 
steps in `applyRewrites` and `discardRewrites` are calls to `IRRewrite::commit` 
and `IRRewrite::rollback`.

WIP, but uploading already to show where this chain of refactorings is going.


>From 7b64a0060de5717bf4b407dc4918eed49ed16e57 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 14 Feb 2024 16:47:46 +
Subject: [PATCH] [WIP] UnresolvedMaterialization

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../Transforms/Utils/DialectConversion.cpp| 374 +-
 1 file changed, 179 insertions(+), 195 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 2bb56d5df1ebd3..83cc05b9e1cd98 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -152,15 +152,11 @@ namespace {
 /// This class contains a snapshot of the current conversion rewriter state.
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
-  RewriterState(unsigned numUnresolvedMaterializations, unsigned numRewrites,
-unsigned numIgnoredOperations, unsigned numErased)
-  : numUnresolvedMaterializations(numUnresolvedMaterializations),
-numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
+  RewriterState(unsigned numRewrites, unsigned numIgnoredOperations,
+unsigned numErased)
+  : numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
 numErased(numErased) {}
 
-  /// The current number of unresolved materializations.
-  unsigned numUnresolvedMaterializations;
-
   /// The current number of rewrites performed.
   unsigned numRewrites;
 
@@ -171,109 +167,10 @@ struct RewriterState {
   unsigned numErased;
 };
 
-//===--===//
-// UnresolvedMaterialization
-
-/// This class represents an unresolved materialization, i.e. a materialization
-/// that was inserted during conversion that needs to be legalized at the end 
of
-/// the conversion process.
-class UnresolvedMaterialization {
-public:
-  /// The type of materialization.
-  enum Kind {
-/// This materialization materializes a conversion for an illegal block
-/// argument type, to a legal one.
-Argument,
-
-/// This materialization materializes a conversion from an illegal type to 
a
-/// legal one.
-Target
-  };
-
-  UnresolvedMaterialization(UnrealizedConversionCastOp op = nullptr,
-const TypeConverter *converter = nullptr,
-Kind kind = Target, Type origOutputType = nullptr)
-  : op(op), converterAndKind(converter, kind),
-origOutputType(origOutputType) {}
-
-  /// Return the temporary conversion operation inserted for this
-  /// materialization.
-  UnrealizedConversionCastOp getOp() const { return op; }
-
-  /// Return the type converter of this materialization (which may be null).
-  const TypeConverter *getConverter() const {
-return converterAndKind.getPointer();
-  }
-
-  /// Return the kind of this materialization.
-  Kind getKind() const { return converterAndKind.getInt(); }
-
-  /// Set the kind of this materialization.
-  void setKind(Kind kind) { converterAndKind.setInt(kind); }
-
-  /// Return the original illegal output type of the input values.
-  Type getOrigOutputType() const { return origOutputType; }
-
-private:
-  /// The unresolved materialization operation created during conversion.
-  UnrealizedConversionCastOp op;
-
-  /// The corresponding type converter to use when resolving this
-  /// materialization, and the kind of this materialization.
-  llvm::PointerIntPair converterAndKind;
-
-  /// The original output type. This is only used for argument conversions.
-  Type origOutputType;
-};
-} // namespace
-
-/// Build an unresolved materialization operation given an output type and set
-/// of input operands.
-static Value buildUnresolvedMaterialization(
-UnresolvedMaterialization::Kind kind, Block *insertBlock,
-Block::iterator insertPt, Location loc, ValueRange inputs, Type outputType,
-Type origOutputType, const TypeConverter *converter,
-SmallVectorImpl &unresolvedMaterializations) {
-  // Avoid materializing an unnecessary cast.
-  if (inputs.size() == 1 && inputs.front().getType() == outputType)
-return inputs.front();
-
-  // Create an unresolved materialization. We use a new OpBuilder to avoid
-  // tracking the materialization like we do for other operations

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn block type conversion into `IRRewrite` (PR #81756)

2024-02-14 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/81756
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `ArgConverter` state (PR #81462)

2024-02-16 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81462

>From a7fffc3e18588d1112411a03936e41a2931cefec Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 16 Feb 2024 15:11:41 +
Subject: [PATCH] [mlir][Transforms][NFC] Simplify `ArgConverter` state

* When converting a block signature, `ArgConverter` creates a new block with 
the new signature and moves all operation from the old block to the new block. 
The new block is temporarily inserted into a region that is stored in 
`regionMapping`. The old block is not yet deleted, so that the conversion can 
be rolled back. `regionMapping` is not needed. Instead of moving the old block 
to a temporary region, it can just be unlinked. Block erasures are handles in 
the same way in the dialect conversion.
* `regionToConverter` is a mapping from regions to type converter. That field 
is never accessed within `ArgConverter`. It should be stored in 
`ConversionPatternRewriterImpl` instead.
---
 .../Transforms/Utils/DialectConversion.cpp| 79 ++-
 1 file changed, 22 insertions(+), 57 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 673bd0383809cb..35028001a03dd9 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -343,23 +343,6 @@ struct ArgConverter {
 const TypeConverter *converter;
   };
 
-  /// Return if the signature of the given block has already been converted.
-  bool hasBeenConverted(Block *block) const {
-return conversionInfo.count(block) || convertedBlocks.count(block);
-  }
-
-  /// Set the type converter to use for the given region.
-  void setConverter(Region *region, const TypeConverter *typeConverter) {
-assert(typeConverter && "expected valid type converter");
-regionToConverter[region] = typeConverter;
-  }
-
-  /// Return the type converter to use for the given region, or null if there
-  /// isn't one.
-  const TypeConverter *getConverter(Region *region) {
-return regionToConverter.lookup(region);
-  }
-
   
//======//
   // Rewrite Application
   
//======//
@@ -409,24 +392,10 @@ struct ArgConverter {
   ConversionValueMapping &mapping,
   SmallVectorImpl &argReplacements);
 
-  /// Insert a new conversion into the cache.
-  void insertConversion(Block *newBlock, ConvertedBlockInfo &&info);
-
   /// A collection of blocks that have had their arguments converted. This is a
   /// map from the new replacement block, back to the original block.
   llvm::MapVector conversionInfo;
 
-  /// The set of original blocks that were converted.
-  DenseSet convertedBlocks;
-
-  /// A mapping from valid regions, to those containing the original blocks of 
a
-  /// conversion.
-  DenseMap> regionMapping;
-
-  /// A mapping of regions to type converters that should be used when
-  /// converting the arguments of blocks within that region.
-  DenseMap regionToConverter;
-
   /// The pattern rewriter to use when materializing conversions.
   PatternRewriter &rewriter;
 
@@ -474,12 +443,12 @@ void ArgConverter::discardRewrites(Block *block) {
 block->getArgument(i).dropAllUses();
   block->replaceAllUsesWith(origBlock);
 
-  // Move the operations back the original block and the delete the new block.
+  // Move the operations back the original block, move the original block back
+  // into its original location and the delete the new block.
   origBlock->getOperations().splice(origBlock->end(), block->getOperations());
-  origBlock->moveBefore(block);
+  block->getParent()->getBlocks().insert(Region::iterator(block), origBlock);
   block->erase();
 
-  convertedBlocks.erase(origBlock);
   conversionInfo.erase(it);
 }
 
@@ -510,6 +479,9 @@ void ArgConverter::applyRewrites(ConversionValueMapping 
&mapping) {
 mapping.lookupOrDefault(castValue, origArg.getType()));
   }
 }
+
+delete origBlock;
+blockInfo.origBlock = nullptr;
   }
 }
 
@@ -572,9 +544,11 @@ FailureOr ArgConverter::convertSignature(
 Block *block, const TypeConverter *converter,
 ConversionValueMapping &mapping,
 SmallVectorImpl &argReplacements) {
-  // Check if the block was already converted. If the block is detached,
-  // conservatively assume it is going to be deleted.
-  if (hasBeenConverted(block) || !block->getParent())
+  // Check if the block was already converted.
+  // * If the block is mapped in `conversionInfo`, it is a converted block.
+  // * If the block is detached, conservatively assume that it is going to be
+  //   deleted; it is likely the old block (before it was converted).
+  if (conversionInfo.count(block) || !block->getParent())
 return block;
   // If a converter wasn't provided, and the block wasn't already converted,
   // there is nothing we can do

[llvm-branch-commits] [mlir] [mlir][Transforms] Dialect conversion: Improve signature conversion API (PR #81997)

2024-02-16 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/81997

This commit improves the block signature conversion API of the dialect 
conversion.

There is the following comment in `ArgConverter::applySignatureConversion`:
```
// If no arguments are being changed or added, there is nothing to do.
```

However, the implementation actually used to replace a block with a new block 
even if the block argument types do not change (i.e., there is "nothing to 
do"). This is fixed in this commit. The documentation of the public 
`ConversionPatternRewriter` API is updated accordingly.

This commit also removes a check that used to *sometimes* skip a block 
signature conversion if the block was already converted. This is not consistent 
with the public `ConversionPatternRewriter` API; block should always be 
converted, regardless of whether they were already converted or not.

Block signature conversion also used to be silently skipped when the specified 
block was detached. Instead of silently skipping, an assertion is triggered. 
Attempting to convert a detached block (which is likely an erased block) is 
invalid API usage.

>From 5dc79f6af9ac00a61767062980b13eb4ae8d2571 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 16 Feb 2024 15:13:37 +
Subject: [PATCH] [mlir][Transforms] Dialect conversion: Improve signature
 conversion API

This commit improves the block signature conversion API of the dialect 
conversion.

There is the following comment in `ArgConverter::applySignatureConversion`:
```
// If no arguments are being changed or added, there is nothing to do.
```

However, the implementation actually used to replace a block with a new block 
even if the block argument types do not change (i.e., there is "nothing to 
do"). This is fixed in this commit. The documentation of the public 
`ConversionPatternRewriter` API is updated accordingly.

This commit also removes a check that used to *sometimes* skip a block 
signature conversion if the block was already converted. This is not consistent 
with the public `ConversionPatternRewriter` API; block should always be 
converted, regardless of whether they were already converted or not.

Block signature conversion also used to be silently skipped when the specified 
block was detached. Instead of silently skipping, an assertion is triggered. 
Attempting to convert a detached block (which is likely an erased block) is 
invalid API usage.
---
 mlir/include/mlir/Transforms/DialectConversion.h | 12 +---
 mlir/lib/Transforms/Utils/DialectConversion.cpp  | 10 +++---
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 0d7722aa07ee38..2575be4cdea1ac 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -663,6 +663,8 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
   /// Apply a signature conversion to the entry block of the given region. This
   /// replaces the entry block with a new block containing the updated
   /// signature. The new entry block to the region is returned for convenience.
+  /// If no block argument types are changing, the entry original block will be
+  /// left in place and returned.
   ///
   /// If provided, `converter` will be used for any materializations.
   Block *
@@ -671,8 +673,11 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
const TypeConverter *converter = nullptr);
 
   /// Convert the types of block arguments within the given region. This
-  /// replaces each block with a new block containing the updated signature. 
The
-  /// entry block may have a special conversion if `entryConversion` is
+  /// replaces each block with a new block containing the updated signature. If
+  /// an updated signature would match the current signature, the respective
+  /// block is left in place as is.
+  ///
+  /// The entry block may have a special conversion if `entryConversion` is
   /// provided. On success, the new entry block to the region is returned for
   /// convenience. Otherwise, failure is returned.
   FailureOr convertRegionTypes(
@@ -681,7 +686,8 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
 
   /// Convert the types of block arguments within the given region except for
   /// the entry region. This replaces each non-entry block with a new block
-  /// containing the updated signature.
+  /// containing the updated signature. If an updated signature would match the
+  /// current signature, the respective block is left in place as is.
   ///
   /// If special conversion behavior is needed for the non-entry blocks (for
   /// example, we need to convert only a subset of a BB arguments), such
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn block type conversion into `IRRewrite` (PR #81756)

2024-02-16 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81756

>From 5dc79f6af9ac00a61767062980b13eb4ae8d2571 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 16 Feb 2024 15:13:37 +
Subject: [PATCH 1/2] [mlir][Transforms] Dialect conversion: Improve signature
 conversion API

This commit improves the block signature conversion API of the dialect 
conversion.

There is the following comment in `ArgConverter::applySignatureConversion`:
```
// If no arguments are being changed or added, there is nothing to do.
```

However, the implementation actually used to replace a block with a new block 
even if the block argument types do not change (i.e., there is "nothing to 
do"). This is fixed in this commit. The documentation of the public 
`ConversionPatternRewriter` API is updated accordingly.

This commit also removes a check that used to *sometimes* skip a block 
signature conversion if the block was already converted. This is not consistent 
with the public `ConversionPatternRewriter` API; block should always be 
converted, regardless of whether they were already converted or not.

Block signature conversion also used to be silently skipped when the specified 
block was detached. Instead of silently skipping, an assertion is triggered. 
Attempting to convert a detached block (which is likely an erased block) is 
invalid API usage.
---
 mlir/include/mlir/Transforms/DialectConversion.h | 12 +---
 mlir/lib/Transforms/Utils/DialectConversion.cpp  | 10 +++---
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 0d7722aa07ee38..2575be4cdea1ac 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -663,6 +663,8 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
   /// Apply a signature conversion to the entry block of the given region. This
   /// replaces the entry block with a new block containing the updated
   /// signature. The new entry block to the region is returned for convenience.
+  /// If no block argument types are changing, the entry original block will be
+  /// left in place and returned.
   ///
   /// If provided, `converter` will be used for any materializations.
   Block *
@@ -671,8 +673,11 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
const TypeConverter *converter = nullptr);
 
   /// Convert the types of block arguments within the given region. This
-  /// replaces each block with a new block containing the updated signature. 
The
-  /// entry block may have a special conversion if `entryConversion` is
+  /// replaces each block with a new block containing the updated signature. If
+  /// an updated signature would match the current signature, the respective
+  /// block is left in place as is.
+  ///
+  /// The entry block may have a special conversion if `entryConversion` is
   /// provided. On success, the new entry block to the region is returned for
   /// convenience. Otherwise, failure is returned.
   FailureOr convertRegionTypes(
@@ -681,7 +686,8 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
 
   /// Convert the types of block arguments within the given region except for
   /// the entry region. This replaces each non-entry block with a new block
-  /// containing the updated signature.
+  /// containing the updated signature. If an updated signature would match the
+  /// current signature, the respective block is left in place as is.
   ///
   /// If special conversion behavior is needed for the non-entry blocks (for
   /// example, we need to convert only a subset of a BB arguments), such
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 35028001a03dd9..c16bb144efecf5 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -544,12 +544,8 @@ FailureOr ArgConverter::convertSignature(
 Block *block, const TypeConverter *converter,
 ConversionValueMapping &mapping,
 SmallVectorImpl &argReplacements) {
-  // Check if the block was already converted.
-  // * If the block is mapped in `conversionInfo`, it is a converted block.
-  // * If the block is detached, conservatively assume that it is going to be
-  //   deleted; it is likely the old block (before it was converted).
-  if (conversionInfo.count(block) || !block->getParent())
-return block;
+  assert(block->getParent() && "cannot convert signature of detached block");
+
   // If a converter wasn't provided, and the block wasn't already converted,
   // there is nothing we can do.
   if (!converter)
@@ -570,7 +566,7 @@ Block *ArgConverter::applySignatureConversion(
   // If no arguments are being changed or added, there is nothing to do.
   unsigned origArgCount

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn block type conversion into `IRRewrite` (PR #81756)

2024-02-16 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/81756
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn op/block arg replacements into `IRRewrite`s (PR #81757)

2024-02-16 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81757

>From b8d4cbd5e237dfc9fa6b7420b85a8e5de94f0725 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 16 Feb 2024 15:19:07 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn op/block arg replacements into
 `IRRewrite`s

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, op replacements and block argument replacements were kept track in 
separate data structures inside the dialect conversion. This commit turns them 
into `IRRewrite`s, so that they can be committed or rolled back just like any 
other rewrite. This simplifies the internal state of the dialect conversion.

Overview of changes:
* Add two new rewrite classes: `ReplaceBlockArgRewrite` and 
`ReplaceOperationRewrite`. Remove the `OpReplacement` helper class; it is now 
part of `ReplaceOperationRewrite`.
* Simplify `RewriterState`: `numReplacements` and `numArgReplacements` are no 
longer needed. (Now being kept track of by `numRewrites`.)
* Add `IRRewrite::cleanup`. Operations should not be erased in `commit` because 
they may still be referenced in other internal state of the dialect conversion 
(`mapping`). Detaching operations is fine.
---
 .../Transforms/Utils/DialectConversion.cpp| 291 +-
 1 file changed, 153 insertions(+), 138 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 30133a14dbae56..21fd02fcd5c725 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -153,14 +153,12 @@ namespace {
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
-unsigned numReplacements, unsigned numArgReplacements,
 unsigned numRewrites, unsigned numIgnoredOperations,
 unsigned numErased)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
-numReplacements(numReplacements),
-numArgReplacements(numArgReplacements), numRewrites(numRewrites),
-numIgnoredOperations(numIgnoredOperations), numErased(numErased) {}
+numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
+numErased(numErased) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -168,12 +166,6 @@ struct RewriterState {
   /// The current number of unresolved materializations.
   unsigned numUnresolvedMaterializations;
 
-  /// The current number of replacements queued.
-  unsigned numReplacements;
-
-  /// The current number of argument replacements queued.
-  unsigned numArgReplacements;
-
   /// The current number of rewrites performed.
   unsigned numRewrites;
 
@@ -184,20 +176,6 @@ struct RewriterState {
   unsigned numErased;
 };
 
-//===--===//
-// OpReplacement
-
-/// This class represents one requested operation replacement via 'replaceOp' 
or
-/// 'eraseOp`.
-struct OpReplacement {
-  OpReplacement(const TypeConverter *converter = nullptr)
-  : converter(converter) {}
-
-  /// An optional type converter that can be used to materialize conversions
-  /// between the new and old values if necessary.
-  const TypeConverter *converter;
-};
-
 
//===--===//
 // UnresolvedMaterialization
 
@@ -318,8 +296,10 @@ class IRRewrite {
 MoveBlock,
 SplitBlock,
 BlockTypeConversion,
+ReplaceBlockArg,
 MoveOperation,
-ModifyOperation
+ModifyOperation,
+ReplaceOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -330,6 +310,12 @@ class IRRewrite {
   /// Commit the rewrite.
   virtual void commit() {}
 
+  /// Cleanup operations. Operations may be unlinked from their blocks during
+  /// the commit/rollback phase, but they must not be erased yet. This is
+  /// because internal dialect conversion state (such as `mapping`) may still
+  /// be using them. Operations must be erased during cleanup.
+  virtual void cleanup() {}
+
   Kind getKind() const { return kind; }
 
   static bool classof(const IRRewrite *rewrite) { return true; }
@@ -356,7 +342,7 @@ class BlockRewrite : public IRRewrite {
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() >= Kind::CreateBlock &&
-   rewrite->getKind() <= Kind::BlockTypeConversion;
+   rewrite->getKind() <= Kind::ReplaceBlockArg;
   }
 
 protected:
@@ -424,6 +410,8 @@ class EraseBlockRewrite : public BlockRewrite {
   void commit() override {
 // Erase the block.
 assert(block && "expected block");
+assert(block->empty() && "expected empty b

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn op creation into `IRRewrite` (PR #81759)

2024-02-16 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81759

>From 67010343f91c6808a18731f01d139db6cb36fde6 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 16 Feb 2024 15:21:48 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn op creation into `IRRewrite`

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, the dialect conversion kept track of "op creation" in separate 
internal data structures. This commit turns "op creation" into an `IRRewrite` 
that can be committed and rolled back just like any other rewrite. This commit 
simplifies the internal state of the dialect conversion.
---
 .../Transforms/Utils/DialectConversion.cpp| 104 +++---
 1 file changed, 66 insertions(+), 38 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 21fd02fcd5c725..5b7ad4e7b8e281 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -152,17 +152,12 @@ namespace {
 /// This class contains a snapshot of the current conversion rewriter state.
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
-  RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
-unsigned numRewrites, unsigned numIgnoredOperations,
-unsigned numErased)
-  : numCreatedOps(numCreatedOps),
-numUnresolvedMaterializations(numUnresolvedMaterializations),
+  RewriterState(unsigned numUnresolvedMaterializations, unsigned numRewrites,
+unsigned numIgnoredOperations, unsigned numErased)
+  : numUnresolvedMaterializations(numUnresolvedMaterializations),
 numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
 numErased(numErased) {}
 
-  /// The current number of created operations.
-  unsigned numCreatedOps;
-
   /// The current number of unresolved materializations.
   unsigned numUnresolvedMaterializations;
 
@@ -299,7 +294,8 @@ class IRRewrite {
 ReplaceBlockArg,
 MoveOperation,
 ModifyOperation,
-ReplaceOperation
+ReplaceOperation,
+CreateOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -372,7 +368,11 @@ class CreateBlockRewrite : public BlockRewrite {
 auto &blockOps = block->getOperations();
 while (!blockOps.empty())
   blockOps.remove(blockOps.begin());
-eraseBlock(block);
+if (block->getParent()) {
+  eraseBlock(block);
+} else {
+  delete block;
+}
   }
 };
 
@@ -602,7 +602,7 @@ class OperationRewrite : public IRRewrite {
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() >= Kind::MoveOperation &&
-   rewrite->getKind() <= Kind::ReplaceOperation;
+   rewrite->getKind() <= Kind::CreateOperation;
   }
 
 protected:
@@ -708,6 +708,19 @@ class ReplaceOperationRewrite : public OperationRewrite {
   /// 1->N conversion of some kind.
   bool changedResults;
 };
+
+class CreateOperationRewrite : public OperationRewrite {
+public:
+  CreateOperationRewrite(ConversionPatternRewriterImpl &rewriterImpl,
+ Operation *op)
+  : OperationRewrite(Kind::CreateOperation, rewriterImpl, op) {}
+
+  static bool classof(const IRRewrite *rewrite) {
+return rewrite->getKind() == Kind::CreateOperation;
+  }
+
+  void rollback() override;
+};
 } // namespace
 
 /// Return "true" if there is an operation rewrite that matches the specified
@@ -925,9 +938,6 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   // replacing a value with one of a different type.
   ConversionValueMapping mapping;
 
-  /// Ordered vector of all of the newly created operations during conversion.
-  SmallVector createdOps;
-
   /// Ordered vector of all unresolved type conversion materializations during
   /// conversion.
   SmallVector unresolvedMaterializations;
@@ -1110,7 +1120,18 @@ void ReplaceOperationRewrite::rollback() {
 
 void ReplaceOperationRewrite::cleanup() { eraseOp(op); }
 
+void CreateOperationRewrite::rollback() {
+  for (Region ®ion : op->getRegions()) {
+while (!region.getBlocks().empty())
+  region.getBlocks().remove(region.getBlocks().begin());
+  }
+  op->dropAllUses();
+  eraseOp(op);
+}
+
 void ConversionPatternRewriterImpl::detachNestedAndErase(Operation *op) {
+  // if (erasedIR.erasedOps.contains(op)) return;
+
   for (Region ®ion : op->getRegions()) {
 for (Block &block : region.getBlocks()) {
   while (!block.getOperations().empty())
@@ -1127,8 +1148,6 @@ void ConversionPatternRewriterImpl::discardRewrites() {
   // Remove any newly created ops.
   for (UnresolvedMaterialization &materialization : unresolvedMaterializations)
 detachNestedAndErase(materialization.getOp());
-  for (auto *op : llvm:

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC][WIP] Turn unresolved materializations into `IRRewrite`s (PR #81761)

2024-02-16 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81761

>From ab0cd8c2d3b66b0a11bee128dc4e11e754e11a36 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 16 Feb 2024 15:24:42 +
Subject: [PATCH] [WIP] UnresolvedMaterialization

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../Transforms/Utils/DialectConversion.cpp| 374 +-
 1 file changed, 179 insertions(+), 195 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 5b7ad4e7b8e281..6fc9225568d028 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -152,15 +152,11 @@ namespace {
 /// This class contains a snapshot of the current conversion rewriter state.
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
-  RewriterState(unsigned numUnresolvedMaterializations, unsigned numRewrites,
-unsigned numIgnoredOperations, unsigned numErased)
-  : numUnresolvedMaterializations(numUnresolvedMaterializations),
-numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
+  RewriterState(unsigned numRewrites, unsigned numIgnoredOperations,
+unsigned numErased)
+  : numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
 numErased(numErased) {}
 
-  /// The current number of unresolved materializations.
-  unsigned numUnresolvedMaterializations;
-
   /// The current number of rewrites performed.
   unsigned numRewrites;
 
@@ -171,109 +167,10 @@ struct RewriterState {
   unsigned numErased;
 };
 
-//===--===//
-// UnresolvedMaterialization
-
-/// This class represents an unresolved materialization, i.e. a materialization
-/// that was inserted during conversion that needs to be legalized at the end 
of
-/// the conversion process.
-class UnresolvedMaterialization {
-public:
-  /// The type of materialization.
-  enum Kind {
-/// This materialization materializes a conversion for an illegal block
-/// argument type, to a legal one.
-Argument,
-
-/// This materialization materializes a conversion from an illegal type to 
a
-/// legal one.
-Target
-  };
-
-  UnresolvedMaterialization(UnrealizedConversionCastOp op = nullptr,
-const TypeConverter *converter = nullptr,
-Kind kind = Target, Type origOutputType = nullptr)
-  : op(op), converterAndKind(converter, kind),
-origOutputType(origOutputType) {}
-
-  /// Return the temporary conversion operation inserted for this
-  /// materialization.
-  UnrealizedConversionCastOp getOp() const { return op; }
-
-  /// Return the type converter of this materialization (which may be null).
-  const TypeConverter *getConverter() const {
-return converterAndKind.getPointer();
-  }
-
-  /// Return the kind of this materialization.
-  Kind getKind() const { return converterAndKind.getInt(); }
-
-  /// Set the kind of this materialization.
-  void setKind(Kind kind) { converterAndKind.setInt(kind); }
-
-  /// Return the original illegal output type of the input values.
-  Type getOrigOutputType() const { return origOutputType; }
-
-private:
-  /// The unresolved materialization operation created during conversion.
-  UnrealizedConversionCastOp op;
-
-  /// The corresponding type converter to use when resolving this
-  /// materialization, and the kind of this materialization.
-  llvm::PointerIntPair converterAndKind;
-
-  /// The original output type. This is only used for argument conversions.
-  Type origOutputType;
-};
-} // namespace
-
-/// Build an unresolved materialization operation given an output type and set
-/// of input operands.
-static Value buildUnresolvedMaterialization(
-UnresolvedMaterialization::Kind kind, Block *insertBlock,
-Block::iterator insertPt, Location loc, ValueRange inputs, Type outputType,
-Type origOutputType, const TypeConverter *converter,
-SmallVectorImpl &unresolvedMaterializations) {
-  // Avoid materializing an unnecessary cast.
-  if (inputs.size() == 1 && inputs.front().getType() == outputType)
-return inputs.front();
-
-  // Create an unresolved materialization. We use a new OpBuilder to avoid
-  // tracking the materialization like we do for other operations.
-  OpBuilder builder(insertBlock, insertPt);
-  auto convertOp =
-  builder.create(loc, outputType, inputs);
-  unresolvedMaterializations.emplace_back(convertOp, converter, kind,
-  origOutputType);
-  return convertOp.getResult(0);
-}
-static Value buildUnresolvedArgumentMaterialization(
-PatternRewriter &rewriter, Location loc, ValueRange inputs,
-Type origOutputType, Type outputType, const TypeConverter *converter,
-SmallVectorImpl &unresolvedMaterial

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC][WIP] Turn unresolved materializations into `IRRewrite`s (PR #81761)

2024-02-19 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81761

>From 51a7e12b4e0e8ceee8429460592307adfad18a96 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 19 Feb 2024 10:29:29 +
Subject: [PATCH] [WIP] UnresolvedMaterialization

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../Transforms/Utils/DialectConversion.cpp| 371 +-
 1 file changed, 176 insertions(+), 195 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 5b7ad4e7b8e281..4ef26a739e4ea1 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -152,15 +152,11 @@ namespace {
 /// This class contains a snapshot of the current conversion rewriter state.
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
-  RewriterState(unsigned numUnresolvedMaterializations, unsigned numRewrites,
-unsigned numIgnoredOperations, unsigned numErased)
-  : numUnresolvedMaterializations(numUnresolvedMaterializations),
-numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
+  RewriterState(unsigned numRewrites, unsigned numIgnoredOperations,
+unsigned numErased)
+  : numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
 numErased(numErased) {}
 
-  /// The current number of unresolved materializations.
-  unsigned numUnresolvedMaterializations;
-
   /// The current number of rewrites performed.
   unsigned numRewrites;
 
@@ -171,109 +167,10 @@ struct RewriterState {
   unsigned numErased;
 };
 
-//===--===//
-// UnresolvedMaterialization
-
-/// This class represents an unresolved materialization, i.e. a materialization
-/// that was inserted during conversion that needs to be legalized at the end 
of
-/// the conversion process.
-class UnresolvedMaterialization {
-public:
-  /// The type of materialization.
-  enum Kind {
-/// This materialization materializes a conversion for an illegal block
-/// argument type, to a legal one.
-Argument,
-
-/// This materialization materializes a conversion from an illegal type to 
a
-/// legal one.
-Target
-  };
-
-  UnresolvedMaterialization(UnrealizedConversionCastOp op = nullptr,
-const TypeConverter *converter = nullptr,
-Kind kind = Target, Type origOutputType = nullptr)
-  : op(op), converterAndKind(converter, kind),
-origOutputType(origOutputType) {}
-
-  /// Return the temporary conversion operation inserted for this
-  /// materialization.
-  UnrealizedConversionCastOp getOp() const { return op; }
-
-  /// Return the type converter of this materialization (which may be null).
-  const TypeConverter *getConverter() const {
-return converterAndKind.getPointer();
-  }
-
-  /// Return the kind of this materialization.
-  Kind getKind() const { return converterAndKind.getInt(); }
-
-  /// Set the kind of this materialization.
-  void setKind(Kind kind) { converterAndKind.setInt(kind); }
-
-  /// Return the original illegal output type of the input values.
-  Type getOrigOutputType() const { return origOutputType; }
-
-private:
-  /// The unresolved materialization operation created during conversion.
-  UnrealizedConversionCastOp op;
-
-  /// The corresponding type converter to use when resolving this
-  /// materialization, and the kind of this materialization.
-  llvm::PointerIntPair converterAndKind;
-
-  /// The original output type. This is only used for argument conversions.
-  Type origOutputType;
-};
-} // namespace
-
-/// Build an unresolved materialization operation given an output type and set
-/// of input operands.
-static Value buildUnresolvedMaterialization(
-UnresolvedMaterialization::Kind kind, Block *insertBlock,
-Block::iterator insertPt, Location loc, ValueRange inputs, Type outputType,
-Type origOutputType, const TypeConverter *converter,
-SmallVectorImpl &unresolvedMaterializations) {
-  // Avoid materializing an unnecessary cast.
-  if (inputs.size() == 1 && inputs.front().getType() == outputType)
-return inputs.front();
-
-  // Create an unresolved materialization. We use a new OpBuilder to avoid
-  // tracking the materialization like we do for other operations.
-  OpBuilder builder(insertBlock, insertPt);
-  auto convertOp =
-  builder.create(loc, outputType, inputs);
-  unresolvedMaterializations.emplace_back(convertOp, converter, kind,
-  origOutputType);
-  return convertOp.getResult(0);
-}
-static Value buildUnresolvedArgumentMaterialization(
-PatternRewriter &rewriter, Location loc, ValueRange inputs,
-Type origOutputType, Type outputType, const TypeConverter *converter,
-SmallVectorImpl &unresolvedMaterial

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC][WIP] Turn unresolved materializations into `IRRewrite`s (PR #81761)

2024-02-19 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/81761
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC][WIP] Turn unresolved materializations into `IRRewrite`s (PR #81761)

2024-02-19 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer ready_for_review 
https://github.com/llvm/llvm-project/pull/81761
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn unresolved materializations into `IRRewrite`s (PR #81761)

2024-02-19 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/81761
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Make `ConversionPatternRewriter` constructor private (PR #82244)

2024-02-19 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/82244

`ConversionPatternRewriter` objects should not be constructed outside of 
dialect conversions. Some IR modifications performed through a 
`ConversionPatternRewriter` are reflected in the IR in a delayed fashion (e.g., 
only when the dialect conversion is guaranteed to succeed). Using a 
`ConversionPatternRewriter` outside of the dialect conversion is incorrect API 
usage and can bring the IR in an inconsistent state.

Migration guide: Use `IRRewriter` instead of `ConversionPatternRewriter`.

>From 9c3b81074c1d1422af00b59ebb4d95465a1c3ad0 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 19 Feb 2024 12:50:30 +
Subject: [PATCH] [mlir][Transforms] Make `ConversionPatternRewriter`
 constructor private

`ConversionPatternRewriter` objects should not be constructed outside of 
dialect conversions. Some IR modifications performed through a 
`ConversionPatternRewriter` are reflected in the IR in a delayed fashion (e.g., 
only when the dialect conversion is guaranteed to succeed). Using a 
`ConversionPatternRewriter` outside of the dialect conversion is incorrect API 
usage and can bring the IR in an inconsistent state.

Migration guide: Use `IRRewriter` instead of `ConversionPatternRewriter`.
---
 .../mlir/Transforms/DialectConversion.h| 10 +-
 .../lib/Transforms/Utils/DialectConversion.cpp | 18 +++---
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 2575be4cdea1ac..5c91a9498b35d4 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -27,6 +27,7 @@ class Block;
 class ConversionPatternRewriter;
 class MLIRContext;
 class Operation;
+struct OperationConverter;
 class Type;
 class Value;
 
@@ -657,7 +658,6 @@ struct ConversionPatternRewriterImpl;
 /// hooks.
 class ConversionPatternRewriter final : public PatternRewriter {
 public:
-  explicit ConversionPatternRewriter(MLIRContext *ctx);
   ~ConversionPatternRewriter() override;
 
   /// Apply a signature conversion to the entry block of the given region. This
@@ -764,6 +764,14 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
   detail::ConversionPatternRewriterImpl &getImpl();
 
 private:
+  // Allow OperationConverter to construct new rewriters.
+  friend struct OperationConverter;
+
+  /// Conversion pattern rewriters must not be used outside of dialect
+  /// conversions. They apply some IR rewrites in a delayed fashion and could
+  /// bring the IR into an inconsistent state when used standalone.
+  explicit ConversionPatternRewriter(MLIRContext *ctx);
+
   // Hide unsupported pattern rewriter API.
   using OpBuilder::setListener;
 
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 4ef26a739e4ea1..6cf178e149be7f 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -594,9 +594,11 @@ class ReplaceOperationRewrite : public OperationRewrite {
 
   void cleanup() override;
 
-private:
-  friend struct OperationConverter;
+  const TypeConverter *getConverter() const { return converter; }
+
+  bool hasChangedResults() const { return changedResults; }
 
+private:
   /// An optional type converter that can be used to materialize conversions
   /// between the new and old values if necessary.
   const TypeConverter *converter;
@@ -2354,7 +2356,9 @@ enum OpConversionMode {
   /// applied to the operations on success.
   Analysis,
 };
+} // namespace
 
+namespace mlir {
 // This class converts operations to a given conversion target via a set of
 // rewrite patterns. The conversion behaves differently depending on the
 // conversion mode.
@@ -2414,7 +2418,7 @@ struct OperationConverter {
   /// *not* to be legalizable to the target.
   DenseSet *trackedOps;
 };
-} // namespace
+} // namespace mlir
 
 LogicalResult OperationConverter::convert(ConversionPatternRewriter &rewriter,
   Operation *op) {
@@ -2506,7 +2510,7 @@ OperationConverter::finalize(ConversionPatternRewriter 
&rewriter) {
   for (unsigned i = 0; i < rewriterImpl.rewrites.size(); ++i) {
 auto *opReplacement =
 dyn_cast(rewriterImpl.rewrites[i].get());
-if (!opReplacement || !opReplacement->changedResults)
+if (!opReplacement || !opReplacement->hasChangedResults())
   continue;
 Operation *op = opReplacement->getOperation();
 for (OpResult result : op->getResults()) {
@@ -2530,9 +2534,9 @@ OperationConverter::finalize(ConversionPatternRewriter 
&rewriter) {
 
   // Legalize this result.
   rewriter.setInsertionPoint(op);
-  if (failed(legalizeChangedResultType(op, result, newValue,
-   opReplacement->converter, rewri

[llvm-branch-commits] [flang] [mlir] [mlir][Transforms] Make `ConversionPatternRewriter` constructor private (PR #82244)

2024-02-19 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/82244

>From f3fe2f1f9e2b561693bcaa2c8df84ac8cc8a60af Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 19 Feb 2024 12:50:30 +
Subject: [PATCH] [mlir][Transforms] Make `ConversionPatternRewriter`
 constructor private

`ConversionPatternRewriter` objects should not be constructed outside of 
dialect conversions. Some IR modifications performed through a 
`ConversionPatternRewriter` are reflected in the IR in a delayed fashion (e.g., 
only when the dialect conversion is guaranteed to succeed). Using a 
`ConversionPatternRewriter` outside of the dialect conversion is incorrect API 
usage and can bring the IR in an inconsistent state.

Migration guide: Use `IRRewriter` instead of `ConversionPatternRewriter`.
---
 flang/lib/Frontend/FrontendActions.cpp |  2 +-
 .../mlir/Transforms/DialectConversion.h| 10 +-
 .../lib/Transforms/Utils/DialectConversion.cpp | 18 +++---
 3 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/flang/lib/Frontend/FrontendActions.cpp 
b/flang/lib/Frontend/FrontendActions.cpp
index 44e80e946ed832..849b3c8e4dc027 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -177,7 +177,7 @@ static void addAMDGPUSpecificMLIRItems(mlir::ModuleOp 
&mlirModule,
 return;
   }
 
-  mlir::ConversionPatternRewriter builder(mlirModule.getContext());
+  mlir::IRRewriter builder(mlirModule.getContext());
   unsigned oclcABIVERsion = codeGenOpts.CodeObjectVersion;
   auto int32Type = builder.getI32Type();
 
diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 2575be4cdea1ac..5c91a9498b35d4 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -27,6 +27,7 @@ class Block;
 class ConversionPatternRewriter;
 class MLIRContext;
 class Operation;
+struct OperationConverter;
 class Type;
 class Value;
 
@@ -657,7 +658,6 @@ struct ConversionPatternRewriterImpl;
 /// hooks.
 class ConversionPatternRewriter final : public PatternRewriter {
 public:
-  explicit ConversionPatternRewriter(MLIRContext *ctx);
   ~ConversionPatternRewriter() override;
 
   /// Apply a signature conversion to the entry block of the given region. This
@@ -764,6 +764,14 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
   detail::ConversionPatternRewriterImpl &getImpl();
 
 private:
+  // Allow OperationConverter to construct new rewriters.
+  friend struct OperationConverter;
+
+  /// Conversion pattern rewriters must not be used outside of dialect
+  /// conversions. They apply some IR rewrites in a delayed fashion and could
+  /// bring the IR into an inconsistent state when used standalone.
+  explicit ConversionPatternRewriter(MLIRContext *ctx);
+
   // Hide unsupported pattern rewriter API.
   using OpBuilder::setListener;
 
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 4ef26a739e4ea1..6cf178e149be7f 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -594,9 +594,11 @@ class ReplaceOperationRewrite : public OperationRewrite {
 
   void cleanup() override;
 
-private:
-  friend struct OperationConverter;
+  const TypeConverter *getConverter() const { return converter; }
+
+  bool hasChangedResults() const { return changedResults; }
 
+private:
   /// An optional type converter that can be used to materialize conversions
   /// between the new and old values if necessary.
   const TypeConverter *converter;
@@ -2354,7 +2356,9 @@ enum OpConversionMode {
   /// applied to the operations on success.
   Analysis,
 };
+} // namespace
 
+namespace mlir {
 // This class converts operations to a given conversion target via a set of
 // rewrite patterns. The conversion behaves differently depending on the
 // conversion mode.
@@ -2414,7 +2418,7 @@ struct OperationConverter {
   /// *not* to be legalizable to the target.
   DenseSet *trackedOps;
 };
-} // namespace
+} // namespace mlir
 
 LogicalResult OperationConverter::convert(ConversionPatternRewriter &rewriter,
   Operation *op) {
@@ -2506,7 +2510,7 @@ OperationConverter::finalize(ConversionPatternRewriter 
&rewriter) {
   for (unsigned i = 0; i < rewriterImpl.rewrites.size(); ++i) {
 auto *opReplacement =
 dyn_cast(rewriterImpl.rewrites[i].get());
-if (!opReplacement || !opReplacement->changedResults)
+if (!opReplacement || !opReplacement->hasChangedResults())
   continue;
 Operation *op = opReplacement->getOperation();
 for (OpResult result : op->getResults()) {
@@ -2530,9 +2534,9 @@ OperationConverter::finalize(ConversionPatternRewriter 
&rewriter) {
 
   // Legalize this result.
   rewriter.setInsertionPoint(op);
-  if (failed(l

[llvm-branch-commits] [mlir] [mlir][Transforms] Encapsulate dialect conversion options in `ConversionConfig` (PR #82250)

2024-02-19 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/82250

This commit adds a new `ConversionConfig` struct that allows users to customize 
the dialect conversion. This configuration is similar to `GreedyRewriteConfig` 
for the greedy pattern rewrite driver.

A few existing options are moved to this objects, simplifying the dialect 
conversion API.

>From 819e5f95ed0857e88972501cb10b9931b1e91a1c Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 19 Feb 2024 14:02:14 +
Subject: [PATCH] [mlir][Transforms] Encapsulate dialect conversion options in
 `ConversionConfig`

This commit adds a new `ConversionConfig` struct that allows users to customize 
the dialect conversion. This configuration is similar to `GreedyRewriteConfig` 
for the greedy pattern rewrite driver.

A few existing options are moved to this objects, simplifying the dialect 
conversion API.
---
 .../mlir/Transforms/DialectConversion.h   |  75 ++
 .../Transforms/Utils/DialectConversion.cpp| 129 +-
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   |  14 +-
 3 files changed, 118 insertions(+), 100 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 5c91a9498b35d4..8da5dcb0be3fd0 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -24,6 +24,7 @@ namespace mlir {
 // Forward declarations.
 class Attribute;
 class Block;
+struct ConversionConfig;
 class ConversionPatternRewriter;
 class MLIRContext;
 class Operation;
@@ -770,7 +771,8 @@ class ConversionPatternRewriter final : public 
PatternRewriter {
   /// Conversion pattern rewriters must not be used outside of dialect
   /// conversions. They apply some IR rewrites in a delayed fashion and could
   /// bring the IR into an inconsistent state when used standalone.
-  explicit ConversionPatternRewriter(MLIRContext *ctx);
+  explicit ConversionPatternRewriter(MLIRContext *ctx,
+ const ConversionConfig &config);
 
   // Hide unsupported pattern rewriter API.
   using OpBuilder::setListener;
@@ -1070,6 +1072,30 @@ class PDLConversionConfig final {
 
 #endif // MLIR_ENABLE_PDL_IN_PATTERNMATCH
 
+//===--===//
+// ConversionConfig
+//===--===//
+
+/// Dialect conversion configuration.
+struct ConversionConfig {
+  /// An optional callback used to notify about match failure diagnostics 
during
+  /// the conversion. Diagnostics are only reported to this callback may only 
be
+  /// available in debug mode.
+  function_ref notifyCallback = nullptr;
+
+  /// Partial conversion only. All operations that are found not to be
+  /// legalizable are placed in this set. (Note that if there is an op
+  /// explicitly marked as illegal, the conversion terminates and the set will
+  /// not necessarily be complete.)
+  DenseSet *unlegalizedOps = nullptr;
+
+  /// Analysis conversion only. All operations that are found to be legalizable
+  /// are placed in this set. Note that no actual rewrites are applied to the
+  /// IR during an analysis conversion and only pre-existing operations are
+  /// added to the set.
+  DenseSet *legalizableOps = nullptr;
+};
+
 
//===--===//
 // Op Conversion Entry Points
 
//===--===//
@@ -1083,19 +1109,16 @@ class PDLConversionConfig final {
 /// Apply a partial conversion on the given operations and all nested
 /// operations. This method converts as many operations to the target as
 /// possible, ignoring operations that failed to legalize. This method only
-/// returns failure if there ops explicitly marked as illegal. If an
-/// `unconvertedOps` set is provided, all operations that are found not to be
-/// legalizable to the given `target` are placed within that set. (Note that if
-/// there is an op explicitly marked as illegal, the conversion terminates and
-/// the `unconvertedOps` set will not necessarily be complete.)
+/// returns failure if there ops explicitly marked as illegal.
 LogicalResult
-applyPartialConversion(ArrayRef ops, const ConversionTarget 
&target,
+applyPartialConversion(ArrayRef ops,
+   const ConversionTarget &target,
const FrozenRewritePatternSet &patterns,
-   DenseSet *unconvertedOps = nullptr);
+   ConversionConfig config = ConversionConfig());
 LogicalResult
 applyPartialConversion(Operation *op, const ConversionTarget &target,
const FrozenRewritePatternSet &patterns,
-   DenseSet *unconvertedOps = nullptr);
+   ConversionConfig config = ConversionConfig());
 
 /// Apply a compl

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Decouple `ConversionPatternRewriterImpl` from `ConversionPatternRewriter` (PR #82333)

2024-02-20 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/82333

`ConversionPatternRewriterImpl` no longer maintains a reference to the 
respective `ConversionPatternRewriter`. An `MLIRContext` is sufficient. This 
commit simplifies the internal state of `ConversionPatternRewriterImpl`.

>From 362813d590d6b61ebc0d03db2ed56764c5332d2c Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Tue, 20 Feb 2024 09:48:57 +
Subject: [PATCH] [mlir][Transforms][NFC] Decouple
 `ConversionPatternRewriterImpl` from `ConversionPatternRewriter`

`ConversionPatternRewriterImpl` no longer maintains a reference to the 
respective `ConversionPatternRewriter`. An `MLIRContext` is sufficient. This 
commit simplifies the internal state of `ConversionPatternRewriterImpl`.
---
 .../Transforms/Utils/DialectConversion.cpp| 44 +--
 1 file changed, 21 insertions(+), 23 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 30fc2298b3deb3..ec97a4247658b8 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -725,10 +725,9 @@ static RewriteTy *findSingleRewrite(R &&rewrites, Block 
*block) {
 namespace mlir {
 namespace detail {
 struct ConversionPatternRewriterImpl : public RewriterBase::Listener {
-  explicit ConversionPatternRewriterImpl(PatternRewriter &rewriter,
+  explicit ConversionPatternRewriterImpl(MLIRContext *ctx,
  const ConversionConfig &config)
-  : rewriter(rewriter), eraseRewriter(rewriter.getContext()),
-config(config) {}
+  : eraseRewriter(ctx), config(config) {}
 
   
//======//
   // State Management
@@ -823,8 +822,8 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
Type origOutputType,
const TypeConverter *converter);
 
-  Value buildUnresolvedArgumentMaterialization(PatternRewriter &rewriter,
-   Location loc, ValueRange inputs,
+  Value buildUnresolvedArgumentMaterialization(Block *block, Location loc,
+   ValueRange inputs,
Type origOutputType,
Type outputType,
const TypeConverter *converter);
@@ -903,8 +902,6 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   // State
   
//======//
 
-  PatternRewriter &rewriter;
-
   /// This rewriter must be used for erasing ops/blocks.
   SingleEraseRewriter eraseRewriter;
 
@@ -1008,8 +1005,12 @@ void BlockTypeConversionRewrite::rollback() {
 
 LogicalResult BlockTypeConversionRewrite::materializeLiveConversions(
 function_ref findLiveUser) {
+  auto builder = OpBuilder::atBlockBegin(block, /*listener=*/&rewriterImpl);
+
   // Process the remapping for each of the original arguments.
   for (unsigned i = 0, e = origBlock->getNumArguments(); i != e; ++i) {
+OpBuilder::InsertionGuard g(builder);
+
 // If the type of this argument changed and the argument is still live, we
 // need to materialize a conversion.
 BlockArgument origArg = origBlock->getArgument(i);
@@ -1021,14 +1022,12 @@ LogicalResult 
BlockTypeConversionRewrite::materializeLiveConversions(
 
 Value replacementValue = rewriterImpl.mapping.lookupOrDefault(origArg);
 bool isDroppedArg = replacementValue == origArg;
-if (isDroppedArg)
-  rewriterImpl.rewriter.setInsertionPointToStart(getBlock());
-else
-  rewriterImpl.rewriter.setInsertionPointAfterValue(replacementValue);
+if (!isDroppedArg)
+  builder.setInsertionPointAfterValue(replacementValue);
 Value newArg;
 if (converter) {
   newArg = converter->materializeSourceConversion(
-  rewriterImpl.rewriter, origArg.getLoc(), origArg.getType(),
+  builder, origArg.getLoc(), origArg.getType(),
   isDroppedArg ? ValueRange() : ValueRange(replacementValue));
   assert((!newArg || newArg.getType() == origArg.getType()) &&
  "materialization hook did not provide a value of the expected "
@@ -1293,6 +1292,8 @@ LogicalResult 
ConversionPatternRewriterImpl::convertNonEntryRegionTypes(
 Block *ConversionPatternRewriterImpl::applySignatureConversion(
 Block *block, const TypeConverter *converter,
 TypeConverter::SignatureConversion &signatureConversion) {
+  MLIRContext *ctx = block->getParentOp()->getContext();
+
   // If no arguments are being changed or added, there is nothing to do.
   unsigned origArgCount = block->getNumArguments();
   auto convertedTypes = signatureConversion.getConvertedTypes();
@@ -1309,7 +1310,7 @@ B

[llvm-branch-commits] [mlir] [mlir][Transforms] Support rolling back properties in dialect conversion (PR #82474)

2024-02-21 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/82474

The dialect conversion rolls back in-place op modifications upon failure. 
Rolling back modifications of attributes is already supported, but there was no 
support for properties until now.

>From 7be59f67152a684a572c45109e8288304cc4833a Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 21 Feb 2024 08:41:44 +
Subject: [PATCH] [mlir][Transforms] Support rolling back properties in dialect
 conversion

The dialect conversion rolls back inplace op modifications upon failure. 
Rolling back modifications of op properties was not supported before this 
commit.
---
 .../Transforms/Utils/DialectConversion.cpp| 28 ++-
 mlir/test/Transforms/test-legalizer.mlir  | 12 
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   | 18 +++-
 3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 673bd0383809cb..495e9d8df19d0a 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -1002,12 +1002,31 @@ class ModifyOperationRewrite : public OperationRewrite {
   : OperationRewrite(Kind::ModifyOperation, rewriterImpl, op),
 loc(op->getLoc()), attrs(op->getAttrDictionary()),
 operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
+successors(op->successor_begin(), op->successor_end()) {
+if (OpaqueProperties prop = op->getPropertiesStorage()) {
+  // Make a copy of the properties.
+  int size = op->getPropertiesStorageSize();
+  propertiesStorage = operator new(size);
+  memcpy(propertiesStorage, prop.as(), size);
+}
+  }
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() == Kind::ModifyOperation;
   }
 
+  ~ModifyOperationRewrite() override {
+assert(!propertiesStorage &&
+   "rewrite was neither committed nor rolled back");
+  }
+
+  void commit() override {
+if (propertiesStorage) {
+  operator delete(propertiesStorage);
+  propertiesStorage = nullptr;
+}
+  }
+
   /// Discard the transaction state and reset the state of the original
   /// operation.
   void rollback() override {
@@ -1016,6 +1035,12 @@ class ModifyOperationRewrite : public OperationRewrite {
 op->setOperands(operands);
 for (const auto &it : llvm::enumerate(successors))
   op->setSuccessor(it.value(), it.index());
+if (propertiesStorage) {
+  OpaqueProperties prop(propertiesStorage);
+  op->copyProperties(prop);
+  operator delete(propertiesStorage);
+  propertiesStorage = nullptr;
+}
   }
 
 private:
@@ -1023,6 +1048,7 @@ class ModifyOperationRewrite : public OperationRewrite {
   DictionaryAttr attrs;
   SmallVector operands;
   SmallVector successors;
+  void *propertiesStorage = nullptr;
 };
 } // namespace
 
diff --git a/mlir/test/Transforms/test-legalizer.mlir 
b/mlir/test/Transforms/test-legalizer.mlir
index 84fcc18ab7d370..62d776cd7573ee 100644
--- a/mlir/test/Transforms/test-legalizer.mlir
+++ b/mlir/test/Transforms/test-legalizer.mlir
@@ -334,3 +334,15 @@ func.func @test_move_op_before_rollback() {
   }) : () -> ()
   "test.return"() : () -> ()
 }
+
+// -
+
+// CHECK-LABEL: func @test_properties_rollback()
+func.func @test_properties_rollback() {
+  // CHECK: test.with_properties <{a = 32 : i64,
+  // expected-remark @below{{op 'test.with_properties' is not legalizable}}
+  test.with_properties
+  <{a = 32 : i64, array = array, b = "foo"}>
+  {modify_inplace}
+  "test.return"() : () -> ()
+}
diff --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp 
b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
index 1c02232b8adbb1..57e846294f8b9f 100644
--- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp
+++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
@@ -806,6 +806,21 @@ struct TestUndoBlockErase : public ConversionPattern {
   }
 };
 
+/// A pattern that modifies a property in-place, but keeps the op illegal.
+struct TestUndoPropertiesModification : public ConversionPattern {
+  TestUndoPropertiesModification(MLIRContext *ctx)
+  : ConversionPattern("test.with_properties", /*benefit=*/1, ctx) {}
+  LogicalResult
+  matchAndRewrite(Operation *op, ArrayRef operands,
+  ConversionPatternRewriter &rewriter) const final {
+if (!op->hasAttr("modify_inplace"))
+  return failure();
+rewriter.modifyOpInPlace(
+op, [&]() { cast(op).getProperties().setA(42); 
});
+return success();
+  }
+};
+
 
//===--===//
 // Type-Conversion Rewrite Testing
 
@@ -1085,7 +1100,8 @@ struct TestLegalizePatternDriver
  TestChangeProducerTypeF32ToInvalid, TestUpdateConsumerType,
  TestNonRootReplacement, TestBoundedRecursiveRewrit

[llvm-branch-commits] [mlir] [mlir][Transforms] Support rolling back properties in dialect conversion (PR #82474)

2024-02-21 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/82474

>From 33f2ae9da319110ca8d2581ec6d66d2db83201cb Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 21 Feb 2024 08:41:44 +
Subject: [PATCH] [mlir][Transforms] Support rolling back properties in dialect
 conversion

The dialect conversion rolls back inplace op modifications upon failure. 
Rolling back modifications of op properties was not supported before this 
commit.
---
 .../Transforms/Utils/DialectConversion.cpp| 28 ++-
 mlir/test/Transforms/test-legalizer.mlir  | 12 
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   | 18 +++-
 3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 673bd0383809cb..5be3e6b90b5d08 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -1002,12 +1002,31 @@ class ModifyOperationRewrite : public OperationRewrite {
   : OperationRewrite(Kind::ModifyOperation, rewriterImpl, op),
 loc(op->getLoc()), attrs(op->getAttrDictionary()),
 operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
+successors(op->successor_begin(), op->successor_end()) {
+if (OpaqueProperties prop = op->getPropertiesStorage()) {
+  // Make a copy of the properties.
+  propertiesStorage = operator new(op->getPropertiesStorageSize());
+  OpaqueProperties propCopy(propertiesStorage);
+  op->getName().copyOpProperties(propCopy, prop);
+}
+  }
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() == Kind::ModifyOperation;
   }
 
+  ~ModifyOperationRewrite() override {
+assert(!propertiesStorage &&
+   "rewrite was neither committed nor rolled back");
+  }
+
+  void commit() override {
+if (propertiesStorage) {
+  operator delete(propertiesStorage);
+  propertiesStorage = nullptr;
+}
+  }
+
   /// Discard the transaction state and reset the state of the original
   /// operation.
   void rollback() override {
@@ -1016,6 +1035,12 @@ class ModifyOperationRewrite : public OperationRewrite {
 op->setOperands(operands);
 for (const auto &it : llvm::enumerate(successors))
   op->setSuccessor(it.value(), it.index());
+if (propertiesStorage) {
+  OpaqueProperties prop(propertiesStorage);
+  op->copyProperties(prop);
+  operator delete(propertiesStorage);
+  propertiesStorage = nullptr;
+}
   }
 
 private:
@@ -1023,6 +1048,7 @@ class ModifyOperationRewrite : public OperationRewrite {
   DictionaryAttr attrs;
   SmallVector operands;
   SmallVector successors;
+  void *propertiesStorage = nullptr;
 };
 } // namespace
 
diff --git a/mlir/test/Transforms/test-legalizer.mlir 
b/mlir/test/Transforms/test-legalizer.mlir
index 84fcc18ab7d370..62d776cd7573ee 100644
--- a/mlir/test/Transforms/test-legalizer.mlir
+++ b/mlir/test/Transforms/test-legalizer.mlir
@@ -334,3 +334,15 @@ func.func @test_move_op_before_rollback() {
   }) : () -> ()
   "test.return"() : () -> ()
 }
+
+// -
+
+// CHECK-LABEL: func @test_properties_rollback()
+func.func @test_properties_rollback() {
+  // CHECK: test.with_properties <{a = 32 : i64,
+  // expected-remark @below{{op 'test.with_properties' is not legalizable}}
+  test.with_properties
+  <{a = 32 : i64, array = array, b = "foo"}>
+  {modify_inplace}
+  "test.return"() : () -> ()
+}
diff --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp 
b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
index 1c02232b8adbb1..57e846294f8b9f 100644
--- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp
+++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
@@ -806,6 +806,21 @@ struct TestUndoBlockErase : public ConversionPattern {
   }
 };
 
+/// A pattern that modifies a property in-place, but keeps the op illegal.
+struct TestUndoPropertiesModification : public ConversionPattern {
+  TestUndoPropertiesModification(MLIRContext *ctx)
+  : ConversionPattern("test.with_properties", /*benefit=*/1, ctx) {}
+  LogicalResult
+  matchAndRewrite(Operation *op, ArrayRef operands,
+  ConversionPatternRewriter &rewriter) const final {
+if (!op->hasAttr("modify_inplace"))
+  return failure();
+rewriter.modifyOpInPlace(
+op, [&]() { cast(op).getProperties().setA(42); 
});
+return success();
+  }
+};
+
 
//===--===//
 // Type-Conversion Rewrite Testing
 
@@ -1085,7 +1100,8 @@ struct TestLegalizePatternDriver
  TestChangeProducerTypeF32ToInvalid, TestUpdateConsumerType,
  TestNonRootReplacement, TestBoundedRecursiveRewrite,
  TestNestedOpCreationUndoRewrite, TestReplaceEraseOp,
- TestCreateUnregisteredOp, TestUndoMoveOpBefore>(&getContext());
+ 

[llvm-branch-commits] [mlir] [mlir][Transforms] Support rolling back properties in dialect conversion (PR #82474)

2024-02-21 Thread Matthias Springer via llvm-branch-commits


@@ -1002,12 +1002,31 @@ class ModifyOperationRewrite : public OperationRewrite {
   : OperationRewrite(Kind::ModifyOperation, rewriterImpl, op),
 loc(op->getLoc()), attrs(op->getAttrDictionary()),
 operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
+successors(op->successor_begin(), op->successor_end()) {
+if (OpaqueProperties prop = op->getPropertiesStorage()) {
+  // Make a copy of the properties.
+  int size = op->getPropertiesStorageSize();
+  propertiesStorage = operator new(size);
+  memcpy(propertiesStorage, prop.as(), size);

matthias-springer wrote:

Changed to `copyOpProperties`.

https://github.com/llvm/llvm-project/pull/82474
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Support rolling back properties in dialect conversion (PR #82474)

2024-02-21 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/82474

>From f7a0cc4dd214b9f2b234ea5a61eaecdb19b6b3c4 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 21 Feb 2024 09:37:48 +
Subject: [PATCH] [mlir][Transforms] Support rolling back properties in dialect
 conversion

The dialect conversion rolls back inplace op modifications upon failure. 
Rolling back modifications of op properties was not supported before this 
commit.
---
 .../Transforms/Utils/DialectConversion.cpp| 31 ++-
 mlir/test/Transforms/test-legalizer.mlir  | 12 +++
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   | 18 ++-
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 673bd0383809cb..37ecc694455e54 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -1002,12 +1002,33 @@ class ModifyOperationRewrite : public OperationRewrite {
   : OperationRewrite(Kind::ModifyOperation, rewriterImpl, op),
 loc(op->getLoc()), attrs(op->getAttrDictionary()),
 operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
+successors(op->successor_begin(), op->successor_end()) {
+if (OpaqueProperties prop = op->getPropertiesStorage()) {
+  // Make a copy of the properties.
+  propertiesStorage = operator new(op->getPropertiesStorageSize());
+  OpaqueProperties propCopy(propertiesStorage);
+  op->getName().initOpProperties(propCopy, /*init=*/prop);
+}
+  }
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() == Kind::ModifyOperation;
   }
 
+  ~ModifyOperationRewrite() override {
+assert(!propertiesStorage &&
+   "rewrite was neither committed nor rolled back");
+  }
+
+  void commit() override {
+if (propertiesStorage) {
+  OpaqueProperties prop(propertiesStorage);
+  op->getName().destroyOpProperties(prop);
+  operator delete(propertiesStorage);
+  propertiesStorage = nullptr;
+}
+  }
+
   /// Discard the transaction state and reset the state of the original
   /// operation.
   void rollback() override {
@@ -1016,6 +1037,13 @@ class ModifyOperationRewrite : public OperationRewrite {
 op->setOperands(operands);
 for (const auto &it : llvm::enumerate(successors))
   op->setSuccessor(it.value(), it.index());
+if (propertiesStorage) {
+  OpaqueProperties prop(propertiesStorage);
+  op->copyProperties(prop);
+  op->getName().destroyOpProperties(prop);
+  operator delete(propertiesStorage);
+  propertiesStorage = nullptr;
+}
   }
 
 private:
@@ -1023,6 +1051,7 @@ class ModifyOperationRewrite : public OperationRewrite {
   DictionaryAttr attrs;
   SmallVector operands;
   SmallVector successors;
+  void *propertiesStorage = nullptr;
 };
 } // namespace
 
diff --git a/mlir/test/Transforms/test-legalizer.mlir 
b/mlir/test/Transforms/test-legalizer.mlir
index 84fcc18ab7d370..62d776cd7573ee 100644
--- a/mlir/test/Transforms/test-legalizer.mlir
+++ b/mlir/test/Transforms/test-legalizer.mlir
@@ -334,3 +334,15 @@ func.func @test_move_op_before_rollback() {
   }) : () -> ()
   "test.return"() : () -> ()
 }
+
+// -
+
+// CHECK-LABEL: func @test_properties_rollback()
+func.func @test_properties_rollback() {
+  // CHECK: test.with_properties <{a = 32 : i64,
+  // expected-remark @below{{op 'test.with_properties' is not legalizable}}
+  test.with_properties
+  <{a = 32 : i64, array = array, b = "foo"}>
+  {modify_inplace}
+  "test.return"() : () -> ()
+}
diff --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp 
b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
index 1c02232b8adbb1..57e846294f8b9f 100644
--- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp
+++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
@@ -806,6 +806,21 @@ struct TestUndoBlockErase : public ConversionPattern {
   }
 };
 
+/// A pattern that modifies a property in-place, but keeps the op illegal.
+struct TestUndoPropertiesModification : public ConversionPattern {
+  TestUndoPropertiesModification(MLIRContext *ctx)
+  : ConversionPattern("test.with_properties", /*benefit=*/1, ctx) {}
+  LogicalResult
+  matchAndRewrite(Operation *op, ArrayRef operands,
+  ConversionPatternRewriter &rewriter) const final {
+if (!op->hasAttr("modify_inplace"))
+  return failure();
+rewriter.modifyOpInPlace(
+op, [&]() { cast(op).getProperties().setA(42); 
});
+return success();
+  }
+};
+
 
//===--===//
 // Type-Conversion Rewrite Testing
 
@@ -1085,7 +1100,8 @@ struct TestLegalizePatternDriver
  TestChangeProducerTypeF32ToInvalid, TestUpdateConsumerType,
  TestNonRootReplacement, TestBoundedRecursiveRewrite,
   

[llvm-branch-commits] [mlir] [mlir][Transforms] Support rolling back properties in dialect conversion (PR #82474)

2024-02-21 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/82474

>From 1795b6dcfdc0b6447c5209000332432de49109cc Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 21 Feb 2024 09:37:48 +
Subject: [PATCH] [mlir][Transforms] Support rolling back properties in dialect
 conversion

The dialect conversion rolls back inplace op modifications upon failure. 
Rolling back modifications of op properties was not supported before this 
commit.
---
 .../Transforms/Utils/DialectConversion.cpp| 31 ++-
 mlir/test/Transforms/test-legalizer.mlir  | 12 +++
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   | 18 ++-
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 673bd0383809cb..75094a41012e8d 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -1002,12 +1002,33 @@ class ModifyOperationRewrite : public OperationRewrite {
   : OperationRewrite(Kind::ModifyOperation, rewriterImpl, op),
 loc(op->getLoc()), attrs(op->getAttrDictionary()),
 operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
+successors(op->successor_begin(), op->successor_end()) {
+if (OpaqueProperties prop = op->getPropertiesStorage()) {
+  // Make a copy of the properties.
+  propertiesStorage = operator new(op->getPropertiesStorageSize());
+  OpaqueProperties propCopy(propertiesStorage);
+  op->getName().initOpProperties(propCopy, /*init=*/prop);
+}
+  }
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() == Kind::ModifyOperation;
   }
 
+  ~ModifyOperationRewrite() override {
+assert(!propertiesStorage &&
+   "rewrite was neither committed nor rolled back");
+  }
+
+  void commit() override {
+if (propertiesStorage) {
+  OpaqueProperties propCopy(propertiesStorage);
+  op->getName().destroyOpProperties(propCopy);
+  operator delete(propertiesStorage);
+  propertiesStorage = nullptr;
+}
+  }
+
   /// Discard the transaction state and reset the state of the original
   /// operation.
   void rollback() override {
@@ -1016,6 +1037,13 @@ class ModifyOperationRewrite : public OperationRewrite {
 op->setOperands(operands);
 for (const auto &it : llvm::enumerate(successors))
   op->setSuccessor(it.value(), it.index());
+if (propertiesStorage) {
+  OpaqueProperties propCopy(propertiesStorage);
+  op->copyProperties(propCopy);
+  op->getName().destroyOpProperties(propCopy);
+  operator delete(propertiesStorage);
+  propertiesStorage = nullptr;
+}
   }
 
 private:
@@ -1023,6 +1051,7 @@ class ModifyOperationRewrite : public OperationRewrite {
   DictionaryAttr attrs;
   SmallVector operands;
   SmallVector successors;
+  void *propertiesStorage = nullptr;
 };
 } // namespace
 
diff --git a/mlir/test/Transforms/test-legalizer.mlir 
b/mlir/test/Transforms/test-legalizer.mlir
index 84fcc18ab7d370..62d776cd7573ee 100644
--- a/mlir/test/Transforms/test-legalizer.mlir
+++ b/mlir/test/Transforms/test-legalizer.mlir
@@ -334,3 +334,15 @@ func.func @test_move_op_before_rollback() {
   }) : () -> ()
   "test.return"() : () -> ()
 }
+
+// -
+
+// CHECK-LABEL: func @test_properties_rollback()
+func.func @test_properties_rollback() {
+  // CHECK: test.with_properties <{a = 32 : i64,
+  // expected-remark @below{{op 'test.with_properties' is not legalizable}}
+  test.with_properties
+  <{a = 32 : i64, array = array, b = "foo"}>
+  {modify_inplace}
+  "test.return"() : () -> ()
+}
diff --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp 
b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
index 1c02232b8adbb1..57e846294f8b9f 100644
--- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp
+++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
@@ -806,6 +806,21 @@ struct TestUndoBlockErase : public ConversionPattern {
   }
 };
 
+/// A pattern that modifies a property in-place, but keeps the op illegal.
+struct TestUndoPropertiesModification : public ConversionPattern {
+  TestUndoPropertiesModification(MLIRContext *ctx)
+  : ConversionPattern("test.with_properties", /*benefit=*/1, ctx) {}
+  LogicalResult
+  matchAndRewrite(Operation *op, ArrayRef operands,
+  ConversionPatternRewriter &rewriter) const final {
+if (!op->hasAttr("modify_inplace"))
+  return failure();
+rewriter.modifyOpInPlace(
+op, [&]() { cast(op).getProperties().setA(42); 
});
+return success();
+  }
+};
+
 
//===--===//
 // Type-Conversion Rewrite Testing
 
@@ -1085,7 +1100,8 @@ struct TestLegalizePatternDriver
  TestChangeProducerTypeF32ToInvalid, TestUpdateConsumerType,
  TestNonRootReplacement, TestBoundedR

[llvm-branch-commits] [mlir] [mlir][Transforms] Support rolling back properties in dialect conversion (PR #82474)

2024-02-21 Thread Matthias Springer via llvm-branch-commits


@@ -1002,12 +1002,31 @@ class ModifyOperationRewrite : public OperationRewrite {
   : OperationRewrite(Kind::ModifyOperation, rewriterImpl, op),
 loc(op->getLoc()), attrs(op->getAttrDictionary()),
 operands(op->operand_begin(), op->operand_end()),
-successors(op->successor_begin(), op->successor_end()) {}
+successors(op->successor_begin(), op->successor_end()) {
+if (OpaqueProperties prop = op->getPropertiesStorage()) {
+  // Make a copy of the properties.
+  propertiesStorage = operator new(op->getPropertiesStorageSize());
+  OpaqueProperties propCopy(propertiesStorage);
+  op->getName().copyOpProperties(propCopy, prop);

matthias-springer wrote:

Replaced `copyOpProperties` with `initProperties`, this is calling the copy 
constructor.





https://github.com/llvm/llvm-project/pull/82474
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn block type conversion into `IRRewrite` (PR #81756)

2024-02-21 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81756

>From 68cb2590ea6295504b64d065326a606c2892a2a1 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 21 Feb 2024 16:48:48 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn block type convertion into
 `IRRewrite`

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, the signature conversion of a block was only a "partial" IR rewrite. 
Rollbacks were triggered via `BlockTypeConversionRewrite::rollback`, but there 
was no `BlockTypeConversionRewrite::commit` equivalent.

Overview of changes:
* Remove `ArgConverter`, an internal helper class that kept track of all block 
type conversions. There is now a separate `BlockTypeConversionRewrite` for each 
block type conversion.
* No more special handling for block type conversions. They are now normal "IR 
rewrites", just like "block creation" or "block movement". In particular, 
trigger "commits" of block type conversion via 
`BlockTypeConversionRewrite::commit`.
* Remove `ArgConverter::notifyOpRemoved`. This function was used to inform the 
`ArgConverter` that an operation was erased, to prevent a double-free of 
operations in certain situations. It would be unpractical to add a 
`notifyOpRemoved` API to `IRRewrite`. Instead, erasing ops/block should go 
through a new `SingleEraseRewriter` (that is owned by the 
`ConversionPatternRewriterImpl`) if there is chance of double-free. This 
rewriter ignores `eraseOp`/`eraseBlock` if the op/block was already freed.

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../Transforms/Utils/DialectConversion.cpp| 794 --
 1 file changed, 364 insertions(+), 430 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index afdd31a748c8c4..db41b9f19e7e8d 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -154,12 +154,13 @@ namespace {
 struct RewriterState {
   RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
 unsigned numReplacements, unsigned numArgReplacements,
-unsigned numRewrites, unsigned numIgnoredOperations)
+unsigned numRewrites, unsigned numIgnoredOperations,
+unsigned numErased)
   : numCreatedOps(numCreatedOps),
 numUnresolvedMaterializations(numUnresolvedMaterializations),
 numReplacements(numReplacements),
 numArgReplacements(numArgReplacements), numRewrites(numRewrites),
-numIgnoredOperations(numIgnoredOperations) {}
+numIgnoredOperations(numIgnoredOperations), numErased(numErased) {}
 
   /// The current number of created operations.
   unsigned numCreatedOps;
@@ -178,6 +179,9 @@ struct RewriterState {
 
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
+
+  /// The current number of erased operations/blocks.
+  unsigned numErased;
 };
 
 
//===--===//
@@ -292,370 +296,6 @@ static Value buildUnresolvedTargetMaterialization(
   outputType, outputType, converter, unresolvedMaterializations);
 }
 
-//===--===//
-// ArgConverter
-//===--===//
-namespace {
-/// This class provides a simple interface for converting the types of block
-/// arguments. This is done by creating a new block that contains the new legal
-/// types and extracting the block that contains the old illegal types to allow
-/// for undoing pending rewrites in the case of failure.
-struct ArgConverter {
-  ArgConverter(
-  PatternRewriter &rewriter,
-  SmallVectorImpl &unresolvedMaterializations)
-  : rewriter(rewriter),
-unresolvedMaterializations(unresolvedMaterializations) {}
-
-  /// This structure contains the information pertaining to an argument that 
has
-  /// been converted.
-  struct ConvertedArgInfo {
-ConvertedArgInfo(unsigned newArgIdx, unsigned newArgSize,
- Value castValue = nullptr)
-: newArgIdx(newArgIdx), newArgSize(newArgSize), castValue(castValue) {}
-
-/// The start index of in the new argument list that contains arguments 
that
-/// replace the original.
-unsigned newArgIdx;
-
-/// The number of arguments that replaced the original argument.
-unsigned newArgSize;
-
-/// The cast value that was created to cast from the new arguments to the
-/// old. This only used if 'newArgSize' > 1.
-Value castValue;
-  };
-
-  /// This structure contains information pertaining to a block that has had 
its
-  /// signature converted.
-  struct ConvertedBlockInfo {
-   

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn op creation into `IRRewrite` (PR #81759)

2024-02-22 Thread Matthias Springer via llvm-branch-commits


@@ -2549,10 +2572,15 @@ LogicalResult 
OperationConverter::legalizeConvertedArgumentTypes(
 });
 return liveUserIt == val.user_end() ? nullptr : *liveUserIt;
   };
-  for (auto &r : rewriterImpl.rewrites)
-if (auto *rewrite = dyn_cast(r.get()))
-  if (failed(rewrite->materializeLiveConversions(findLiveUser)))
+  // Note: `rewrites` may be reallocated as the loop is running.
+  for (int64_t i = 0; i < rewriterImpl.rewrites.size(); ++i) {

matthias-springer wrote:

That won't work here because things may get added to the vector while the loop 
is running and that could invalidate the iterator (when the vector reallocates 
storage).


https://github.com/llvm/llvm-project/pull/81759
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn op creation into `IRRewrite` (PR #81759)

2024-02-22 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81759

>From d15c439f166426a613ac0021a9101b774d544357 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Fri, 16 Feb 2024 15:21:48 +
Subject: [PATCH] [mlir][Transforms][NFC] Turn op creation into `IRRewrite`

This commit is a refactoring of the dialect conversion. The dialect conversion 
maintains a list of "IR rewrites" that can be commited (upon success) or rolled 
back (upon failure).

Until now, the dialect conversion kept track of "op creation" in separate 
internal data structures. This commit turns "op creation" into an `IRRewrite` 
that can be committed and rolled back just like any other rewrite. This commit 
simplifies the internal state of the dialect conversion.
---
 .../Transforms/Utils/DialectConversion.cpp| 101 +++---
 1 file changed, 63 insertions(+), 38 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index dec68048dc1d30..ae81dfa4d8303b 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -152,17 +152,12 @@ namespace {
 /// This class contains a snapshot of the current conversion rewriter state.
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
-  RewriterState(unsigned numCreatedOps, unsigned numUnresolvedMaterializations,
-unsigned numRewrites, unsigned numIgnoredOperations,
-unsigned numErased)
-  : numCreatedOps(numCreatedOps),
-numUnresolvedMaterializations(numUnresolvedMaterializations),
+  RewriterState(unsigned numUnresolvedMaterializations, unsigned numRewrites,
+unsigned numIgnoredOperations, unsigned numErased)
+  : numUnresolvedMaterializations(numUnresolvedMaterializations),
 numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
 numErased(numErased) {}
 
-  /// The current number of created operations.
-  unsigned numCreatedOps;
-
   /// The current number of unresolved materializations.
   unsigned numUnresolvedMaterializations;
 
@@ -303,7 +298,8 @@ class IRRewrite {
 // Operation rewrites
 MoveOperation,
 ModifyOperation,
-ReplaceOperation
+ReplaceOperation,
+CreateOperation
   };
 
   virtual ~IRRewrite() = default;
@@ -376,7 +372,10 @@ class CreateBlockRewrite : public BlockRewrite {
 auto &blockOps = block->getOperations();
 while (!blockOps.empty())
   blockOps.remove(blockOps.begin());
-eraseBlock(block);
+if (block->getParent())
+  eraseBlock(block);
+else
+  delete block;
   }
 };
 
@@ -606,7 +605,7 @@ class OperationRewrite : public IRRewrite {
 
   static bool classof(const IRRewrite *rewrite) {
 return rewrite->getKind() >= Kind::MoveOperation &&
-   rewrite->getKind() <= Kind::ReplaceOperation;
+   rewrite->getKind() <= Kind::CreateOperation;
   }
 
 protected:
@@ -740,6 +739,19 @@ class ReplaceOperationRewrite : public OperationRewrite {
   /// A boolean flag that indicates whether result types have changed or not.
   bool changedResults;
 };
+
+class CreateOperationRewrite : public OperationRewrite {
+public:
+  CreateOperationRewrite(ConversionPatternRewriterImpl &rewriterImpl,
+ Operation *op)
+  : OperationRewrite(Kind::CreateOperation, rewriterImpl, op) {}
+
+  static bool classof(const IRRewrite *rewrite) {
+return rewrite->getKind() == Kind::CreateOperation;
+  }
+
+  void rollback() override;
+};
 } // namespace
 
 /// Return "true" if there is an operation rewrite that matches the specified
@@ -957,9 +969,6 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   // replacing a value with one of a different type.
   ConversionValueMapping mapping;
 
-  /// Ordered vector of all of the newly created operations during conversion.
-  SmallVector createdOps;
-
   /// Ordered vector of all unresolved type conversion materializations during
   /// conversion.
   SmallVector unresolvedMaterializations;
@@ -1144,6 +1153,15 @@ void ReplaceOperationRewrite::rollback() {
 
 void ReplaceOperationRewrite::cleanup() { eraseOp(op); }
 
+void CreateOperationRewrite::rollback() {
+  for (Region ®ion : op->getRegions()) {
+while (!region.getBlocks().empty())
+  region.getBlocks().remove(region.getBlocks().begin());
+  }
+  op->dropAllUses();
+  eraseOp(op);
+}
+
 void ConversionPatternRewriterImpl::detachNestedAndErase(Operation *op) {
   for (Region ®ion : op->getRegions()) {
 for (Block &block : region.getBlocks()) {
@@ -1161,8 +1179,6 @@ void ConversionPatternRewriterImpl::discardRewrites() {
   // Remove any newly created ops.
   for (UnresolvedMaterialization &materialization : unresolvedMaterializations)
 detachNestedAndErase(materialization.getOp());
-  for (auto *op : llvm::reverse(createdOps))
-detachNestedAndErase(op);
 }
 
 void C

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Turn unresolved materializations into `IRRewrite`s (PR #81761)

2024-02-22 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/81761

>From 6d02f6d545fff81a41b7e40fa48f19c55483c77b Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Mon, 19 Feb 2024 10:29:29 +
Subject: [PATCH] [WIP] UnresolvedMaterialization

BEGIN_PUBLIC
No public commit message needed for presubmit.
END_PUBLIC
---
 .../Transforms/Utils/DialectConversion.cpp| 369 +-
 1 file changed, 176 insertions(+), 193 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index ae81dfa4d8303b..5ed31e35dc0705 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -152,15 +152,11 @@ namespace {
 /// This class contains a snapshot of the current conversion rewriter state.
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
-  RewriterState(unsigned numUnresolvedMaterializations, unsigned numRewrites,
-unsigned numIgnoredOperations, unsigned numErased)
-  : numUnresolvedMaterializations(numUnresolvedMaterializations),
-numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
+  RewriterState(unsigned numRewrites, unsigned numIgnoredOperations,
+unsigned numErased)
+  : numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
 numErased(numErased) {}
 
-  /// The current number of unresolved materializations.
-  unsigned numUnresolvedMaterializations;
-
   /// The current number of rewrites performed.
   unsigned numRewrites;
 
@@ -171,109 +167,10 @@ struct RewriterState {
   unsigned numErased;
 };
 
-//===--===//
-// UnresolvedMaterialization
-
-/// This class represents an unresolved materialization, i.e. a materialization
-/// that was inserted during conversion that needs to be legalized at the end 
of
-/// the conversion process.
-class UnresolvedMaterialization {
-public:
-  /// The type of materialization.
-  enum Kind {
-/// This materialization materializes a conversion for an illegal block
-/// argument type, to a legal one.
-Argument,
-
-/// This materialization materializes a conversion from an illegal type to 
a
-/// legal one.
-Target
-  };
-
-  UnresolvedMaterialization(UnrealizedConversionCastOp op = nullptr,
-const TypeConverter *converter = nullptr,
-Kind kind = Target, Type origOutputType = nullptr)
-  : op(op), converterAndKind(converter, kind),
-origOutputType(origOutputType) {}
-
-  /// Return the temporary conversion operation inserted for this
-  /// materialization.
-  UnrealizedConversionCastOp getOp() const { return op; }
-
-  /// Return the type converter of this materialization (which may be null).
-  const TypeConverter *getConverter() const {
-return converterAndKind.getPointer();
-  }
-
-  /// Return the kind of this materialization.
-  Kind getKind() const { return converterAndKind.getInt(); }
-
-  /// Set the kind of this materialization.
-  void setKind(Kind kind) { converterAndKind.setInt(kind); }
-
-  /// Return the original illegal output type of the input values.
-  Type getOrigOutputType() const { return origOutputType; }
-
-private:
-  /// The unresolved materialization operation created during conversion.
-  UnrealizedConversionCastOp op;
-
-  /// The corresponding type converter to use when resolving this
-  /// materialization, and the kind of this materialization.
-  llvm::PointerIntPair converterAndKind;
-
-  /// The original output type. This is only used for argument conversions.
-  Type origOutputType;
-};
-} // namespace
-
-/// Build an unresolved materialization operation given an output type and set
-/// of input operands.
-static Value buildUnresolvedMaterialization(
-UnresolvedMaterialization::Kind kind, Block *insertBlock,
-Block::iterator insertPt, Location loc, ValueRange inputs, Type outputType,
-Type origOutputType, const TypeConverter *converter,
-SmallVectorImpl &unresolvedMaterializations) {
-  // Avoid materializing an unnecessary cast.
-  if (inputs.size() == 1 && inputs.front().getType() == outputType)
-return inputs.front();
-
-  // Create an unresolved materialization. We use a new OpBuilder to avoid
-  // tracking the materialization like we do for other operations.
-  OpBuilder builder(insertBlock, insertPt);
-  auto convertOp =
-  builder.create(loc, outputType, inputs);
-  unresolvedMaterializations.emplace_back(convertOp, converter, kind,
-  origOutputType);
-  return convertOp.getResult(0);
-}
-static Value buildUnresolvedArgumentMaterialization(
-PatternRewriter &rewriter, Location loc, ValueRange inputs,
-Type origOutputType, Type outputType, const TypeConverter *converter,
-SmallVectorImpl &unresolvedMaterial

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Remove `SplitBlockRewrite` (PR #82777)

2024-02-27 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/82777
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `BlockTypeConversionRewrite` (PR #83286)

2024-02-28 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/83286

When a block signature is converted during dialect conversion a 
`BlockTypeConversionRewrite` object is stored in the stack of rewrites. Such an 
object represents multiple steps:
- Splitting the old block, i.e., creating a new block and moving all operations 
over.
- Rewriting block arguments.
- Erasing the old block.

We have dedicated `IRRewrite` objects that represent "creating a block", 
"moving an op" and "erasing a block". This commit reuses those rewrite objects, 
so that there is less work to do in  `BlockTypeConversionRewrite::rollback` and 
`BlockTypeConversionRewrite::commit`.

>From ab78e8c90ca3ecf60e1192c198d9f5025563dec2 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Wed, 28 Feb 2024 16:33:00 +
Subject: [PATCH] [mlir][Transforms][NFC] Simplify `BlockTypeConversionRewrite`

---
 .../Transforms/Utils/DialectConversion.cpp| 80 +--
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index b81495a95c80ed..cac990d498d7d3 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -746,24 +746,27 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// block is returned containing the new arguments. Returns `block` if it did
   /// not require conversion.
   FailureOr convertBlockSignature(
-  Block *block, const TypeConverter *converter,
+  ConversionPatternRewriter &rewriter, Block *block,
+  const TypeConverter *converter,
   TypeConverter::SignatureConversion *conversion = nullptr);
 
   /// Convert the types of non-entry block arguments within the given region.
   LogicalResult convertNonEntryRegionTypes(
-  Region *region, const TypeConverter &converter,
+  ConversionPatternRewriter &rewriter, Region *region,
+  const TypeConverter &converter,
   ArrayRef blockConversions = {});
 
   /// Apply a signature conversion on the given region, using `converter` for
   /// materializations if not null.
   Block *
-  applySignatureConversion(Region *region,
+  applySignatureConversion(ConversionPatternRewriter &rewriter, Region *region,
TypeConverter::SignatureConversion &conversion,
const TypeConverter *converter);
 
   /// Convert the types of block arguments within the given region.
   FailureOr
-  convertRegionTypes(Region *region, const TypeConverter &converter,
+  convertRegionTypes(ConversionPatternRewriter &rewriter, Region *region,
+ const TypeConverter &converter,
  TypeConverter::SignatureConversion *entryConversion);
 
   /// Apply the given signature conversion on the given block. The new block
@@ -773,7 +776,8 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
   /// translate between the origin argument types and those specified in the
   /// signature conversion.
   Block *applySignatureConversion(
-  Block *block, const TypeConverter *converter,
+  ConversionPatternRewriter &rewriter, Block *block,
+  const TypeConverter *converter,
   TypeConverter::SignatureConversion &signatureConversion);
 
   
//======//
@@ -940,24 +944,10 @@ void BlockTypeConversionRewrite::commit() {
   rewriterImpl.mapping.lookupOrDefault(castValue, origArg.getType()));
 }
   }
-
-  assert(origBlock->empty() && "expected empty block");
-  origBlock->dropAllDefinedValueUses();
-  delete origBlock;
-  origBlock = nullptr;
 }
 
 void BlockTypeConversionRewrite::rollback() {
-  // Drop all uses of the new block arguments and replace uses of the new 
block.
-  for (int i = block->getNumArguments() - 1; i >= 0; --i)
-block->getArgument(i).dropAllUses();
   block->replaceAllUsesWith(origBlock);
-
-  // Move the operations back the original block, move the original block back
-  // into its original location and the delete the new block.
-  origBlock->getOperations().splice(origBlock->end(), block->getOperations());
-  block->getParent()->getBlocks().insert(Region::iterator(block), origBlock);
-  eraseBlock(block);
 }
 
 LogicalResult BlockTypeConversionRewrite::materializeLiveConversions(
@@ -1173,10 +1163,11 @@ bool 
ConversionPatternRewriterImpl::wasOpReplaced(Operation *op) const {
 // Type Conversion
 
 FailureOr ConversionPatternRewriterImpl::convertBlockSignature(
-Block *block, const TypeConverter *converter,
+ConversionPatternRewriter &rewriter, Block *block,
+const TypeConverter *converter,
 TypeConverter::SignatureConversion *conversion) {
   if (conversion)
-return applySignatureConversion(block, converter, *conversion);
+return applySignatureConversion(rewriter, block, converter, *conversion);
 
   // If a converter 

[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `BlockTypeConversionRewrite` (PR #83286)

2024-02-28 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/83286
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify `BlockTypeConversionRewrite` (PR #83286)

2024-02-28 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/83286
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Simplify handling of erased IR (PR #83423)

2024-02-29 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/83423

The dialect conversion uses a `SingleEraseRewriter` to ensure that an op/block 
is not erased twice. This can happen during the "commit" phase when an 
unresolved materialization is inserted into a block and the enclosing op is 
erased by the user. In that case, the unresolved materialization should not be 
erased a second time later in the "commit" phase.

This problem cannot happen during "rollback", so ops/block can be erased 
directly without using the rewriter. With this change, the 
`SingleEraseRewriter` is used only during "commit"/"cleanup". At that point, 
the dialect conversion is guaranteed to succeed and no rollback can happen. 
Therefore, it is not necessary to store the number of erased IR objects 
(because we will never "reset" the rewriter to previous a previous state).


>From 6b6c4b1a7dd4943bfe2d97245e8369b9ba63aa20 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 29 Feb 2024 12:48:28 +
Subject: [PATCH] [mlir][Transforms][NFC] Do not use SingleEraseRewriter during
 rollback

---
 .../Transforms/Utils/DialectConversion.cpp| 22 +++
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index cac990d498d7d3..9f6468402686bd 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -153,9 +153,9 @@ namespace {
 /// This is useful when saving and undoing a set of rewrites.
 struct RewriterState {
   RewriterState(unsigned numRewrites, unsigned numIgnoredOperations,
-unsigned numErased, unsigned numReplacedOps)
+unsigned numReplacedOps)
   : numRewrites(numRewrites), numIgnoredOperations(numIgnoredOperations),
-numErased(numErased), numReplacedOps(numReplacedOps) {}
+numReplacedOps(numReplacedOps) {}
 
   /// The current number of rewrites performed.
   unsigned numRewrites;
@@ -163,9 +163,6 @@ struct RewriterState {
   /// The current number of ignored operations.
   unsigned numIgnoredOperations;
 
-  /// The current number of erased operations/blocks.
-  unsigned numErased;
-
   /// The current number of replaced ops that are scheduled for erasure.
   unsigned numReplacedOps;
 };
@@ -273,8 +270,9 @@ class CreateBlockRewrite : public BlockRewrite {
 auto &blockOps = block->getOperations();
 while (!blockOps.empty())
   blockOps.remove(blockOps.begin());
+block->dropAllUses();
 if (block->getParent())
-  eraseBlock(block);
+  block->erase();
 else
   delete block;
   }
@@ -858,7 +856,7 @@ struct ConversionPatternRewriterImpl : public 
RewriterBase::Listener {
 void notifyBlockErased(Block *block) override { erased.insert(block); }
 
 /// Pointers to all erased operations and blocks.
-SetVector erased;
+DenseSet erased;
   };
 
   
//======//
@@ -1044,7 +1042,7 @@ void CreateOperationRewrite::rollback() {
   region.getBlocks().remove(region.getBlocks().begin());
   }
   op->dropAllUses();
-  eraseOp(op);
+  op->erase();
 }
 
 void UnresolvedMaterializationRewrite::rollback() {
@@ -1052,7 +1050,7 @@ void UnresolvedMaterializationRewrite::rollback() {
 for (Value input : op->getOperands())
   rewriterImpl.mapping.erase(input);
   }
-  eraseOp(op);
+  op->erase();
 }
 
 void UnresolvedMaterializationRewrite::cleanup() { eraseOp(op); }
@@ -1069,8 +1067,7 @@ void ConversionPatternRewriterImpl::applyRewrites() {
 // State Management
 
 RewriterState ConversionPatternRewriterImpl::getCurrentState() {
-  return RewriterState(rewrites.size(), ignoredOps.size(),
-   eraseRewriter.erased.size(), replacedOps.size());
+  return RewriterState(rewrites.size(), ignoredOps.size(), replacedOps.size());
 }
 
 void ConversionPatternRewriterImpl::resetState(RewriterState state) {
@@ -1081,9 +1078,6 @@ void 
ConversionPatternRewriterImpl::resetState(RewriterState state) {
   while (ignoredOps.size() != state.numIgnoredOperations)
 ignoredOps.pop_back();
 
-  while (eraseRewriter.erased.size() != state.numErased)
-eraseRewriter.erased.pop_back();
-
   while (replacedOps.size() != state.numReplacedOps)
 replacedOps.pop_back();
 }

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Add listener support to dialect conversion (PR #83425)

2024-02-29 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer created 
https://github.com/llvm/llvm-project/pull/83425

This commit adds listener support to the dialect conversion. Similarly to the 
greedy pattern rewrite driver, an optional listener can be specified in the 
configuration object.

Listeners are notified only if the dialect conversion succeeds. In case of a 
failure, where some IR changes are first performed and then rolled back, no 
notifications are sent.

Due to the fact that some kinds of rewrite are reflected in the IR immediately 
and some in a delayed fashion, there are certain limitations when attaching a 
listener; these are documented in `ConversionConfig`. To summarize, users are 
always notified about all rewrites that happened, but the notifications are 
sent all at once at the very end, and not interleaved with the actual IR 
changes.

This change is in preparation improvements to 
`transform.apply_conversion_patterns`, which currently invalidates all handles. 
In the future, it can use a listener to update handles accordingly, similar  to 
`transform.apply_patterns`.


>From 216e0b2d62e418cddcb6e4ecf6b07be361141131 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 29 Feb 2024 12:58:26 +
Subject: [PATCH] [mlir][Transforms] Add listener support to dialect conversion

---
 .../mlir/Transforms/DialectConversion.h   |  26 +++
 .../Transforms/Utils/DialectConversion.cpp| 174 +-
 mlir/test/Transforms/test-legalizer.mlir  |  71 ++-
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   |  28 ++-
 4 files changed, 248 insertions(+), 51 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 84396529eb7c2e..98944b8a1ea648 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -1091,6 +1091,32 @@ struct ConversionConfig {
   /// IR during an analysis conversion and only pre-existing operations are
   /// added to the set.
   DenseSet *legalizableOps = nullptr;
+
+  /// An optional listener that is notified about all IR modifications in case
+  /// dialect conversion succeeds. If the dialect conversion fails and no IR
+  /// modifications are visible (i.e., they were all rolled back), no
+  /// notifications are sent.
+  ///
+  /// Note: Notifications are sent in a delayed fashion, when the dialect
+  /// conversion is guaranteed to succeed. At that point, some IR modifications
+  /// may already have been materialized. Consequently, operations/blocks that
+  /// are passed to listener callbacks should not be accessed. (Ops/blocks are
+  /// guaranteed to be valid pointers and accessing op names is allowed. But
+  /// there are no guarantees about the state of ops/blocks at the time that a
+  /// callback is triggered.)
+  ///
+  /// Example: Consider a dialect conversion a new op ("test.foo") is created
+  /// and inserted, and later moved to another block. (Moving ops also triggers
+  /// "notifyOperationInserted".)
+  ///
+  /// (1) notifyOperationInserted: "test.foo" (into block "b1")
+  /// (2) notifyOperationInserted: "test.foo" (moved to another block "b2")
+  ///
+  /// When querying "op->getBlock()" during the first 
"notifyOperationInserted",
+  /// "b2" would be returned because "moving an op" is a kind of rewrite that 
is
+  /// immediately performed by the dialect conversion (and rolled back upon
+  /// failure).
+  RewriterBase::Listener *listener = nullptr;
 };
 
 
//===--===//
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 9f6468402686bd..0048347cae9314 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -203,14 +203,22 @@ class IRRewrite {
   /// Roll back the rewrite. Operations may be erased during rollback.
   virtual void rollback() = 0;
 
-  /// Commit the rewrite. Operations may be unlinked from their blocks during
-  /// the commit phase, but they must not be erased yet. This is because
-  /// internal dialect conversion state (such as `mapping`) may still be using
-  /// them. Operations must be erased during cleanup.
-  virtual void commit() {}
+  /// Commit the rewrite. At this point, it is certain that the dialect
+  /// conversion will succeed. All IR modifications, except for operation
+  /// erasure, must be performed through the given rewriter.
+  ///
+  /// Instead of erasing operations, they should merely be unlinked from their
+  /// blocks during the commit phase and finally be erased during the cleanup
+  /// phase. This is because internal dialect conversion state (such as
+  /// `mapping`) may still be using them.
+  ///
+  /// Any IR modification that was already performed before the commit phase
+  /// (e.g., insertion of an op) must be communicated to the listener that may
+  /// be attache

[llvm-branch-commits] [mlir] [mlir][Transforms] Add listener support to dialect conversion (PR #83425)

2024-02-29 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer updated 
https://github.com/llvm/llvm-project/pull/83425

>From 22e8d5ea80b74d687c3e792c512f50b9de81f489 Mon Sep 17 00:00:00 2001
From: Matthias Springer 
Date: Thu, 29 Feb 2024 12:58:26 +
Subject: [PATCH] [mlir][Transforms] Add listener support to dialect conversion

---
 .../mlir/Transforms/DialectConversion.h   |  26 +++
 .../Transforms/Utils/DialectConversion.cpp| 174 +-
 mlir/test/Transforms/test-legalizer.mlir  |  71 ++-
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   |  28 ++-
 4 files changed, 248 insertions(+), 51 deletions(-)

diff --git a/mlir/include/mlir/Transforms/DialectConversion.h 
b/mlir/include/mlir/Transforms/DialectConversion.h
index 84396529eb7c2e..98944b8a1ea648 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -1091,6 +1091,32 @@ struct ConversionConfig {
   /// IR during an analysis conversion and only pre-existing operations are
   /// added to the set.
   DenseSet *legalizableOps = nullptr;
+
+  /// An optional listener that is notified about all IR modifications in case
+  /// dialect conversion succeeds. If the dialect conversion fails and no IR
+  /// modifications are visible (i.e., they were all rolled back), no
+  /// notifications are sent.
+  ///
+  /// Note: Notifications are sent in a delayed fashion, when the dialect
+  /// conversion is guaranteed to succeed. At that point, some IR modifications
+  /// may already have been materialized. Consequently, operations/blocks that
+  /// are passed to listener callbacks should not be accessed. (Ops/blocks are
+  /// guaranteed to be valid pointers and accessing op names is allowed. But
+  /// there are no guarantees about the state of ops/blocks at the time that a
+  /// callback is triggered.)
+  ///
+  /// Example: Consider a dialect conversion a new op ("test.foo") is created
+  /// and inserted, and later moved to another block. (Moving ops also triggers
+  /// "notifyOperationInserted".)
+  ///
+  /// (1) notifyOperationInserted: "test.foo" (into block "b1")
+  /// (2) notifyOperationInserted: "test.foo" (moved to another block "b2")
+  ///
+  /// When querying "op->getBlock()" during the first 
"notifyOperationInserted",
+  /// "b2" would be returned because "moving an op" is a kind of rewrite that 
is
+  /// immediately performed by the dialect conversion (and rolled back upon
+  /// failure).
+  RewriterBase::Listener *listener = nullptr;
 };
 
 
//===--===//
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp 
b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 9f6468402686bd..0048347cae9314 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -203,14 +203,22 @@ class IRRewrite {
   /// Roll back the rewrite. Operations may be erased during rollback.
   virtual void rollback() = 0;
 
-  /// Commit the rewrite. Operations may be unlinked from their blocks during
-  /// the commit phase, but they must not be erased yet. This is because
-  /// internal dialect conversion state (such as `mapping`) may still be using
-  /// them. Operations must be erased during cleanup.
-  virtual void commit() {}
+  /// Commit the rewrite. At this point, it is certain that the dialect
+  /// conversion will succeed. All IR modifications, except for operation
+  /// erasure, must be performed through the given rewriter.
+  ///
+  /// Instead of erasing operations, they should merely be unlinked from their
+  /// blocks during the commit phase and finally be erased during the cleanup
+  /// phase. This is because internal dialect conversion state (such as
+  /// `mapping`) may still be using them.
+  ///
+  /// Any IR modification that was already performed before the commit phase
+  /// (e.g., insertion of an op) must be communicated to the listener that may
+  /// be attached to the given rewriter.
+  virtual void commit(RewriterBase &rewriter) {}
 
   /// Cleanup operations. Cleanup is called after commit.
-  virtual void cleanup() {}
+  virtual void cleanup(RewriterBase &rewriter) {}
 
   Kind getKind() const { return kind; }
 
@@ -220,12 +228,6 @@ class IRRewrite {
   IRRewrite(Kind kind, ConversionPatternRewriterImpl &rewriterImpl)
   : kind(kind), rewriterImpl(rewriterImpl) {}
 
-  /// Erase the given op (unless it was already erased).
-  void eraseOp(Operation *op);
-
-  /// Erase the given block (unless it was already erased).
-  void eraseBlock(Block *block);
-
   const ConversionConfig &getConfig() const;
 
   const Kind kind;
@@ -264,6 +266,12 @@ class CreateBlockRewrite : public BlockRewrite {
 return rewrite->getKind() == Kind::CreateBlock;
   }
 
+  void commit(RewriterBase &rewriter) override {
+// The block was already created and inserted. Just inform the listener.
+if (auto *listener = rewriter.getListener())
+  lis

[llvm-branch-commits] [mlir] [mlir][Transforms] Encapsulate dialect conversion options in `ConversionConfig` (PR #83754)

2024-03-03 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/83754
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms] Add listener support to dialect conversion (PR #83425)

2024-03-04 Thread Matthias Springer via llvm-branch-commits

https://github.com/matthias-springer edited 
https://github.com/llvm/llvm-project/pull/83425
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


  1   2   3   4   >