MLIR: lib/Conversion/FuncToLLVM/FuncToLLVM.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
15
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"
48 #include
49 #include
50 #include
51
52 namespace mlir {
53 #define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS
54 #define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS
55 #include "mlir/Conversion/Passes.h.inc"
56 }
57
58 using namespace mlir;
59
60 #define PASS_NAME "convert-func-to-llvm"
61
65
66
71 }
72
73
74
77 for (const NamedAttribute &attr : func->getDiscardableAttrs()) {
80 attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName())
81 continue;
82 result.push_back(attr);
83 }
84 }
85
86
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);
94 if (argAttrs)
95 wrapperFuncOp.setAllArgAttrs(argAttrs);
96 } else {
98
99
100 if (argAttrs) {
102 argAttributes.append(argAttrs.begin(), argAttrs.end());
103 wrapperFuncOp.setAllArgAttrs(argAttributes);
104 }
105 }
106 cast(wrapperFuncOp.getOperation())
107 .setVisibility(funcOp.getVisibility());
108 }
109
110
111
112
113
114
115
116
117
120 FunctionOpInterface funcOp,
121 LLVM::LLVMFuncOp newFuncOp) {
122 auto type = cast(funcOp.getFunctionType());
123 auto [wrapperFuncType, resultStructType] =
125
128
129 auto wrapperFuncOp = rewriter.createLLVM::LLVMFuncOp(
130 loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(),
131 wrapperFuncType, LLVM::Linkage::External, false,
132 LLVM::CConv::C, nullptr, attributes);
134
137
139 size_t argOffset = resultStructType ? 1 : 0;
140 for (auto [index, argType] : llvm::enumerate(type.getInputs())) {
141 Value arg = wrapperFuncOp.getArgument(index + argOffset);
142 if (auto memrefType = dyn_cast(argType)) {
143 Value loaded = rewriter.createLLVM::LoadOp(
144 loc, typeConverter.convertType(memrefType), arg);
146 continue;
147 }
148 if (isa(argType)) {
149 Value loaded = rewriter.createLLVM::LoadOp(
150 loc, typeConverter.convertType(argType), arg);
152 continue;
153 }
154
155 args.push_back(arg);
156 }
157
158 auto call = rewriter.createLLVM::CallOp(loc, newFuncOp, args);
159
160 if (resultStructType) {
161 rewriter.createLLVM::StoreOp(loc, call.getResult(),
162 wrapperFuncOp.getArgument(0));
164 } else {
165 rewriter.createLLVM::ReturnOp(loc, call.getResults());
166 }
167 }
168
169
170
171
172
173
174
175
176
177
180 FunctionOpInterface funcOp,
181 LLVM::LLVMFuncOp newFuncOp) {
183
184 auto [wrapperType, resultStructType] =
186 cast(funcOp.getFunctionType()));
187
188
189
190 assert(wrapperType && "unexpected type conversion failure");
191
194
195
196 auto wrapperFunc = builder.createLLVM::LLVMFuncOp(
197 loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(),
198 wrapperType, LLVM::Linkage::External, false,
199 LLVM::CConv::C, nullptr, attributes);
201
202
203 newFuncOp.setLinkage(LLVM::Linkage::Private);
205
206
207 FunctionType type = cast(funcOp.getFunctionType());
209 args.reserve(type.getNumInputs());
210 ValueRange wrapperArgsRange(newFuncOp.getArguments());
211
212 if (resultStructType) {
213
214 Type resultType = castLLVM::LLVMFunctionType(wrapperType).getParamType(0);
215 Value one = builder.createLLVM::ConstantOp(
219 builder.createLLVM::AllocaOp(loc, resultType, resultStructType, one);
220 args.push_back(result);
221 }
222
223
224
225 for (Type input : type.getInputs()) {
227 int numToDrop = 1;
228 auto memRefType = dyn_cast(input);
229 auto unrankedMemRefType = dyn_cast(input);
230 if (memRefType || unrankedMemRefType) {
231 numToDrop = memRefType
235 memRefType
237 wrapperArgsRange.take_front(numToDrop))
239 builder, loc, typeConverter, unrankedMemRefType,
240 wrapperArgsRange.take_front(numToDrop));
241
243 Value one = builder.createLLVM::ConstantOp(
246 Value allocated = builder.createLLVM::AllocaOp(
247 loc, ptrTy, packed.getType(), one, 0);
248 builder.createLLVM::StoreOp(loc, packed, allocated);
249 arg = allocated;
250 } else {
251 arg = wrapperArgsRange[0];
252 }
253
254 args.push_back(arg);
255 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);
256 }
257 assert(wrapperArgsRange.empty() && "did not map some of the arguments");
258
259 auto call = builder.createLLVM::CallOp(loc, wrapperFunc, args);
260
261 if (resultStructType) {
263 builder.createLLVM::LoadOp(loc, resultStructType, args.front());
264 builder.createLLVM::ReturnOp(loc, result);
265 } else {
266 builder.createLLVM::ReturnOp(loc, call.getResults());
267 }
268 }
269
270
271
272
275 ArrayRef<std::optional> byValRefNonPtrAttrs,
277
278 if (funcOp.isExternal())
279 return;
280
281 ConversionPatternRewriter::InsertionGuard guard(rewriter);
283
284 for (const auto &[arg, oldArg, byValRefAttr] :
285 llvm::zip(funcOp.getArguments(), oldBlockArgs, byValRefNonPtrAttrs)) {
286
287 if (!byValRefAttr)
288 continue;
289
290
291 assert(isaLLVM::LLVMPointerType(arg.getType()) &&
292 "Expected LLVM pointer type for argument with "
293 "`llvm.byval`/`llvm.byref` attribute");
295 cast(byValRefAttr->getValue()).getValue());
296
297 auto valueArg = rewriter.createLLVM::LoadOp(arg.getLoc(), resTy, arg);
299 }
300 }
301
302 FailureOrLLVM::LLVMFuncOp
306
307 auto funcTy = dyn_cast(funcOp.getFunctionType());
308 if (!funcTy)
310 funcOp, "Only support FunctionOpInterface with FunctionType");
311
312
314 llvm::to_vector(funcOp.getArguments());
315
316
317
319
320
323 auto llvmType = dyn_cast_or_nullLLVM::LLVMFunctionType(
325 funcOp, varargsAttr && varargsAttr.getValue(),
327 byValRefNonPtrAttrs));
328 if (!llvmType)
329 return rewriter.notifyMatchFailure(funcOp, "signature conversion failed");
330
331
333 if (funcOp->getAttrOfType(
334 LLVM::LLVMDialect::getEmitCWrapperAttrName()))
335 if (llvmType.isVarArg())
336 return funcOp.emitError("C interface for variadic functions is not "
337 "supported yet.");
338
339
340
341 LLVM::Linkage linkage = LLVM::Linkage::External;
343 auto attr =
344 dyn_castmlir::LLVM::LinkageAttr(funcOp->getAttr(linkageAttrName));
345 if (!attr) {
347 << " attribute not of type LLVM::LinkageAttr";
349 funcOp, "Contains linkage attribute not of type LLVM::LinkageAttr");
350 }
351 linkage = attr.getLinkage();
352 }
353
354
355 StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();
356 if (funcOp->hasAttr(readnoneAttrName)) {
357 auto attr = funcOp->getAttrOfType(readnoneAttrName);
358 if (!attr) {
359 funcOp->emitError() << "Contains " << readnoneAttrName
360 << " attribute not of type UnitAttr";
362 funcOp, "Contains readnone attribute not of type UnitAttr");
363 }
364 }
365
368 auto newFuncOp = rewriter.createLLVM::LLVMFuncOp(
369 funcOp.getLoc(), funcOp.getName(), llvmType, linkage,
370 false, LLVM::CConv::C, nullptr,
371 attributes);
372 cast(newFuncOp.getOperation())
373 .setVisibility(funcOp.getVisibility());
374
375
376 if (funcOp->hasAttr(readnoneAttrName)) {
379 {LLVM::ModRefInfo::NoModRef, LLVM::ModRefInfo::NoModRef,
380 LLVM::ModRefInfo::NoModRef});
381 newFuncOp.setMemoryEffectsAttr(memoryAttr);
382 }
383
384
385
386 if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
387 assert(!resAttrDicts.empty() && "expected array to be non-empty");
388 if (funcOp.getNumResults() == 1)
389 newFuncOp.setAllResultAttrs(resAttrDicts);
390 }
391 if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
393 castLLVM::LLVMFunctionType(llvmType).getNumParams());
394 for (unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
395
396
397
399 auto attrsDict = cast(argAttrDicts[i]);
400 convertedAttrs.reserve(attrsDict.size());
402 const auto convert = [&](const NamedAttribute &attr) {
404 cast(attr.getValue()).getValue()));
405 };
406 if (attr.getName().getValue() ==
407 LLVM::LLVMDialect::getByValAttrName()) {
408 convertedAttrs.push_back(rewriter.getNamedAttr(
409 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
410 } else if (attr.getName().getValue() ==
411 LLVM::LLVMDialect::getByRefAttrName()) {
412 convertedAttrs.push_back(rewriter.getNamedAttr(
413 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
414 } else if (attr.getName().getValue() ==
415 LLVM::LLVMDialect::getStructRetAttrName()) {
416 convertedAttrs.push_back(rewriter.getNamedAttr(
417 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
418 } else if (attr.getName().getValue() ==
419 LLVM::LLVMDialect::getInAllocaAttrName()) {
420 convertedAttrs.push_back(rewriter.getNamedAttr(
421 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
422 } else {
423 convertedAttrs.push_back(attr);
424 }
425 }
427 assert(mapping && "unexpected deletion of function argument");
428
429
430
431 if (mapping->size == 1) {
432 newArgAttrs[mapping->inputNo] =
434 continue;
435 }
436
437
438 for (size_t j = 0; j < mapping->size; ++j)
439 newArgAttrs[mapping->inputNo + j] =
441 }
442 if (!newArgAttrs.empty())
443 newFuncOp.setAllArgAttrs(rewriter.getArrayAttr(newArgAttrs));
444 }
445
446 rewriter.inlineRegionBefore(funcOp.getFunctionBody(), newFuncOp.getBody(),
447 newFuncOp.end());
448
449
450 if (!newFuncOp.getBody().empty())
452 &converter);
453
454
455
456
458 oldBlockArgs, newFuncOp);
459
461 if (funcOp->getAttrOfType(
462 LLVM::LLVMDialect::getEmitCWrapperAttrName())) {
463 if (newFuncOp.isExternal())
465 newFuncOp);
466 else
468 newFuncOp);
469 }
470 }
471
472 return newFuncOp;
473 }
474
475 namespace {
476
477
478
479
483
484 LogicalResult
485 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
488 cast(funcOp.getOperation()), rewriter,
489 *getTypeConverter());
490 if (failed(newFuncOp))
491 return rewriter.notifyMatchFailure(funcOp, "Could not convert funcop");
492
493 rewriter.eraseOp(funcOp);
494 return success();
495 }
496 };
497
500
501 LogicalResult
502 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
504 auto type = typeConverter->convertType(op.getResult().getType());
506 return rewriter.notifyMatchFailure(op, "failed to convert result type");
507
508 auto newOp =
509 rewriter.createLLVM::AddressOfOp(op.getLoc(), type, op.getValue());
511 if (attr.getName().strref() == "value")
512 continue;
513 newOp->setAttr(attr.getName(), attr.getValue());
514 }
515 rewriter.replaceOp(op, newOp->getResults());
516 return success();
517 }
518 };
519
520
521
522 template
525 using Super = CallOpInterfaceLowering;
527
528 LogicalResult matchAndRewriteImpl(CallOpType callOp,
529 typename CallOpType::Adaptor adaptor,
531 bool useBarePtrCallConv = false) const {
532
533 Type packedResult = nullptr;
534 unsigned numResults = callOp.getNumResults();
535 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
536
537 if (numResults != 0) {
538 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
539 resultTypes, useBarePtrCallConv)))
540 return failure();
541 }
542
543 if (useBarePtrCallConv) {
544 for (auto it : callOp->getOperands()) {
545 Type operandType = it.getType();
546 if (isa(operandType)) {
547
548
549 return failure();
550 }
551 }
552 }
553 auto promoted = this->getTypeConverter()->promoteOperands(
554 callOp.getLoc(), callOp->getOperands(),
555 adaptor.getOperands(), rewriter, useBarePtrCallConv);
556 auto newOp = rewriter.createLLVM::CallOp(
557 callOp.getLoc(), packedResult ? TypeRange(packedResult) : TypeRange(),
558 promoted, callOp->getAttrs());
559
560 newOp.getProperties().operandSegmentSizes = {
561 static_cast<int32_t>(promoted.size()), 0};
563
565 if (numResults < 2) {
566
567 results.append(newOp.result_begin(), newOp.result_end());
568 } else {
569
570
571 results.reserve(numResults);
572 for (unsigned i = 0; i < numResults; ++i) {
573 results.push_back(rewriter.createLLVM::ExtractValueOp(
574 callOp.getLoc(), newOp->getResult(0), i));
575 }
576 }
577
578 if (useBarePtrCallConv) {
579
580
581 assert(results.size() == resultTypes.size() &&
582 "The number of arguments and types doesn't match");
583 this->getTypeConverter()->promoteBarePtrsToDescriptors(
584 rewriter, callOp.getLoc(), resultTypes, results);
585 } else if (failed(this->copyUnrankedDescriptors(rewriter, callOp.getLoc(),
586 resultTypes, results,
587 false))) {
588 return failure();
589 }
590
591 rewriter.replaceOp(callOp, results);
592 return success();
593 }
594 };
595
596 class CallOpLowering : public CallOpInterfaceLoweringfunc::CallOp {
597 public:
599
601 : CallOpInterfaceLoweringfunc::CallOp(typeConverter, benefit),
602 symbolTable(symbolTable) {}
603
604 LogicalResult
605 matchAndRewrite(func::CallOp callOp, OpAdaptor adaptor,
607 bool useBarePtrCallConv = false;
608 if (getTypeConverter()->getOptions().useBarePtrCallConv) {
609 useBarePtrCallConv = true;
610 } else if (symbolTable != nullptr) {
611
613 symbolTable->lookup(callOp.getCalleeAttr().getValue());
614 useBarePtrCallConv =
616 } else {
617
620 useBarePtrCallConv =
622 }
623 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
624 }
625
626 private:
627 const SymbolTable *symbolTable = nullptr;
628 };
629
630 struct CallIndirectOpLowering
631 : public CallOpInterfaceLoweringfunc::CallIndirectOp {
632 using Super::Super;
633
634 LogicalResult
635 matchAndRewrite(func::CallIndirectOp callIndirectOp, OpAdaptor adaptor,
637 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
638 }
639 };
640
641 struct UnrealizedConversionCastOpLowering
645
646 LogicalResult
647 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
650 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
651 convertedTypes)) &&
652 convertedTypes == adaptor.getInputs().getTypes()) {
653 rewriter.replaceOp(op, adaptor.getInputs());
654 return success();
655 }
656
657 convertedTypes.clear();
658 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
659 convertedTypes)) &&
660 convertedTypes == op.getOutputs().getType()) {
661 rewriter.replaceOp(op, adaptor.getInputs());
662 return success();
663 }
664 return failure();
665 }
666 };
667
668
669
670
671
672
673
676
677 LogicalResult
678 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
681 unsigned numArguments = op.getNumOperands();
683
684 auto funcOp = op->getParentOfTypeLLVM::LLVMFuncOp();
685 bool useBarePtrCallConv =
687 if (useBarePtrCallConv) {
688
689
690 for (auto it : llvm::zip(op->getOperands(), adaptor.getOperands())) {
691 Type oldTy = std::get<0>(it).getType();
692 Value newOperand = std::get<1>(it);
693 if (isa(oldTy) && getTypeConverter()->canConvertToBarePtr(
694 cast(oldTy))) {
696 newOperand = memrefDesc.allocatedPtr(rewriter, loc);
697 } else if (isa(oldTy)) {
698
699
700 return failure();
701 }
702 updatedOperands.push_back(newOperand);
703 }
704 } else {
705 updatedOperands = llvm::to_vector<4>(adaptor.getOperands());
706 (void)copyUnrankedDescriptors(rewriter, loc, op.getOperands().getTypes(),
707 updatedOperands,
708 true);
709 }
710
711
712 if (numArguments <= 1) {
714 op, TypeRange(), updatedOperands, op->getAttrs());
715 return success();
716 }
717
718
719
720 auto packedType = getTypeConverter()->packFunctionResults(
721 op.getOperandTypes(), useBarePtrCallConv);
722 if (!packedType) {
723 return rewriter.notifyMatchFailure(op, "could not convert result types");
724 }
725
726 Value packed = rewriter.createLLVM::PoisonOp(loc, packedType);
727 for (auto [idx, operand] : llvm::enumerate(updatedOperands)) {
728 packed = rewriter.createLLVM::InsertValueOp(loc, packed, operand, idx);
729 }
731 op->getAttrs());
732 return success();
733 }
734 };
735 }
736
739 patterns.add(converter);
740 }
741
746 patterns.add(converter);
747 patterns.add(converter, symbolTable);
748 patterns.add(converter);
749 patterns.add(converter);
750 }
751
752 namespace {
753
754 struct ConvertFuncToLLVMPass
755 : public impl::ConvertFuncToLLVMPassBase {
756 using Base::Base;
757
758
759 void runOnOperation() override {
760 ModuleOp m = getOperation();
761 StringRef dataLayout;
762 auto dataLayoutAttr = dyn_cast_or_null(
763 m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
764 if (dataLayoutAttr)
765 dataLayout = dataLayoutAttr.getValue();
766
767 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
768 dataLayout, [this](const Twine &message) {
769 getOperation().emitError() << message.str();
770 }))) {
771 signalPassFailure();
772 return;
773 }
774
775 const auto &dataLayoutAnalysis = getAnalysis();
776
778 dataLayoutAnalysis.getAtOrAbove(m));
779 options.useBarePtrCallConv = useBarePtrCallConv;
781 options.overrideIndexBitwidth(indexBitwidth);
782 options.dataLayout = llvm::DataLayout(dataLayout);
783
785 &dataLayoutAnalysis);
786
787 std::optional optSymbolTable = std::nullopt;
788 const SymbolTable *symbolTable = nullptr;
789 if (.useBarePtrCallConv) {
790 optSymbolTable.emplace(m);
791 symbolTable = &optSymbolTable.value();
792 }
793
796
799 signalPassFailure();
800 }
801 };
802
803 struct SetLLVMModuleDataLayoutPass
804 : public impl::SetLLVMModuleDataLayoutPassBase<
805 SetLLVMModuleDataLayoutPass> {
806 using Base::Base;
807
808
809 void runOnOperation() override {
810 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
811 this->dataLayout, [this](const Twine &message) {
812 getOperation().emitError() << message.str();
813 }))) {
814 signalPassFailure();
815 return;
816 }
817 ModuleOp m = getOperation();
818 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
820 }
821 };
822 }
823
824
825
826
827
828 namespace {
829
832
833
834 void populateConvertToLLVMConversionPatterns(
838 }
839 };
840 }
841
844 dialect->addInterfaces();
845 });
846 }
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 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.
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.