28 #include "llvm/ADT/StringRef.h"
32 #define GEN_PASS_DEF_CONVERTCONTROLFLOWTOLLVMPASS
33 #include "mlir/Conversion/Passes.h.inc"
38 #define PASS_NAME "convert-cf-to-llvm"
47 bool abortOnFailedAssert =
true)
49 abortOnFailedAssert(abortOnFailedAssert) {}
52 matchAndRewrite(cf::AssertOp op, OpAdaptor adaptor,
54 auto loc = op.getLoc();
55 auto module = op->getParentOfType<ModuleOp>();
65 *getTypeConverter(),
false,
67 if (abortOnFailedAssert) {
69 auto abortFunc = module.lookupSymbol<LLVM::LLVMFuncOp>(
"abort");
75 "abort", abortFuncTy);
77 rewriter.
create<LLVM::CallOp>(loc, abortFunc, std::nullopt);
78 rewriter.
create<LLVM::UnreachableOp>(loc);
86 op, adaptor.getArg(), continuationBlock, failureBlock);
94 bool abortOnFailedAssert =
true;
103 llvm::StringRef messagePrefix) {
104 for (
const auto &idxAndTypes :
106 int64_t i = idxAndTypes.index();
109 Type operandType = std::get<1>(idxAndTypes.value()).getType();
114 if (
auto op = dyn_cast_or_null<UnrealizedConversionCastOp>(
116 if (op.getOperandTypes().front() != operandType) {
118 diag << messagePrefix;
119 diag <<
"mismatched types from operand # " << i <<
" ";
121 diag <<
" not compatible with destination block argument type ";
122 diag << op.getOperandTypes().front();
123 diag <<
" which should be converted with the parent op.";
136 matchAndRewrite(cf::BranchOp op,
typename cf::BranchOp::Adaptor adaptor,
138 if (failed(verifyMatchingValues(rewriter, adaptor.getDestOperands(),
139 op.getSuccessor()->getArguments(),
145 op, adaptor.getOperands(), op->getSuccessors(), op->getAttrs());
155 matchAndRewrite(cf::CondBranchOp op,
156 typename cf::CondBranchOp::Adaptor adaptor,
158 if (failed(verifyMatchingValues(rewriter, adaptor.getFalseDestOperands(),
159 op.getFalseDest()->getArguments(),
160 op.getLoc(),
"in false case branch ")))
162 if (failed(verifyMatchingValues(rewriter, adaptor.getTrueDestOperands(),
163 op.getTrueDest()->getArguments(),
164 op.getLoc(),
"in true case branch ")))
168 op, adaptor.getOperands(), op->getSuccessors(), op->getAttrs());
178 matchAndRewrite(cf::SwitchOp op,
typename cf::SwitchOp::Adaptor adaptor,
180 if (failed(verifyMatchingValues(rewriter, adaptor.getDefaultOperands(),
181 op.getDefaultDestination()->getArguments(),
182 op.getLoc(),
"in switch default case ")))
186 llvm::zip(adaptor.getCaseOperands(), op.getCaseDestinations()))) {
187 if (failed(verifyMatchingValues(
188 rewriter, std::get<0>(i.value()),
189 std::get<1>(i.value())->getArguments(), op.getLoc(),
190 "in switch case " + std::to_string(i.index()) +
" "))) {
196 op, adaptor.getOperands(), op->getSuccessors(), op->getAttrs());
209 CondBranchOpLowering,
210 SwitchOpLowering>(converter);
216 bool abortOnFailure) {
226 struct ConvertControlFlowToLLVM
227 :
public impl::ConvertControlFlowToLLVMPassBase<ConvertControlFlowToLLVM> {
232 void runOnOperation()
override {
238 options.overrideIndexBitwidth(indexBitwidth);
244 std::move(patterns))))
256 struct ControlFlowToLLVMDialectInterface
259 void loadDependentDialects(
MLIRContext *context)
const final {
260 context->loadDialect<LLVM::LLVMDialect>();
265 void populateConvertToLLVMConversionPatterns(
277 dialect->addInterfaces<ControlFlowToLLVMDialectInterface>();
static MLIRContext * getContext(OpFoldResult val)
static std::string diag(const llvm::Value &value)
static llvm::ManagedStatic< PassManagerOptions > options
Block represents an ordered list of Operations.
This class implements a pattern rewriter for use with ConversionPatterns.
Value getRemappedValue(Value key)
Return the converted value of 'key' with a type defined by the type converter of the currently execut...
This class describes a specific conversion target.
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
Base class for dialect interfaces providing translation to LLVM IR.
ConvertToLLVMPatternInterface(Dialect *dialect)
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Derived class that automatically populates legalization information for different LLVM ops.
Conversion from types to the LLVM IR dialect.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Options to control the LLVM lowering.
MLIRContext is the top-level object for a collection of MLIR operations.
RAII guard to reset the insertion point of the builder when destroyed.
Block::iterator getInsertionPoint() const
Returns the current insertion point of the builder.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
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.
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
Block * splitBlock(Block *block, Block::iterator before)
Split the operations starting at "before" (inclusive) out of the given block into a new block,...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
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.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
void createPrintStrCall(OpBuilder &builder, Location loc, ModuleOp moduleOp, StringRef symbolName, StringRef string, const LLVMTypeConverter &typeConverter, bool addNewline=true, std::optional< StringRef > runtimeFunctionName={})
Generate IR that prints the given string to stdout.
void populateAssertToLLVMConversionPattern(const LLVMTypeConverter &converter, RewritePatternSet &patterns, bool abortOnFailure=true)
Populate the cf.assert to LLVM conversion pattern.
void registerConvertControlFlowToLLVMInterface(DialectRegistry ®istry)
void populateControlFlowToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns)
Collect the patterns to convert from the ControlFlow dialect to LLVM.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Include the generated interface declarations.
static constexpr unsigned kDeriveIndexBitwidthFromDataLayout
Value to pass as bitwidth for the index type when the converter is expected to derive the bitwidth fr...
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, ConversionConfig config=ConversionConfig())
Below we define several entry points for operation conversion.