[mlir][Transforms] Support rolling back properties in dialect conversion (#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.
This commit is contained in:
Matthias Springer
2024-02-21 16:41:45 +01:00
committed by GitHub
parent e214f004cb
commit 3a70335bae
3 changed files with 59 additions and 2 deletions

View File

@@ -1006,18 +1006,46 @@ public:
: 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;
}
}
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());
if (propertiesStorage) {
OpaqueProperties propCopy(propertiesStorage);
op->copyProperties(propCopy);
op->getName().destroyOpProperties(propCopy);
operator delete(propertiesStorage);
propertiesStorage = nullptr;
}
}
private:
@@ -1025,6 +1053,7 @@ private:
DictionaryAttr attrs;
SmallVector<Value, 8> operands;
SmallVector<Block *, 2> successors;
void *propertiesStorage = nullptr;
};
} // namespace

View File

@@ -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<i64: 1, 2, 3, 4>, b = "foo"}>
{modify_inplace}
"test.return"() : () -> ()
}

View File

@@ -807,6 +807,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<Value> operands,
ConversionPatternRewriter &rewriter) const final {
if (!op->hasAttr("modify_inplace"))
return failure();
rewriter.modifyOpInPlace(
op, [&]() { cast<TestOpWithProperties>(op).getProperties().setA(42); });
return success();
}
};
//===----------------------------------------------------------------------===//
// Type-Conversion Rewrite Testing
@@ -1086,7 +1101,8 @@ struct TestLegalizePatternDriver
TestChangeProducerTypeF32ToInvalid, TestUpdateConsumerType,
TestNonRootReplacement, TestBoundedRecursiveRewrite,
TestNestedOpCreationUndoRewrite, TestReplaceEraseOp,
TestCreateUnregisteredOp, TestUndoMoveOpBefore>(&getContext());
TestCreateUnregisteredOp, TestUndoMoveOpBefore,
TestUndoPropertiesModification>(&getContext());
patterns.add<TestDropOpSignatureConversion>(&getContext(), converter);
mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(patterns,
converter);