25 #define GEN_PASS_DEF_LIFTCONTROLFLOWTOSCFPASS
26 #include "mlir/Conversion/Passes.h.inc"
31 FailureOr<Operation *>
35 if (
auto condBrOp = dyn_cast<cf::CondBranchOp>(controlFlowCondOp)) {
36 assert(regions.size() == 2);
37 auto ifOp = builder.
create<scf::IfOp>(controlFlowCondOp->
getLoc(),
38 resultTypes, condBrOp.getCondition());
39 ifOp.getThenRegion().takeBody(regions[0]);
40 ifOp.getElseRegion().takeBody(regions[1]);
41 return ifOp.getOperation();
44 if (
auto switchOp = dyn_cast<cf::SwitchOp>(controlFlowCondOp)) {
47 auto cast = builder.
create<arith::IndexCastUIOp>(
51 if (
auto caseValues = switchOp.getCaseValues())
53 cases, llvm::map_range(*caseValues, [](
const llvm::APInt &apInt) {
54 return apInt.getZExtValue();
57 assert(regions.size() == cases.size() + 1);
59 auto indexSwitchOp = builder.
create<scf::IndexSwitchOp>(
60 controlFlowCondOp->
getLoc(), resultTypes, cast, cases, cases.size());
62 indexSwitchOp.getDefaultRegion().takeBody(regions[0]);
63 for (
auto &&[targetRegion, sourceRegion] :
64 llvm::zip(indexSwitchOp.getCaseRegions(), llvm::drop_begin(regions)))
65 targetRegion.takeBody(sourceRegion);
67 return indexSwitchOp.getOperation();
71 "Cannot convert unknown control flow op to structured control flow");
79 builder.
create<scf::YieldOp>(loc, results);
83 FailureOr<Operation *>
88 auto whileOp = builder.
create<scf::WhileOp>(loc, loopVariablesInit.
getTypes(),
91 whileOp.getBefore().takeBody(loopBody);
96 builder.
create<scf::ConditionOp>(
97 loc, builder.
create<arith::TruncIOp>(loc, builder.
getI1Type(), condition),
98 loopVariablesNextIter);
106 return whileOp.getOperation();
111 unsigned int value) {
112 return builder.
create<arith::ConstantOp>(loc,
121 builder.
create<cf::SwitchOp>(loc, flag, defaultDest, defaultArgs,
122 llvm::to_vector_of<int32_t>(caseValues),
123 caseDestinations, caseArguments);
129 return builder.
create<ub::PoisonOp>(loc, type,
nullptr);
132 FailureOr<Operation *>
141 auto funcOp = dyn_cast<func::FuncOp>(parentOp);
143 return emitError(loc,
"Cannot create unreachable terminator for '")
148 loc, llvm::map_to_vector(funcOp.getResultTypes(),
150 return getUndefValue(loc, builder, type);
157 struct LiftControlFlowToSCF
158 :
public impl::LiftControlFlowToSCFPassBase<LiftControlFlowToSCF> {
162 void runOnOperation()
override {
165 bool changed =
false;
168 if (funcOp.getBody().empty())
171 auto &domInfo = funcOp != op ? getChildAnalysis<DominanceInfo>(funcOp)
172 : getAnalysis<DominanceInfo>();
175 for (Region ® : innerOp->getRegions()) {
176 FailureOr<bool> changedFunc =
177 transformCFGToSCF(reg, transformation, domInfo);
178 if (failed(changedFunc))
179 return WalkResult::interrupt();
181 changed |= *changedFunc;
192 return signalPassFailure();
195 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)
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Operation is the basic unit of execution within MLIR.
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),...
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.
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()
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.