36 #include "llvm/ADT/SmallVector.h"
37 #include "llvm/IR/Type.h"
38 #include "llvm/Support/FormatVariadic.h"
42 #define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS
43 #define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS
44 #include "mlir/Conversion/Passes.h.inc"
49 #define PASS_NAME "convert-func-to-llvm"
69 attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName())
71 result.push_back(attr);
77 FunctionOpInterface funcOp,
78 LLVM::LLVMFuncOp wrapperFuncOp) {
79 auto argAttrs = funcOp.getAllArgAttrs();
80 if (!resultStructType) {
81 if (
auto resAttrs = funcOp.getAllResultAttrs())
82 wrapperFuncOp.setAllResultAttrs(resAttrs);
84 wrapperFuncOp.setAllArgAttrs(argAttrs);
91 argAttributes.append(argAttrs.begin(), argAttrs.end());
92 wrapperFuncOp.setAllArgAttrs(argAttributes);
95 cast<FunctionOpInterface>(wrapperFuncOp.getOperation())
96 .setVisibility(funcOp.getVisibility());
109 FunctionOpInterface funcOp,
110 LLVM::LLVMFuncOp newFuncOp) {
111 auto type = cast<FunctionType>(funcOp.getFunctionType());
112 auto [wrapperFuncType, resultStructType] =
118 auto wrapperFuncOp = LLVM::LLVMFuncOp::create(
119 rewriter, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
120 wrapperFuncType, LLVM::Linkage::External,
false,
121 LLVM::CConv::C,
nullptr, attributes);
128 size_t argOffset = resultStructType ? 1 : 0;
130 Value arg = wrapperFuncOp.getArgument(index + argOffset);
131 if (
auto memrefType = dyn_cast<MemRefType>(argType)) {
132 Value loaded = LLVM::LoadOp::create(
133 rewriter, loc, typeConverter.
convertType(memrefType), arg);
137 if (isa<UnrankedMemRefType>(argType)) {
138 Value loaded = LLVM::LoadOp::create(
139 rewriter, loc, typeConverter.
convertType(argType), arg);
147 auto call = LLVM::CallOp::create(rewriter, loc, newFuncOp, args);
149 if (resultStructType) {
150 LLVM::StoreOp::create(rewriter, loc, call.getResult(),
151 wrapperFuncOp.getArgument(0));
152 LLVM::ReturnOp::create(rewriter, loc,
ValueRange{});
154 LLVM::ReturnOp::create(rewriter, loc, call.getResults());
169 FunctionOpInterface funcOp,
170 LLVM::LLVMFuncOp newFuncOp) {
173 auto [wrapperType, resultStructType] =
175 cast<FunctionType>(funcOp.getFunctionType()));
179 assert(wrapperType &&
"unexpected type conversion failure");
185 auto wrapperFunc = LLVM::LLVMFuncOp::create(
186 builder, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
187 wrapperType, LLVM::Linkage::External,
false,
188 LLVM::CConv::C,
nullptr, attributes);
192 newFuncOp.setLinkage(LLVM::Linkage::Private);
196 FunctionType type = cast<FunctionType>(funcOp.getFunctionType());
198 args.reserve(type.getNumInputs());
199 ValueRange wrapperArgsRange(newFuncOp.getArguments());
201 if (resultStructType) {
203 Type resultType = cast<LLVM::LLVMFunctionType>(wrapperType).getParamType(0);
204 Value one = LLVM::ConstantOp::create(
208 LLVM::AllocaOp::create(builder, loc, resultType, resultStructType, one);
209 args.push_back(result);
214 for (
Type input : type.getInputs()) {
217 auto memRefType = dyn_cast<MemRefType>(input);
218 auto unrankedMemRefType = dyn_cast<UnrankedMemRefType>(input);
219 if (memRefType || unrankedMemRefType) {
220 numToDrop = memRefType
226 wrapperArgsRange.take_front(numToDrop))
228 builder, loc, typeConverter, unrankedMemRefType,
229 wrapperArgsRange.take_front(numToDrop));
232 Value one = LLVM::ConstantOp::create(
235 Value allocated = LLVM::AllocaOp::create(
236 builder, loc, ptrTy, packed.
getType(), one, 0);
237 LLVM::StoreOp::create(builder, loc, packed, allocated);
240 arg = wrapperArgsRange[0];
244 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);
246 assert(wrapperArgsRange.empty() &&
"did not map some of the arguments");
248 auto call = LLVM::CallOp::create(builder, loc, wrapperFunc, args);
250 if (resultStructType) {
252 LLVM::LoadOp::create(builder, loc, resultStructType, args.front());
253 LLVM::ReturnOp::create(builder, loc, result);
255 LLVM::ReturnOp::create(builder, loc, call.getResults());
264 ArrayRef<std::optional<NamedAttribute>> byValRefNonPtrAttrs,
265 LLVM::LLVMFuncOp funcOp) {
267 if (funcOp.isExternal())
270 ConversionPatternRewriter::InsertionGuard guard(rewriter);
273 for (
const auto &[arg, byValRefAttr] :
274 llvm::zip(funcOp.getArguments(), byValRefNonPtrAttrs)) {
280 assert(isa<LLVM::LLVMPointerType>(arg.getType()) &&
281 "Expected LLVM pointer type for argument with "
282 "`llvm.byval`/`llvm.byref` attribute");
284 cast<TypeAttr>(byValRefAttr->getValue()).getValue());
286 Value valueArg = LLVM::LoadOp::create(rewriter, arg.getLoc(), resTy, arg);
295 auto funcTy = dyn_cast<FunctionType>(funcOp.getFunctionType());
298 funcOp,
"Only support FunctionOpInterface with FunctionType");
307 auto llvmType = dyn_cast_or_null<LLVM::LLVMFunctionType>(
309 funcOp, varargsAttr && varargsAttr.getValue(),
311 byValRefNonPtrAttrs));
317 if (funcOp->getAttrOfType<UnitAttr>(
318 LLVM::LLVMDialect::getEmitCWrapperAttrName()))
319 if (llvmType.isVarArg())
320 return funcOp.emitError(
"C interface for variadic functions is not "
325 LLVM::Linkage linkage = LLVM::Linkage::External;
331 <<
" attribute not of type LLVM::LinkageAttr";
333 funcOp,
"Contains linkage attribute not of type LLVM::LinkageAttr");
335 linkage = attr.getLinkage();
339 StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();
340 if (funcOp->hasAttr(readnoneAttrName)) {
341 auto attr = funcOp->getAttrOfType<UnitAttr>(readnoneAttrName);
343 funcOp->emitError() <<
"Contains " << readnoneAttrName
344 <<
" attribute not of type UnitAttr";
346 funcOp,
"Contains readnone attribute not of type UnitAttr");
355 if (symbolTables && symbolTableOp) {
357 symbolTable.
remove(funcOp);
360 auto newFuncOp = LLVM::LLVMFuncOp::create(
361 rewriter, funcOp.getLoc(), funcOp.getName(), llvmType, linkage,
362 false, LLVM::CConv::C,
nullptr,
365 if (symbolTables && symbolTableOp) {
368 symbolTable.
insert(newFuncOp, ip);
371 cast<FunctionOpInterface>(newFuncOp.getOperation())
372 .setVisibility(funcOp.getVisibility());
375 if (funcOp->hasAttr(readnoneAttrName)) {
378 {LLVM::ModRefInfo::NoModRef, LLVM::ModRefInfo::NoModRef,
379 LLVM::ModRefInfo::NoModRef});
380 newFuncOp.setMemoryEffectsAttr(memoryAttr);
385 if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
386 assert(!resAttrDicts.empty() &&
"expected array to be non-empty");
387 if (funcOp.getNumResults() == 1)
388 newFuncOp.setAllResultAttrs(resAttrDicts);
390 if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
392 cast<LLVM::LLVMFunctionType>(llvmType).getNumParams());
393 for (
unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
398 auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
399 convertedAttrs.reserve(attrsDict.size());
403 cast<TypeAttr>(attr.getValue()).getValue()));
405 if (attr.getName().getValue() ==
406 LLVM::LLVMDialect::getByValAttrName()) {
408 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
409 }
else if (attr.getName().getValue() ==
410 LLVM::LLVMDialect::getByRefAttrName()) {
412 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
413 }
else if (attr.getName().getValue() ==
414 LLVM::LLVMDialect::getStructRetAttrName()) {
416 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
417 }
else if (attr.getName().getValue() ==
418 LLVM::LLVMDialect::getInAllocaAttrName()) {
420 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
422 convertedAttrs.push_back(attr);
426 assert(mapping &&
"unexpected deletion of function argument");
430 if (mapping->size == 1) {
431 newArgAttrs[mapping->inputNo] =
437 for (
size_t j = 0;
j < mapping->size; ++
j)
438 newArgAttrs[mapping->inputNo +
j] =
441 if (!newArgAttrs.empty())
442 newFuncOp.setAllArgAttrs(rewriter.
getArrayAttr(newArgAttrs));
449 if (!newFuncOp.getBody().empty())
460 if (funcOp->getAttrOfType<UnitAttr>(
461 LLVM::LLVMDialect::getEmitCWrapperAttrName())) {
462 if (newFuncOp.isExternal())
488 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
491 cast<FunctionOpInterface>(funcOp.getOperation()), rewriter,
492 *getTypeConverter(), symbolTables);
493 if (failed(newFuncOp))
505 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
507 auto type = typeConverter->convertType(op.getResult().getType());
512 LLVM::AddressOfOp::create(rewriter, op.getLoc(), type, op.getValue());
514 if (attr.getName().strref() ==
"value")
516 newOp->setAttr(attr.getName(), attr.getValue());
518 rewriter.
replaceOp(op, newOp->getResults());
525 template <
typename CallOpType>
528 using Super = CallOpInterfaceLowering<CallOpType>;
531 LogicalResult matchAndRewriteImpl(CallOpType callOp,
532 typename CallOpType::Adaptor adaptor,
534 bool useBarePtrCallConv =
false)
const {
536 Type packedResult =
nullptr;
537 unsigned numResults = callOp.getNumResults();
538 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
540 if (numResults != 0) {
541 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
542 resultTypes, useBarePtrCallConv)))
546 if (useBarePtrCallConv) {
547 for (
auto it : callOp->getOperands()) {
548 Type operandType = it.getType();
549 if (isa<UnrankedMemRefType>(operandType)) {
556 auto promoted = this->getTypeConverter()->promoteOperands(
557 callOp.getLoc(), callOp->getOperands(),
558 adaptor.getOperands(), rewriter, useBarePtrCallConv);
559 auto newOp = LLVM::CallOp::create(rewriter, callOp.getLoc(),
562 promoted, callOp->getAttrs());
564 newOp.getProperties().operandSegmentSizes = {
565 static_cast<int32_t
>(promoted.size()), 0};
569 if (numResults < 2) {
571 results.append(newOp.result_begin(), newOp.result_end());
575 results.reserve(numResults);
576 for (
unsigned i = 0; i < numResults; ++i) {
577 results.push_back(LLVM::ExtractValueOp::create(
578 rewriter, callOp.getLoc(), newOp->getResult(0), i));
582 if (useBarePtrCallConv) {
585 assert(results.size() == resultTypes.size() &&
586 "The number of arguments and types doesn't match");
587 this->getTypeConverter()->promoteBarePtrsToDescriptors(
588 rewriter, callOp.getLoc(), resultTypes, results);
589 }
else if (failed(this->copyUnrankedDescriptors(rewriter, callOp.getLoc(),
590 resultTypes, results,
600 class CallOpLowering :
public CallOpInterfaceLowering<func::CallOp> {
605 : CallOpInterfaceLowering<func::CallOp>(typeConverter, benefit),
606 symbolTables(symbolTables) {}
609 matchAndRewrite(func::CallOp callOp, OpAdaptor adaptor,
611 bool useBarePtrCallConv =
false;
612 if (getTypeConverter()->getOptions().useBarePtrCallConv) {
613 useBarePtrCallConv =
true;
614 }
else if (symbolTables !=
nullptr) {
627 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
634 struct CallIndirectOpLowering
635 :
public CallOpInterfaceLowering<func::CallIndirectOp> {
639 matchAndRewrite(func::CallIndirectOp callIndirectOp, OpAdaptor adaptor,
641 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
645 struct UnrealizedConversionCastOpLowering
651 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
654 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
656 convertedTypes == adaptor.getInputs().getTypes()) {
657 rewriter.
replaceOp(op, adaptor.getInputs());
661 convertedTypes.clear();
662 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
664 convertedTypes == op.getOutputs().getType()) {
665 rewriter.
replaceOp(op, adaptor.getInputs());
682 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
685 unsigned numArguments = op.getNumOperands();
688 auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
689 bool useBarePtrCallConv =
691 if (useBarePtrCallConv) {
694 for (
auto it : llvm::zip(op->getOperands(), adaptor.getOperands())) {
695 Type oldTy = std::get<0>(it).getType();
696 Value newOperand = std::get<1>(it);
697 if (isa<MemRefType>(oldTy) && getTypeConverter()->canConvertToBarePtr(
698 cast<BaseMemRefType>(oldTy))) {
700 newOperand = memrefDesc.allocatedPtr(rewriter, loc);
701 }
else if (isa<UnrankedMemRefType>(oldTy)) {
706 updatedOperands.push_back(newOperand);
709 updatedOperands = llvm::to_vector<4>(adaptor.getOperands());
710 (void)copyUnrankedDescriptors(rewriter, loc, op.getOperands().getTypes(),
716 if (numArguments <= 1) {
718 op,
TypeRange(), updatedOperands, op->getAttrs());
724 auto packedType = getTypeConverter()->packFunctionResults(
725 op.getOperandTypes(), useBarePtrCallConv);
730 Value packed = LLVM::PoisonOp::create(rewriter, loc, packedType);
732 packed = LLVM::InsertValueOp::create(rewriter, loc, packed, operand, idx);
744 patterns.add<FuncOpConversion>(converter, symbolTables);
751 patterns.add<CallIndirectOpLowering>(converter);
752 patterns.add<CallOpLowering>(converter, symbolTables);
753 patterns.add<ConstantOpLowering>(converter);
754 patterns.add<ReturnOpLowering>(converter);
759 struct ConvertFuncToLLVMPass
760 :
public impl::ConvertFuncToLLVMPassBase<ConvertFuncToLLVMPass> {
764 void runOnOperation()
override {
765 ModuleOp m = getOperation();
766 StringRef dataLayout;
767 auto dataLayoutAttr = dyn_cast_or_null<StringAttr>(
768 m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
770 dataLayout = dataLayoutAttr.getValue();
772 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
773 dataLayout, [
this](
const Twine &message) {
774 getOperation().emitError() << message.str();
780 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
783 dataLayoutAnalysis.getAtOrAbove(m));
784 options.useBarePtrCallConv = useBarePtrCallConv;
786 options.overrideIndexBitwidth(indexBitwidth);
787 options.dataLayout = llvm::DataLayout(dataLayout);
790 &dataLayoutAnalysis);
804 struct SetLLVMModuleDataLayoutPass
805 :
public impl::SetLLVMModuleDataLayoutPassBase<
806 SetLLVMModuleDataLayoutPass> {
810 void runOnOperation()
override {
811 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
812 this->dataLayout, [
this](
const Twine &message) {
813 getOperation().emitError() << message.str();
818 ModuleOp m = getOperation();
819 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
835 void populateConvertToLLVMConversionPatterns(
845 dialect->addInterfaces<FuncToLLVMDialectInterface>();
static void propagateArgResAttrs(OpBuilder &builder, bool resultStructType, FunctionOpInterface funcOp, LLVM::LLVMFuncOp wrapperFuncOp)
Propagate argument/results attributes.
static void restoreByValRefArgumentType(ConversionPatternRewriter &rewriter, const LLVMTypeConverter &typeConverter, ArrayRef< std::optional< NamedAttribute >> byValRefNonPtrAttrs, LLVM::LLVMFuncOp funcOp)
Inserts llvm.load ops in the function body to restore the expected pointee value from llvm....
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 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, ValueRange to)
Replace all the uses of the block argument from with 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 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 unsigned getNumUnpackedValues(MemRefType type)
Returns the number of non-aggregate values that would be produced by unpack.
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...
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.
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.
A trait used to provide symbol table functionalities to a region operation.
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.
Operation * getParentWithTrait()
Returns the closest surrounding parent operation with trait Trait.
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 represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual SymbolTable & getSymbolTable(Operation *op)
Lookup, or create, a symbol table for an operation.
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,...
StringAttr insert(Operation *symbol, Block::iterator insertPt={})
Insert a new symbol into the table, and rename it as necessary to avoid collisions.
void remove(Operation *op)
Remove the given symbol from the table, without deleting it.
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 registerConvertFuncToLLVMInterface(DialectRegistry ®istry)
void populateFuncToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, SymbolTableCollection *symbolTables=nullptr)
Collect the patterns to convert from the Func dialect to LLVM.
void populateFuncToLLVMFuncOpConversionPattern(const LLVMTypeConverter &converter, RewritePatternSet &patterns, SymbolTableCollection *symbolTables=nullptr)
Collect the default pattern to convert a FuncOp to the LLVM dialect.
const FrozenRewritePatternSet & patterns
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
FailureOr< LLVM::LLVMFuncOp > convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter, SymbolTableCollection *symbolTables=nullptr)
Convert input FunctionOpInterface operation to LLVMFuncOp by using the provided LLVMTypeConverter.
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.