[Mlir-commits] [mlir] 0db1ae3 - [mlir][CFGToSCF] Visit subregions in CFGToSCF pass
Ivan Butygin
llvmlistbot at llvm.org
Sun Aug 20 10:36:04 PDT 2023
Author: Ivan Butygin
Date: 2023-08-20T19:29:51+02:00
New Revision: 0db1ae3ed111a213e95e2317c3b4457c0f8826c1
URL: https://github.com/llvm/llvm-project/commit/0db1ae3ed111a213e95e2317c3b4457c0f8826c1
DIFF: https://github.com/llvm/llvm-project/commit/0db1ae3ed111a213e95e2317c3b4457c0f8826c1.diff
LOG: [mlir][CFGToSCF] Visit subregions in CFGToSCF pass
This is useful when user already have partially-scf'ed IR or other ops with nested regions (e.g. linalg.generic).
Also, improve error message and pass docs.
Differential Revision: https://reviews.llvm.org/D158349
Added:
Modified:
mlir/include/mlir/Conversion/Passes.td
mlir/lib/Conversion/ControlFlowToSCF/ControlFlowToSCF.cpp
mlir/test/Conversion/ControlFlowToSCF/test.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 95af8a8daa1e9d..d239cb12e03a5a 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -304,6 +304,12 @@ def LiftControlFlowToSCFPass : Pass<"lift-cf-to-scf"> {
ControlFlow operations will be replaced successfully.
Otherwise a single ControlFlow switch branching to one block per return-like
operation kind remains.
+
+ This pass may need to create unreachable terminators in case of infinite
+ loops, which is only supported for 'func.func' for now. If you potentially
+ have infinite loops inside CFG regions not belonging to 'func.func',
+ consider using `transformCFGToSCF` function directly with corresponding
+ `CFGToSCFInterface::createUnreachableTerminator` implementation.
}];
let dependentDialects = ["scf::SCFDialect",
diff --git a/mlir/lib/Conversion/ControlFlowToSCF/ControlFlowToSCF.cpp b/mlir/lib/Conversion/ControlFlowToSCF/ControlFlowToSCF.cpp
index c0169a024bd5e8..363e5f9b8cefe7 100644
--- a/mlir/lib/Conversion/ControlFlowToSCF/ControlFlowToSCF.cpp
+++ b/mlir/lib/Conversion/ControlFlowToSCF/ControlFlowToSCF.cpp
@@ -140,10 +140,11 @@ ControlFlowToSCFTransformation::createUnreachableTerminator(Location loc,
// TODO: This should create a `ub.unreachable` op. Once such an operation
// exists to make the pass independent of the func dialect. For now just
// return poison values.
- auto funcOp = dyn_cast<func::FuncOp>(region.getParentOp());
+ Operation *parentOp = region.getParentOp();
+ auto funcOp = dyn_cast<func::FuncOp>(parentOp);
if (!funcOp)
- return emitError(loc, "Expected '")
- << func::FuncOp::getOperationName() << "' as top level operation";
+ return emitError(loc, "Cannot create unreachable terminator for '")
+ << parentOp->getName() << "'";
return builder
.create<func::ReturnOp>(
@@ -165,18 +166,29 @@ struct LiftControlFlowToSCF
ControlFlowToSCFTransformation transformation;
bool changed = false;
- WalkResult result = getOperation()->walk([&](func::FuncOp funcOp) {
+ Operation *op = getOperation();
+ WalkResult result = op->walk([&](func::FuncOp funcOp) {
if (funcOp.getBody().empty())
return WalkResult::advance();
- FailureOr<bool> changedFunc = transformCFGToSCF(
- funcOp.getBody(), transformation,
- funcOp != getOperation() ? getChildAnalysis<DominanceInfo>(funcOp)
- : getAnalysis<DominanceInfo>());
- if (failed(changedFunc))
+ auto &domInfo = funcOp != op ? getChildAnalysis<DominanceInfo>(funcOp)
+ : getAnalysis<DominanceInfo>();
+
+ auto visitor = [&](Operation *innerOp) -> WalkResult {
+ for (Region ® : innerOp->getRegions()) {
+ FailureOr<bool> changedFunc =
+ transformCFGToSCF(reg, transformation, domInfo);
+ if (failed(changedFunc))
+ return WalkResult::interrupt();
+
+ changed |= *changedFunc;
+ }
+ return WalkResult::advance();
+ };
+
+ if (funcOp->walk<WalkOrder::PostOrder>(visitor).wasInterrupted())
return WalkResult::interrupt();
- changed |= *changedFunc;
return WalkResult::advance();
});
if (result.wasInterrupted())
diff --git a/mlir/test/Conversion/ControlFlowToSCF/test.mlir b/mlir/test/Conversion/ControlFlowToSCF/test.mlir
index a9e6f24f329bfc..ec35b4bc944213 100644
--- a/mlir/test/Conversion/ControlFlowToSCF/test.mlir
+++ b/mlir/test/Conversion/ControlFlowToSCF/test.mlir
@@ -678,3 +678,35 @@ func.func @multi_entry_loop(%cond: i1) {
// CHECK: scf.yield
// CHECK: call @foo(%[[WHILE]]#1)
// CHECK-NEXT: return
+
+// -----
+
+func.func @nested_region() {
+ scf.execute_region {
+ %cond = "test.test1"() : () -> i1
+ cf.cond_br %cond, ^bb1, ^bb2
+ ^bb1:
+ "test.test2"() : () -> ()
+ cf.br ^bb3
+ ^bb2:
+ "test.test3"() : () -> ()
+ cf.br ^bb3
+ ^bb3:
+ "test.test4"() : () -> ()
+ scf.yield
+ }
+ return
+}
+
+// CHECK-LABEL: func @nested_region
+// CHECK: scf.execute_region {
+// CHECK: %[[COND:.*]] = "test.test1"()
+// CHECK-NEXT: scf.if %[[COND]]
+// CHECK-NEXT: "test.test2"()
+// CHECK-NEXT: else
+// CHECK-NEXT: "test.test3"()
+// CHECK-NEXT: }
+// CHECK-NEXT: "test.test4"()
+// CHECK-NEXT: scf.yield
+// CHECK-NEXT: }
+// CHECK-NEXT: return
More information about the Mlir-commits
mailing list