void create(OpBuilder &builder, SmallVectorImpl<Value> &results,
Location location, Args &&... args) {
// The op needs to be inserted only if the fold (below) fails, or the number
- // of results of the op is zero (which is treated as an in-place
- // fold). Using create methods of the builder will insert the op, so not
- // using it here.
+ // of results produced by the successful folding is zero (which is treated
+ // as an in-place fold). Using create methods of the builder will insert the
+ // op, so not using it here.
OperationState state(location, OpTy::getOperationName());
OpTy::build(builder, state, std::forward<Args>(args)...);
Operation *op = Operation::create(state);
- if (failed(tryToFold(builder, op, results)) || op->getNumResults() == 0) {
+ if (failed(tryToFold(builder, op, results)) || results.empty()) {
builder.insert(op);
results.assign(op->result_begin(), op->result_end());
return;
return success();
}
+OpFoldResult TestOpInPlaceFold::fold(ArrayRef<Attribute> operands) {
+ assert(operands.size() == 1);
+ if (operands.front()) {
+ setAttr("attr", operands.front());
+ return getResult();
+ }
+ return {};
+}
+
LogicalResult mlir::OpWithInferTypeInterfaceOp::inferReturnTypes(
MLIRContext *, Optional<Location> location, ValueRange operands,
ArrayRef<NamedAttribute> attributes, RegionRange regions,
let results = (outs I32);
}
+def TestOpInPlaceFoldAnchor : TEST_Op<"op_in_place_fold_anchor"> {
+ let arguments = (ins I32);
+ let results = (outs I32);
+}
+
+def TestOpInPlaceFold : TEST_Op<"op_in_place_fold"> {
+ let arguments = (ins I32:$op, I32Attr:$attr);
+ let results = (outs I32);
+ let hasFolder = 1;
+}
+
//===----------------------------------------------------------------------===//
// Test Patterns (Symbol Binding)
#include "TestDialect.h"
#include "mlir/Conversion/StandardToStandard/StandardToStandard.h"
+#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/FoldUtils.h"
using namespace mlir;
//===----------------------------------------------------------------------===//
namespace {
+struct FoldingPattern : public RewritePattern {
+public:
+ FoldingPattern(MLIRContext *context)
+ : RewritePattern(TestOpInPlaceFoldAnchor::getOperationName(),
+ /*benefit=*/1, context) {}
+
+ LogicalResult matchAndRewrite(Operation *op,
+ PatternRewriter &rewriter) const override {
+ // Exercice OperationFolder API for a single-result operation that is folded
+ // upon construction. The operation being created through the folder has an
+ // in-place folder, and it should be still present in the output.
+ // Furthermore, the folder should not crash when attempting to recover the
+ // (unchanged) opeation result.
+ OperationFolder folder(op->getContext());
+ Value result = folder.create<TestOpInPlaceFold>(
+ rewriter, op->getLoc(), rewriter.getIntegerType(32), op->getOperand(0),
+ rewriter.getI32IntegerAttr(0));
+ assert(result);
+ rewriter.replaceOp(op, result);
+ return success();
+ }
+};
+
struct TestPatternDriver : public PassWrapper<TestPatternDriver, FunctionPass> {
void runOnFunction() override {
mlir::OwningRewritePatternList patterns;
populateWithGenerated(&getContext(), &patterns);
// Verify named pattern is generated with expected name.
- patterns.insert<TestNamedPatternRule>(&getContext());
+ patterns.insert<FoldingPattern, TestNamedPatternRule>(&getContext());
applyPatternsAndFoldGreedily(getFunction(), patterns);
}