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 *>
147 auto funcOp = dyn_cast<func::FuncOp>(parentOp);
149 return emitError(loc,
"Cannot create unreachable terminator for '")
152 return func::ReturnOp::create(
155 funcOp.getResultTypes(),
156 [&](
Type type) { return getUndefValue(loc, builder, type); }))
162struct LiftControlFlowToSCF
163 :
public impl::LiftControlFlowToSCFPassBase<LiftControlFlowToSCF> {
167 void runOnOperation()
override {
170 bool changed =
false;
173 if (funcOp.getBody().empty())
176 auto &domInfo = funcOp != op ? getChildAnalysis<DominanceInfo>(funcOp)
180 for (
Region ® : innerOp->getRegions()) {
181 FailureOr<bool> changedFunc =
183 if (failed(changedFunc))
186 changed |= *changedFunc;
191 if (funcOp->walk<WalkOrder::PostOrder>(visitor).wasInterrupted())
196 if (
result.wasInterrupted())
197 return signalPassFailure();
200 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.
OperationName getName()
The name of an operation is the key identifier for it.
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.
Operation * getParentOp()
Return the parent operation this region 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.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
FailureOr< bool > transformCFGToSCF(Region ®ion, CFGToSCFInterface &interface, DominanceInfo &dominanceInfo)
Transformation lifting any dialect implementing control flow graph operations to a dialect implementi...