27#include "llvm/Support/DebugLog.h"
28#include "llvm/Support/MathExtras.h"
32#define DEBUG_TYPE "memref-to-llvm"
35#define GEN_PASS_DEF_FINALIZEMEMREFTOLLVMCONVERSIONPASS
36#include "mlir/Conversion/Passes.h.inc"
47 auto [strides, offset] = type.getStridesAndOffset();
48 LLVM::GEPNoWrapFlags flags = LLVM::GEPNoWrapFlags::inbounds;
49 if (llvm::all_of(strides, [](
int64_t s) {
50 return !ShapedType::isDynamic(s) && s >= 0;
52 flags = flags | LLVM::GEPNoWrapFlags::nuw;
58static bool isStaticStrideOrOffset(
int64_t strideOrOffset) {
59 return ShapedType::isStatic(strideOrOffset);
62static FailureOr<LLVM::LLVMFuncOp>
73static FailureOr<LLVM::LLVMFuncOp>
85static FailureOr<LLVM::LLVMFuncOp>
101static Value createAligned(ConversionPatternRewriter &rewriter,
Location loc,
103 Value one = LLVM::ConstantOp::create(rewriter, loc, alignment.
getType(),
104 rewriter.getIndexAttr(1));
105 Value bump = LLVM::SubOp::create(rewriter, loc, alignment, one);
106 Value bumped = LLVM::AddOp::create(rewriter, loc, input, bump);
107 Value mod = LLVM::URemOp::create(rewriter, loc, bumped, alignment);
108 return LLVM::SubOp::create(rewriter, loc, bumped, mod);
120 Type elementType = memRefType.getElementType();
121 if (
auto memRefElementType = dyn_cast<MemRefType>(elementType))
123 if (
auto memRefElementType = dyn_cast<UnrankedMemRefType>(elementType))
129static Value castAllocFuncResult(ConversionPatternRewriter &rewriter,
131 MemRefType memRefType,
Type elementPtrType,
133 auto allocatedPtrTy = cast<LLVM::LLVMPointerType>(allocatedPtr.
getType());
134 FailureOr<unsigned> maybeMemrefAddrSpace =
136 assert(succeeded(maybeMemrefAddrSpace) &&
"unsupported address space");
137 unsigned memrefAddrSpace = *maybeMemrefAddrSpace;
138 if (allocatedPtrTy.getAddressSpace() != memrefAddrSpace)
139 allocatedPtr = LLVM::AddrSpaceCastOp::create(
141 LLVM::LLVMPointerType::get(rewriter.getContext(), memrefAddrSpace),
147 SymbolTableCollection *symbolTables =
nullptr;
150 explicit AllocOpLowering(
const LLVMTypeConverter &typeConverter,
151 SymbolTableCollection *symbolTables =
nullptr,
152 PatternBenefit benefit = 1)
153 : ConvertOpToLLVMPattern<memref::AllocOp>(typeConverter, benefit),
154 symbolTables(symbolTables) {}
157 matchAndRewrite(memref::AllocOp op, OpAdaptor adaptor,
158 ConversionPatternRewriter &rewriter)
const override {
159 auto loc = op.getLoc();
160 MemRefType memRefType = op.getType();
161 if (!isConvertibleAndHasIdentityMaps(memRefType))
162 return rewriter.notifyMatchFailure(op,
"incompatible memref type");
165 FailureOr<LLVM::LLVMFuncOp> allocFuncOp =
166 getNotalignedAllocFn(rewriter, getTypeConverter(),
167 op->getParentWithTrait<OpTrait::SymbolTable>(),
168 getIndexType(), symbolTables);
175 SmallVector<Value, 4> sizes;
176 SmallVector<Value, 4> strides;
179 this->getMemRefDescriptorSizes(loc, memRefType, adaptor.getOperands(),
180 rewriter, sizes, strides, sizeBytes,
true);
182 Value alignment = getAlignment(rewriter, loc, op);
185 sizeBytes = LLVM::AddOp::create(rewriter, loc, sizeBytes, alignment);
189 Type elementPtrType = this->getElementPtrType(memRefType);
190 assert(elementPtrType &&
"could not compute element ptr type");
192 LLVM::CallOp::create(rewriter, loc, allocFuncOp.value(), sizeBytes);
195 castAllocFuncResult(rewriter, loc, results.getResult(), memRefType,
196 elementPtrType, *getTypeConverter());
197 Value alignedPtr = allocatedPtr;
201 LLVM::PtrToIntOp::create(rewriter, loc, getIndexType(), allocatedPtr);
203 createAligned(rewriter, loc, allocatedInt, alignment);
205 LLVM::IntToPtrOp::create(rewriter, loc, elementPtrType, alignmentInt);
209 auto memRefDescriptor = this->createMemRefDescriptor(
210 loc, memRefType, allocatedPtr, alignedPtr, sizes, strides, rewriter);
213 rewriter.replaceOp(op, {memRefDescriptor});
218 template <
typename OpType>
219 Value getAlignment(ConversionPatternRewriter &rewriter, Location loc,
221 MemRefType memRefType = op.getType();
223 if (
auto alignmentAttr = op.getAlignment()) {
224 Type indexType = getIndexType();
227 }
else if (!memRefType.getElementType().isSignlessIntOrIndexOrFloat()) {
232 alignment =
getSizeInBytes(loc, memRefType.getElementType(), rewriter);
239 SymbolTableCollection *symbolTables =
nullptr;
242 explicit AlignedAllocOpLowering(
const LLVMTypeConverter &typeConverter,
243 SymbolTableCollection *symbolTables =
nullptr,
244 PatternBenefit benefit = 1)
245 : ConvertOpToLLVMPattern<memref::AllocOp>(typeConverter, benefit),
246 symbolTables(symbolTables) {}
249 matchAndRewrite(memref::AllocOp op, OpAdaptor adaptor,
250 ConversionPatternRewriter &rewriter)
const override {
251 auto loc = op.getLoc();
252 MemRefType memRefType = op.getType();
253 if (!isConvertibleAndHasIdentityMaps(memRefType))
254 return rewriter.notifyMatchFailure(op,
"incompatible memref type");
257 FailureOr<LLVM::LLVMFuncOp> allocFuncOp =
258 getAlignedAllocFn(rewriter, getTypeConverter(),
259 op->getParentWithTrait<OpTrait::SymbolTable>(),
260 getIndexType(), symbolTables);
267 SmallVector<Value, 4> sizes;
268 SmallVector<Value, 4> strides;
271 this->getMemRefDescriptorSizes(loc, memRefType, adaptor.getOperands(),
272 rewriter, sizes, strides, sizeBytes, !
false);
274 int64_t alignment = alignedAllocationGetAlignment(op, &defaultLayout);
276 Value allocAlignment =
281 if (!isMemRefSizeMultipleOf(memRefType, alignment, op, &defaultLayout))
282 sizeBytes = createAligned(rewriter, loc, sizeBytes, allocAlignment);
284 Type elementPtrType = this->getElementPtrType(memRefType);
286 LLVM::CallOp::create(rewriter, loc, allocFuncOp.value(),
290 castAllocFuncResult(rewriter, loc, results.getResult(), memRefType,
291 elementPtrType, *getTypeConverter());
294 auto memRefDescriptor = this->createMemRefDescriptor(
295 loc, memRefType, ptr, ptr, sizes, strides, rewriter);
298 rewriter.replaceOp(op, {memRefDescriptor});
303 static constexpr uint64_t kMinAlignedAllocAlignment = 16UL;
310 int64_t alignedAllocationGetAlignment(memref::AllocOp op,
311 const DataLayout *defaultLayout)
const {
312 if (std::optional<uint64_t> alignment = op.getAlignment())
318 unsigned eltSizeBytes = getMemRefEltSizeInBytes(
319 getTypeConverter(), op.getType(), op, defaultLayout);
320 return std::max(kMinAlignedAllocAlignment,
321 llvm::PowerOf2Ceil(eltSizeBytes));
326 bool isMemRefSizeMultipleOf(MemRefType type, uint64_t factor, Operation *op,
327 const DataLayout *defaultLayout)
const {
328 uint64_t sizeDivisor =
329 getMemRefEltSizeInBytes(getTypeConverter(), type, op, defaultLayout);
330 for (
unsigned i = 0, e = type.getRank(); i < e; i++) {
331 if (type.isDynamicDim(i))
333 sizeDivisor = sizeDivisor * type.getDimSize(i);
335 return sizeDivisor % factor == 0;
340 DataLayout defaultLayout;
344 using ConvertOpToLLVMPattern<memref::AllocaOp>::ConvertOpToLLVMPattern;
350 matchAndRewrite(memref::AllocaOp op, OpAdaptor adaptor,
351 ConversionPatternRewriter &rewriter)
const override {
352 auto loc = op.getLoc();
353 MemRefType memRefType = op.getType();
354 if (!isConvertibleAndHasIdentityMaps(memRefType))
355 return rewriter.notifyMatchFailure(op,
"incompatible memref type");
360 SmallVector<Value, 4> sizes;
361 SmallVector<Value, 4> strides;
364 this->getMemRefDescriptorSizes(loc, memRefType, adaptor.getOperands(),
365 rewriter, sizes, strides, size, !
true);
370 typeConverter->convertType(op.getType().getElementType());
371 FailureOr<unsigned> maybeAddressSpace =
373 assert(succeeded(maybeAddressSpace) &&
"unsupported address space");
374 unsigned addrSpace = *maybeAddressSpace;
375 auto elementPtrType =
376 LLVM::LLVMPointerType::get(rewriter.getContext(), addrSpace);
378 auto allocatedElementPtr =
379 LLVM::AllocaOp::create(rewriter, loc, elementPtrType, elementType, size,
380 op.getAlignment().value_or(0));
383 auto memRefDescriptor = this->createMemRefDescriptor(
384 loc, memRefType, allocatedElementPtr, allocatedElementPtr, sizes,
388 rewriter.replaceOp(op, {memRefDescriptor});
393struct AllocaScopeOpLowering
395 using ConvertOpToLLVMPattern<memref::AllocaScopeOp>::ConvertOpToLLVMPattern;
398 matchAndRewrite(memref::AllocaScopeOp allocaScopeOp, OpAdaptor adaptor,
399 ConversionPatternRewriter &rewriter)
const override {
400 OpBuilder::InsertionGuard guard(rewriter);
401 Location loc = allocaScopeOp.getLoc();
405 auto *currentBlock = rewriter.getInsertionBlock();
406 auto *remainingOpsBlock =
407 rewriter.splitBlock(currentBlock, rewriter.getInsertionPoint());
408 Block *continueBlock;
409 if (allocaScopeOp.getNumResults() == 0) {
410 continueBlock = remainingOpsBlock;
412 continueBlock = rewriter.createBlock(
413 remainingOpsBlock, allocaScopeOp.getResultTypes(),
414 SmallVector<Location>(allocaScopeOp->getNumResults(),
415 allocaScopeOp.getLoc()));
416 LLVM::BrOp::create(rewriter, loc,
ValueRange(), remainingOpsBlock);
420 Block *beforeBody = &allocaScopeOp.getBodyRegion().front();
421 Block *afterBody = &allocaScopeOp.getBodyRegion().back();
422 rewriter.inlineRegionBefore(allocaScopeOp.getBodyRegion(), continueBlock);
425 rewriter.setInsertionPointToEnd(currentBlock);
426 auto stackSaveOp = LLVM::StackSaveOp::create(rewriter, loc, getPtrType());
427 LLVM::BrOp::create(rewriter, loc,
ValueRange(), beforeBody);
431 rewriter.setInsertionPointToEnd(afterBody);
433 cast<memref::AllocaScopeReturnOp>(afterBody->
getTerminator());
434 auto branchOp = rewriter.replaceOpWithNewOp<LLVM::BrOp>(
435 returnOp, returnOp.getResults(), continueBlock);
438 rewriter.setInsertionPoint(branchOp);
439 LLVM::StackRestoreOp::create(rewriter, loc, stackSaveOp);
442 rewriter.replaceOp(allocaScopeOp, continueBlock->
getArguments());
448struct AssumeAlignmentOpLowering
450 using ConvertOpToLLVMPattern<
451 memref::AssumeAlignmentOp>::ConvertOpToLLVMPattern;
452 explicit AssumeAlignmentOpLowering(
const LLVMTypeConverter &converter)
453 : ConvertOpToLLVMPattern<memref::AssumeAlignmentOp>(converter) {}
456 matchAndRewrite(memref::AssumeAlignmentOp op, OpAdaptor adaptor,
457 ConversionPatternRewriter &rewriter)
const override {
458 Value memref = adaptor.getMemref();
459 unsigned alignment = op.getAlignment();
460 auto loc = op.getLoc();
462 auto srcMemRefType = cast<MemRefType>(op.getMemref().getType());
470 LLVM::ConstantOp::create(rewriter, loc, rewriter.getBoolAttr(
true));
471 Value alignmentConst =
473 LLVM::AssumeOp::create(rewriter, loc, trueCond, LLVM::AssumeAlignTag(), ptr,
475 rewriter.replaceOp(op, memref);
480struct DistinctObjectsOpLowering
482 using ConvertOpToLLVMPattern<
483 memref::DistinctObjectsOp>::ConvertOpToLLVMPattern;
484 explicit DistinctObjectsOpLowering(
const LLVMTypeConverter &converter)
485 : ConvertOpToLLVMPattern<memref::DistinctObjectsOp>(converter) {}
488 matchAndRewrite(memref::DistinctObjectsOp op, OpAdaptor adaptor,
489 ConversionPatternRewriter &rewriter)
const override {
491 if (operands.size() <= 1) {
493 rewriter.replaceOp(op, operands);
497 Location loc = op.getLoc();
498 SmallVector<Value> ptrs;
499 for (
auto [origOperand, newOperand] :
500 llvm::zip_equal(op.getOperands(), operands)) {
501 auto memrefType = cast<MemRefType>(origOperand.getType());
502 MemRefDescriptor memRefDescriptor(newOperand);
503 Value ptr = memRefDescriptor.bufferPtr(rewriter, loc, *getTypeConverter(),
509 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI1Type(), 1);
511 for (
auto i : llvm::seq<size_t>(ptrs.size() - 1)) {
512 for (
auto j : llvm::seq<size_t>(i + 1, ptrs.size())) {
513 Value ptr1 = ptrs[i];
514 Value ptr2 = ptrs[j];
515 LLVM::AssumeOp::create(rewriter, loc, cond,
516 LLVM::AssumeSeparateStorageTag{}, ptr1, ptr2);
520 rewriter.replaceOp(op, operands);
529 SymbolTableCollection *symbolTables =
nullptr;
532 explicit DeallocOpLowering(
const LLVMTypeConverter &typeConverter,
533 SymbolTableCollection *symbolTables =
nullptr,
534 PatternBenefit benefit = 1)
535 : ConvertOpToLLVMPattern<memref::DeallocOp>(typeConverter, benefit),
536 symbolTables(symbolTables) {}
539 matchAndRewrite(memref::DeallocOp op, OpAdaptor adaptor,
540 ConversionPatternRewriter &rewriter)
const override {
542 FailureOr<LLVM::LLVMFuncOp> freeFunc =
543 getFreeFn(rewriter, getTypeConverter(),
544 op->getParentWithTrait<OpTrait::SymbolTable>(), symbolTables);
548 if (
auto unrankedTy =
549 llvm::dyn_cast<UnrankedMemRefType>(op.getMemref().getType())) {
550 auto elementPtrTy = LLVM::LLVMPointerType::get(
551 rewriter.getContext(), unrankedTy.getMemorySpaceAsInt());
553 rewriter, op.getLoc(),
554 UnrankedMemRefDescriptor(adaptor.getMemref())
555 .memRefDescPtr(rewriter, op.getLoc()),
558 allocatedPtr = MemRefDescriptor(adaptor.getMemref())
559 .allocatedPtr(rewriter, op.getLoc());
561 rewriter.replaceOpWithNewOp<LLVM::CallOp>(op, freeFunc.value(),
570 using ConvertOpToLLVMPattern<memref::DimOp>::ConvertOpToLLVMPattern;
573 matchAndRewrite(memref::DimOp dimOp, OpAdaptor adaptor,
574 ConversionPatternRewriter &rewriter)
const override {
575 Type operandType = dimOp.getSource().getType();
576 if (isa<UnrankedMemRefType>(operandType)) {
577 FailureOr<Value> extractedSize = extractSizeOfUnrankedMemRef(
578 operandType, dimOp, adaptor.getOperands(), rewriter);
579 if (
failed(extractedSize))
581 rewriter.replaceOp(dimOp, {*extractedSize});
584 if (isa<MemRefType>(operandType)) {
586 dimOp, {extractSizeOfRankedMemRef(operandType, dimOp,
587 adaptor.getOperands(), rewriter)});
590 llvm_unreachable(
"expected MemRefType or UnrankedMemRefType");
595 extractSizeOfUnrankedMemRef(Type operandType, memref::DimOp dimOp,
597 ConversionPatternRewriter &rewriter)
const {
598 Location loc = dimOp.getLoc();
600 auto unrankedMemRefType = cast<UnrankedMemRefType>(operandType);
601 auto scalarMemRefType =
602 MemRefType::get({}, unrankedMemRefType.getElementType());
603 FailureOr<unsigned> maybeAddressSpace =
604 getTypeConverter()->getMemRefAddressSpace(unrankedMemRefType);
605 if (
failed(maybeAddressSpace)) {
606 dimOp.emitOpError(
"memref memory space must be convertible to an integer "
610 unsigned addressSpace = *maybeAddressSpace;
615 UnrankedMemRefDescriptor unrankedDesc(adaptor.getSource());
616 Value underlyingRankedDesc = unrankedDesc.memRefDescPtr(rewriter, loc);
618 Type elementType = typeConverter->convertType(scalarMemRefType);
622 LLVM::LLVMPointerType::get(rewriter.getContext(), addressSpace);
624 LLVM::GEPOp::create(rewriter, loc, indexPtrTy, elementType,
625 underlyingRankedDesc, ArrayRef<LLVM::GEPArg>{0, 2});
629 Value idxPlusOne = LLVM::AddOp::create(
633 Value sizePtr = LLVM::GEPOp::create(rewriter, loc, indexPtrTy,
634 getTypeConverter()->getIndexType(),
635 offsetPtr, idxPlusOne);
636 return LLVM::LoadOp::create(rewriter, loc,
637 getTypeConverter()->getIndexType(), sizePtr)
641 std::optional<int64_t> getConstantDimIndex(memref::DimOp dimOp)
const {
642 if (
auto idx = dimOp.getConstantIndex())
645 if (
auto constantOp = dimOp.getIndex().getDefiningOp<LLVM::ConstantOp>())
646 return cast<IntegerAttr>(constantOp.getValue()).getValue().getSExtValue();
651 Value extractSizeOfRankedMemRef(Type operandType, memref::DimOp dimOp,
653 ConversionPatternRewriter &rewriter)
const {
654 Location loc = dimOp.getLoc();
657 MemRefType memRefType = cast<MemRefType>(operandType);
658 Type indexType = getIndexType();
659 if (std::optional<int64_t> index = getConstantDimIndex(dimOp)) {
661 if (i >= 0 && i < memRefType.getRank()) {
662 if (memRefType.isDynamicDim(i)) {
664 MemRefDescriptor descriptor(adaptor.getSource());
665 return descriptor.size(rewriter, loc, i);
668 int64_t dimSize = memRefType.getDimSize(i);
672 Value index = adaptor.getIndex();
673 int64_t rank = memRefType.getRank();
674 MemRefDescriptor memrefDescriptor(adaptor.getSource());
675 return memrefDescriptor.size(rewriter, loc, index, rank);
682template <
typename Derived>
684 using ConvertOpToLLVMPattern<Derived>::ConvertOpToLLVMPattern;
685 using ConvertOpToLLVMPattern<Derived>::isConvertibleAndHasIdentityMaps;
686 using Base = LoadStoreOpLowering<Derived>;
716struct GenericAtomicRMWOpLowering
717 :
public LoadStoreOpLowering<memref::GenericAtomicRMWOp> {
721 matchAndRewrite(memref::GenericAtomicRMWOp atomicOp, OpAdaptor adaptor,
722 ConversionPatternRewriter &rewriter)
const override {
723 auto loc = atomicOp.getLoc();
724 Type valueType = typeConverter->convertType(atomicOp.getResult().getType());
729 bool needsBitcast = isa<FloatType>(valueType);
730 Type cmpxchgType = valueType;
732 unsigned bitWidth = cast<FloatType>(valueType).getWidth();
733 cmpxchgType = rewriter.getIntegerType(bitWidth);
737 auto *initBlock = rewriter.getInsertionBlock();
738 auto *loopBlock = rewriter.splitBlock(initBlock,
Block::iterator(atomicOp));
739 loopBlock->addArgument(cmpxchgType, loc);
745 rewriter.setInsertionPointToEnd(initBlock);
746 auto memRefType = cast<MemRefType>(atomicOp.getMemref().getType());
748 rewriter, loc, memRefType, adaptor.getMemref(), adaptor.getIndices());
749 Value init = LLVM::LoadOp::create(
750 rewriter, loc, typeConverter->convertType(memRefType.getElementType()),
753 init = LLVM::BitcastOp::create(rewriter, loc, cmpxchgType, init);
754 LLVM::BrOp::create(rewriter, loc, init, loopBlock);
757 rewriter.setInsertionPointToStart(loopBlock);
760 Value loopArgument = loopBlock->getArgument(0);
761 Value loopArgForBody = loopArgument;
764 LLVM::BitcastOp::create(rewriter, loc, valueType, loopArgument);
766 mapping.
map(atomicOp.getCurrentValue(), loopArgForBody);
767 Block &entryBlock = atomicOp.body().front();
769 Operation *
clone = rewriter.clone(nestedOp, mapping);
776 return atomicOp.emitError(
"result not defined in region");
779 result = LLVM::BitcastOp::create(rewriter, loc, cmpxchgType,
result);
783 auto successOrdering = LLVM::AtomicOrdering::acq_rel;
784 auto failureOrdering = LLVM::AtomicOrdering::monotonic;
786 LLVM::AtomicCmpXchgOp::create(rewriter, loc, dataPtr, loopArgument,
787 result, successOrdering, failureOrdering);
789 Value newLoaded = LLVM::ExtractValueOp::create(rewriter, loc, cmpxchg, 0);
790 Value ok = LLVM::ExtractValueOp::create(rewriter, loc, cmpxchg, 1);
793 LLVM::CondBrOp::create(rewriter, loc, ok, endBlock, ArrayRef<Value>(),
794 loopBlock, newLoaded);
800 rewriter.setInsertionPointToStart(endBlock);
801 newLoaded = LLVM::BitcastOp::create(rewriter, loc, valueType, newLoaded);
803 rewriter.setInsertionPointToEnd(endBlock);
804 rewriter.replaceOp(atomicOp, {newLoaded});
812convertGlobalMemrefTypeToLLVM(MemRefType type,
819 Type elementType = typeConverter.convertType(type.getElementType());
820 Type arrayTy = elementType;
822 for (
int64_t dim : llvm::reverse(type.getShape()))
823 arrayTy = LLVM::LLVMArrayType::get(arrayTy, dim);
829 SymbolTableCollection *symbolTables =
nullptr;
832 explicit GlobalMemrefOpLowering(
const LLVMTypeConverter &typeConverter,
833 SymbolTableCollection *symbolTables =
nullptr,
834 PatternBenefit benefit = 1)
835 : ConvertOpToLLVMPattern<memref::GlobalOp>(typeConverter, benefit),
836 symbolTables(symbolTables) {}
839 matchAndRewrite(memref::GlobalOp global, OpAdaptor adaptor,
840 ConversionPatternRewriter &rewriter)
const override {
841 MemRefType type = global.
getType();
842 if (!isConvertibleAndHasIdentityMaps(type))
845 Type arrayTy = convertGlobalMemrefTypeToLLVM(type, *getTypeConverter());
847 LLVM::Linkage linkage =
848 global.isPublic() ? LLVM::Linkage::External : LLVM::Linkage::Private;
849 bool isExternal = global.isExternal();
850 bool isUninitialized = global.isUninitialized();
852 Attribute initialValue =
nullptr;
853 if (!isExternal && !isUninitialized) {
854 auto elementsAttr = llvm::cast<ElementsAttr>(*global.getInitialValue());
855 initialValue = elementsAttr;
859 if (type.getRank() == 0)
860 initialValue = elementsAttr.getSplatValue<Attribute>();
863 uint64_t alignment = global.getAlignment().value_or(0);
864 FailureOr<unsigned> addressSpace =
865 getTypeConverter()->getMemRefAddressSpace(type);
867 return global.emitOpError(
868 "memory space cannot be converted to an integer address space");
871 SymbolTable *symbolTable =
nullptr;
873 Operation *symbolTableOp =
874 global->getParentWithTrait<OpTrait::SymbolTable>();
875 symbolTable = &symbolTables->getSymbolTable(symbolTableOp);
876 symbolTable->remove(global);
880 auto newGlobal = rewriter.replaceOpWithNewOp<LLVM::GlobalOp>(
881 global, arrayTy, global.getConstant(), linkage, global.getSymName(),
882 initialValue, alignment, *addressSpace);
886 symbolTable->insert(newGlobal, rewriter.getInsertionPoint());
888 if (!isExternal && isUninitialized) {
889 rewriter.createBlock(&newGlobal.getInitializerRegion());
891 LLVM::UndefOp::create(rewriter, newGlobal.getLoc(), arrayTy)};
892 LLVM::ReturnOp::create(rewriter, newGlobal.getLoc(), undef);
901struct GetGlobalMemrefOpLowering
903 using ConvertOpToLLVMPattern<memref::GetGlobalOp>::ConvertOpToLLVMPattern;
908 matchAndRewrite(memref::GetGlobalOp op, OpAdaptor adaptor,
909 ConversionPatternRewriter &rewriter)
const override {
910 auto loc = op.getLoc();
911 MemRefType memRefType = op.getType();
912 if (!isConvertibleAndHasIdentityMaps(memRefType))
913 return rewriter.notifyMatchFailure(op,
"incompatible memref type");
918 SmallVector<Value, 4> sizes;
919 SmallVector<Value, 4> strides;
922 this->getMemRefDescriptorSizes(loc, memRefType, adaptor.getOperands(),
923 rewriter, sizes, strides, sizeBytes, !
false);
925 MemRefType type = cast<MemRefType>(op.getResult().getType());
929 FailureOr<unsigned> maybeAddressSpace =
930 getTypeConverter()->getMemRefAddressSpace(type);
931 assert(succeeded(maybeAddressSpace) &&
"unsupported address space");
932 unsigned memSpace = *maybeAddressSpace;
934 Type arrayTy = convertGlobalMemrefTypeToLLVM(type, *getTypeConverter());
935 auto ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext(), memSpace);
937 LLVM::AddressOfOp::create(rewriter, loc, ptrTy, op.getName());
942 LLVM::GEPOp::create(rewriter, loc, ptrTy, arrayTy, addressOf,
943 SmallVector<LLVM::GEPArg>(type.getRank() + 1, 0));
948 auto intPtrType = getIntPtrType(memSpace);
949 Value deadBeefConst =
952 LLVM::IntToPtrOp::create(rewriter, loc, ptrTy, deadBeefConst);
957 auto memRefDescriptor = this->createMemRefDescriptor(
958 loc, memRefType, deadBeefPtr, gep, sizes, strides, rewriter);
961 rewriter.replaceOp(op, {memRefDescriptor});
968struct LoadOpLowering :
public LoadStoreOpLowering<memref::LoadOp> {
972 matchAndRewrite(memref::LoadOp loadOp, OpAdaptor adaptor,
973 ConversionPatternRewriter &rewriter)
const override {
974 auto type = loadOp.getMemRefType();
980 rewriter, loadOp.getLoc(), type, adaptor.getMemref(),
982 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(
983 loadOp, typeConverter->convertType(type.getElementType()), dataPtr,
984 loadOp.getAlignment().value_or(0),
false, loadOp.getNontemporal(),
985 loadOp.getInvariant());
992struct StoreOpLowering :
public LoadStoreOpLowering<memref::StoreOp> {
996 matchAndRewrite(memref::StoreOp op, OpAdaptor adaptor,
997 ConversionPatternRewriter &rewriter)
const override {
998 auto type = op.getMemRefType();
1004 rewriter, op.getLoc(), type, adaptor.getMemref(), adaptor.getIndices(),
1006 rewriter.replaceOpWithNewOp<LLVM::StoreOp>(op, adaptor.getValue(), dataPtr,
1007 op.getAlignment().value_or(0),
1008 false, op.getNontemporal());
1015struct PrefetchOpLowering :
public LoadStoreOpLowering<memref::PrefetchOp> {
1019 matchAndRewrite(memref::PrefetchOp prefetchOp, OpAdaptor adaptor,
1020 ConversionPatternRewriter &rewriter)
const override {
1021 auto type = prefetchOp.getMemRefType();
1022 auto loc = prefetchOp.getLoc();
1025 rewriter, loc, type, adaptor.getMemref(), adaptor.getIndices());
1028 IntegerAttr isWrite = rewriter.getI32IntegerAttr(prefetchOp.getIsWrite());
1029 IntegerAttr localityHint = prefetchOp.getLocalityHintAttr();
1030 IntegerAttr isData =
1031 rewriter.getI32IntegerAttr(prefetchOp.getIsDataCache());
1032 rewriter.replaceOpWithNewOp<LLVM::Prefetch>(prefetchOp, dataPtr, isWrite,
1033 localityHint, isData);
1039 using ConvertOpToLLVMPattern<memref::RankOp>::ConvertOpToLLVMPattern;
1042 matchAndRewrite(memref::RankOp op, OpAdaptor adaptor,
1043 ConversionPatternRewriter &rewriter)
const override {
1044 Location loc = op.getLoc();
1045 Type operandType = op.getMemref().getType();
1046 if (isa<UnrankedMemRefType>(operandType)) {
1047 UnrankedMemRefDescriptor desc(adaptor.getMemref());
1048 rewriter.replaceOp(op, {desc.rank(rewriter, loc)});
1051 if (
auto rankedMemRefType = dyn_cast<MemRefType>(operandType)) {
1052 Type indexType = getIndexType();
1053 rewriter.replaceOp(op,
1055 rankedMemRefType.getRank())});
1066 matchAndRewrite(memref::CastOp memRefCastOp, OpAdaptor adaptor,
1067 ConversionPatternRewriter &rewriter)
const override {
1068 Type srcType = memRefCastOp.getOperand().getType();
1069 Type dstType = memRefCastOp.getType();
1076 if (isa<MemRefType>(srcType) && isa<MemRefType>(dstType))
1077 if (typeConverter->convertType(srcType) !=
1078 typeConverter->convertType(dstType))
1082 if (isa<UnrankedMemRefType>(srcType) && isa<UnrankedMemRefType>(dstType))
1085 auto targetStructType = typeConverter->convertType(memRefCastOp.getType());
1086 auto loc = memRefCastOp.getLoc();
1089 if (isa<MemRefType>(srcType) && isa<MemRefType>(dstType)) {
1090 rewriter.replaceOp(memRefCastOp, {adaptor.getSource()});
1094 if (isa<MemRefType>(srcType) && isa<UnrankedMemRefType>(dstType)) {
1099 auto srcMemRefType = cast<MemRefType>(srcType);
1100 int64_t rank = srcMemRefType.getRank();
1102 auto ptr = getTypeConverter()->promoteOneMemRefDescriptor(
1103 loc, adaptor.getSource(), rewriter);
1106 auto rankVal = LLVM::ConstantOp::create(rewriter, loc, getIndexType(),
1107 rewriter.getIndexAttr(rank));
1109 UnrankedMemRefDescriptor memRefDesc =
1112 memRefDesc.
setRank(rewriter, loc, rankVal);
1115 rewriter.replaceOp(memRefCastOp, (Value)memRefDesc);
1117 }
else if (isa<UnrankedMemRefType>(srcType) && isa<MemRefType>(dstType)) {
1121 UnrankedMemRefDescriptor memRefDesc(adaptor.getSource());
1126 auto loadOp = LLVM::LoadOp::create(rewriter, loc, targetStructType, ptr);
1127 rewriter.replaceOp(memRefCastOp, loadOp.getResult());
1129 llvm_unreachable(
"Unsupported unranked memref to unranked memref cast");
1142 SymbolTableCollection *symbolTables =
nullptr;
1145 explicit MemRefCopyOpLowering(
const LLVMTypeConverter &typeConverter,
1146 SymbolTableCollection *symbolTables =
nullptr,
1147 PatternBenefit benefit = 1)
1148 : ConvertOpToLLVMPattern<memref::CopyOp>(typeConverter, benefit),
1149 symbolTables(symbolTables) {}
1152 lowerToMemCopyIntrinsic(memref::CopyOp op, OpAdaptor adaptor,
1153 ConversionPatternRewriter &rewriter)
const {
1154 auto loc = op.getLoc();
1155 auto srcType = dyn_cast<MemRefType>(op.getSource().getType());
1157 MemRefDescriptor srcDesc(adaptor.getSource());
1160 Value numElements = LLVM::ConstantOp::create(rewriter, loc, getIndexType(),
1161 rewriter.getIndexAttr(1));
1162 for (
int pos = 0; pos < srcType.getRank(); ++pos) {
1163 auto size = srcDesc.size(rewriter, loc, pos);
1164 numElements = LLVM::MulOp::create(rewriter, loc, numElements, size);
1168 auto sizeInBytes =
getSizeInBytes(loc, srcType.getElementType(), rewriter);
1171 LLVM::MulOp::create(rewriter, loc, numElements, sizeInBytes);
1173 Type elementType = typeConverter->convertType(srcType.getElementType());
1175 Value srcBasePtr = srcDesc.alignedPtr(rewriter, loc);
1176 Value srcOffset = srcDesc.offset(rewriter, loc);
1177 Value srcPtr = LLVM::GEPOp::create(rewriter, loc, srcBasePtr.
getType(),
1178 elementType, srcBasePtr, srcOffset);
1179 MemRefDescriptor targetDesc(adaptor.getTarget());
1180 Value targetBasePtr = targetDesc.alignedPtr(rewriter, loc);
1181 Value targetOffset = targetDesc.offset(rewriter, loc);
1183 LLVM::GEPOp::create(rewriter, loc, targetBasePtr.
getType(), elementType,
1184 targetBasePtr, targetOffset);
1185 LLVM::MemcpyOp::create(rewriter, loc, targetPtr, srcPtr, totalSize,
1187 rewriter.eraseOp(op);
1193 lowerToMemCopyFunctionCall(memref::CopyOp op, OpAdaptor adaptor,
1194 ConversionPatternRewriter &rewriter)
const {
1195 auto loc = op.getLoc();
1196 auto srcType = cast<BaseMemRefType>(op.getSource().getType());
1197 auto targetType = cast<BaseMemRefType>(op.getTarget().getType());
1200 auto makeUnranked = [&,
this](Value ranked, MemRefType type) {
1201 auto rank = LLVM::ConstantOp::create(rewriter, loc, getIndexType(),
1203 auto *typeConverter = getTypeConverter();
1208 UnrankedMemRefType::get(type.getElementType(), type.getMemorySpace());
1210 rewriter, loc, *typeConverter, unrankedType,
ValueRange{rank, ptr});
1214 auto stackSaveOp = LLVM::StackSaveOp::create(rewriter, loc, getPtrType());
1216 auto srcMemRefType = dyn_cast<MemRefType>(srcType);
1217 Value unrankedSource =
1218 srcMemRefType ? makeUnranked(adaptor.getSource(), srcMemRefType)
1219 : adaptor.getSource();
1220 auto targetMemRefType = dyn_cast<MemRefType>(targetType);
1221 Value unrankedTarget =
1222 targetMemRefType ? makeUnranked(adaptor.getTarget(), targetMemRefType)
1223 : adaptor.getTarget();
1226 auto one = LLVM::ConstantOp::create(rewriter, loc, getIndexType(),
1227 rewriter.getIndexAttr(1));
1228 auto promote = [&](Value desc) {
1229 auto ptrType = LLVM::LLVMPointerType::get(rewriter.getContext());
1231 LLVM::AllocaOp::create(rewriter, loc, ptrType, desc.getType(), one);
1232 LLVM::StoreOp::create(rewriter, loc, desc, allocated);
1236 auto sourcePtr =
promote(unrankedSource);
1237 auto targetPtr =
promote(unrankedTarget);
1241 auto elemSize =
getSizeInBytes(loc, srcType.getElementType(), rewriter);
1243 rewriter, op->getParentOfType<ModuleOp>(), getIndexType(),
1244 sourcePtr.getType(), symbolTables);
1247 LLVM::CallOp::create(rewriter, loc, copyFn.value(),
1251 LLVM::StackRestoreOp::create(rewriter, loc, stackSaveOp);
1253 rewriter.eraseOp(op);
1259 matchAndRewrite(memref::CopyOp op, OpAdaptor adaptor,
1260 ConversionPatternRewriter &rewriter)
const override {
1261 auto srcType = cast<BaseMemRefType>(op.getSource().getType());
1262 auto targetType = cast<BaseMemRefType>(op.getTarget().getType());
1264 auto isContiguousMemrefType = [&](BaseMemRefType type) {
1265 auto memrefType = dyn_cast<mlir::MemRefType>(type);
1269 return memrefType &&
1270 (memrefType.getLayout().isIdentity() ||
1271 (memrefType.hasStaticShape() && memrefType.getNumElements() > 0 &&
1275 if (isContiguousMemrefType(srcType) && isContiguousMemrefType(targetType))
1276 return lowerToMemCopyIntrinsic(op, adaptor, rewriter);
1278 return lowerToMemCopyFunctionCall(op, adaptor, rewriter);
1282struct MemorySpaceCastOpLowering
1284 using ConvertOpToLLVMPattern<
1285 memref::MemorySpaceCastOp>::ConvertOpToLLVMPattern;
1288 matchAndRewrite(memref::MemorySpaceCastOp op, OpAdaptor adaptor,
1289 ConversionPatternRewriter &rewriter)
const override {
1290 Location loc = op.getLoc();
1292 Type resultType = op.getDest().getType();
1293 if (
auto resultTypeR = dyn_cast<MemRefType>(resultType)) {
1294 auto convertedType =
1295 typeConverter->convertType<LLVM::LLVMStructType>(resultTypeR);
1297 return rewriter.notifyMatchFailure(op,
"memref type conversion failed");
1298 Type newPtrType = convertedType.getBody()[0];
1300 SmallVector<Value> descVals;
1301 MemRefDescriptor::unpack(rewriter, loc, adaptor.getSource(), resultTypeR,
1304 LLVM::AddrSpaceCastOp::create(rewriter, loc, newPtrType, descVals[0]);
1306 LLVM::AddrSpaceCastOp::create(rewriter, loc, newPtrType, descVals[1]);
1307 Value
result = MemRefDescriptor::pack(rewriter, loc, *getTypeConverter(),
1308 resultTypeR, descVals);
1309 rewriter.replaceOp(op,
result);
1312 if (
auto resultTypeU = dyn_cast<UnrankedMemRefType>(resultType)) {
1315 auto sourceType = cast<UnrankedMemRefType>(op.getSource().getType());
1316 FailureOr<unsigned> maybeSourceAddrSpace =
1317 getTypeConverter()->getMemRefAddressSpace(sourceType);
1318 if (
failed(maybeSourceAddrSpace))
1319 return rewriter.notifyMatchFailure(loc,
1320 "non-integer source address space");
1321 unsigned sourceAddrSpace = *maybeSourceAddrSpace;
1322 FailureOr<unsigned> maybeResultAddrSpace =
1323 getTypeConverter()->getMemRefAddressSpace(resultTypeU);
1324 if (
failed(maybeResultAddrSpace))
1325 return rewriter.notifyMatchFailure(loc,
1326 "non-integer result address space");
1327 unsigned resultAddrSpace = *maybeResultAddrSpace;
1329 UnrankedMemRefDescriptor sourceDesc(adaptor.getSource());
1330 Value rank = sourceDesc.rank(rewriter, loc);
1331 Value sourceUnderlyingDesc = sourceDesc.memRefDescPtr(rewriter, loc);
1335 rewriter, loc, typeConverter->convertType(resultTypeU));
1336 result.setRank(rewriter, loc, rank);
1338 rewriter, loc, *getTypeConverter(),
result, resultAddrSpace);
1339 Value resultUnderlyingDesc =
1340 LLVM::AllocaOp::create(rewriter, loc, getPtrType(),
1341 rewriter.getI8Type(), resultUnderlyingSize);
1342 result.setMemRefDescPtr(rewriter, loc, resultUnderlyingDesc);
1345 auto sourceElemPtrType =
1346 LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace);
1347 auto resultElemPtrType =
1348 LLVM::LLVMPointerType::get(rewriter.getContext(), resultAddrSpace);
1350 Value allocatedPtr = sourceDesc.allocatedPtr(
1351 rewriter, loc, sourceUnderlyingDesc, sourceElemPtrType);
1353 sourceDesc.alignedPtr(rewriter, loc, *getTypeConverter(),
1354 sourceUnderlyingDesc, sourceElemPtrType);
1355 allocatedPtr = LLVM::AddrSpaceCastOp::create(
1356 rewriter, loc, resultElemPtrType, allocatedPtr);
1357 alignedPtr = LLVM::AddrSpaceCastOp::create(rewriter, loc,
1358 resultElemPtrType, alignedPtr);
1360 result.setAllocatedPtr(rewriter, loc, resultUnderlyingDesc,
1361 resultElemPtrType, allocatedPtr);
1362 result.setAlignedPtr(rewriter, loc, *getTypeConverter(),
1363 resultUnderlyingDesc, resultElemPtrType, alignedPtr);
1366 Value sourceIndexVals =
1367 sourceDesc.offsetBasePtr(rewriter, loc, *getTypeConverter(),
1368 sourceUnderlyingDesc, sourceElemPtrType);
1369 Value resultIndexVals =
1370 result.offsetBasePtr(rewriter, loc, *getTypeConverter(),
1371 resultUnderlyingDesc, resultElemPtrType);
1373 int64_t bytesToSkip =
1374 2 * llvm::divideCeil(
1375 getTypeConverter()->getPointerBitwidth(resultAddrSpace), 8);
1376 Value bytesToSkipConst = LLVM::ConstantOp::create(
1377 rewriter, loc, getIndexType(), rewriter.getIndexAttr(bytesToSkip));
1379 LLVM::SubOp::create(rewriter, loc, getIndexType(),
1380 resultUnderlyingSize, bytesToSkipConst);
1381 LLVM::MemcpyOp::create(rewriter, loc, resultIndexVals, sourceIndexVals,
1387 return rewriter.notifyMatchFailure(loc,
"unexpected memref type");
1394static void extractPointersAndOffset(
Location loc,
1395 ConversionPatternRewriter &rewriter,
1397 Value originalOperand,
1398 Value convertedOperand,
1400 Value *offset =
nullptr) {
1402 if (isa<MemRefType>(operandType)) {
1404 *allocatedPtr = desc.allocatedPtr(rewriter, loc);
1405 *alignedPtr = desc.alignedPtr(rewriter, loc);
1406 if (offset !=
nullptr)
1407 *offset = desc.offset(rewriter, loc);
1413 cast<UnrankedMemRefType>(operandType));
1414 auto elementPtrType =
1415 LLVM::LLVMPointerType::get(rewriter.getContext(), memorySpace);
1420 Value underlyingDescPtr = unrankedDesc.memRefDescPtr(rewriter, loc);
1423 rewriter, loc, underlyingDescPtr, elementPtrType);
1425 rewriter, loc, typeConverter, underlyingDescPtr, elementPtrType);
1426 if (offset !=
nullptr) {
1428 rewriter, loc, typeConverter, underlyingDescPtr, elementPtrType);
1432struct MemRefReinterpretCastOpLowering
1434 using ConvertOpToLLVMPattern<
1435 memref::ReinterpretCastOp>::ConvertOpToLLVMPattern;
1438 matchAndRewrite(memref::ReinterpretCastOp castOp, OpAdaptor adaptor,
1439 ConversionPatternRewriter &rewriter)
const override {
1440 Type srcType = castOp.getSource().getType();
1443 if (
failed(convertSourceMemRefToDescriptor(rewriter, srcType, castOp,
1444 adaptor, &descriptor)))
1446 rewriter.replaceOp(castOp, {descriptor});
1451 LogicalResult convertSourceMemRefToDescriptor(
1452 ConversionPatternRewriter &rewriter, Type srcType,
1453 memref::ReinterpretCastOp castOp,
1454 memref::ReinterpretCastOp::Adaptor adaptor, Value *descriptor)
const {
1455 MemRefType targetMemRefType =
1456 cast<MemRefType>(castOp.getResult().getType());
1457 auto llvmTargetDescriptorTy =
1458 typeConverter->convertType<LLVM::LLVMStructType>(targetMemRefType);
1459 if (!llvmTargetDescriptorTy)
1463 Location loc = castOp.getLoc();
1464 auto desc = MemRefDescriptor::poison(rewriter, loc, llvmTargetDescriptorTy);
1467 Value allocatedPtr, alignedPtr;
1468 extractPointersAndOffset(loc, rewriter, *getTypeConverter(),
1469 castOp.getSource(), adaptor.getSource(),
1470 &allocatedPtr, &alignedPtr);
1471 desc.setAllocatedPtr(rewriter, loc, allocatedPtr);
1472 desc.setAlignedPtr(rewriter, loc, alignedPtr);
1475 if (castOp.isDynamicOffset(0))
1476 desc.setOffset(rewriter, loc, adaptor.getOffsets()[0]);
1478 desc.setConstantOffset(rewriter, loc, castOp.getStaticOffset(0));
1481 unsigned dynSizeId = 0;
1482 unsigned dynStrideId = 0;
1483 for (
unsigned i = 0, e = targetMemRefType.getRank(); i < e; ++i) {
1484 if (castOp.isDynamicSize(i))
1485 desc.setSize(rewriter, loc, i, adaptor.getSizes()[dynSizeId++]);
1487 desc.setConstantSize(rewriter, loc, i, castOp.getStaticSize(i));
1489 if (castOp.isDynamicStride(i))
1490 desc.setStride(rewriter, loc, i, adaptor.getStrides()[dynStrideId++]);
1492 desc.setConstantStride(rewriter, loc, i, castOp.getStaticStride(i));
1499struct MemRefReshapeOpLowering
1501 using ConvertOpToLLVMPattern<memref::ReshapeOp>::ConvertOpToLLVMPattern;
1504 matchAndRewrite(memref::ReshapeOp reshapeOp, OpAdaptor adaptor,
1505 ConversionPatternRewriter &rewriter)
const override {
1506 Type srcType = reshapeOp.getSource().getType();
1509 if (
failed(convertSourceMemRefToDescriptor(rewriter, srcType, reshapeOp,
1510 adaptor, &descriptor)))
1512 rewriter.replaceOp(reshapeOp, {descriptor});
1518 convertSourceMemRefToDescriptor(ConversionPatternRewriter &rewriter,
1519 Type srcType, memref::ReshapeOp reshapeOp,
1520 memref::ReshapeOp::Adaptor adaptor,
1521 Value *descriptor)
const {
1522 auto shapeMemRefType = cast<MemRefType>(reshapeOp.getShape().getType());
1523 if (shapeMemRefType.hasStaticShape()) {
1524 MemRefType targetMemRefType =
1525 cast<MemRefType>(reshapeOp.getResult().getType());
1526 auto llvmTargetDescriptorTy =
1527 typeConverter->convertType<LLVM::LLVMStructType>(targetMemRefType);
1528 if (!llvmTargetDescriptorTy)
1532 Location loc = reshapeOp.getLoc();
1534 MemRefDescriptor::poison(rewriter, loc, llvmTargetDescriptorTy);
1537 Value allocatedPtr, alignedPtr;
1538 extractPointersAndOffset(loc, rewriter, *getTypeConverter(),
1539 reshapeOp.getSource(), adaptor.getSource(),
1540 &allocatedPtr, &alignedPtr);
1541 desc.setAllocatedPtr(rewriter, loc, allocatedPtr);
1542 desc.setAlignedPtr(rewriter, loc, alignedPtr);
1546 SmallVector<int64_t> strides;
1547 if (
failed(targetMemRefType.getStridesAndOffset(strides, offset)))
1548 return rewriter.notifyMatchFailure(
1549 reshapeOp,
"failed to get stride and offset exprs");
1551 if (!isStaticStrideOrOffset(offset))
1552 return rewriter.notifyMatchFailure(reshapeOp,
1553 "dynamic offset is unsupported");
1555 desc.setConstantOffset(rewriter, loc, offset);
1557 assert(targetMemRefType.getLayout().isIdentity() &&
1558 "Identity layout map is a precondition of a valid reshape op");
1560 Type indexType = getIndexType();
1561 Value stride =
nullptr;
1562 int64_t targetRank = targetMemRefType.getRank();
1563 for (
auto i : llvm::reverse(llvm::seq<int64_t>(0, targetRank))) {
1564 if (ShapedType::isStatic(strides[i])) {
1569 }
else if (!stride) {
1579 if (!targetMemRefType.isDynamicDim(i)) {
1581 targetMemRefType.getDimSize(i));
1583 Value shapeOp = reshapeOp.getShape();
1585 dimSize = memref::LoadOp::create(rewriter, loc, shapeOp, index);
1586 Type indexType = getIndexType();
1587 if (dimSize.
getType() != indexType)
1588 dimSize = typeConverter->materializeTargetConversion(
1589 rewriter, loc, indexType, dimSize);
1590 assert(dimSize &&
"Invalid memref element type");
1593 desc.setSize(rewriter, loc, i, dimSize);
1594 desc.setStride(rewriter, loc, i, stride);
1597 stride = LLVM::MulOp::create(rewriter, loc, stride, dimSize);
1605 Location loc = reshapeOp.getLoc();
1606 MemRefDescriptor shapeDesc(adaptor.getShape());
1607 Value resultRank = shapeDesc.size(rewriter, loc, 0);
1610 auto targetType = cast<UnrankedMemRefType>(reshapeOp.getResult().getType());
1611 unsigned addressSpace =
1612 *getTypeConverter()->getMemRefAddressSpace(targetType);
1617 rewriter, loc, typeConverter->convertType(targetType));
1618 targetDesc.setRank(rewriter, loc, resultRank);
1620 rewriter, loc, *getTypeConverter(), targetDesc, addressSpace);
1621 Value underlyingDescPtr = LLVM::AllocaOp::create(
1622 rewriter, loc, getPtrType(), IntegerType::get(
getContext(), 8),
1624 targetDesc.setMemRefDescPtr(rewriter, loc, underlyingDescPtr);
1627 Value allocatedPtr, alignedPtr, offset;
1628 extractPointersAndOffset(loc, rewriter, *getTypeConverter(),
1629 reshapeOp.getSource(), adaptor.getSource(),
1630 &allocatedPtr, &alignedPtr, &offset);
1633 auto elementPtrType =
1634 LLVM::LLVMPointerType::get(rewriter.getContext(), addressSpace);
1637 elementPtrType, allocatedPtr);
1639 underlyingDescPtr, elementPtrType,
1642 underlyingDescPtr, elementPtrType,
1648 rewriter, loc, *getTypeConverter(), underlyingDescPtr, elementPtrType);
1650 rewriter, loc, *getTypeConverter(), targetSizesBase, resultRank);
1651 Value shapeOperandPtr = shapeDesc.alignedPtr(rewriter, loc);
1653 Value resultRankMinusOne =
1654 LLVM::SubOp::create(rewriter, loc, resultRank, oneIndex);
1656 Block *initBlock = rewriter.getInsertionBlock();
1657 Type indexType = getTypeConverter()->getIndexType();
1658 Block::iterator remainingOpsIt = std::next(rewriter.getInsertionPoint());
1660 Block *condBlock = rewriter.createBlock(initBlock->
getParent(), {},
1661 {indexType, indexType}, {loc, loc});
1664 Block *remainingBlock = rewriter.splitBlock(initBlock, remainingOpsIt);
1665 rewriter.mergeBlocks(remainingBlock, condBlock,
ValueRange());
1667 rewriter.setInsertionPointToEnd(initBlock);
1668 LLVM::BrOp::create(rewriter, loc,
1669 ValueRange({resultRankMinusOne, oneIndex}), condBlock);
1670 rewriter.setInsertionPointToStart(condBlock);
1675 Value pred = LLVM::ICmpOp::create(
1676 rewriter, loc, IntegerType::get(rewriter.getContext(), 1),
1677 LLVM::ICmpPredicate::sge, indexArg, zeroIndex);
1680 rewriter.splitBlock(condBlock, rewriter.getInsertionPoint());
1681 rewriter.setInsertionPointToStart(bodyBlock);
1684 auto llvmIndexPtrType = LLVM::LLVMPointerType::get(rewriter.getContext());
1685 Value sizeLoadGep = LLVM::GEPOp::create(
1686 rewriter, loc, llvmIndexPtrType,
1687 typeConverter->convertType(shapeMemRefType.getElementType()),
1688 shapeOperandPtr, indexArg);
1689 Value size = LLVM::LoadOp::create(rewriter, loc, indexType, sizeLoadGep);
1691 targetSizesBase, indexArg, size);
1695 targetStridesBase, indexArg, strideArg);
1696 Value nextStride = LLVM::MulOp::create(rewriter, loc, strideArg, size);
1699 Value decrement = LLVM::SubOp::create(rewriter, loc, indexArg, oneIndex);
1700 LLVM::BrOp::create(rewriter, loc,
ValueRange({decrement, nextStride}),
1704 rewriter.splitBlock(bodyBlock, rewriter.getInsertionPoint());
1707 rewriter.setInsertionPointToEnd(condBlock);
1708 LLVM::CondBrOp::create(rewriter, loc, pred, bodyBlock,
ValueRange(),
1712 rewriter.setInsertionPointToStart(remainder);
1714 *descriptor = targetDesc;
1721template <
typename ReshapeOp>
1722class ReassociatingReshapeOpConversion
1725 using ConvertOpToLLVMPattern<ReshapeOp>::ConvertOpToLLVMPattern;
1726 using ReshapeOpAdaptor =
typename ReshapeOp::Adaptor;
1729 matchAndRewrite(ReshapeOp reshapeOp,
typename ReshapeOp::Adaptor adaptor,
1730 ConversionPatternRewriter &rewriter)
const override {
1731 return rewriter.notifyMatchFailure(
1733 "reassociation operations should have been expanded beforehand");
1740 using ConvertOpToLLVMPattern<memref::SubViewOp>::ConvertOpToLLVMPattern;
1743 matchAndRewrite(memref::SubViewOp subViewOp, OpAdaptor adaptor,
1744 ConversionPatternRewriter &rewriter)
const override {
1745 return rewriter.notifyMatchFailure(
1746 subViewOp,
"subview operations should have been expanded beforehand");
1763 ConversionPatternRewriter &rewriter)
const override {
1764 auto loc = transposeOp.getLoc();
1765 MemRefDescriptor viewMemRef(adaptor.getIn());
1768 if (transposeOp.getPermutation().isIdentity())
1769 return rewriter.replaceOp(transposeOp, {viewMemRef}),
success();
1771 auto targetMemRef = MemRefDescriptor::poison(
1773 typeConverter->convertType(transposeOp.getIn().getType()));
1777 targetMemRef.setAllocatedPtr(rewriter, loc,
1778 viewMemRef.allocatedPtr(rewriter, loc));
1779 targetMemRef.setAlignedPtr(rewriter, loc,
1780 viewMemRef.alignedPtr(rewriter, loc));
1783 targetMemRef.setOffset(rewriter, loc, viewMemRef.offset(rewriter, loc));
1789 for (
const auto &en :
1790 llvm::enumerate(transposeOp.getPermutation().getResults())) {
1791 int targetPos = en.index();
1792 int sourcePos = cast<AffineDimExpr>(en.value()).getPosition();
1793 targetMemRef.setSize(rewriter, loc, targetPos,
1794 viewMemRef.size(rewriter, loc, sourcePos));
1795 targetMemRef.setStride(rewriter, loc, targetPos,
1796 viewMemRef.stride(rewriter, loc, sourcePos));
1799 rewriter.replaceOp(transposeOp, {targetMemRef});
1810 using ConvertOpToLLVMPattern<memref::ViewOp>::ConvertOpToLLVMPattern;
1814 Value getSize(ConversionPatternRewriter &rewriter, Location loc,
1815 ArrayRef<int64_t> shape,
ValueRange dynamicSizes,
unsigned idx,
1816 Type indexType)
const {
1817 assert(idx < shape.size());
1818 if (ShapedType::isStatic(shape[idx]))
1822 llvm::count_if(shape.take_front(idx), ShapedType::isDynamic);
1823 return dynamicSizes[nDynamic];
1830 Value getStride(ConversionPatternRewriter &rewriter, Location loc,
1831 ArrayRef<int64_t> strides, Value nextSize,
1832 Value runningStride,
unsigned idx, Type indexType)
const {
1833 assert(idx < strides.size());
1834 if (ShapedType::isStatic(strides[idx]))
1837 return runningStride
1838 ? LLVM::MulOp::create(rewriter, loc, runningStride, nextSize)
1840 assert(!runningStride);
1845 matchAndRewrite(memref::ViewOp viewOp, OpAdaptor adaptor,
1846 ConversionPatternRewriter &rewriter)
const override {
1847 auto loc = viewOp.getLoc();
1849 auto viewMemRefType = viewOp.getType();
1850 auto targetElementTy =
1851 typeConverter->convertType(viewMemRefType.getElementType());
1852 auto targetDescTy = typeConverter->convertType(viewMemRefType);
1853 if (!targetDescTy || !targetElementTy ||
1856 return viewOp.emitWarning(
"Target descriptor type not converted to LLVM"),
1860 SmallVector<int64_t, 4> strides;
1861 auto successStrides = viewMemRefType.getStridesAndOffset(strides, offset);
1862 if (
failed(successStrides))
1863 return viewOp.emitWarning(
"cannot cast to non-strided shape"), failure();
1864 assert(offset == 0 &&
"expected offset to be 0");
1868 if (!strides.empty() && (strides.back() != 1 && strides.back() != 0))
1869 return viewOp.emitWarning(
"cannot cast to non-contiguous shape"),
1873 MemRefDescriptor sourceMemRef(adaptor.getSource());
1874 auto targetMemRef = MemRefDescriptor::poison(rewriter, loc, targetDescTy);
1877 Value allocatedPtr = sourceMemRef.allocatedPtr(rewriter, loc);
1878 auto srcMemRefType = cast<MemRefType>(viewOp.getSource().getType());
1879 targetMemRef.setAllocatedPtr(rewriter, loc, allocatedPtr);
1882 Value alignedPtr = sourceMemRef.alignedPtr(rewriter, loc);
1883 alignedPtr = LLVM::GEPOp::create(
1884 rewriter, loc, alignedPtr.
getType(),
1885 typeConverter->convertType(srcMemRefType.getElementType()), alignedPtr,
1886 adaptor.getByteShift());
1888 targetMemRef.setAlignedPtr(rewriter, loc, alignedPtr);
1890 Type indexType = getIndexType();
1894 targetMemRef.setOffset(
1899 if (viewMemRefType.getRank() == 0)
1900 return rewriter.replaceOp(viewOp, {targetMemRef}),
success();
1903 Value stride =
nullptr, nextSize =
nullptr;
1904 for (
int i = viewMemRefType.getRank() - 1; i >= 0; --i) {
1906 Value size = getSize(rewriter, loc, viewMemRefType.getShape(),
1907 adaptor.getSizes(), i, indexType);
1908 targetMemRef.setSize(rewriter, loc, i, size);
1911 getStride(rewriter, loc, strides, nextSize, stride, i, indexType);
1912 targetMemRef.setStride(rewriter, loc, i, stride);
1916 rewriter.replaceOp(viewOp, {targetMemRef});
1927static std::optional<LLVM::AtomicBinOp>
1928matchSimpleAtomicOp(memref::AtomicRMWOp atomicOp) {
1929 switch (atomicOp.getKind()) {
1930 case arith::AtomicRMWKind::addf:
1931 return LLVM::AtomicBinOp::fadd;
1932 case arith::AtomicRMWKind::addi:
1933 return LLVM::AtomicBinOp::add;
1934 case arith::AtomicRMWKind::assign:
1935 return LLVM::AtomicBinOp::xchg;
1936 case arith::AtomicRMWKind::maximumf:
1938 LDBG() <<
"the lowering of memref.atomicrmw maximumf changed "
1939 "from fmax to fmaximum, expect more NaNs";
1940 return LLVM::AtomicBinOp::fmaximum;
1941 case arith::AtomicRMWKind::maxnumf:
1942 return LLVM::AtomicBinOp::fmax;
1943 case arith::AtomicRMWKind::maxs:
1944 return LLVM::AtomicBinOp::max;
1945 case arith::AtomicRMWKind::maxu:
1946 return LLVM::AtomicBinOp::umax;
1947 case arith::AtomicRMWKind::minimumf:
1949 LDBG() <<
"the lowering of memref.atomicrmw minimum changed "
1950 "from fmin to fminimum, expect more NaNs";
1951 return LLVM::AtomicBinOp::fminimum;
1952 case arith::AtomicRMWKind::minnumf:
1953 return LLVM::AtomicBinOp::fmin;
1954 case arith::AtomicRMWKind::mins:
1955 return LLVM::AtomicBinOp::min;
1956 case arith::AtomicRMWKind::minu:
1957 return LLVM::AtomicBinOp::umin;
1958 case arith::AtomicRMWKind::ori:
1959 return LLVM::AtomicBinOp::_or;
1960 case arith::AtomicRMWKind::xori:
1961 return LLVM::AtomicBinOp::_xor;
1962 case arith::AtomicRMWKind::andi:
1963 return LLVM::AtomicBinOp::_and;
1965 return std::nullopt;
1967 llvm_unreachable(
"Invalid AtomicRMWKind");
1970struct AtomicRMWOpLowering :
public LoadStoreOpLowering<memref::AtomicRMWOp> {
1974 matchAndRewrite(memref::AtomicRMWOp atomicOp, OpAdaptor adaptor,
1975 ConversionPatternRewriter &rewriter)
const override {
1976 auto maybeKind = matchSimpleAtomicOp(atomicOp);
1979 auto memRefType = atomicOp.getMemRefType();
1980 SmallVector<int64_t> strides;
1982 if (
failed(memRefType.getStridesAndOffset(strides, offset)))
1986 adaptor.getMemref(), adaptor.getIndices());
1987 rewriter.replaceOpWithNewOp<LLVM::AtomicRMWOp>(
1988 atomicOp, *maybeKind, dataPtr, adaptor.getValue(),
1989 LLVM::AtomicOrdering::acq_rel);
1995class ConvertExtractAlignedPointerAsIndex
1998 using ConvertOpToLLVMPattern<
1999 memref::ExtractAlignedPointerAsIndexOp>::ConvertOpToLLVMPattern;
2002 matchAndRewrite(memref::ExtractAlignedPointerAsIndexOp extractOp,
2004 ConversionPatternRewriter &rewriter)
const override {
2005 BaseMemRefType sourceTy = extractOp.getSource().getType();
2009 MemRefDescriptor desc(adaptor.getSource());
2010 alignedPtr = desc.alignedPtr(rewriter, extractOp->getLoc());
2012 auto elementPtrTy = LLVM::LLVMPointerType::get(
2015 UnrankedMemRefDescriptor desc(adaptor.getSource());
2016 Value descPtr = desc.memRefDescPtr(rewriter, extractOp->getLoc());
2019 rewriter, extractOp->getLoc(), *getTypeConverter(), descPtr,
2023 rewriter.replaceOpWithNewOp<LLVM::PtrToIntOp>(
2024 extractOp, getTypeConverter()->getIndexType(), alignedPtr);
2031class ExtractStridedMetadataOpLowering
2034 using ConvertOpToLLVMPattern<
2035 memref::ExtractStridedMetadataOp>::ConvertOpToLLVMPattern;
2038 matchAndRewrite(memref::ExtractStridedMetadataOp extractStridedMetadataOp,
2040 ConversionPatternRewriter &rewriter)
const override {
2046 MemRefDescriptor sourceMemRef(adaptor.getSource());
2047 Location loc = extractStridedMetadataOp.getLoc();
2048 Value source = extractStridedMetadataOp.getSource();
2050 auto sourceMemRefType = cast<MemRefType>(source.
getType());
2051 int64_t rank = sourceMemRefType.getRank();
2052 SmallVector<Value> results;
2053 results.reserve(2 + rank * 2);
2056 Value baseBuffer = sourceMemRef.allocatedPtr(rewriter, loc);
2057 Value alignedBuffer = sourceMemRef.alignedPtr(rewriter, loc);
2058 MemRefDescriptor dstMemRef = MemRefDescriptor::fromStaticShape(
2059 rewriter, loc, *getTypeConverter(),
2060 cast<MemRefType>(extractStridedMetadataOp.getBaseBuffer().getType()),
2061 baseBuffer, alignedBuffer);
2062 results.push_back((Value)dstMemRef);
2065 results.push_back(sourceMemRef.offset(rewriter, loc));
2068 for (
unsigned i = 0; i < rank; ++i)
2069 results.push_back(sourceMemRef.size(rewriter, loc, i));
2071 for (
unsigned i = 0; i < rank; ++i)
2072 results.push_back(sourceMemRef.stride(rewriter, loc, i));
2074 rewriter.replaceOp(extractStridedMetadataOp, results);
2087 AllocaScopeOpLowering,
2088 AssumeAlignmentOpLowering,
2089 AtomicRMWOpLowering,
2090 ConvertExtractAlignedPointerAsIndex,
2092 DistinctObjectsOpLowering,
2093 ExtractStridedMetadataOpLowering,
2094 GenericAtomicRMWOpLowering,
2095 GetGlobalMemrefOpLowering,
2097 MemRefCastOpLowering,
2098 MemRefReinterpretCastOpLowering,
2099 MemRefReshapeOpLowering,
2100 MemorySpaceCastOpLowering,
2103 ReassociatingReshapeOpConversion<memref::CollapseShapeOp>,
2104 ReassociatingReshapeOpConversion<memref::ExpandShapeOp>,
2108 ViewOpLowering>(converter);
2110 patterns.
add<GlobalMemrefOpLowering, MemRefCopyOpLowering>(converter,
2114 patterns.
add<AlignedAllocOpLowering, DeallocOpLowering>(converter,
2117 patterns.
add<AllocOpLowering, DeallocOpLowering>(converter, symbolTables);
2121struct FinalizeMemRefToLLVMConversionPass
2123 FinalizeMemRefToLLVMConversionPass> {
2124 using FinalizeMemRefToLLVMConversionPassBase::
2125 FinalizeMemRefToLLVMConversionPassBase;
2127 void runOnOperation()
override {
2129 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
2131 dataLayoutAnalysis.getAtOrAbove(op));
2136 options.useGenericFunctions = useGenericFunctions;
2139 options.overrideIndexBitwidth(indexBitwidth);
2142 &dataLayoutAnalysis);
2148 target.addLegalOp<func::FuncOp>();
2149 if (failed(applyPartialConversion(op,
target, std::move(patterns))))
2150 signalPassFailure();
2155struct MemRefToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
2156 MemRefToLLVMDialectInterface(Dialect *dialect)
2157 : ConvertToLLVMPatternInterface(dialect) {}
2159 void loadDependentDialects(MLIRContext *context)
const final {
2160 context->loadDialect<LLVM::LLVMDialect>();
2165 void populateConvertToLLVMConversionPatterns(
2166 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
2167 RewritePatternSet &patterns)
const final {
2176 dialect->addInterfaces<MemRefToLLVMDialectInterface>();
static Value createIndexAttrConstant(OpBuilder &builder, Location loc, Type resultType, int64_t value)
static LLVM::GEPNoWrapFlags getLoadStoreNoWrapFlags(MemRefType type)
Returns GEP no-wrap flags for a memref load/store.
static llvm::Value * getSizeInBytes(DataLayout &dl, const mlir::Type &type, Operation *clauseOp, llvm::Value *basePointer, llvm::Type *baseType, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::ManagedStatic< PassManagerOptions > options
Rewrite AVX2-specific vector.transpose, for the supported cases and depending on the TransposeLowerin...
LogicalResult matchAndRewrite(vector::TransposeOp op, PatternRewriter &rewriter) const override
unsigned getMemorySpaceAsInt() const
[deprecated] Returns the memory space in old raw integer representation.
bool hasRank() const
Returns if this type is ranked, i.e. it has a known number of dimensions.
OpListType::iterator iterator
BlockArgument getArgument(unsigned i)
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgListType getArguments()
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
ConvertOpToLLVMPattern(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
Stores data layout objects for each operation that specifies the data layout above and below the give...
The main mechanism for performing data layout queries.
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
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.
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
auto lookupOrNull(T from) const
Lookup a mapped value within the map.
Derived class that automatically populates legalization information for different LLVM ops.
Conversion from types to the LLVM IR dialect.
unsigned getUnrankedMemRefDescriptorSize(UnrankedMemRefType type, const DataLayout &layout) const
Returns the size of the unranked memref descriptor object in bytes.
Value promoteOneMemRefDescriptor(Location loc, Value operand, OpBuilder &builder) const
Promote the LLVM struct representation of one MemRef descriptor to stack and use pointer to struct to...
const LowerToLLVMOptions & getOptions() const
FailureOr< unsigned > getMemRefAddressSpace(BaseMemRefType type) const
Return the LLVM address space corresponding to the memory space of the memref type type or failure if...
const DataLayoutAnalysis * getDataLayoutAnalysis() const
Returns the data layout analysis to query during conversion.
unsigned getMemRefDescriptorSize(MemRefType type, const DataLayout &layout) const
Returns the size of the memref descriptor object in bytes.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Options to control the LLVM lowering.
AllocLowering allocLowering
@ Malloc
Use malloc for heap allocations.
@ AlignedAlloc
Use aligned_alloc for heap allocations.
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...
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
Value getOperand(unsigned idx)
result_range getResults()
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
This class represents a collection of SymbolTables.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
static void setOffset(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType, Value offset)
Builds IR inserting the offset into the descriptor.
static Value allocatedPtr(OpBuilder &builder, Location loc, Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType)
TODO: The following accessors don't take alignment rules between elements of the descriptor struct in...
static Value computeSize(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, UnrankedMemRefDescriptor desc, unsigned addressSpace)
Builds and returns IR computing the size in bytes (suitable for opaque allocation).
void setRank(OpBuilder &builder, Location loc, Value value)
Builds IR setting the rank in the descriptor.
Value memRefDescPtr(OpBuilder &builder, Location loc) const
Builds IR extracting ranked memref descriptor ptr.
static void setAllocatedPtr(OpBuilder &builder, Location loc, Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType, Value allocatedPtr)
Builds IR inserting the allocated pointer into the descriptor.
static void setSize(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, Value sizeBasePtr, Value index, Value size)
Builds IR inserting the size[index] into the descriptor.
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 UnrankedMemRefDescriptor poison(OpBuilder &builder, Location loc, Type descriptorType)
Builds IR creating an undef value of the descriptor type.
static void setAlignedPtr(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType, Value alignedPtr)
Builds IR inserting the aligned pointer into the descriptor.
static Value offset(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType)
Builds IR extracting the offset from the descriptor.
static Value strideBasePtr(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, Value sizeBasePtr, Value rank)
Builds IR extracting the pointer to the first element of the stride array.
void setMemRefDescPtr(OpBuilder &builder, Location loc, Value value)
Builds IR setting ranked memref descriptor ptr.
static void setStride(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, Value strideBasePtr, Value index, Value stride)
Builds IR inserting the stride[index] into the descriptor.
static Value sizeBasePtr(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType)
Builds IR extracting the pointer to the first element of the size array.
static Value alignedPtr(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType)
Builds IR extracting the aligned pointer from the descriptor.
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.
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateFreeFn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateMemRefCopyFn(OpBuilder &b, Operation *moduleOp, Type indexType, Type unrankedDescriptorType, SymbolTableCollection *symbolTables=nullptr)
Value getStridedElementPtr(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, MemRefType type, Value memRefDesc, ValueRange indices, LLVM::GEPNoWrapFlags noWrapFlags=LLVM::GEPNoWrapFlags::none)
Performs the index computation to get to the element at indices of the memory pointed to by memRefDes...
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateGenericAlignedAllocFn(OpBuilder &b, Operation *moduleOp, Type indexType, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateMallocFn(OpBuilder &b, Operation *moduleOp, Type indexType, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateGenericAllocFn(OpBuilder &b, Operation *moduleOp, Type indexType, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateAlignedAllocFn(OpBuilder &b, Operation *moduleOp, Type indexType, SymbolTableCollection *symbolTables=nullptr)
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateGenericFreeFn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
bool isStaticShapeAndContiguousRowMajor(MemRefType type)
Returns true, if the memref type has static shapes and represents a contiguous chunk of memory.
void promote(RewriterBase &rewriter, scf::ForallOp forallOp)
Promotes the loop body of a scf::ForallOp to its containing block.
Include the generated interface declarations.
void registerConvertMemRefToLLVMInterface(DialectRegistry ®istry)
static constexpr unsigned kDeriveIndexBitwidthFromDataLayout
Value to pass as bitwidth for the index type when the converter is expected to derive the bitwidth fr...
void populateFinalizeMemRefToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, SymbolTableCollection *symbolTables=nullptr)
Collect a set of patterns to convert memory-related operations from the MemRef dialect to the LLVM di...
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)