26 #define GEN_PASS_DEF_LIFTCONTROLFLOWTOSCFPASS
27 #include "mlir/Conversion/Passes.h.inc"
36 if (
auto condBrOp = dyn_cast<cf::CondBranchOp>(controlFlowCondOp)) {
37 assert(regions.size() == 2);
38 auto ifOp = builder.
create<scf::IfOp>(controlFlowCondOp->
getLoc(),
39 resultTypes, condBrOp.getCondition());
40 ifOp.getThenRegion().takeBody(regions[0]);
41 ifOp.getElseRegion().takeBody(regions[1]);
42 return ifOp.getOperation();
45 if (
auto switchOp = dyn_cast<cf::SwitchOp>(controlFlowCondOp)) {
48 auto cast = builder.
create<arith::IndexCastUIOp>(
52 if (
auto caseValues = switchOp.getCaseValues())
54 cases, llvm::map_range(*caseValues, [](
const llvm::APInt &apInt) {
55 return apInt.getZExtValue();
58 assert(regions.size() == cases.size() + 1);
60 auto indexSwitchOp = builder.
create<scf::IndexSwitchOp>(
61 controlFlowCondOp->
getLoc(), resultTypes, cast, cases, cases.size());
63 indexSwitchOp.getDefaultRegion().takeBody(regions[0]);
64 for (
auto &&[targetRegion, sourceRegion] :
65 llvm::zip(indexSwitchOp.getCaseRegions(), llvm::drop_begin(regions)))
66 targetRegion.takeBody(sourceRegion);
68 return indexSwitchOp.getOperation();
72 "Cannot convert unknown control flow op to structured control flow");
80 builder.
create<scf::YieldOp>(loc, results);
89 auto whileOp = builder.
create<scf::WhileOp>(loc, loopVariablesInit.
getTypes(),
92 whileOp.getBefore().takeBody(loopBody);
97 builder.
create<scf::ConditionOp>(
98 loc, builder.
create<arith::TruncIOp>(loc, builder.
getI1Type(), condition),
99 loopVariablesNextIter);
101 auto *afterBlock =
new Block;
102 whileOp.getAfter().
push_back(afterBlock);
103 afterBlock->addArguments(
107 builder.
create<scf::YieldOp>(loc, afterBlock->getArguments());
109 return whileOp.getOperation();
114 unsigned int value) {
115 return builder.
create<arith::ConstantOp>(loc,
124 builder.
create<cf::SwitchOp>(loc, flag, defaultDest, defaultArgs,
125 llvm::to_vector_of<int32_t>(caseValues),
126 caseDestinations, caseArguments);
132 return builder.
create<ub::PoisonOp>(loc, type,
nullptr);
144 auto funcOp = dyn_cast<func::FuncOp>(parentOp);
146 return emitError(loc,
"Cannot create unreachable terminator for '")
151 loc, llvm::map_to_vector(funcOp.getResultTypes(),
153 return getUndefValue(loc, builder, type);
160 struct LiftControlFlowToSCF
161 :
public impl::LiftControlFlowToSCFPassBase<LiftControlFlowToSCF> {
165 void runOnOperation()
override {
168 bool changed =
false;
171 if (funcOp.getBody().empty())
174 auto &domInfo = funcOp != op ? getChildAnalysis<DominanceInfo>(funcOp)
175 : getAnalysis<DominanceInfo>();
178 for (Region ® : innerOp->getRegions()) {
179 FailureOr<bool> changedFunc =
180 transformCFGToSCF(reg, transformation, domInfo);
181 if (failed(changedFunc))
182 return WalkResult::interrupt();
184 changed |= *changedFunc;
195 return signalPassFailure();
198 markAllAnalysesPreserved();
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
void push_back(Operation *op)
IntegerAttr getI32IntegerAttr(int32_t value)
This class provides support for representing a failure result, or a valid value of type T.
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.
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.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
This class represents an efficient way to signal success or failure.