// ExecuteRegionOp
//===----------------------------------------------------------------------===//
+/// Replaces the given op with the contents of the given single-block region,
+/// using the operands of the block terminator to replace operation results.
+static void replaceOpWithRegion(PatternRewriter &rewriter, Operation *op,
+ Region ®ion, ValueRange blockArgs = {}) {
+ assert(llvm::hasSingleElement(region) && "expected single-region block");
+ Block *block = ®ion.front();
+ Operation *terminator = block->getTerminator();
+ ValueRange results = terminator->getOperands();
+ rewriter.mergeBlockBefore(block, op, blockArgs);
+ rewriter.replaceOp(op, results);
+ rewriter.eraseOp(terminator);
+}
+
///
/// (ssa-id `=`)? `execute_region` `->` function-result-type `{`
/// block+
return success();
}
+// Inline an ExecuteRegionOp if it only contains one block.
+// "test.foo"() : () -> ()
+// %v = scf.execute_region -> i64 {
+// %x = "test.val"() : () -> i64
+// scf.yield %x : i64
+// }
+// "test.bar"(%v) : (i64) -> ()
+//
+// becomes
+//
+// "test.foo"() : () -> ()
+// %x = "test.val"() : () -> i64
+// "test.bar"(%v) : (i64) -> ()
+//
+struct SingleBlockExecuteInliner : public OpRewritePattern<ExecuteRegionOp> {
+ using OpRewritePattern<ExecuteRegionOp>::OpRewritePattern;
+
+ LogicalResult matchAndRewrite(ExecuteRegionOp op,
+ PatternRewriter &rewriter) const override {
+ if (op.region().getBlocks().size() != 1)
+ return failure();
+ replaceOpWithRegion(rewriter, op, op.region());
+ return success();
+ }
+};
+
+void ExecuteRegionOp::getCanonicalizationPatterns(RewritePatternSet &results,
+ MLIRContext *context) {
+ results.add<SingleBlockExecuteInliner>(context);
+}
+
//===----------------------------------------------------------------------===//
// ForOp
//===----------------------------------------------------------------------===//
});
}
-/// Replaces the given op with the contents of the given single-block region,
-/// using the operands of the block terminator to replace operation results.
-static void replaceOpWithRegion(PatternRewriter &rewriter, Operation *op,
- Region ®ion, ValueRange blockArgs = {}) {
- assert(llvm::hasSingleElement(region) && "expected single-region block");
- Block *block = ®ion.front();
- Operation *terminator = block->getTerminator();
- ValueRange results = terminator->getOperands();
- rewriter.mergeBlockBefore(block, op, blockArgs);
- rewriter.replaceOp(op, results);
- rewriter.eraseOp(terminator);
-}
-
namespace {
// Fold away ForOp iter arguments when:
// 1) The op yields the iter arguments.
}
"test.bar"(%v) : (i64) -> ()
// CHECK: %[[C2:.*]] = constant 2 : i64
- // CHECK: scf.execute_region -> i64 {
- // CHECK-NEXT: scf.yield %[[C2]] : i64
- // CHECK-NEXT: }
+ // CHECK: "test.foo"
+ // CHECK-NEXT: "test.bar"(%[[C2]]) : (i64) -> ()
}
return
}
+
+// -----
+
+// CHECK-LABEL: func @execute_region_elim
+func @execute_region_elim() {
+ affine.for %i = 0 to 100 {
+ "test.foo"() : () -> ()
+ %v = scf.execute_region -> i64 {
+ %x = "test.val"() : () -> i64
+ scf.yield %x : i64
+ }
+ "test.bar"(%v) : (i64) -> ()
+ }
+ return
+}
+
+// CHECK-NEXT: affine.for %arg0 = 0 to 100 {
+// CHECK-NEXT: "test.foo"() : () -> ()
+// CHECK-NEXT: %[[VAL:.*]] = "test.val"() : () -> i64
+// CHECK-NEXT: "test.bar"(%[[VAL]]) : (i64) -> ()
+// CHECK-NEXT: }
+