24#define GEN_PASS_DEF_LIFTCONTROLFLOWTOSCFPASS
25#include "mlir/Conversion/Passes.h.inc"
32 return isa<cf::CondBranchOp, cf::SwitchOp>(op);
39 if (
auto condBrOp = dyn_cast<cf::CondBranchOp>(controlFlowCondOp)) {
40 assert(regions.size() == 2);
41 auto ifOp = scf::IfOp::create(builder, controlFlowCondOp->
getLoc(),
42 resultTypes, condBrOp.getCondition());
43 ifOp.getThenRegion().takeBody(regions[0]);
44 ifOp.getElseRegion().takeBody(regions[1]);
45 return ifOp.getOperation();
48 if (
auto switchOp = dyn_cast<cf::SwitchOp>(controlFlowCondOp)) {
51 auto cast = arith::IndexCastUIOp::create(
55 if (
auto caseValues = switchOp.getCaseValues())
57 cases, llvm::map_range(*caseValues, [](
const llvm::APInt &apInt) {
58 return apInt.getZExtValue();
61 assert(regions.size() == cases.size() + 1);
64 scf::IndexSwitchOp::create(builder, controlFlowCondOp->
getLoc(),
65 resultTypes, cast, cases, cases.size());
67 indexSwitchOp.getDefaultRegion().takeBody(regions[0]);
68 for (
auto &&[targetRegion, sourceRegion] :
69 llvm::zip(indexSwitchOp.getCaseRegions(), llvm::drop_begin(regions)))
70 targetRegion.takeBody(sourceRegion);
72 return indexSwitchOp.getOperation();
76 "Cannot convert unknown control flow op to structured control flow");
84 scf::YieldOp::create(builder, loc, results);
93 auto whileOp = scf::WhileOp::create(
94 builder, loc, loopVariablesInit.
getTypes(), loopVariablesInit);
96 whileOp.getBefore().takeBody(loopBody);
101 scf::ConditionOp::create(
103 arith::TruncIOp::create(builder, loc, builder.
getI1Type(), condition),
104 loopVariablesNextIter);
110 scf::YieldOp::create(builder, loc, afterBlock->
getArguments());
112 return whileOp.getOperation();
117 unsigned int value) {
118 return arith::ConstantOp::create(builder, loc,
127 cf::SwitchOp::create(builder, loc, flag, defaultDest, defaultArgs,
128 llvm::to_vector_of<int32_t>(caseValues),
129 caseDestinations, caseArguments);
135 return ub::PoisonOp::create(builder, loc, type,
nullptr);
138FailureOr<Operation *>
142 return ub::UnreachableOp::create(builder, loc).getOperation();
146 return isa<ub::UnreachableOp>(op);
151struct LiftControlFlowToSCF
152 :
public impl::LiftControlFlowToSCFPassBase<LiftControlFlowToSCF> {
156 void runOnOperation()
override {
159 bool changed =
false;
162 if (funcOp.getFunctionBody().empty())
165 auto &domInfo = funcOp != op ? getChildAnalysis<DominanceInfo>(funcOp)
169 for (
Region ® : innerOp->getRegions()) {
170 FailureOr<bool> changedFunc =
172 if (failed(changedFunc))
175 changed |= *changedFunc;
180 if (funcOp->walk<WalkOrder::PostOrder>(visitor).wasInterrupted())
185 if (
result.wasInterrupted())
186 return signalPassFailure();
189 markAllAnalysesPreserved();
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
iterator_range< args_iterator > addArguments(TypeRange types, ArrayRef< Location > locs)
Add one argument to the argument list for each type specified in the list.
BlockArgListType getArguments()
IntegerAttr getI32IntegerAttr(int32_t value)
A class for computing basic dominance information.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Operation is the basic unit of execution within MLIR.
Location getLoc()
The source location the operation was defined or derived from.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
static WalkResult interrupt()
Include the generated interface declarations.
FailureOr< bool > transformCFGToSCF(Region ®ion, CFGToSCFInterface &interface, DominanceInfo &dominanceInfo)
Transformation lifting any dialect implementing control flow graph operations to a dialect implementi...