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,
104 LLVM::ConstantOp::create(rewriter, loc, alignment.
getType(),
105 rewriter.getIntegerAttr(alignment.
getType(), 1));
106 Value bump = LLVM::SubOp::create(rewriter, loc, alignment, one);
107 Value bumped = LLVM::AddOp::create(rewriter, loc, input, bump);
108 Value mod = LLVM::URemOp::create(rewriter, loc, bumped, alignment);
109 return LLVM::SubOp::create(rewriter, loc, bumped, mod);
121 Type elementType = memRefType.getElementType();
122 if (
auto memRefElementType = dyn_cast<MemRefType>(elementType))
124 if (
auto memRefElementType = dyn_cast<UnrankedMemRefType>(elementType))
130static Value castAllocFuncResult(ConversionPatternRewriter &rewriter,
132 MemRefType memRefType,
Type elementPtrType,
134 auto allocatedPtrTy = cast<LLVM::LLVMPointerType>(allocatedPtr.
getType());
135 FailureOr<unsigned> maybeMemrefAddrSpace =
137 assert(succeeded(maybeMemrefAddrSpace) &&
"unsupported address space");
138 unsigned memrefAddrSpace = *maybeMemrefAddrSpace;
139 if (allocatedPtrTy.getAddressSpace() != memrefAddrSpace)
140 allocatedPtr = LLVM::AddrSpaceCastOp::create(
142 LLVM::LLVMPointerType::get(rewriter.getContext(), memrefAddrSpace),
148 SymbolTableCollection *symbolTables =
nullptr;
151 explicit AllocOpLowering(
const LLVMTypeConverter &typeConverter,
152 SymbolTableCollection *symbolTables =
nullptr,
153 PatternBenefit benefit = 1)
154 : ConvertOpToLLVMPattern<memref::AllocOp>(typeConverter, benefit),
155 symbolTables(symbolTables) {}
158 matchAndRewrite(memref::AllocOp op, OpAdaptor adaptor,
159 ConversionPatternRewriter &rewriter)
const override {
160 auto loc = op.getLoc();
161 MemRefType memRefType = op.getType();
162 if (!isConvertibleAndHasIdentityMaps(memRefType))
163 return rewriter.notifyMatchFailure(op,
"incompatible memref type");
166 FailureOr<LLVM::LLVMFuncOp> allocFuncOp =
167 getNotalignedAllocFn(rewriter, getTypeConverter(),
168 op->getParentWithTrait<OpTrait::SymbolTable>(),
169 getIndexType(), symbolTables);
176 SmallVector<Value, 4> sizes;
177 SmallVector<Value, 4> strides;
180 this->getMemRefDescriptorSizes(loc, memRefType, adaptor.getOperands(),
181 rewriter, sizes, strides, sizeBytes,
true);
183 Value alignment = getAlignment(rewriter, loc, op);
186 sizeBytes = LLVM::AddOp::create(rewriter, loc, sizeBytes, alignment);
190 Type elementPtrType = this->getElementPtrType(memRefType);
191 assert(elementPtrType &&
"could not compute element ptr type");
193 LLVM::CallOp::create(rewriter, loc, allocFuncOp.value(), sizeBytes);
196 castAllocFuncResult(rewriter, loc, results.getResult(), memRefType,
197 elementPtrType, *getTypeConverter());
198 Value alignedPtr = allocatedPtr;
202 LLVM::PtrToIntOp::create(rewriter, loc, getIndexType(), allocatedPtr);
204 createAligned(rewriter, loc, allocatedInt, alignment);
206 LLVM::IntToPtrOp::create(rewriter, loc, elementPtrType, alignmentInt);
210 auto memRefDescriptor = this->createMemRefDescriptor(
211 loc, memRefType, allocatedPtr, alignedPtr, sizes, strides, rewriter);
214 rewriter.replaceOp(op, {memRefDescriptor});
219 template <
typename OpType>
220 Value getAlignment(ConversionPatternRewriter &rewriter, Location loc,
222 MemRefType memRefType = op.getType();
224 if (
auto alignmentAttr = op.getAlignment()) {
225 Type indexType = getIndexType();
228 }
else if (!memRefType.getElementType().isSignlessIntOrIndexOrFloat()) {
233 alignment =
getSizeInBytes(loc, memRefType.getElementType(), rewriter);
240 SymbolTableCollection *symbolTables =
nullptr;
243 explicit AlignedAllocOpLowering(
const LLVMTypeConverter &typeConverter,
244 SymbolTableCollection *symbolTables =
nullptr,
245 PatternBenefit benefit = 1)
246 : ConvertOpToLLVMPattern<memref::AllocOp>(typeConverter, benefit),
247 symbolTables(symbolTables) {}
250 matchAndRewrite(memref::AllocOp op, OpAdaptor adaptor,
251 ConversionPatternRewriter &rewriter)
const override {
252 auto loc = op.getLoc();
253 MemRefType memRefType = op.getType();
254 if (!isConvertibleAndHasIdentityMaps(memRefType))
255 return rewriter.notifyMatchFailure(op,
"incompatible memref type");
258 FailureOr<LLVM::LLVMFuncOp> allocFuncOp =
259 getAlignedAllocFn(rewriter, getTypeConverter(),
260 op->getParentWithTrait<OpTrait::SymbolTable>(),
261 getIndexType(), symbolTables);
268 SmallVector<Value, 4> sizes;
269 SmallVector<Value, 4> strides;
272 this->getMemRefDescriptorSizes(loc, memRefType, adaptor.getOperands(),
273 rewriter, sizes, strides, sizeBytes, !
false);
275 int64_t alignment = alignedAllocationGetAlignment(op, &defaultLayout);
277 Value allocAlignment =
282 if (!isMemRefSizeMultipleOf(memRefType, alignment, op, &defaultLayout))
283 sizeBytes = createAligned(rewriter, loc, sizeBytes, allocAlignment);
285 Type elementPtrType = this->getElementPtrType(memRefType);
287 LLVM::CallOp::create(rewriter, loc, allocFuncOp.value(),
291 castAllocFuncResult(rewriter, loc, results.getResult(), memRefType,
292 elementPtrType, *getTypeConverter());
295 auto memRefDescriptor = this->createMemRefDescriptor(
296 loc, memRefType, ptr, ptr, sizes, strides, rewriter);
299 rewriter.replaceOp(op, {memRefDescriptor});
304 static constexpr uint64_t kMinAlignedAllocAlignment = 16UL;
311 int64_t alignedAllocationGetAlignment(memref::AllocOp op,
312 const DataLayout *defaultLayout)
const {
313 if (std::optional<uint64_t> alignment = op.getAlignment())
319 unsigned eltSizeBytes = getMemRefEltSizeInBytes(
320 getTypeConverter(), op.getType(), op, defaultLayout);
321 return std::max(kMinAlignedAllocAlignment,
322 llvm::PowerOf2Ceil(eltSizeBytes));
327 bool isMemRefSizeMultipleOf(MemRefType type, uint64_t factor, Operation *op,
328 const DataLayout *defaultLayout)
const {
329 uint64_t sizeDivisor =
330 getMemRefEltSizeInBytes(getTypeConverter(), type, op, defaultLayout);
331 for (
unsigned i = 0, e = type.getRank(); i < e; i++) {
332 if (type.isDynamicDim(i))
334 sizeDivisor = sizeDivisor * type.getDimSize(i);
336 return sizeDivisor % factor == 0;
341 DataLayout defaultLayout;
345 using ConvertOpToLLVMPattern<memref::AllocaOp>::ConvertOpToLLVMPattern;
351 matchAndRewrite(memref::AllocaOp op, OpAdaptor adaptor,
352 ConversionPatternRewriter &rewriter)
const override {
353 auto loc = op.getLoc();
354 MemRefType memRefType = op.getType();
355 if (!isConvertibleAndHasIdentityMaps(memRefType))
356 return rewriter.notifyMatchFailure(op,
"incompatible memref type");
361 SmallVector<Value, 4> sizes;
362 SmallVector<Value, 4> strides;
365 this->getMemRefDescriptorSizes(loc, memRefType, adaptor.getOperands(),
366 rewriter, sizes, strides, size, !
true);
371 typeConverter->convertType(op.getType().getElementType());
372 FailureOr<unsigned> maybeAddressSpace =
374 assert(succeeded(maybeAddressSpace) &&
"unsupported address space");
375 unsigned addrSpace = *maybeAddressSpace;
376 auto elementPtrType =
377 LLVM::LLVMPointerType::get(rewriter.getContext(), addrSpace);
379 auto allocatedElementPtr =
380 LLVM::AllocaOp::create(rewriter, loc, elementPtrType, elementType, size,
381 op.getAlignment().value_or(0));
384 auto memRefDescriptor = this->createMemRefDescriptor(
385 loc, memRefType, allocatedElementPtr, allocatedElementPtr, sizes,
389 rewriter.replaceOp(op, {memRefDescriptor});
394struct AllocaScopeOpLowering
396 using ConvertOpToLLVMPattern<memref::AllocaScopeOp>::ConvertOpToLLVMPattern;
399 matchAndRewrite(memref::AllocaScopeOp allocaScopeOp, OpAdaptor adaptor,
400 ConversionPatternRewriter &rewriter)
const override {
401 OpBuilder::InsertionGuard guard(rewriter);
402 Location loc = allocaScopeOp.getLoc();
406 auto *currentBlock = rewriter.getInsertionBlock();
407 auto *remainingOpsBlock =
408 rewriter.splitBlock(currentBlock, rewriter.getInsertionPoint());
409 Block *continueBlock;
410 if (allocaScopeOp.getNumResults() == 0) {
411 continueBlock = remainingOpsBlock;
413 continueBlock = rewriter.createBlock(
414 remainingOpsBlock, allocaScopeOp.getResultTypes(),
415 SmallVector<Location>(allocaScopeOp->getNumResults(),
416 allocaScopeOp.getLoc()));
417 LLVM::BrOp::create(rewriter, loc,
ValueRange(), remainingOpsBlock);
421 Block *beforeBody = &allocaScopeOp.getBodyRegion().front();
422 Block *afterBody = &allocaScopeOp.getBodyRegion().back();
423 rewriter.inlineRegionBefore(allocaScopeOp.getBodyRegion(), continueBlock);
426 rewriter.setInsertionPointToEnd(currentBlock);
427 auto stackSaveOp = LLVM::StackSaveOp::create(rewriter, loc, getPtrType());
428 LLVM::BrOp::create(rewriter, loc,
ValueRange(), beforeBody);
432 rewriter.setInsertionPointToEnd(afterBody);
434 cast<memref::AllocaScopeReturnOp>(afterBody->
getTerminator());
435 auto branchOp = rewriter.replaceOpWithNewOp<LLVM::BrOp>(
436 returnOp, returnOp.getResults(), continueBlock);
439 rewriter.setInsertionPoint(branchOp);
440 LLVM::StackRestoreOp::create(rewriter, loc, stackSaveOp);
443 rewriter.replaceOp(allocaScopeOp, continueBlock->
getArguments());
449struct AssumeAlignmentOpLowering
451 using ConvertOpToLLVMPattern<
452 memref::AssumeAlignmentOp>::ConvertOpToLLVMPattern;
453 explicit AssumeAlignmentOpLowering(
const LLVMTypeConverter &converter)
454 : ConvertOpToLLVMPattern<memref::AssumeAlignmentOp>(converter) {}
457 matchAndRewrite(memref::AssumeAlignmentOp op, OpAdaptor adaptor,
458 ConversionPatternRewriter &rewriter)
const override {
459 Value memref = adaptor.getMemref();
460 unsigned alignment = op.getAlignment();
461 auto loc = op.getLoc();
463 auto srcMemRefType = cast<MemRefType>(op.getMemref().getType());
471 LLVM::ConstantOp::create(rewriter, loc, rewriter.getBoolAttr(
true));
472 Value alignmentConst =
474 LLVM::AssumeOp::create(rewriter, loc, trueCond, LLVM::AssumeAlignTag(), ptr,
476 rewriter.replaceOp(op, memref);
481struct DistinctObjectsOpLowering
483 using ConvertOpToLLVMPattern<
484 memref::DistinctObjectsOp>::ConvertOpToLLVMPattern;
485 explicit DistinctObjectsOpLowering(
const LLVMTypeConverter &converter)
486 : ConvertOpToLLVMPattern<memref::DistinctObjectsOp>(converter) {}
489 matchAndRewrite(memref::DistinctObjectsOp op, OpAdaptor adaptor,
490 ConversionPatternRewriter &rewriter)
const override {
492 if (operands.size() <= 1) {
494 rewriter.replaceOp(op, operands);
498 Location loc = op.getLoc();
499 SmallVector<Value> ptrs;
500 for (
auto [origOperand, newOperand] :
501 llvm::zip_equal(op.getOperands(), operands)) {
502 auto memrefType = cast<MemRefType>(origOperand.getType());
503 MemRefDescriptor memRefDescriptor(newOperand);
504 Value ptr = memRefDescriptor.bufferPtr(rewriter, loc, *getTypeConverter(),
510 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI1Type(), 1);
512 for (
auto i : llvm::seq<size_t>(ptrs.size() - 1)) {
513 for (
auto j : llvm::seq<size_t>(i + 1, ptrs.size())) {
514 Value ptr1 = ptrs[i];
515 Value ptr2 = ptrs[j];
516 LLVM::AssumeOp::create(rewriter, loc, cond,
517 LLVM::AssumeSeparateStorageTag{}, ptr1, ptr2);
521 rewriter.replaceOp(op, operands);
530 SymbolTableCollection *symbolTables =
nullptr;
533 explicit DeallocOpLowering(
const LLVMTypeConverter &typeConverter,
534 SymbolTableCollection *symbolTables =
nullptr,
535 PatternBenefit benefit = 1)
536 : ConvertOpToLLVMPattern<memref::DeallocOp>(typeConverter, benefit),
537 symbolTables(symbolTables) {}
540 matchAndRewrite(memref::DeallocOp op, OpAdaptor adaptor,
541 ConversionPatternRewriter &rewriter)
const override {
543 FailureOr<LLVM::LLVMFuncOp> freeFunc =
544 getFreeFn(rewriter, getTypeConverter(),
545 op->getParentWithTrait<OpTrait::SymbolTable>(), symbolTables);
549 if (
auto unrankedTy =
550 llvm::dyn_cast<UnrankedMemRefType>(op.getMemref().getType())) {
551 auto elementPtrTy = LLVM::LLVMPointerType::get(
552 rewriter.getContext(), unrankedTy.getMemorySpaceAsInt());
554 rewriter, op.getLoc(),
555 UnrankedMemRefDescriptor(adaptor.getMemref())
556 .memRefDescPtr(rewriter, op.getLoc()),
559 allocatedPtr = MemRefDescriptor(adaptor.getMemref())
560 .allocatedPtr(rewriter, op.getLoc());
564 Type freeArgTy = getPtrType();
565 if (allocatedPtr.
getType() != freeArgTy)
566 allocatedPtr = LLVM::AddrSpaceCastOp::create(rewriter, op.getLoc(),
567 freeArgTy, allocatedPtr);
568 rewriter.replaceOpWithNewOp<LLVM::CallOp>(op, freeFunc.value(),
577 using ConvertOpToLLVMPattern<memref::DimOp>::ConvertOpToLLVMPattern;
580 matchAndRewrite(memref::DimOp dimOp, OpAdaptor adaptor,
581 ConversionPatternRewriter &rewriter)
const override {
582 Type operandType = dimOp.getSource().getType();
583 if (isa<UnrankedMemRefType>(operandType)) {
584 FailureOr<Value> extractedSize = extractSizeOfUnrankedMemRef(
585 operandType, dimOp, adaptor.getOperands(), rewriter);
586 if (
failed(extractedSize))
588 rewriter.replaceOp(dimOp, {*extractedSize});
591 if (isa<MemRefType>(operandType)) {
593 dimOp, {extractSizeOfRankedMemRef(operandType, dimOp,
594 adaptor.getOperands(), rewriter)});
597 llvm_unreachable(
"expected MemRefType or UnrankedMemRefType");
602 extractSizeOfUnrankedMemRef(Type operandType, memref::DimOp dimOp,
604 ConversionPatternRewriter &rewriter)
const {
605 Location loc = dimOp.getLoc();
607 auto unrankedMemRefType = cast<UnrankedMemRefType>(operandType);
608 auto scalarMemRefType =
609 MemRefType::get({}, unrankedMemRefType.getElementType());
610 FailureOr<unsigned> maybeAddressSpace =
611 getTypeConverter()->getMemRefAddressSpace(unrankedMemRefType);
612 if (
failed(maybeAddressSpace)) {
613 dimOp.emitOpError(
"memref memory space must be convertible to an integer "
617 unsigned addressSpace = *maybeAddressSpace;
622 UnrankedMemRefDescriptor unrankedDesc(adaptor.getSource());
623 Value underlyingRankedDesc = unrankedDesc.memRefDescPtr(rewriter, loc);
625 Type elementType = typeConverter->convertType(scalarMemRefType);
629 LLVM::LLVMPointerType::get(rewriter.getContext(), addressSpace);
631 LLVM::GEPOp::create(rewriter, loc, indexPtrTy, elementType,
632 underlyingRankedDesc, ArrayRef<LLVM::GEPArg>{0, 2});
636 Value idxPlusOne = LLVM::AddOp::create(
640 Value sizePtr = LLVM::GEPOp::create(rewriter, loc, indexPtrTy,
641 getTypeConverter()->getIndexType(),
642 offsetPtr, idxPlusOne);
643 return LLVM::LoadOp::create(rewriter, loc,
644 getTypeConverter()->getIndexType(), sizePtr)
648 std::optional<int64_t> getConstantDimIndex(memref::DimOp dimOp)
const {
649 if (
auto idx = dimOp.getConstantIndex())
652 if (
auto constantOp = dimOp.getIndex().getDefiningOp<LLVM::ConstantOp>())
653 return cast<IntegerAttr>(constantOp.getValue()).getValue().getSExtValue();
658 Value extractSizeOfRankedMemRef(Type operandType, memref::DimOp dimOp,
660 ConversionPatternRewriter &rewriter)
const {
661 Location loc = dimOp.getLoc();
664 MemRefType memRefType = cast<MemRefType>(operandType);
665 Type indexType = getIndexType();
666 if (std::optional<int64_t> index = getConstantDimIndex(dimOp)) {
668 if (i >= 0 && i < memRefType.getRank()) {
669 if (memRefType.isDynamicDim(i)) {
671 MemRefDescriptor descriptor(adaptor.getSource());
672 return descriptor.size(rewriter, loc, i);
675 int64_t dimSize = memRefType.getDimSize(i);
679 Value index = adaptor.getIndex();
680 int64_t rank = memRefType.getRank();
681 MemRefDescriptor memrefDescriptor(adaptor.getSource());
682 return memrefDescriptor.size(rewriter, loc, index, rank);
689template <
typename Derived>
691 using ConvertOpToLLVMPattern<Derived>::ConvertOpToLLVMPattern;
692 using ConvertOpToLLVMPattern<Derived>::isConvertibleAndHasIdentityMaps;
693 using Base = LoadStoreOpLowering<Derived>;
723struct GenericAtomicRMWOpLowering
724 :
public LoadStoreOpLowering<memref::GenericAtomicRMWOp> {
728 matchAndRewrite(memref::GenericAtomicRMWOp atomicOp, OpAdaptor adaptor,
729 ConversionPatternRewriter &rewriter)
const override {
730 auto loc = atomicOp.getLoc();
731 Type valueType = typeConverter->convertType(atomicOp.getResult().getType());
736 bool needsBitcast = isa<FloatType>(valueType);
737 Type cmpxchgType = valueType;
739 unsigned bitWidth = cast<FloatType>(valueType).getWidth();
740 cmpxchgType = rewriter.getIntegerType(bitWidth);
744 auto *initBlock = rewriter.getInsertionBlock();
745 auto *loopBlock = rewriter.splitBlock(initBlock,
Block::iterator(atomicOp));
746 loopBlock->addArgument(cmpxchgType, loc);
752 rewriter.setInsertionPointToEnd(initBlock);
753 auto memRefType = cast<MemRefType>(atomicOp.getMemref().getType());
755 rewriter, loc, memRefType, adaptor.getMemref(), adaptor.getIndices());
756 Value init = LLVM::LoadOp::create(
757 rewriter, loc, typeConverter->convertType(memRefType.getElementType()),
760 init = LLVM::BitcastOp::create(rewriter, loc, cmpxchgType, init);
761 LLVM::BrOp::create(rewriter, loc, init, loopBlock);
764 rewriter.setInsertionPointToStart(loopBlock);
767 Value loopArgument = loopBlock->getArgument(0);
768 Value loopArgForBody = loopArgument;
771 LLVM::BitcastOp::create(rewriter, loc, valueType, loopArgument);
773 mapping.
map(atomicOp.getCurrentValue(), loopArgForBody);
774 Block &entryBlock = atomicOp.body().front();
776 Operation *
clone = rewriter.clone(nestedOp, mapping);
784 result = LLVM::BitcastOp::create(rewriter, loc, cmpxchgType,
result);
788 auto successOrdering = LLVM::AtomicOrdering::acq_rel;
789 auto failureOrdering = LLVM::AtomicOrdering::monotonic;
791 LLVM::AtomicCmpXchgOp::create(rewriter, loc, dataPtr, loopArgument,
792 result, successOrdering, failureOrdering);
794 Value newLoaded = LLVM::ExtractValueOp::create(rewriter, loc, cmpxchg, 0);
795 Value ok = LLVM::ExtractValueOp::create(rewriter, loc, cmpxchg, 1);
798 LLVM::CondBrOp::create(rewriter, loc, ok, endBlock, ArrayRef<Value>(),
799 loopBlock, newLoaded);
805 rewriter.setInsertionPointToStart(endBlock);
806 newLoaded = LLVM::BitcastOp::create(rewriter, loc, valueType, newLoaded);
808 rewriter.setInsertionPointToEnd(endBlock);
809 rewriter.replaceOp(atomicOp, {newLoaded});
817convertGlobalMemrefTypeToLLVM(MemRefType type,
824 Type elementType = typeConverter.convertType(type.getElementType());
825 Type arrayTy = elementType;
827 for (
int64_t dim : llvm::reverse(type.getShape()))
828 arrayTy = LLVM::LLVMArrayType::get(arrayTy, dim);
834 SymbolTableCollection *symbolTables =
nullptr;
837 explicit GlobalMemrefOpLowering(
const LLVMTypeConverter &typeConverter,
838 SymbolTableCollection *symbolTables =
nullptr,
839 PatternBenefit benefit = 1)
840 : ConvertOpToLLVMPattern<memref::GlobalOp>(typeConverter, benefit),
841 symbolTables(symbolTables) {}
844 matchAndRewrite(memref::GlobalOp global, OpAdaptor adaptor,
845 ConversionPatternRewriter &rewriter)
const override {
846 MemRefType type = global.
getType();
847 if (!isConvertibleAndHasIdentityMaps(type))
850 Type arrayTy = convertGlobalMemrefTypeToLLVM(type, *getTypeConverter());
852 LLVM::Linkage linkage =
853 global.isPublic() ? LLVM::Linkage::External : LLVM::Linkage::Private;
854 bool isExternal = global.isExternal();
855 bool isUninitialized = global.isUninitialized();
857 Attribute initialValue =
nullptr;
858 if (!isExternal && !isUninitialized) {
859 auto elementsAttr = llvm::cast<ElementsAttr>(*global.getInitialValue());
860 initialValue = elementsAttr;
864 if (type.getRank() == 0)
865 initialValue = elementsAttr.getSplatValue<Attribute>();
868 uint64_t alignment = global.getAlignment().value_or(0);
869 FailureOr<unsigned> addressSpace =
870 getTypeConverter()->getMemRefAddressSpace(type);
872 return global.emitOpError(
873 "memory space cannot be converted to an integer address space");
876 SymbolTable *symbolTable =
nullptr;
878 Operation *symbolTableOp =
879 global->getParentWithTrait<OpTrait::SymbolTable>();
880 symbolTable = &symbolTables->getSymbolTable(symbolTableOp);
881 symbolTable->remove(global);
885 auto newGlobal = rewriter.replaceOpWithNewOp<LLVM::GlobalOp>(
886 global, arrayTy, global.getConstant(), linkage, global.getSymName(),
887 initialValue, alignment, *addressSpace);
891 symbolTable->insert(newGlobal, rewriter.getInsertionPoint());
893 if (!isExternal && isUninitialized) {
894 rewriter.createBlock(&newGlobal.getInitializerRegion());
896 LLVM::UndefOp::create(rewriter, newGlobal.getLoc(), arrayTy)};
897 LLVM::ReturnOp::create(rewriter, newGlobal.getLoc(), undef);
906struct GetGlobalMemrefOpLowering
908 using ConvertOpToLLVMPattern<memref::GetGlobalOp>::ConvertOpToLLVMPattern;
913 matchAndRewrite(memref::GetGlobalOp op, OpAdaptor adaptor,
914 ConversionPatternRewriter &rewriter)
const override {
915 auto loc = op.getLoc();
916 MemRefType memRefType = op.getType();
917 if (!isConvertibleAndHasIdentityMaps(memRefType))
918 return rewriter.notifyMatchFailure(op,
"incompatible memref type");
923 SmallVector<Value, 4> sizes;
924 SmallVector<Value, 4> strides;
927 this->getMemRefDescriptorSizes(loc, memRefType, adaptor.getOperands(),
928 rewriter, sizes, strides, sizeBytes, !
false);
930 MemRefType type = cast<MemRefType>(op.getResult().getType());
934 FailureOr<unsigned> maybeAddressSpace =
935 getTypeConverter()->getMemRefAddressSpace(type);
936 assert(succeeded(maybeAddressSpace) &&
"unsupported address space");
937 unsigned memSpace = *maybeAddressSpace;
939 Type arrayTy = convertGlobalMemrefTypeToLLVM(type, *getTypeConverter());
940 auto ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext(), memSpace);
942 LLVM::AddressOfOp::create(rewriter, loc, ptrTy, op.getName());
947 LLVM::GEPOp::create(rewriter, loc, ptrTy, arrayTy, addressOf,
948 SmallVector<LLVM::GEPArg>(type.getRank() + 1, 0));
953 auto intPtrType = getIntPtrType(memSpace);
954 Value deadBeefConst =
957 LLVM::IntToPtrOp::create(rewriter, loc, ptrTy, deadBeefConst);
962 auto memRefDescriptor = this->createMemRefDescriptor(
963 loc, memRefType, deadBeefPtr, gep, sizes, strides, rewriter);
966 rewriter.replaceOp(op, {memRefDescriptor});
973struct LoadOpLowering :
public LoadStoreOpLowering<memref::LoadOp> {
977 matchAndRewrite(memref::LoadOp loadOp, OpAdaptor adaptor,
978 ConversionPatternRewriter &rewriter)
const override {
979 auto type = loadOp.getMemRefType();
985 rewriter, loadOp.getLoc(), type, adaptor.getMemref(),
987 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(
988 loadOp, typeConverter->convertType(type.getElementType()), dataPtr,
989 loadOp.getAlignment().value_or(0),
false, loadOp.getNontemporal(),
990 loadOp.getInvariant());
997struct StoreOpLowering :
public LoadStoreOpLowering<memref::StoreOp> {
1001 matchAndRewrite(memref::StoreOp op, OpAdaptor adaptor,
1002 ConversionPatternRewriter &rewriter)
const override {
1003 auto type = op.getMemRefType();
1009 rewriter, op.getLoc(), type, adaptor.getMemref(), adaptor.getIndices(),
1011 rewriter.replaceOpWithNewOp<LLVM::StoreOp>(op, adaptor.getValue(), dataPtr,
1012 op.getAlignment().value_or(0),
1013 false, op.getNontemporal());
1020struct PrefetchOpLowering :
public LoadStoreOpLowering<memref::PrefetchOp> {
1024 matchAndRewrite(memref::PrefetchOp prefetchOp, OpAdaptor adaptor,
1025 ConversionPatternRewriter &rewriter)
const override {
1026 auto type = prefetchOp.getMemRefType();
1027 auto loc = prefetchOp.getLoc();
1030 rewriter, loc, type, adaptor.getMemref(), adaptor.getIndices());
1033 IntegerAttr isWrite = rewriter.getI32IntegerAttr(prefetchOp.getIsWrite());
1034 IntegerAttr localityHint = prefetchOp.getLocalityHintAttr();
1035 IntegerAttr isData =
1036 rewriter.getI32IntegerAttr(prefetchOp.getIsDataCache());
1037 rewriter.replaceOpWithNewOp<LLVM::Prefetch>(prefetchOp, dataPtr, isWrite,
1038 localityHint, isData);
1044 using ConvertOpToLLVMPattern<memref::RankOp>::ConvertOpToLLVMPattern;
1047 matchAndRewrite(memref::RankOp op, OpAdaptor adaptor,
1048 ConversionPatternRewriter &rewriter)
const override {
1049 Location loc = op.getLoc();
1050 Type operandType = op.getMemref().getType();
1051 if (isa<UnrankedMemRefType>(operandType)) {
1052 UnrankedMemRefDescriptor desc(adaptor.getMemref());
1053 rewriter.replaceOp(op, {desc.rank(rewriter, loc)});
1056 if (
auto rankedMemRefType = dyn_cast<MemRefType>(operandType)) {
1057 Type indexType = getIndexType();
1058 rewriter.replaceOp(op,
1060 rankedMemRefType.getRank())});
1071 matchAndRewrite(memref::CastOp memRefCastOp, OpAdaptor adaptor,
1072 ConversionPatternRewriter &rewriter)
const override {
1073 Type srcType = memRefCastOp.getOperand().getType();
1074 Type dstType = memRefCastOp.getType();
1081 if (isa<MemRefType>(srcType) && isa<MemRefType>(dstType))
1082 if (typeConverter->convertType(srcType) !=
1083 typeConverter->convertType(dstType))
1087 if (isa<UnrankedMemRefType>(srcType) && isa<UnrankedMemRefType>(dstType))
1090 auto targetStructType = typeConverter->convertType(memRefCastOp.getType());
1091 auto loc = memRefCastOp.getLoc();
1094 if (isa<MemRefType>(srcType) && isa<MemRefType>(dstType)) {
1095 rewriter.replaceOp(memRefCastOp, {adaptor.getSource()});
1099 if (isa<MemRefType>(srcType) && isa<UnrankedMemRefType>(dstType)) {
1104 auto srcMemRefType = cast<MemRefType>(srcType);
1105 int64_t rank = srcMemRefType.getRank();
1107 auto ptr = getTypeConverter()->promoteOneMemRefDescriptor(
1108 loc, adaptor.getSource(), rewriter);
1114 UnrankedMemRefDescriptor memRefDesc =
1117 memRefDesc.
setRank(rewriter, loc, rankVal);
1120 rewriter.replaceOp(memRefCastOp, (Value)memRefDesc);
1122 }
else if (isa<UnrankedMemRefType>(srcType) && isa<MemRefType>(dstType)) {
1126 UnrankedMemRefDescriptor memRefDesc(adaptor.getSource());
1131 auto loadOp = LLVM::LoadOp::create(rewriter, loc, targetStructType, ptr);
1132 rewriter.replaceOp(memRefCastOp, loadOp.getResult());
1134 llvm_unreachable(
"Unsupported unranked memref to unranked memref cast");
1147 SymbolTableCollection *symbolTables =
nullptr;
1150 explicit MemRefCopyOpLowering(
const LLVMTypeConverter &typeConverter,
1151 SymbolTableCollection *symbolTables =
nullptr,
1152 PatternBenefit benefit = 1)
1153 : ConvertOpToLLVMPattern<memref::CopyOp>(typeConverter, benefit),
1154 symbolTables(symbolTables) {}
1157 lowerToMemCopyIntrinsic(memref::CopyOp op, OpAdaptor adaptor,
1158 ConversionPatternRewriter &rewriter)
const {
1159 auto loc = op.getLoc();
1160 auto srcType = dyn_cast<MemRefType>(op.getSource().getType());
1162 MemRefDescriptor srcDesc(adaptor.getSource());
1167 for (
int pos = 0; pos < srcType.getRank(); ++pos) {
1168 auto size = srcDesc.size(rewriter, loc, pos);
1169 numElements = LLVM::MulOp::create(rewriter, loc, numElements, size);
1173 auto sizeInBytes =
getSizeInBytes(loc, srcType.getElementType(), rewriter);
1176 LLVM::MulOp::create(rewriter, loc, numElements, sizeInBytes);
1178 Type elementType = typeConverter->convertType(srcType.getElementType());
1180 Value srcBasePtr = srcDesc.alignedPtr(rewriter, loc);
1181 Value srcOffset = srcDesc.offset(rewriter, loc);
1182 Value srcPtr = LLVM::GEPOp::create(rewriter, loc, srcBasePtr.
getType(),
1183 elementType, srcBasePtr, srcOffset);
1184 MemRefDescriptor targetDesc(adaptor.getTarget());
1185 Value targetBasePtr = targetDesc.alignedPtr(rewriter, loc);
1186 Value targetOffset = targetDesc.offset(rewriter, loc);
1188 LLVM::GEPOp::create(rewriter, loc, targetBasePtr.
getType(), elementType,
1189 targetBasePtr, targetOffset);
1190 LLVM::MemcpyOp::create(rewriter, loc, targetPtr, srcPtr, totalSize,
1192 rewriter.eraseOp(op);
1198 lowerToMemCopyFunctionCall(memref::CopyOp op, OpAdaptor adaptor,
1199 ConversionPatternRewriter &rewriter)
const {
1200 auto loc = op.getLoc();
1201 auto srcType = cast<BaseMemRefType>(op.getSource().getType());
1202 auto targetType = cast<BaseMemRefType>(op.getTarget().getType());
1205 auto makeUnranked = [&,
this](Value ranked, MemRefType type) {
1206 auto rank = LLVM::ConstantOp::create(rewriter, loc, getIndexType(),
1208 auto *typeConverter = getTypeConverter();
1213 UnrankedMemRefType::get(type.getElementType(), type.getMemorySpace());
1215 rewriter, loc, *typeConverter, unrankedType,
ValueRange{rank, ptr});
1219 auto stackSaveOp = LLVM::StackSaveOp::create(rewriter, loc, getPtrType());
1221 auto srcMemRefType = dyn_cast<MemRefType>(srcType);
1222 Value unrankedSource =
1223 srcMemRefType ? makeUnranked(adaptor.getSource(), srcMemRefType)
1224 : adaptor.getSource();
1225 auto targetMemRefType = dyn_cast<MemRefType>(targetType);
1226 Value unrankedTarget =
1227 targetMemRefType ? makeUnranked(adaptor.getTarget(), targetMemRefType)
1228 : adaptor.getTarget();
1232 auto promote = [&](Value desc) {
1233 auto ptrType = LLVM::LLVMPointerType::get(rewriter.getContext());
1235 LLVM::AllocaOp::create(rewriter, loc, ptrType, desc.getType(), one);
1236 LLVM::StoreOp::create(rewriter, loc, desc, allocated);
1240 auto sourcePtr =
promote(unrankedSource);
1241 auto targetPtr =
promote(unrankedTarget);
1245 auto elemSize =
getSizeInBytes(loc, srcType.getElementType(), rewriter);
1246 auto copyFn = LLVM::lookupOrCreateMemRefCopyFn(
1247 rewriter, op->getParentOfType<ModuleOp>(), getIndexType(),
1248 sourcePtr.getType(), symbolTables);
1251 LLVM::CallOp::create(rewriter, loc, copyFn.value(),
1255 LLVM::StackRestoreOp::create(rewriter, loc, stackSaveOp);
1257 rewriter.eraseOp(op);
1263 matchAndRewrite(memref::CopyOp op, OpAdaptor adaptor,
1264 ConversionPatternRewriter &rewriter)
const override {
1265 auto srcType = cast<BaseMemRefType>(op.getSource().getType());
1266 auto targetType = cast<BaseMemRefType>(op.getTarget().getType());
1268 auto isContiguousMemrefType = [&](BaseMemRefType type) {
1269 auto memrefType = dyn_cast<mlir::MemRefType>(type);
1273 return memrefType &&
1274 (memrefType.getLayout().isIdentity() ||
1275 (memrefType.hasStaticShape() && memrefType.getNumElements() > 0 &&
1279 if (isContiguousMemrefType(srcType) && isContiguousMemrefType(targetType))
1280 return lowerToMemCopyIntrinsic(op, adaptor, rewriter);
1282 return lowerToMemCopyFunctionCall(op, adaptor, rewriter);
1286struct MemorySpaceCastOpLowering
1288 using ConvertOpToLLVMPattern<
1289 memref::MemorySpaceCastOp>::ConvertOpToLLVMPattern;
1292 matchAndRewrite(memref::MemorySpaceCastOp op, OpAdaptor adaptor,
1293 ConversionPatternRewriter &rewriter)
const override {
1294 Location loc = op.getLoc();
1296 Type resultType = op.getDest().getType();
1297 if (
auto resultTypeR = dyn_cast<MemRefType>(resultType)) {
1298 auto convertedType =
1299 typeConverter->convertType<LLVM::LLVMStructType>(resultTypeR);
1301 return rewriter.notifyMatchFailure(op,
"memref type conversion failed");
1302 Type newPtrType = convertedType.getBody()[0];
1304 SmallVector<Value> descVals;
1305 MemRefDescriptor::unpack(rewriter, loc, adaptor.getSource(), resultTypeR,
1308 LLVM::AddrSpaceCastOp::create(rewriter, loc, newPtrType, descVals[0]);
1310 LLVM::AddrSpaceCastOp::create(rewriter, loc, newPtrType, descVals[1]);
1311 Value
result = MemRefDescriptor::pack(rewriter, loc, *getTypeConverter(),
1312 resultTypeR, descVals);
1313 rewriter.replaceOp(op,
result);
1316 if (
auto resultTypeU = dyn_cast<UnrankedMemRefType>(resultType)) {
1319 auto sourceType = cast<UnrankedMemRefType>(op.getSource().getType());
1320 FailureOr<unsigned> maybeSourceAddrSpace =
1321 getTypeConverter()->getMemRefAddressSpace(sourceType);
1322 if (
failed(maybeSourceAddrSpace))
1323 return rewriter.notifyMatchFailure(loc,
1324 "non-integer source address space");
1325 unsigned sourceAddrSpace = *maybeSourceAddrSpace;
1326 FailureOr<unsigned> maybeResultAddrSpace =
1327 getTypeConverter()->getMemRefAddressSpace(resultTypeU);
1328 if (
failed(maybeResultAddrSpace))
1329 return rewriter.notifyMatchFailure(loc,
1330 "non-integer result address space");
1331 unsigned resultAddrSpace = *maybeResultAddrSpace;
1333 UnrankedMemRefDescriptor sourceDesc(adaptor.getSource());
1334 Value rank = sourceDesc.rank(rewriter, loc);
1335 Value sourceUnderlyingDesc = sourceDesc.memRefDescPtr(rewriter, loc);
1339 rewriter, loc, typeConverter->convertType(resultTypeU));
1340 result.setRank(rewriter, loc, rank);
1342 rewriter, loc, *getTypeConverter(),
result, resultAddrSpace);
1343 Value resultUnderlyingDesc =
1344 LLVM::AllocaOp::create(rewriter, loc, getPtrType(),
1345 rewriter.getI8Type(), resultUnderlyingSize);
1346 result.setMemRefDescPtr(rewriter, loc, resultUnderlyingDesc);
1349 auto sourceElemPtrType =
1350 LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace);
1351 auto resultElemPtrType =
1352 LLVM::LLVMPointerType::get(rewriter.getContext(), resultAddrSpace);
1354 Value allocatedPtr = sourceDesc.allocatedPtr(
1355 rewriter, loc, sourceUnderlyingDesc, sourceElemPtrType);
1357 sourceDesc.alignedPtr(rewriter, loc, *getTypeConverter(),
1358 sourceUnderlyingDesc, sourceElemPtrType);
1359 allocatedPtr = LLVM::AddrSpaceCastOp::create(
1360 rewriter, loc, resultElemPtrType, allocatedPtr);
1361 alignedPtr = LLVM::AddrSpaceCastOp::create(rewriter, loc,
1362 resultElemPtrType, alignedPtr);
1364 result.setAllocatedPtr(rewriter, loc, resultUnderlyingDesc,
1365 resultElemPtrType, allocatedPtr);
1366 result.setAlignedPtr(rewriter, loc, *getTypeConverter(),
1367 resultUnderlyingDesc, resultElemPtrType, alignedPtr);
1370 Value sourceIndexVals =
1371 sourceDesc.offsetBasePtr(rewriter, loc, *getTypeConverter(),
1372 sourceUnderlyingDesc, sourceElemPtrType);
1373 Value resultIndexVals =
1374 result.offsetBasePtr(rewriter, loc, *getTypeConverter(),
1375 resultUnderlyingDesc, resultElemPtrType);
1377 int64_t bytesToSkip =
1378 2 * llvm::divideCeil(
1379 getTypeConverter()->getPointerBitwidth(resultAddrSpace), 8);
1380 Value bytesToSkipConst =
1383 LLVM::SubOp::create(rewriter, loc, getIndexType(),
1384 resultUnderlyingSize, bytesToSkipConst);
1385 LLVM::MemcpyOp::create(rewriter, loc, resultIndexVals, sourceIndexVals,
1391 return rewriter.notifyMatchFailure(loc,
"unexpected memref type");
1398static void extractPointersAndOffset(
Location loc,
1399 ConversionPatternRewriter &rewriter,
1401 Value originalOperand,
1402 Value convertedOperand,
1404 Value *offset =
nullptr) {
1406 if (isa<MemRefType>(operandType)) {
1408 *allocatedPtr = desc.allocatedPtr(rewriter, loc);
1409 *alignedPtr = desc.alignedPtr(rewriter, loc);
1410 if (offset !=
nullptr)
1411 *offset = desc.offset(rewriter, loc);
1417 cast<UnrankedMemRefType>(operandType));
1418 auto elementPtrType =
1419 LLVM::LLVMPointerType::get(rewriter.getContext(), memorySpace);
1424 Value underlyingDescPtr = unrankedDesc.memRefDescPtr(rewriter, loc);
1427 rewriter, loc, underlyingDescPtr, elementPtrType);
1429 rewriter, loc, typeConverter, underlyingDescPtr, elementPtrType);
1430 if (offset !=
nullptr) {
1432 rewriter, loc, typeConverter, underlyingDescPtr, elementPtrType);
1436struct MemRefReinterpretCastOpLowering
1438 using ConvertOpToLLVMPattern<
1439 memref::ReinterpretCastOp>::ConvertOpToLLVMPattern;
1442 matchAndRewrite(memref::ReinterpretCastOp castOp, OpAdaptor adaptor,
1443 ConversionPatternRewriter &rewriter)
const override {
1444 Type srcType = castOp.getSource().getType();
1447 if (
failed(convertSourceMemRefToDescriptor(rewriter, srcType, castOp,
1448 adaptor, &descriptor)))
1450 rewriter.replaceOp(castOp, {descriptor});
1455 LogicalResult convertSourceMemRefToDescriptor(
1456 ConversionPatternRewriter &rewriter, Type srcType,
1457 memref::ReinterpretCastOp castOp,
1458 memref::ReinterpretCastOp::Adaptor adaptor, Value *descriptor)
const {
1459 MemRefType targetMemRefType =
1460 cast<MemRefType>(castOp.getResult().getType());
1461 auto llvmTargetDescriptorTy =
1462 typeConverter->convertType<LLVM::LLVMStructType>(targetMemRefType);
1463 if (!llvmTargetDescriptorTy)
1467 Location loc = castOp.getLoc();
1468 auto desc = MemRefDescriptor::poison(rewriter, loc, llvmTargetDescriptorTy);
1471 Value allocatedPtr, alignedPtr;
1472 extractPointersAndOffset(loc, rewriter, *getTypeConverter(),
1473 castOp.getSource(), adaptor.getSource(),
1474 &allocatedPtr, &alignedPtr);
1475 desc.setAllocatedPtr(rewriter, loc, allocatedPtr);
1476 desc.setAlignedPtr(rewriter, loc, alignedPtr);
1479 if (castOp.isDynamicOffset(0))
1480 desc.setOffset(rewriter, loc, adaptor.getOffsets()[0]);
1482 desc.setConstantOffset(rewriter, loc, castOp.getStaticOffset(0));
1485 unsigned dynSizeId = 0;
1486 unsigned dynStrideId = 0;
1487 for (
unsigned i = 0, e = targetMemRefType.getRank(); i < e; ++i) {
1488 if (castOp.isDynamicSize(i))
1489 desc.setSize(rewriter, loc, i, adaptor.getSizes()[dynSizeId++]);
1491 desc.setConstantSize(rewriter, loc, i, castOp.getStaticSize(i));
1493 if (castOp.isDynamicStride(i))
1494 desc.setStride(rewriter, loc, i, adaptor.getStrides()[dynStrideId++]);
1496 desc.setConstantStride(rewriter, loc, i, castOp.getStaticStride(i));
1503struct MemRefReshapeOpLowering
1505 using ConvertOpToLLVMPattern<memref::ReshapeOp>::ConvertOpToLLVMPattern;
1508 matchAndRewrite(memref::ReshapeOp reshapeOp, OpAdaptor adaptor,
1509 ConversionPatternRewriter &rewriter)
const override {
1510 Type srcType = reshapeOp.getSource().getType();
1513 if (
failed(convertSourceMemRefToDescriptor(rewriter, srcType, reshapeOp,
1514 adaptor, &descriptor)))
1516 rewriter.replaceOp(reshapeOp, {descriptor});
1522 convertSourceMemRefToDescriptor(ConversionPatternRewriter &rewriter,
1523 Type srcType, memref::ReshapeOp reshapeOp,
1524 memref::ReshapeOp::Adaptor adaptor,
1525 Value *descriptor)
const {
1526 auto shapeMemRefType = cast<MemRefType>(reshapeOp.getShape().getType());
1527 if (shapeMemRefType.hasStaticShape()) {
1528 MemRefType targetMemRefType =
1529 cast<MemRefType>(reshapeOp.getResult().getType());
1530 auto llvmTargetDescriptorTy =
1531 typeConverter->convertType<LLVM::LLVMStructType>(targetMemRefType);
1532 if (!llvmTargetDescriptorTy)
1536 Location loc = reshapeOp.getLoc();
1538 MemRefDescriptor::poison(rewriter, loc, llvmTargetDescriptorTy);
1541 Value allocatedPtr, alignedPtr;
1542 extractPointersAndOffset(loc, rewriter, *getTypeConverter(),
1543 reshapeOp.getSource(), adaptor.getSource(),
1544 &allocatedPtr, &alignedPtr);
1545 desc.setAllocatedPtr(rewriter, loc, allocatedPtr);
1546 desc.setAlignedPtr(rewriter, loc, alignedPtr);
1550 SmallVector<int64_t> strides;
1551 if (
failed(targetMemRefType.getStridesAndOffset(strides, offset)))
1552 return rewriter.notifyMatchFailure(
1553 reshapeOp,
"failed to get stride and offset exprs");
1555 if (!isStaticStrideOrOffset(offset))
1556 return rewriter.notifyMatchFailure(reshapeOp,
1557 "dynamic offset is unsupported");
1559 desc.setConstantOffset(rewriter, loc, offset);
1561 assert(targetMemRefType.getLayout().isIdentity() &&
1562 "Identity layout map is a precondition of a valid reshape op");
1564 Type indexType = getIndexType();
1565 Value stride =
nullptr;
1566 int64_t targetRank = targetMemRefType.getRank();
1567 for (
auto i : llvm::reverse(llvm::seq<int64_t>(0, targetRank))) {
1568 if (ShapedType::isStatic(strides[i])) {
1573 }
else if (!stride) {
1583 if (!targetMemRefType.isDynamicDim(i)) {
1585 targetMemRefType.getDimSize(i));
1587 Value shapeOp = reshapeOp.getShape();
1589 dimSize = memref::LoadOp::create(rewriter, loc, shapeOp, index);
1590 Type indexType = getIndexType();
1591 if (dimSize.
getType() != indexType)
1592 dimSize = typeConverter->materializeTargetConversion(
1593 rewriter, loc, indexType, dimSize);
1594 assert(dimSize &&
"Invalid memref element type");
1597 desc.setSize(rewriter, loc, i, dimSize);
1598 desc.setStride(rewriter, loc, i, stride);
1601 stride = LLVM::MulOp::create(rewriter, loc, stride, dimSize);
1609 Location loc = reshapeOp.getLoc();
1610 MemRefDescriptor shapeDesc(adaptor.getShape());
1611 Value resultRank = shapeDesc.size(rewriter, loc, 0);
1614 auto targetType = cast<UnrankedMemRefType>(reshapeOp.getResult().getType());
1615 unsigned addressSpace =
1616 *getTypeConverter()->getMemRefAddressSpace(targetType);
1621 rewriter, loc, typeConverter->convertType(targetType));
1622 targetDesc.setRank(rewriter, loc, resultRank);
1624 rewriter, loc, *getTypeConverter(), targetDesc, addressSpace);
1625 Value underlyingDescPtr = LLVM::AllocaOp::create(
1626 rewriter, loc, getPtrType(), IntegerType::get(
getContext(), 8),
1628 targetDesc.setMemRefDescPtr(rewriter, loc, underlyingDescPtr);
1631 Value allocatedPtr, alignedPtr, offset;
1632 extractPointersAndOffset(loc, rewriter, *getTypeConverter(),
1633 reshapeOp.getSource(), adaptor.getSource(),
1634 &allocatedPtr, &alignedPtr, &offset);
1637 auto elementPtrType =
1638 LLVM::LLVMPointerType::get(rewriter.getContext(), addressSpace);
1641 elementPtrType, allocatedPtr);
1643 underlyingDescPtr, elementPtrType,
1646 underlyingDescPtr, elementPtrType,
1652 rewriter, loc, *getTypeConverter(), underlyingDescPtr, elementPtrType);
1654 rewriter, loc, *getTypeConverter(), targetSizesBase, resultRank);
1655 Value shapeOperandPtr = shapeDesc.alignedPtr(rewriter, loc);
1657 Value resultRankMinusOne =
1658 LLVM::SubOp::create(rewriter, loc, resultRank, oneIndex);
1660 Block *initBlock = rewriter.getInsertionBlock();
1661 Type indexType = getTypeConverter()->getIndexType();
1662 Block::iterator remainingOpsIt = std::next(rewriter.getInsertionPoint());
1664 Block *condBlock = rewriter.createBlock(initBlock->
getParent(), {},
1665 {indexType, indexType}, {loc, loc});
1668 Block *remainingBlock = rewriter.splitBlock(initBlock, remainingOpsIt);
1669 rewriter.mergeBlocks(remainingBlock, condBlock,
ValueRange());
1671 rewriter.setInsertionPointToEnd(initBlock);
1672 LLVM::BrOp::create(rewriter, loc,
1673 ValueRange({resultRankMinusOne, oneIndex}), condBlock);
1674 rewriter.setInsertionPointToStart(condBlock);
1679 Value pred = LLVM::ICmpOp::create(
1680 rewriter, loc, IntegerType::get(rewriter.getContext(), 1),
1681 LLVM::ICmpPredicate::sge, indexArg, zeroIndex);
1684 rewriter.splitBlock(condBlock, rewriter.getInsertionPoint());
1685 rewriter.setInsertionPointToStart(bodyBlock);
1688 auto llvmIndexPtrType = LLVM::LLVMPointerType::get(rewriter.getContext());
1689 Value sizeLoadGep = LLVM::GEPOp::create(
1690 rewriter, loc, llvmIndexPtrType,
1691 typeConverter->convertType(shapeMemRefType.getElementType()),
1692 shapeOperandPtr, indexArg);
1693 Value size = LLVM::LoadOp::create(rewriter, loc, indexType, sizeLoadGep);
1695 targetSizesBase, indexArg, size);
1699 targetStridesBase, indexArg, strideArg);
1700 Value nextStride = LLVM::MulOp::create(rewriter, loc, strideArg, size);
1703 Value decrement = LLVM::SubOp::create(rewriter, loc, indexArg, oneIndex);
1704 LLVM::BrOp::create(rewriter, loc,
ValueRange({decrement, nextStride}),
1708 rewriter.splitBlock(bodyBlock, rewriter.getInsertionPoint());
1711 rewriter.setInsertionPointToEnd(condBlock);
1712 LLVM::CondBrOp::create(rewriter, loc, pred, bodyBlock,
ValueRange(),
1716 rewriter.setInsertionPointToStart(remainder);
1718 *descriptor = targetDesc;
1725template <
typename ReshapeOp>
1726class ReassociatingReshapeOpConversion
1729 using ConvertOpToLLVMPattern<ReshapeOp>::ConvertOpToLLVMPattern;
1730 using ReshapeOpAdaptor =
typename ReshapeOp::Adaptor;
1733 matchAndRewrite(ReshapeOp reshapeOp,
typename ReshapeOp::Adaptor adaptor,
1734 ConversionPatternRewriter &rewriter)
const override {
1735 return rewriter.notifyMatchFailure(
1737 "reassociation operations should have been expanded beforehand");
1744 using ConvertOpToLLVMPattern<memref::SubViewOp>::ConvertOpToLLVMPattern;
1747 matchAndRewrite(memref::SubViewOp subViewOp, OpAdaptor adaptor,
1748 ConversionPatternRewriter &rewriter)
const override {
1749 return rewriter.notifyMatchFailure(
1750 subViewOp,
"subview operations should have been expanded beforehand");
1767 ConversionPatternRewriter &rewriter)
const override {
1768 auto loc = transposeOp.getLoc();
1769 MemRefDescriptor viewMemRef(adaptor.getIn());
1772 if (transposeOp.getPermutation().isIdentity())
1773 return rewriter.replaceOp(transposeOp, {viewMemRef}),
success();
1775 auto targetMemRef = MemRefDescriptor::poison(
1777 typeConverter->convertType(transposeOp.getIn().getType()));
1781 targetMemRef.setAllocatedPtr(rewriter, loc,
1782 viewMemRef.allocatedPtr(rewriter, loc));
1783 targetMemRef.setAlignedPtr(rewriter, loc,
1784 viewMemRef.alignedPtr(rewriter, loc));
1787 targetMemRef.setOffset(rewriter, loc, viewMemRef.offset(rewriter, loc));
1793 for (
const auto &en :
1794 llvm::enumerate(transposeOp.getPermutation().getResults())) {
1795 int targetPos = en.index();
1796 int sourcePos = cast<AffineDimExpr>(en.value()).getPosition();
1797 targetMemRef.setSize(rewriter, loc, targetPos,
1798 viewMemRef.size(rewriter, loc, sourcePos));
1799 targetMemRef.setStride(rewriter, loc, targetPos,
1800 viewMemRef.stride(rewriter, loc, sourcePos));
1803 rewriter.replaceOp(transposeOp, {targetMemRef});
1814 using ConvertOpToLLVMPattern<memref::ViewOp>::ConvertOpToLLVMPattern;
1818 Value getSize(ConversionPatternRewriter &rewriter, Location loc,
1819 ArrayRef<int64_t> shape,
ValueRange dynamicSizes,
unsigned idx,
1820 Type indexType)
const {
1821 assert(idx < shape.size());
1822 if (ShapedType::isStatic(shape[idx]))
1826 llvm::count_if(shape.take_front(idx), ShapedType::isDynamic);
1827 return dynamicSizes[nDynamic];
1834 Value getStride(ConversionPatternRewriter &rewriter, Location loc,
1835 ArrayRef<int64_t> strides, Value nextSize,
1836 Value runningStride,
unsigned idx, Type indexType)
const {
1837 assert(idx < strides.size());
1838 if (ShapedType::isStatic(strides[idx]))
1841 return runningStride
1842 ? LLVM::MulOp::create(rewriter, loc, runningStride, nextSize)
1844 assert(!runningStride);
1849 matchAndRewrite(memref::ViewOp viewOp, OpAdaptor adaptor,
1850 ConversionPatternRewriter &rewriter)
const override {
1851 auto loc = viewOp.getLoc();
1853 auto viewMemRefType = viewOp.getType();
1854 auto targetElementTy =
1855 typeConverter->convertType(viewMemRefType.getElementType());
1856 auto targetDescTy = typeConverter->convertType(viewMemRefType);
1857 if (!targetDescTy || !targetElementTy ||
1858 !LLVM::isCompatibleType(targetElementTy) ||
1859 !LLVM::isCompatibleType(targetDescTy))
1860 return viewOp.emitWarning(
"Target descriptor type not converted to LLVM"),
1864 SmallVector<int64_t, 4> strides;
1865 auto successStrides = viewMemRefType.getStridesAndOffset(strides, offset);
1866 if (
failed(successStrides))
1867 return viewOp.emitWarning(
"cannot cast to non-strided shape"), failure();
1868 assert(offset == 0 &&
"expected offset to be 0");
1872 if (!strides.empty() && (strides.back() != 1 && strides.back() != 0))
1873 return viewOp.emitWarning(
"cannot cast to non-contiguous shape"),
1877 MemRefDescriptor sourceMemRef(adaptor.getSource());
1878 auto targetMemRef = MemRefDescriptor::poison(rewriter, loc, targetDescTy);
1881 Value allocatedPtr = sourceMemRef.allocatedPtr(rewriter, loc);
1882 auto srcMemRefType = cast<MemRefType>(viewOp.getSource().getType());
1883 targetMemRef.setAllocatedPtr(rewriter, loc, allocatedPtr);
1886 Value alignedPtr = sourceMemRef.alignedPtr(rewriter, loc);
1887 alignedPtr = LLVM::GEPOp::create(
1888 rewriter, loc, alignedPtr.
getType(),
1889 typeConverter->convertType(srcMemRefType.getElementType()), alignedPtr,
1890 adaptor.getByteShift());
1892 targetMemRef.setAlignedPtr(rewriter, loc, alignedPtr);
1894 Type indexType = getIndexType();
1898 targetMemRef.setOffset(
1903 if (viewMemRefType.getRank() == 0)
1904 return rewriter.replaceOp(viewOp, {targetMemRef}),
success();
1907 Value stride =
nullptr, nextSize =
nullptr;
1908 for (
int i = viewMemRefType.getRank() - 1; i >= 0; --i) {
1910 Value size = getSize(rewriter, loc, viewMemRefType.getShape(),
1911 adaptor.getSizes(), i, indexType);
1912 targetMemRef.setSize(rewriter, loc, i, size);
1915 getStride(rewriter, loc, strides, nextSize, stride, i, indexType);
1916 targetMemRef.setStride(rewriter, loc, i, stride);
1920 rewriter.replaceOp(viewOp, {targetMemRef});
1931static std::optional<LLVM::AtomicBinOp>
1932matchSimpleAtomicOp(memref::AtomicRMWOp atomicOp) {
1933 switch (atomicOp.getKind()) {
1934 case arith::AtomicRMWKind::addf:
1935 return LLVM::AtomicBinOp::fadd;
1936 case arith::AtomicRMWKind::addi:
1937 return LLVM::AtomicBinOp::add;
1938 case arith::AtomicRMWKind::assign:
1939 return LLVM::AtomicBinOp::xchg;
1940 case arith::AtomicRMWKind::maximumf:
1942 LDBG() <<
"the lowering of memref.atomicrmw maximumf changed "
1943 "from fmax to fmaximum, expect more NaNs";
1944 return LLVM::AtomicBinOp::fmaximum;
1945 case arith::AtomicRMWKind::maxnumf:
1946 return LLVM::AtomicBinOp::fmax;
1947 case arith::AtomicRMWKind::maxs:
1948 return LLVM::AtomicBinOp::max;
1949 case arith::AtomicRMWKind::maxu:
1950 return LLVM::AtomicBinOp::umax;
1951 case arith::AtomicRMWKind::minimumf:
1953 LDBG() <<
"the lowering of memref.atomicrmw minimum changed "
1954 "from fmin to fminimum, expect more NaNs";
1955 return LLVM::AtomicBinOp::fminimum;
1956 case arith::AtomicRMWKind::minnumf:
1957 return LLVM::AtomicBinOp::fmin;
1958 case arith::AtomicRMWKind::mins:
1959 return LLVM::AtomicBinOp::min;
1960 case arith::AtomicRMWKind::minu:
1961 return LLVM::AtomicBinOp::umin;
1962 case arith::AtomicRMWKind::ori:
1963 return LLVM::AtomicBinOp::_or;
1964 case arith::AtomicRMWKind::xori:
1965 return LLVM::AtomicBinOp::_xor;
1966 case arith::AtomicRMWKind::andi:
1967 return LLVM::AtomicBinOp::_and;
1969 return std::nullopt;
1971 llvm_unreachable(
"Invalid AtomicRMWKind");
1974struct AtomicRMWOpLowering :
public LoadStoreOpLowering<memref::AtomicRMWOp> {
1978 matchAndRewrite(memref::AtomicRMWOp atomicOp, OpAdaptor adaptor,
1979 ConversionPatternRewriter &rewriter)
const override {
1980 auto maybeKind = matchSimpleAtomicOp(atomicOp);
1983 auto memRefType = atomicOp.getMemRefType();
1984 SmallVector<int64_t> strides;
1986 if (
failed(memRefType.getStridesAndOffset(strides, offset)))
1990 adaptor.getMemref(), adaptor.getIndices());
1991 rewriter.replaceOpWithNewOp<LLVM::AtomicRMWOp>(
1992 atomicOp, *maybeKind, dataPtr, adaptor.getValue(),
1993 LLVM::AtomicOrdering::acq_rel);
1999class ConvertExtractAlignedPointerAsIndex
2002 using ConvertOpToLLVMPattern<
2003 memref::ExtractAlignedPointerAsIndexOp>::ConvertOpToLLVMPattern;
2006 matchAndRewrite(memref::ExtractAlignedPointerAsIndexOp extractOp,
2008 ConversionPatternRewriter &rewriter)
const override {
2009 BaseMemRefType sourceTy = extractOp.getSource().getType();
2013 MemRefDescriptor desc(adaptor.getSource());
2014 alignedPtr = desc.alignedPtr(rewriter, extractOp->getLoc());
2016 auto elementPtrTy = LLVM::LLVMPointerType::get(
2019 UnrankedMemRefDescriptor desc(adaptor.getSource());
2020 Value descPtr = desc.memRefDescPtr(rewriter, extractOp->getLoc());
2023 rewriter, extractOp->getLoc(), *getTypeConverter(), descPtr,
2027 rewriter.replaceOpWithNewOp<LLVM::PtrToIntOp>(
2028 extractOp, getTypeConverter()->getIndexType(), alignedPtr);
2035class ExtractStridedMetadataOpLowering
2038 using ConvertOpToLLVMPattern<
2039 memref::ExtractStridedMetadataOp>::ConvertOpToLLVMPattern;
2042 matchAndRewrite(memref::ExtractStridedMetadataOp extractStridedMetadataOp,
2044 ConversionPatternRewriter &rewriter)
const override {
2046 if (!LLVM::isCompatibleType(adaptor.getOperands().front().getType()))
2050 MemRefDescriptor sourceMemRef(adaptor.getSource());
2051 Location loc = extractStridedMetadataOp.getLoc();
2052 Value source = extractStridedMetadataOp.getSource();
2054 auto sourceMemRefType = cast<MemRefType>(source.
getType());
2055 int64_t rank = sourceMemRefType.getRank();
2056 SmallVector<Value> results;
2057 results.reserve(2 + rank * 2);
2060 Value baseBuffer = sourceMemRef.allocatedPtr(rewriter, loc);
2061 Value alignedBuffer = sourceMemRef.alignedPtr(rewriter, loc);
2062 MemRefDescriptor dstMemRef = MemRefDescriptor::fromStaticShape(
2063 rewriter, loc, *getTypeConverter(),
2064 cast<MemRefType>(extractStridedMetadataOp.getBaseBuffer().getType()),
2065 baseBuffer, alignedBuffer);
2066 results.push_back((Value)dstMemRef);
2069 results.push_back(sourceMemRef.offset(rewriter, loc));
2072 for (
unsigned i = 0; i < rank; ++i)
2073 results.push_back(sourceMemRef.size(rewriter, loc, i));
2075 for (
unsigned i = 0; i < rank; ++i)
2076 results.push_back(sourceMemRef.stride(rewriter, loc, i));
2078 rewriter.replaceOp(extractStridedMetadataOp, results);
2091 AllocaScopeOpLowering,
2092 AssumeAlignmentOpLowering,
2093 AtomicRMWOpLowering,
2094 ConvertExtractAlignedPointerAsIndex,
2096 DistinctObjectsOpLowering,
2097 ExtractStridedMetadataOpLowering,
2098 GenericAtomicRMWOpLowering,
2099 GetGlobalMemrefOpLowering,
2101 MemRefCastOpLowering,
2102 MemRefReinterpretCastOpLowering,
2103 MemRefReshapeOpLowering,
2104 MemorySpaceCastOpLowering,
2107 ReassociatingReshapeOpConversion<memref::CollapseShapeOp>,
2108 ReassociatingReshapeOpConversion<memref::ExpandShapeOp>,
2112 ViewOpLowering>(converter);
2114 patterns.
add<GlobalMemrefOpLowering, MemRefCopyOpLowering>(converter,
2118 patterns.
add<AlignedAllocOpLowering, DeallocOpLowering>(converter,
2121 patterns.
add<AllocOpLowering, DeallocOpLowering>(converter, symbolTables);
2125struct FinalizeMemRefToLLVMConversionPass
2126 :
public impl::FinalizeMemRefToLLVMConversionPassBase<
2127 FinalizeMemRefToLLVMConversionPass> {
2128 using FinalizeMemRefToLLVMConversionPassBase::
2129 FinalizeMemRefToLLVMConversionPassBase;
2131 void runOnOperation()
override {
2133 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
2135 dataLayoutAnalysis.getAtOrAbove(op));
2140 options.useGenericFunctions = useGenericFunctions;
2143 options.overrideIndexBitwidth(indexBitwidth);
2146 &dataLayoutAnalysis);
2152 target.addLegalOp<func::FuncOp>();
2153 if (failed(applyPartialConversion(op,
target, std::move(patterns))))
2154 signalPassFailure();
2159struct MemRefToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
2160 MemRefToLLVMDialectInterface(Dialect *dialect)
2161 : ConvertToLLVMPatternInterface(dialect) {}
2163 void loadDependentDialects(MLIRContext *context)
const final {
2164 context->loadDialect<LLVM::LLVMDialect>();
2169 void populateConvertToLLVMConversionPatterns(
2170 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
2171 RewritePatternSet &patterns)
const final {
2180 dialect->addInterfaces<MemRefToLLVMDialectInterface>();
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.
auto lookupOrDefault(T from) const
Lookup a mapped value within the map.
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
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)
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...
Value createIndexAttrConstant(OpBuilder &builder, Location loc, Type resultType, int64_t value)
Creates an llvm.mlir.constant producing value as resultType, which is expected to be the converted in...
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)
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.
LogicalResult 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)