29#define GEN_PASS_DEF_CONVERTCONTROLFLOWTOLLVMPASS
30#include "mlir/Conversion/Passes.h.inc"
35#define PASS_NAME "convert-cf-to-llvm"
44 bool abortOnFailedAssert =
true,
47 abortOnFailedAssert(abortOnFailedAssert), symbolTables(symbolTables) {}
50 matchAndRewrite(cf::AssertOp op, OpAdaptor adaptor,
51 ConversionPatternRewriter &rewriter)
const override {
52 auto loc = op.getLoc();
53 auto module = op->getParentOfType<ModuleOp>();
56 Block *opBlock = rewriter.getInsertionBlock();
57 auto opPosition = rewriter.getInsertionPoint();
58 Block *continuationBlock = rewriter.splitBlock(opBlock, opPosition);
63 rewriter, loc, module,
"assert_msg", op.getMsg(), *getTypeConverter(),
65 "puts", symbolTables);
66 if (createResult.failed())
69 if (abortOnFailedAssert) {
71 auto abortFunc =
module.lookupSymbol<LLVM::LLVMFuncOp>("abort");
74 rewriter.setInsertionPointToStart(module.getBody());
75 auto abortFuncTy = LLVM::LLVMFunctionType::get(getVoidType(), {});
76 abortFunc = LLVM::LLVMFuncOp::create(rewriter, rewriter.getUnknownLoc(),
77 "abort", abortFuncTy);
79 LLVM::CallOp::create(rewriter, loc, abortFunc,
ValueRange());
80 LLVM::UnreachableOp::create(rewriter, loc);
82 LLVM::BrOp::create(rewriter, loc,
ValueRange(), continuationBlock);
86 rewriter.setInsertionPointToEnd(opBlock);
87 rewriter.replaceOpWithNewOp<LLVM::CondBrOp>(
88 op, adaptor.getArg(), continuationBlock, failureBlock);
96 bool abortOnFailedAssert =
true;
104static FailureOr<Block *> getConvertedBlock(ConversionPatternRewriter &rewriter,
108 assert(converter &&
"expected non-null type converter");
109 assert(!block->
isEntryBlock() &&
"entry blocks have no predecessors");
116 std::optional<TypeConverter::SignatureConversion> conversion =
117 converter->convertBlockSignature(block);
119 return rewriter.notifyMatchFailure(branchOp,
120 "could not compute block signature");
121 if (expectedTypes != conversion->getConvertedTypes())
122 return rewriter.notifyMatchFailure(
124 "mismatch between adaptor operand types and computed block signature");
125 return rewriter.applySignatureConversion(block, *conversion, converter);
132 llvm::append_range(
result, vals);
137static void setConvertedAttrs(
Operation *op, DictionaryAttr attrs) {
143 discardableAttrs.push_back(attr);
155 matchAndRewrite(cf::BranchOp op, Adaptor adaptor,
156 ConversionPatternRewriter &rewriter)
const override {
158 FailureOr<Block *> convertedBlock =
159 getConvertedBlock(rewriter, getTypeConverter(), op, op.getSuccessor(),
161 if (failed(convertedBlock))
163 DictionaryAttr attrs = op->getDiscardableAttrDictionary();
164 auto loopAnnotation =
165 op->getAttrOfType<LLVM::LoopAnnotationAttr>(
"loop_annotation");
166 Operation *newOp = rewriter.replaceOpWithNewOp<LLVM::BrOp>(
167 op, flattenedAdaptor, loopAnnotation, *convertedBlock);
170 setConvertedAttrs(newOp, attrs);
182 matchAndRewrite(cf::CondBranchOp op, Adaptor adaptor,
183 ConversionPatternRewriter &rewriter)
const override {
188 if (!llvm::hasSingleElement(adaptor.getCondition()))
189 return rewriter.notifyMatchFailure(op,
190 "expected single element condition");
191 FailureOr<Block *> convertedTrueBlock =
192 getConvertedBlock(rewriter, getTypeConverter(), op, op.getTrueDest(),
194 if (failed(convertedTrueBlock))
196 FailureOr<Block *> convertedFalseBlock =
197 getConvertedBlock(rewriter, getTypeConverter(), op, op.getFalseDest(),
199 if (failed(convertedFalseBlock))
201 DictionaryAttr attrs = op->getDiscardableAttrDictionary();
202 auto loopAnnotation =
203 op->getAttrOfType<LLVM::LoopAnnotationAttr>(
"loop_annotation");
204 auto newOp = rewriter.replaceOpWithNewOp<LLVM::CondBrOp>(
205 op, llvm::getSingleElement(adaptor.getCondition()),
206 flattenedAdaptorTrue, flattenedAdaptorFalse, op.getBranchWeightsAttr(),
207 loopAnnotation, *convertedTrueBlock, *convertedFalseBlock);
210 setConvertedAttrs(newOp, attrs);
221 matchAndRewrite(cf::SwitchOp op, cf::SwitchOp::Adaptor adaptor,
222 ConversionPatternRewriter &rewriter)
const override {
224 FailureOr<Block *> convertedDefaultBlock = getConvertedBlock(
225 rewriter, getTypeConverter(), op, op.getDefaultDestination(),
226 TypeRange(adaptor.getDefaultOperands()));
227 if (failed(convertedDefaultBlock))
233 for (
auto it : llvm::enumerate(op.getCaseDestinations())) {
235 FailureOr<Block *> convertedBlock =
236 getConvertedBlock(rewriter, getTypeConverter(), op,
b,
238 if (failed(convertedBlock))
240 caseDestinations.push_back(*convertedBlock);
243 rewriter.replaceOpWithNewOp<LLVM::SwitchOp>(
244 op, adaptor.getFlag(), *convertedDefaultBlock,
245 adaptor.getDefaultOperands(), adaptor.getCaseValuesAttr(),
246 caseDestinations, caseOperands);
258 CondBranchOpLowering,
259 SwitchOpLowering>(converter);
275struct ConvertControlFlowToLLVM
276 :
public impl::ConvertControlFlowToLLVMPassBase<ConvertControlFlowToLLVM> {
281 void runOnOperation()
override {
294 options.overrideIndexBitwidth(indexBitwidth);
301 if (failed(applyPartialConversion(getOperation(),
target,
302 std::move(patterns))))
314struct ControlFlowToLLVMDialectInterface
315 :
public ConvertToLLVMPatternInterface {
316 ControlFlowToLLVMDialectInterface(Dialect *dialect)
317 : ConvertToLLVMPatternInterface(dialect) {}
319 void loadDependentDialects(MLIRContext *context)
const final {
320 context->loadDialect<LLVM::LLVMDialect>();
325 void populateConvertToLLVMConversionPatterns(
326 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
327 RewritePatternSet &patterns)
const final {
338 dialect->addInterfaces<ControlFlowToLLVMDialectInterface>();
static SmallVector< Value > flattenValues(ArrayRef< ValueRange > values)
Flatten the given value ranges into a single vector of values.
static llvm::ManagedStatic< PassManagerOptions > options
Block represents an ordered list of Operations.
ValueTypeRange< BlockArgListType > getArgumentTypes()
Return a range containing the types of the arguments for this block.
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
bool isEntryBlock()
Return if this block is the entry block in the parent region.
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
typename SourceOp::template GenericAdaptor< ArrayRef< ValueRange > > OneToNOpAdaptor
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.
Options to control the LLVM lowering.
MLIRContext is the top-level object for a collection of MLIR operations.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
NamedAttribute represents a combination of a name and an Attribute value.
RAII guard to reset the insertion point of the builder when destroyed.
Operation is the basic unit of execution within MLIR.
void setInherentAttr(StringAttr name, Attribute value)
Set an inherent attribute by name.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
std::optional< Attribute > getInherentAttr(StringRef name)
Access an inherent attribute by name: returns an empty optional if there is no inherent attribute wit...
void setDiscardableAttrs(DictionaryAttr newAttrs)
Set the discardable attribute dictionary on this operation.
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
This class represents a collection of SymbolTables.
This class provides an abstraction over the various different ranges of value types.
This class provides an abstraction over the different types of ranges over Values.
LogicalResult createPrintStrCall(OpBuilder &builder, Location loc, ModuleOp moduleOp, StringRef symbolName, StringRef string, const LLVMTypeConverter &typeConverter, bool addNewline=true, std::optional< StringRef > runtimeFunctionName={}, SymbolTableCollection *symbolTables=nullptr)
Generate IR that prints the given string to stdout.
void registerConvertControlFlowToLLVMInterface(DialectRegistry ®istry)
void populateControlFlowToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns)
Collect the patterns to convert from the ControlFlow dialect to LLVM.
void populateAssertToLLVMConversionPattern(const LLVMTypeConverter &converter, RewritePatternSet &patterns, bool abortOnFailure=true, SymbolTableCollection *symbolTables=nullptr)
Populate the cf.assert to LLVM conversion pattern.
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...