41 #include "llvm/ADT/SmallVector.h"
42 #include "llvm/ADT/TypeSwitch.h"
43 #include "llvm/IR/DerivedTypes.h"
44 #include "llvm/IR/IRBuilder.h"
45 #include "llvm/IR/Type.h"
46 #include "llvm/Support/Casting.h"
47 #include "llvm/Support/CommandLine.h"
48 #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() == func.getFunctionTypeAttrName() ||
83 attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName() ||
84 (filterArgAndResAttrs &&
85 (attr.getName() == func.getArgAttrsAttrName() ||
86 attr.getName() == func.getResAttrsAttrName())))
88 result.push_back(attr);
97 auto argAttrs = func.getArgAttrs();
102 size_t numArguments = func.getNumArguments();
104 newArgAttrs.reserve(numArguments + 1);
108 llvm::append_range(newArgAttrs, *argAttrs);
109 auto newNamedAttr = builder.
getNamedAttr(func.getArgAttrsAttrName(),
111 newFuncAttrs.push_back(newNamedAttr);
125 LLVM::LLVMFuncOp newFuncOp) {
126 auto type = funcOp.getFunctionType();
127 auto [wrapperFuncType, resultStructType] =
133 if (resultStructType)
136 funcOp,
static_cast<bool>(resultStructType),
138 auto wrapperFuncOp = rewriter.
create<LLVM::LLVMFuncOp>(
139 loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
140 wrapperFuncType, LLVM::Linkage::External,
false,
141 LLVM::CConv::C,
nullptr, attributes);
147 size_t argOffset = resultStructType ? 1 : 0;
149 Value arg = wrapperFuncOp.getArgument(index + argOffset);
150 if (
auto memrefType = dyn_cast<MemRefType>(argType)) {
156 if (isa<UnrankedMemRefType>(argType)) {
166 auto call = rewriter.
create<LLVM::CallOp>(loc, newFuncOp, args);
168 if (resultStructType) {
169 rewriter.
create<LLVM::StoreOp>(loc, call.getResult(),
170 wrapperFuncOp.getArgument(0));
173 rewriter.
create<LLVM::ReturnOp>(loc, call.getResults());
189 LLVM::LLVMFuncOp newFuncOp) {
192 auto [wrapperType, resultStructType] =
197 assert(wrapperType &&
"unexpected type conversion failure");
202 if (resultStructType)
205 funcOp,
static_cast<bool>(resultStructType),
209 auto wrapperFunc = builder.
create<LLVM::LLVMFuncOp>(
210 loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
211 wrapperType, LLVM::Linkage::External,
false,
212 LLVM::CConv::C,
nullptr, attributes);
215 newFuncOp.setLinkage(LLVM::Linkage::Private);
219 FunctionType type = funcOp.getFunctionType();
221 args.reserve(type.getNumInputs());
222 ValueRange wrapperArgsRange(newFuncOp.getArguments());
224 if (resultStructType) {
226 Type resultType = cast<LLVM::LLVMFunctionType>(wrapperType).getParamType(0);
231 builder.
create<LLVM::AllocaOp>(loc, resultType, resultStructType, one);
232 args.push_back(result);
237 for (
Type input : type.getInputs()) {
240 auto memRefType = dyn_cast<MemRefType>(input);
241 auto unrankedMemRefType = dyn_cast<UnrankedMemRefType>(input);
242 if (memRefType || unrankedMemRefType) {
243 numToDrop = memRefType
249 wrapperArgsRange.take_front(numToDrop))
251 builder, loc, typeConverter, unrankedMemRefType,
252 wrapperArgsRange.take_front(numToDrop));
259 loc, ptrTy, packed.
getType(), one, 0);
260 builder.
create<LLVM::StoreOp>(loc, packed, allocated);
263 arg = wrapperArgsRange[0];
267 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);
269 assert(wrapperArgsRange.empty() &&
"did not map some of the arguments");
271 auto call = builder.
create<LLVM::CallOp>(loc, wrapperFunc, args);
273 if (resultStructType) {
275 builder.
create<LLVM::LoadOp>(loc, resultStructType, args.front());
276 builder.
create<LLVM::ReturnOp>(loc, result);
278 builder.
create<LLVM::ReturnOp>(loc, call.getResults());
288 if (funcOp.getBody().empty())
294 Block *entryBlock = &funcOp.getBody().
front();
296 assert(blockArgs.size() == oldArgTypes.size() &&
297 "The number of arguments and types doesn't match");
301 for (
auto it : llvm::zip(blockArgs, oldArgTypes)) {
303 Type argTy = std::get<1>(it);
308 assert(!isa<UnrankedMemRefType>(argTy) &&
309 "Unranked memref is not supported");
310 auto memrefTy = dyn_cast<MemRefType>(argTy);
321 auto placeholder = rewriter.
create<LLVM::UndefOp>(
340 convertFuncOpToLLVMFuncOp(func::FuncOp funcOp,
346 auto llvmType = getTypeConverter()->convertFunctionSignature(
347 funcOp.getFunctionType(), varargsAttr && varargsAttr.getValue(),
356 if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
357 assert(!resAttrDicts.empty() &&
"expected array to be non-empty");
358 auto newResAttrDicts =
359 (funcOp.getNumResults() == 1)
362 attributes.push_back(
363 rewriter.
getNamedAttr(funcOp.getResAttrsAttrName(), newResAttrDicts));
365 if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
367 cast<LLVM::LLVMFunctionType>(llvmType).getNumParams());
368 for (
unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
373 auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
374 convertedAttrs.reserve(attrsDict.size());
378 cast<TypeAttr>(attr.getValue()).getValue()));
380 if (attr.getName().getValue() ==
381 LLVM::LLVMDialect::getByValAttrName()) {
383 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
384 }
else if (attr.getName().getValue() ==
385 LLVM::LLVMDialect::getByRefAttrName()) {
387 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
388 }
else if (attr.getName().getValue() ==
389 LLVM::LLVMDialect::getStructRetAttrName()) {
391 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
392 }
else if (attr.getName().getValue() ==
393 LLVM::LLVMDialect::getInAllocaAttrName()) {
395 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
397 convertedAttrs.push_back(attr);
400 auto mapping = result.getInputMapping(i);
401 assert(mapping &&
"unexpected deletion of function argument");
405 if (mapping->size == 1) {
406 newArgAttrs[mapping->inputNo] =
412 for (
size_t j = 0;
j < mapping->size; ++
j)
413 newArgAttrs[mapping->inputNo +
j] =
417 funcOp.getArgAttrsAttrName(), rewriter.
getArrayAttr(newArgAttrs)));
422 LLVM::Linkage linkage = LLVM::Linkage::External;
428 <<
" attribute not of type LLVM::LinkageAttr";
430 funcOp,
"Contains linkage attribute not of type LLVM::LinkageAttr");
432 linkage = attr.getLinkage();
436 StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();
437 LLVM::MemoryEffectsAttr memoryAttr = {};
438 if (funcOp->hasAttr(readnoneAttrName)) {
439 auto attr = funcOp->getAttrOfType<UnitAttr>(readnoneAttrName);
441 funcOp->emitError() <<
"Contains " << readnoneAttrName
442 <<
" attribute not of type UnitAttr";
444 funcOp,
"Contains readnone attribute not of type UnitAttr");
447 {LLVM::ModRefInfo::NoModRef,
448 LLVM::ModRefInfo::NoModRef,
449 LLVM::ModRefInfo::NoModRef});
451 auto newFuncOp = rewriter.
create<LLVM::LLVMFuncOp>(
452 funcOp.getLoc(), funcOp.getName(), llvmType, linkage,
453 false, LLVM::CConv::C,
nullptr,
457 newFuncOp.setMemoryAttr(memoryAttr);
463 "region types conversion failed");
473 struct FuncOpConversion :
public FuncOpConversionBase {
475 : FuncOpConversionBase(converter) {}
478 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
481 convertFuncOpToLLVMFuncOp(funcOp, rewriter);
486 if (funcOp->getAttrOfType<UnitAttr>(
487 LLVM::LLVMDialect::getEmitCWrapperAttrName())) {
488 if (newFuncOp->isVarArg())
489 return funcOp->emitError(
"C interface for variadic functions is not "
492 if (newFuncOp->isExternal())
497 *getTypeConverter(), funcOp, *newFuncOp);
501 *getTypeConverter(), *newFuncOp,
502 funcOp.getFunctionType().getInputs());
514 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
521 rewriter.
create<LLVM::AddressOfOp>(op.
getLoc(), type, op.getValue());
523 if (attr.getName().strref() ==
"value")
525 newOp->
setAttr(attr.getName(), attr.getValue());
527 rewriter.
replaceOp(op, newOp->getResults());
534 template <
typename CallOpType>
537 using Super = CallOpInterfaceLowering<CallOpType>;
541 typename CallOpType::Adaptor adaptor,
543 bool useBarePtrCallConv =
false)
const {
545 Type packedResult =
nullptr;
546 unsigned numResults = callOp.getNumResults();
547 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
549 if (numResults != 0) {
550 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
551 resultTypes, useBarePtrCallConv)))
555 if (useBarePtrCallConv) {
556 for (
auto it : callOp->getOperands()) {
557 Type operandType = it.getType();
558 if (isa<UnrankedMemRefType>(operandType)) {
565 auto promoted = this->getTypeConverter()->promoteOperands(
566 callOp.getLoc(), callOp->getOperands(),
567 adaptor.getOperands(), rewriter, useBarePtrCallConv);
568 auto newOp = rewriter.
create<LLVM::CallOp>(
570 promoted, callOp->getAttrs());
573 if (numResults < 2) {
575 results.append(newOp.result_begin(), newOp.result_end());
579 results.reserve(numResults);
580 for (
unsigned i = 0; i < numResults; ++i) {
581 results.push_back(rewriter.
create<LLVM::ExtractValueOp>(
582 callOp.getLoc(), newOp->getResult(0), i));
586 if (useBarePtrCallConv) {
589 assert(results.size() == resultTypes.size() &&
590 "The number of arguments and types doesn't match");
591 this->getTypeConverter()->promoteBarePtrsToDescriptors(
592 rewriter, callOp.getLoc(), resultTypes, results);
593 }
else if (
failed(this->copyUnrankedDescriptors(rewriter, callOp.getLoc(),
594 resultTypes, results,
604 struct CallOpLowering :
public CallOpInterfaceLowering<func::CallOp> {
608 matchAndRewrite(func::CallOp callOp, OpAdaptor adaptor,
610 bool useBarePtrCallConv =
false;
612 callOp, callOp.getCalleeAttr())) {
615 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
619 struct CallIndirectOpLowering
620 :
public CallOpInterfaceLowering<func::CallIndirectOp> {
624 matchAndRewrite(func::CallIndirectOp callIndirectOp, OpAdaptor adaptor,
626 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
630 struct UnrealizedConversionCastOpLowering
636 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
639 if (
succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
641 convertedTypes == adaptor.getInputs().getTypes()) {
642 rewriter.
replaceOp(op, adaptor.getInputs());
646 convertedTypes.clear();
647 if (
succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
649 convertedTypes == op.getOutputs().getType()) {
650 rewriter.
replaceOp(op, adaptor.getInputs());
667 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
674 bool useBarePtrCallConv =
676 if (useBarePtrCallConv) {
679 for (
auto it : llvm::zip(op->
getOperands(), adaptor.getOperands())) {
680 Type oldTy = std::get<0>(it).getType();
681 Value newOperand = std::get<1>(it);
682 if (isa<MemRefType>(oldTy) && getTypeConverter()->canConvertToBarePtr(
683 cast<BaseMemRefType>(oldTy))) {
685 newOperand = memrefDesc.allocatedPtr(rewriter, loc);
686 }
else if (isa<UnrankedMemRefType>(oldTy)) {
691 updatedOperands.push_back(newOperand);
694 updatedOperands = llvm::to_vector<4>(adaptor.getOperands());
701 if (numArguments <= 1) {
709 auto packedType = getTypeConverter()->packFunctionResults(
715 Value packed = rewriter.
create<LLVM::UndefOp>(loc, packedType);
717 packed = rewriter.
create<LLVM::InsertValueOp>(loc, packed, operand, idx);
728 patterns.
add<FuncOpConversion>(converter);
736 CallIndirectOpLowering,
739 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);
774 options.useOpaquePointers = useOpaquePointers;
777 &dataLayoutAnalysis);
792 struct SetLLVMModuleDataLayoutPass
793 :
public impl::SetLLVMModuleDataLayoutPassBase<
794 SetLLVMModuleDataLayoutPass> {
798 void runOnOperation()
override {
799 if (
failed(LLVM::LLVMDialect::verifyDataLayoutString(
800 this->dataLayout, [
this](
const Twine &message) {
801 getOperation().emitError() << message.str();
806 ModuleOp m = getOperation();
807 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
823 void populateConvertToLLVMConversionPatterns(
833 dialect->addInterfaces<FuncToLLVMDialectInterface>();
static void modifyFuncOpToUseBarePtrCallingConv(ConversionPatternRewriter &rewriter, Location loc, const LLVMTypeConverter &typeConverter, LLVM::LLVMFuncOp funcOp, TypeRange oldArgTypes)
Modifies the body of the function to construct the MemRefDescriptor from the bare pointer calling con...
static void prependEmptyArgAttr(OpBuilder &builder, SmallVectorImpl< NamedAttribute > &newFuncAttrs, func::FuncOp func)
Adds a an empty set of argument attributes for the newly added argument in front of the existing ones...
static void wrapForExternalCallers(OpBuilder &rewriter, Location loc, const LLVMTypeConverter &typeConverter, func::FuncOp funcOp, LLVM::LLVMFuncOp newFuncOp)
Creates an auxiliary function with pointer-to-memref-descriptor-struct arguments instead of unpacked ...
static constexpr StringRef barePtrAttrName
static constexpr StringRef varargsAttrName
static constexpr StringRef linkageAttrName
static void filterFuncAttributes(func::FuncOp func, bool filterArgAndResAttrs, 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 wrapExternalFunction(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, func::FuncOp 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
This class represents an argument of a Block.
Block represents an ordered list of Operations.
BlockArgListType getArguments()
Special case of IntegerAttr to represent boolean integers, i.e., signless i1 integers.
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
PatternRewriter hook for replacing an operation.
FailureOr< Block * > convertRegionTypes(Region *region, const TypeConverter &converter, TypeConverter::SignatureConversion *entryConversion=nullptr)
Convert the types of block arguments within the given region.
LogicalResult notifyMatchFailure(Location loc, function_ref< void(Diagnostic &)> reasonCallback) override
PatternRewriter hook for notifying match failure reasons.
void inlineRegionBefore(Region ®ion, Region &parent, Region::iterator before) override
PatternRewriter hook for moving blocks out of a region.
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.
void addExtension(std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
This class provides support for representing a failure result, or a valid value of type T.
Derived class that automatically populates legalization information for different LLVM ops.
Conversion from types to the LLVM IR dialect.
const LowerToLLVMOptions & getOptions() const
LogicalResult convertType(Type t, SmallVectorImpl< Type > &results) const
Convert the given type.
LLVM::LLVMPointerType getPointerType(Type elementType, unsigned addressSpace=0) const
Creates an LLVM pointer type with the given element type and address space.
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...
static MemRefDescriptor fromStaticShape(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, MemRefType type, Value memory)
Builds IR creating a MemRef descriptor that represents type and populates it with static shape and st...
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.
type_range getTypes() const
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.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
unsigned getNumOperands()
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
operand_type_range getOperandTypes()
operand_range getOperands()
Returns an iterator on the underlying Value's.
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replaces the result op with a new op that is created without verification.
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
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.
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.
void populateArithToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns)
void populateControlFlowToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Collect the patterns to convert from the ControlFlow dialect to LLVM.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
This header declares functions that assist transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
static constexpr unsigned kDeriveIndexBitwidthFromDataLayout
Value to pass as bitwidth for the index type when the converter is expected to derive the bitwidth fr...
LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, DenseSet< Operation * > *unconvertedOps=nullptr)
Below we define several entry points for operation conversion.
void registerConvertFuncToLLVMInterface(DialectRegistry ®istry)
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
void populateFuncToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Collect the patterns to convert from the Func dialect to LLVM.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
void populateFuncToLLVMFuncOpConversionPattern(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Collect the default pattern to convert a FuncOp to the LLVM dialect.
This class represents an efficient way to signal success or failure.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.