40 #include "llvm/ADT/SmallVector.h"
41 #include "llvm/ADT/TypeSwitch.h"
42 #include "llvm/IR/DerivedTypes.h"
43 #include "llvm/IR/IRBuilder.h"
44 #include "llvm/IR/Type.h"
45 #include "llvm/Support/Casting.h"
46 #include "llvm/Support/CommandLine.h"
47 #include "llvm/Support/FormatVariadic.h"
53 #define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS
54 #define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS
55 #include "mlir/Conversion/Passes.h.inc"
60 #define PASS_NAME "convert-func-to-llvm"
80 attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName())
82 result.push_back(attr);
88 FunctionOpInterface funcOp,
89 LLVM::LLVMFuncOp wrapperFuncOp) {
90 auto argAttrs = funcOp.getAllArgAttrs();
91 if (!resultStructType) {
92 if (
auto resAttrs = funcOp.getAllResultAttrs())
93 wrapperFuncOp.setAllResultAttrs(resAttrs);
95 wrapperFuncOp.setAllArgAttrs(argAttrs);
102 argAttributes.append(argAttrs.begin(), argAttrs.end());
103 wrapperFuncOp.setAllArgAttrs(argAttributes);
106 cast<FunctionOpInterface>(wrapperFuncOp.getOperation())
107 .setVisibility(funcOp.getVisibility());
120 FunctionOpInterface funcOp,
121 LLVM::LLVMFuncOp newFuncOp) {
122 auto type = cast<FunctionType>(funcOp.getFunctionType());
123 auto [wrapperFuncType, resultStructType] =
129 auto wrapperFuncOp = rewriter.
create<LLVM::LLVMFuncOp>(
130 loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
131 wrapperFuncType, LLVM::Linkage::External,
false,
132 LLVM::CConv::C,
nullptr, attributes);
139 size_t argOffset = resultStructType ? 1 : 0;
141 Value arg = wrapperFuncOp.getArgument(index + argOffset);
142 if (
auto memrefType = dyn_cast<MemRefType>(argType)) {
148 if (isa<UnrankedMemRefType>(argType)) {
158 auto call = rewriter.
create<LLVM::CallOp>(loc, newFuncOp, args);
160 if (resultStructType) {
161 rewriter.
create<LLVM::StoreOp>(loc, call.getResult(),
162 wrapperFuncOp.getArgument(0));
165 rewriter.
create<LLVM::ReturnOp>(loc, call.getResults());
180 FunctionOpInterface funcOp,
181 LLVM::LLVMFuncOp newFuncOp) {
184 auto [wrapperType, resultStructType] =
186 cast<FunctionType>(funcOp.getFunctionType()));
190 assert(wrapperType &&
"unexpected type conversion failure");
196 auto wrapperFunc = builder.
create<LLVM::LLVMFuncOp>(
197 loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
198 wrapperType, LLVM::Linkage::External,
false,
199 LLVM::CConv::C,
nullptr, attributes);
203 newFuncOp.setLinkage(LLVM::Linkage::Private);
207 FunctionType type = cast<FunctionType>(funcOp.getFunctionType());
209 args.reserve(type.getNumInputs());
210 ValueRange wrapperArgsRange(newFuncOp.getArguments());
212 if (resultStructType) {
214 Type resultType = cast<LLVM::LLVMFunctionType>(wrapperType).getParamType(0);
219 builder.
create<LLVM::AllocaOp>(loc, resultType, resultStructType, one);
220 args.push_back(result);
225 for (
Type input : type.getInputs()) {
228 auto memRefType = dyn_cast<MemRefType>(input);
229 auto unrankedMemRefType = dyn_cast<UnrankedMemRefType>(input);
230 if (memRefType || unrankedMemRefType) {
231 numToDrop = memRefType
237 wrapperArgsRange.take_front(numToDrop))
239 builder, loc, typeConverter, unrankedMemRefType,
240 wrapperArgsRange.take_front(numToDrop));
247 loc, ptrTy, packed.
getType(), one, 0);
248 builder.
create<LLVM::StoreOp>(loc, packed, allocated);
251 arg = wrapperArgsRange[0];
255 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);
257 assert(wrapperArgsRange.empty() &&
"did not map some of the arguments");
259 auto call = builder.
create<LLVM::CallOp>(loc, wrapperFunc, args);
261 if (resultStructType) {
263 builder.
create<LLVM::LoadOp>(loc, resultStructType, args.front());
264 builder.
create<LLVM::ReturnOp>(loc, result);
266 builder.
create<LLVM::ReturnOp>(loc, call.getResults());
275 ArrayRef<std::optional<NamedAttribute>> byValRefNonPtrAttrs,
278 if (funcOp.isExternal())
281 ConversionPatternRewriter::InsertionGuard guard(rewriter);
284 for (
const auto &[arg, oldArg, byValRefAttr] :
285 llvm::zip(funcOp.getArguments(), oldBlockArgs, byValRefNonPtrAttrs)) {
291 assert(isa<LLVM::LLVMPointerType>(arg.getType()) &&
292 "Expected LLVM pointer type for argument with "
293 "`llvm.byval`/`llvm.byref` attribute");
295 cast<TypeAttr>(byValRefAttr->getValue()).getValue());
297 auto valueArg = rewriter.
create<LLVM::LoadOp>(arg.getLoc(), resTy, arg);
302 FailureOr<LLVM::LLVMFuncOp>
307 auto funcTy = dyn_cast<FunctionType>(funcOp.getFunctionType());
310 funcOp,
"Only support FunctionOpInterface with FunctionType");
314 llvm::to_vector(funcOp.getArguments());
324 funcOp, varargsAttr && varargsAttr.getValue(),
326 byValRefNonPtrAttrs);
332 LLVM::Linkage linkage = LLVM::Linkage::External;
338 <<
" attribute not of type LLVM::LinkageAttr";
340 funcOp,
"Contains linkage attribute not of type LLVM::LinkageAttr");
342 linkage = attr.getLinkage();
347 auto newFuncOp = rewriter.
create<LLVM::LLVMFuncOp>(
348 funcOp.getLoc(), funcOp.getName(), llvmType, linkage,
349 false, LLVM::CConv::C,
nullptr,
351 cast<FunctionOpInterface>(newFuncOp.getOperation())
352 .setVisibility(funcOp.getVisibility());
355 StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();
356 if (funcOp->hasAttr(readnoneAttrName)) {
357 auto attr = funcOp->getAttrOfType<UnitAttr>(readnoneAttrName);
359 funcOp->emitError() <<
"Contains " << readnoneAttrName
360 <<
" attribute not of type UnitAttr";
362 funcOp,
"Contains readnone attribute not of type UnitAttr");
366 {LLVM::ModRefInfo::NoModRef, LLVM::ModRefInfo::NoModRef,
367 LLVM::ModRefInfo::NoModRef});
368 newFuncOp.setMemoryEffectsAttr(memoryAttr);
373 if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
374 assert(!resAttrDicts.empty() &&
"expected array to be non-empty");
375 if (funcOp.getNumResults() == 1)
376 newFuncOp.setAllResultAttrs(resAttrDicts);
378 if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
380 cast<LLVM::LLVMFunctionType>(llvmType).getNumParams());
381 for (
unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
386 auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
387 convertedAttrs.reserve(attrsDict.size());
391 cast<TypeAttr>(attr.getValue()).getValue()));
393 if (attr.getName().getValue() ==
394 LLVM::LLVMDialect::getByValAttrName()) {
396 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
397 }
else if (attr.getName().getValue() ==
398 LLVM::LLVMDialect::getByRefAttrName()) {
400 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
401 }
else if (attr.getName().getValue() ==
402 LLVM::LLVMDialect::getStructRetAttrName()) {
404 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
405 }
else if (attr.getName().getValue() ==
406 LLVM::LLVMDialect::getInAllocaAttrName()) {
408 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
410 convertedAttrs.push_back(attr);
414 assert(mapping &&
"unexpected deletion of function argument");
418 if (mapping->size == 1) {
419 newArgAttrs[mapping->inputNo] =
425 for (
size_t j = 0;
j < mapping->size; ++
j)
426 newArgAttrs[mapping->inputNo +
j] =
429 if (!newArgAttrs.empty())
430 newFuncOp.setAllArgAttrs(rewriter.
getArrayAttr(newArgAttrs));
437 if (!newFuncOp.getBody().empty())
445 oldBlockArgs, newFuncOp);
448 if (funcOp->getAttrOfType<UnitAttr>(
449 LLVM::LLVMDialect::getEmitCWrapperAttrName())) {
450 if (newFuncOp.isVarArg())
451 return funcOp.emitError(
"C interface for variadic functions is not "
454 if (newFuncOp.isExternal())
476 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
479 cast<FunctionOpInterface>(funcOp.getOperation()), rewriter,
480 *getTypeConverter());
481 if (failed(newFuncOp))
493 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
495 auto type = typeConverter->convertType(op.getResult().getType());
500 rewriter.
create<LLVM::AddressOfOp>(op.getLoc(), type, op.getValue());
502 if (attr.getName().strref() ==
"value")
504 newOp->
setAttr(attr.getName(), attr.getValue());
506 rewriter.
replaceOp(op, newOp->getResults());
513 template <
typename CallOpType>
516 using Super = CallOpInterfaceLowering<CallOpType>;
519 LogicalResult matchAndRewriteImpl(CallOpType callOp,
520 typename CallOpType::Adaptor adaptor,
522 bool useBarePtrCallConv =
false)
const {
524 Type packedResult =
nullptr;
525 unsigned numResults = callOp.getNumResults();
526 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
528 if (numResults != 0) {
529 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
530 resultTypes, useBarePtrCallConv)))
534 if (useBarePtrCallConv) {
535 for (
auto it : callOp->getOperands()) {
536 Type operandType = it.getType();
537 if (isa<UnrankedMemRefType>(operandType)) {
544 auto promoted = this->getTypeConverter()->promoteOperands(
545 callOp.getLoc(), callOp->getOperands(),
546 adaptor.getOperands(), rewriter, useBarePtrCallConv);
547 auto newOp = rewriter.
create<LLVM::CallOp>(
549 promoted, callOp->getAttrs());
551 newOp.getProperties().operandSegmentSizes = {
552 static_cast<int32_t
>(promoted.size()), 0};
556 if (numResults < 2) {
558 results.append(newOp.result_begin(), newOp.result_end());
562 results.reserve(numResults);
563 for (
unsigned i = 0; i < numResults; ++i) {
564 results.push_back(rewriter.
create<LLVM::ExtractValueOp>(
565 callOp.getLoc(), newOp->getResult(0), i));
569 if (useBarePtrCallConv) {
572 assert(results.size() == resultTypes.size() &&
573 "The number of arguments and types doesn't match");
574 this->getTypeConverter()->promoteBarePtrsToDescriptors(
575 rewriter, callOp.getLoc(), resultTypes, results);
576 }
else if (failed(this->copyUnrankedDescriptors(rewriter, callOp.getLoc(),
577 resultTypes, results,
587 class CallOpLowering :
public CallOpInterfaceLowering<func::CallOp> {
592 : CallOpInterfaceLowering<func::CallOp>(typeConverter, benefit),
593 symbolTable(symbolTable) {}
596 matchAndRewrite(func::CallOp callOp, OpAdaptor adaptor,
598 bool useBarePtrCallConv =
false;
599 if (getTypeConverter()->getOptions().useBarePtrCallConv) {
600 useBarePtrCallConv =
true;
601 }
else if (symbolTable !=
nullptr) {
604 symbolTable->lookup(callOp.getCalleeAttr().getValue());
614 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
621 struct CallIndirectOpLowering
622 :
public CallOpInterfaceLowering<func::CallIndirectOp> {
626 matchAndRewrite(func::CallIndirectOp callIndirectOp, OpAdaptor adaptor,
628 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
632 struct UnrealizedConversionCastOpLowering
638 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
641 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
643 convertedTypes == adaptor.getInputs().getTypes()) {
644 rewriter.
replaceOp(op, adaptor.getInputs());
648 convertedTypes.clear();
649 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
651 convertedTypes == op.getOutputs().getType()) {
652 rewriter.
replaceOp(op, adaptor.getInputs());
669 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
672 unsigned numArguments = op.getNumOperands();
675 auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
676 bool useBarePtrCallConv =
678 if (useBarePtrCallConv) {
681 for (
auto it : llvm::zip(op->getOperands(), adaptor.getOperands())) {
682 Type oldTy = std::get<0>(it).getType();
683 Value newOperand = std::get<1>(it);
684 if (isa<MemRefType>(oldTy) && getTypeConverter()->canConvertToBarePtr(
685 cast<BaseMemRefType>(oldTy))) {
687 newOperand = memrefDesc.allocatedPtr(rewriter, loc);
688 }
else if (isa<UnrankedMemRefType>(oldTy)) {
693 updatedOperands.push_back(newOperand);
696 updatedOperands = llvm::to_vector<4>(adaptor.getOperands());
697 (void)copyUnrankedDescriptors(rewriter, loc, op.getOperands().getTypes(),
703 if (numArguments <= 1) {
705 op,
TypeRange(), updatedOperands, op->getAttrs());
711 auto packedType = getTypeConverter()->packFunctionResults(
712 op.getOperandTypes(), useBarePtrCallConv);
717 Value packed = rewriter.
create<LLVM::UndefOp>(loc, packedType);
719 packed = rewriter.
create<LLVM::InsertValueOp>(loc, packed, operand, idx);
730 patterns.add<FuncOpConversion>(converter);
737 patterns.add<CallIndirectOpLowering>(converter);
738 patterns.add<CallOpLowering>(converter, symbolTable);
739 patterns.add<ConstantOpLowering>(converter);
740 patterns.add<ReturnOpLowering>(converter);
745 struct ConvertFuncToLLVMPass
746 :
public impl::ConvertFuncToLLVMPassBase<ConvertFuncToLLVMPass> {
750 void runOnOperation()
override {
751 ModuleOp m = getOperation();
752 StringRef dataLayout;
753 auto dataLayoutAttr = dyn_cast_or_null<StringAttr>(
754 m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
756 dataLayout = dataLayoutAttr.getValue();
758 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
759 dataLayout, [
this](
const Twine &message) {
760 getOperation().emitError() << message.str();
766 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
769 dataLayoutAnalysis.getAtOrAbove(m));
770 options.useBarePtrCallConv = useBarePtrCallConv;
772 options.overrideIndexBitwidth(indexBitwidth);
773 options.dataLayout = llvm::DataLayout(dataLayout);
776 &dataLayoutAnalysis);
778 std::optional<SymbolTable> optSymbolTable = std::nullopt;
780 if (!
options.useBarePtrCallConv) {
781 optSymbolTable.emplace(m);
782 symbolTable = &optSymbolTable.value();
794 struct SetLLVMModuleDataLayoutPass
795 :
public impl::SetLLVMModuleDataLayoutPassBase<
796 SetLLVMModuleDataLayoutPass> {
800 void runOnOperation()
override {
801 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
802 this->dataLayout, [
this](
const Twine &message) {
803 getOperation().emitError() << message.str();
808 ModuleOp m = getOperation();
809 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
825 void populateConvertToLLVMConversionPatterns(
835 dialect->addInterfaces<FuncToLLVMDialectInterface>();
static void propagateArgResAttrs(OpBuilder &builder, bool resultStructType, FunctionOpInterface funcOp, LLVM::LLVMFuncOp wrapperFuncOp)
Propagate argument/results attributes.
static constexpr StringRef barePtrAttrName
static constexpr StringRef varargsAttrName
static constexpr StringRef linkageAttrName
static void filterFuncAttributes(FunctionOpInterface func, SmallVectorImpl< NamedAttribute > &result)
Only retain those attributes that are not constructed by LLVMFuncOp::build.
static bool shouldUseBarePtrCallConv(Operation *op, const LLVMTypeConverter *typeConverter)
Return true if the op should use bare pointer calling convention.
static void restoreByValRefArgumentType(ConversionPatternRewriter &rewriter, const LLVMTypeConverter &typeConverter, ArrayRef< std::optional< NamedAttribute >> byValRefNonPtrAttrs, ArrayRef< BlockArgument > oldBlockArgs, LLVM::LLVMFuncOp funcOp)
Inserts llvm.load ops in the function body to restore the expected pointee value from llvm....
static void wrapExternalFunction(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, FunctionOpInterface funcOp, LLVM::LLVMFuncOp newFuncOp)
Creates an auxiliary function with pointer-to-memref-descriptor-struct arguments instead of unpacked ...
static void wrapForExternalCallers(OpBuilder &rewriter, Location loc, const LLVMTypeConverter &typeConverter, FunctionOpInterface funcOp, LLVM::LLVMFuncOp newFuncOp)
Creates an auxiliary function with pointer-to-memref-descriptor-struct arguments instead of unpacked ...
static MLIRContext * getContext(OpFoldResult val)
static llvm::ManagedStatic< PassManagerOptions > options
Special case of IntegerAttr to represent boolean integers, i.e., signless i1 integers.
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerAttr getIntegerAttr(Type type, int64_t value)
MLIRContext * getContext() const
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
This class implements a pattern rewriter for use with ConversionPatterns.
void replaceOp(Operation *op, ValueRange newValues) override
Replace the given operation with the new values.
Block * applySignatureConversion(Block *block, TypeConverter::SignatureConversion &conversion, const TypeConverter *converter=nullptr)
Apply a signature conversion to given block.
void eraseOp(Operation *op) override
PatternRewriter hook for erasing a dead operation.
void replaceUsesOfBlockArgument(BlockArgument from, Value to)
Replace all the uses of the block argument from with value to.
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)
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.
const LowerToLLVMOptions & getOptions() const
Type convertFunctionSignature(FunctionType funcTy, bool isVariadic, bool useBarePtrCallConv, SignatureConversion &result) const
Convert a function type.
LogicalResult convertType(Type t, SmallVectorImpl< Type > &results) const
Convert the given type.
std::pair< LLVM::LLVMFunctionType, LLVM::LLVMStructType > convertFunctionTypeCWrapper(FunctionType type) const
Converts the function type to a C-compatible format, in particular using pointers to memref descripto...
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.
Helper class to produce LLVM dialect operations extracting or inserting elements of a MemRef descript...
static Value pack(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, MemRefType type, ValueRange values)
Builds IR populating a MemRef descriptor structure from a list of individual values composing that de...
static unsigned getNumUnpackedValues(MemRefType type)
Returns the number of non-aggregate values that would be produced by unpack.
static void unpack(OpBuilder &builder, Location loc, Value packed, MemRefType type, SmallVectorImpl< Value > &results)
Builds IR extracting individual elements of a MemRef descriptor structure and returning them as resul...
NamedAttribute represents a combination of a name and an Attribute value.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start 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.
bool hasAttr(StringAttr name)
Return true if the operation has an attribute with the provided name, false otherwise.
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
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,...
void inlineRegionBefore(Region ®ion, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent".
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides all of the information necessary to convert a type signature.
std::optional< InputMapping > getInputMapping(unsigned input) const
Get the input mapping for the given argument.
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...
static Value pack(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, UnrankedMemRefType type, ValueRange values)
Builds IR populating an unranked MemRef descriptor structure from a list of individual constituent va...
static void unpack(OpBuilder &builder, Location loc, Value packed, SmallVectorImpl< Value > &results)
Builds IR extracting individual elements that compose an unranked memref descriptor and returns them ...
static unsigned getNumUnpackedValues()
Returns the number of non-aggregate values that would be produced by unpack.
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...
Type getType() const
Return the type of this value.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
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...
void populateFuncToLLVMFuncOpConversionPattern(const LLVMTypeConverter &converter, RewritePatternSet &patterns)
Collect the default pattern to convert a FuncOp to the LLVM dialect.
void registerConvertFuncToLLVMInterface(DialectRegistry ®istry)
const FrozenRewritePatternSet & patterns
FailureOr< LLVM::LLVMFuncOp > convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter)
Convert input FunctionOpInterface operation to LLVMFuncOp by using the provided LLVMTypeConverter.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
void populateFuncToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, const SymbolTable *symbolTable=nullptr)
Collect the patterns to convert from the Func dialect to LLVM.
LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, ConversionConfig config=ConversionConfig())
Below we define several entry points for operation conversion.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.