1684dfe8aSAlex Zinenko //===- Pattern.cpp - Conversion pattern to the LLVM dialect ---------------===// 2684dfe8aSAlex Zinenko // 3684dfe8aSAlex Zinenko // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4684dfe8aSAlex Zinenko // See https://llvm.org/LICENSE.txt for license information. 5684dfe8aSAlex Zinenko // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6684dfe8aSAlex Zinenko // 7684dfe8aSAlex Zinenko //===----------------------------------------------------------------------===// 8684dfe8aSAlex Zinenko 9684dfe8aSAlex Zinenko #include "mlir/Conversion/LLVMCommon/Pattern.h" 10ed1f149bSFrederik Gossen #include "mlir/Dialect/LLVMIR/FunctionCallUtils.h" 11684dfe8aSAlex Zinenko #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 12684dfe8aSAlex Zinenko #include "mlir/Dialect/LLVMIR/LLVMTypes.h" 13684dfe8aSAlex Zinenko #include "mlir/IR/AffineMap.h" 1414ecafd0SChia-hung Duan #include "mlir/IR/BuiltinAttributes.h" 15684dfe8aSAlex Zinenko 16684dfe8aSAlex Zinenko using namespace mlir; 17684dfe8aSAlex Zinenko 18684dfe8aSAlex Zinenko //===----------------------------------------------------------------------===// 19684dfe8aSAlex Zinenko // ConvertToLLVMPattern 20684dfe8aSAlex Zinenko //===----------------------------------------------------------------------===// 21684dfe8aSAlex Zinenko 22ce254598SMatthias Springer ConvertToLLVMPattern::ConvertToLLVMPattern( 23ce254598SMatthias Springer StringRef rootOpName, MLIRContext *context, 24ce254598SMatthias Springer const LLVMTypeConverter &typeConverter, PatternBenefit benefit) 25684dfe8aSAlex Zinenko : ConversionPattern(typeConverter, rootOpName, benefit, context) {} 26684dfe8aSAlex Zinenko 27ce254598SMatthias Springer const LLVMTypeConverter *ConvertToLLVMPattern::getTypeConverter() const { 28ce254598SMatthias Springer return static_cast<const LLVMTypeConverter *>( 29684dfe8aSAlex Zinenko ConversionPattern::getTypeConverter()); 30684dfe8aSAlex Zinenko } 31684dfe8aSAlex Zinenko 32684dfe8aSAlex Zinenko LLVM::LLVMDialect &ConvertToLLVMPattern::getDialect() const { 33684dfe8aSAlex Zinenko return *getTypeConverter()->getDialect(); 34684dfe8aSAlex Zinenko } 35684dfe8aSAlex Zinenko 36684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getIndexType() const { 37684dfe8aSAlex Zinenko return getTypeConverter()->getIndexType(); 38684dfe8aSAlex Zinenko } 39684dfe8aSAlex Zinenko 40684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getIntPtrType(unsigned addressSpace) const { 41684dfe8aSAlex Zinenko return IntegerType::get(&getTypeConverter()->getContext(), 42684dfe8aSAlex Zinenko getTypeConverter()->getPointerBitwidth(addressSpace)); 43684dfe8aSAlex Zinenko } 44684dfe8aSAlex Zinenko 45684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getVoidType() const { 46684dfe8aSAlex Zinenko return LLVM::LLVMVoidType::get(&getTypeConverter()->getContext()); 47684dfe8aSAlex Zinenko } 48684dfe8aSAlex Zinenko 49684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getVoidPtrType() const { 5097a238e8SChristian Ulmann return LLVM::LLVMPointerType::get(&getTypeConverter()->getContext()); 51684dfe8aSAlex Zinenko } 52684dfe8aSAlex Zinenko 53684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::createIndexAttrConstant(OpBuilder &builder, 54684dfe8aSAlex Zinenko Location loc, 55684dfe8aSAlex Zinenko Type resultType, 56684dfe8aSAlex Zinenko int64_t value) { 570af643f3SJeff Niu return builder.create<LLVM::ConstantOp>(loc, resultType, 580af643f3SJeff Niu builder.getIndexAttr(value)); 59684dfe8aSAlex Zinenko } 60684dfe8aSAlex Zinenko 61684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::getStridedElementPtr( 62684dfe8aSAlex Zinenko Location loc, MemRefType type, Value memRefDesc, ValueRange indices, 63684dfe8aSAlex Zinenko ConversionPatternRewriter &rewriter) const { 64684dfe8aSAlex Zinenko 656aaa8f25SMatthias Springer auto [strides, offset] = type.getStridesAndOffset(); 66684dfe8aSAlex Zinenko 67684dfe8aSAlex Zinenko MemRefDescriptor memRefDescriptor(memRefDesc); 68e02d4142SQuentin Colombet // Use a canonical representation of the start address so that later 69e02d4142SQuentin Colombet // optimizations have a longer sequence of instructions to CSE. 70e02d4142SQuentin Colombet // If we don't do that we would sprinkle the memref.offset in various 71e02d4142SQuentin Colombet // position of the different address computations. 72e02d4142SQuentin Colombet Value base = 73e02d4142SQuentin Colombet memRefDescriptor.bufferPtr(rewriter, loc, *getTypeConverter(), type); 74684dfe8aSAlex Zinenko 75e98e5995SAlex Zinenko Type indexType = getIndexType(); 76684dfe8aSAlex Zinenko Value index; 77684dfe8aSAlex Zinenko for (int i = 0, e = indices.size(); i < e; ++i) { 78684dfe8aSAlex Zinenko Value increment = indices[i]; 79684dfe8aSAlex Zinenko if (strides[i] != 1) { // Skip if stride is 1. 80620e2bb2SNicolas Vasilache Value stride = 81620e2bb2SNicolas Vasilache ShapedType::isDynamic(strides[i]) 82684dfe8aSAlex Zinenko ? memRefDescriptor.stride(rewriter, loc, i) 83620e2bb2SNicolas Vasilache : createIndexAttrConstant(rewriter, loc, indexType, strides[i]); 84684dfe8aSAlex Zinenko increment = rewriter.create<LLVM::MulOp>(loc, increment, stride); 85684dfe8aSAlex Zinenko } 86684dfe8aSAlex Zinenko index = 87684dfe8aSAlex Zinenko index ? rewriter.create<LLVM::AddOp>(loc, index, increment) : increment; 88684dfe8aSAlex Zinenko } 89684dfe8aSAlex Zinenko 90684dfe8aSAlex Zinenko Type elementPtrType = memRefDescriptor.getElementPtrType(); 9150ea17b8SMarkus Böck return index ? rewriter.create<LLVM::GEPOp>( 9250ea17b8SMarkus Böck loc, elementPtrType, 9350ea17b8SMarkus Böck getTypeConverter()->convertType(type.getElementType()), 9450ea17b8SMarkus Böck base, index) 95684dfe8aSAlex Zinenko : base; 96684dfe8aSAlex Zinenko } 97684dfe8aSAlex Zinenko 98684dfe8aSAlex Zinenko // Check if the MemRefType `type` is supported by the lowering. We currently 99684dfe8aSAlex Zinenko // only support memrefs with identity maps. 100684dfe8aSAlex Zinenko bool ConvertToLLVMPattern::isConvertibleAndHasIdentityMaps( 101684dfe8aSAlex Zinenko MemRefType type) const { 102684dfe8aSAlex Zinenko if (!typeConverter->convertType(type.getElementType())) 103684dfe8aSAlex Zinenko return false; 104e41ebbecSVladislav Vinogradov return type.getLayout().isIdentity(); 105684dfe8aSAlex Zinenko } 106684dfe8aSAlex Zinenko 107684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getElementPtrType(MemRefType type) const { 108499abb24SKrzysztof Drewniak auto addressSpace = getTypeConverter()->getMemRefAddressSpace(type); 109499abb24SKrzysztof Drewniak if (failed(addressSpace)) 110499abb24SKrzysztof Drewniak return {}; 11197a238e8SChristian Ulmann return LLVM::LLVMPointerType::get(type.getContext(), *addressSpace); 112684dfe8aSAlex Zinenko } 113684dfe8aSAlex Zinenko 114684dfe8aSAlex Zinenko void ConvertToLLVMPattern::getMemRefDescriptorSizes( 115684dfe8aSAlex Zinenko Location loc, MemRefType memRefType, ValueRange dynamicSizes, 116684dfe8aSAlex Zinenko ConversionPatternRewriter &rewriter, SmallVectorImpl<Value> &sizes, 117041f1abeSFabian Mora SmallVectorImpl<Value> &strides, Value &size, bool sizeInBytes) const { 118684dfe8aSAlex Zinenko assert(isConvertibleAndHasIdentityMaps(memRefType) && 119684dfe8aSAlex Zinenko "layout maps must have been normalized away"); 120399638f9SAliia Khasanova assert(count(memRefType.getShape(), ShapedType::kDynamic) == 121684dfe8aSAlex Zinenko static_cast<ssize_t>(dynamicSizes.size()) && 122684dfe8aSAlex Zinenko "dynamicSizes size doesn't match dynamic sizes count in memref shape"); 123684dfe8aSAlex Zinenko 124684dfe8aSAlex Zinenko sizes.reserve(memRefType.getRank()); 125684dfe8aSAlex Zinenko unsigned dynamicIndex = 0; 126e98e5995SAlex Zinenko Type indexType = getIndexType(); 127684dfe8aSAlex Zinenko for (int64_t size : memRefType.getShape()) { 128620e2bb2SNicolas Vasilache sizes.push_back( 129620e2bb2SNicolas Vasilache size == ShapedType::kDynamic 130684dfe8aSAlex Zinenko ? dynamicSizes[dynamicIndex++] 131620e2bb2SNicolas Vasilache : createIndexAttrConstant(rewriter, loc, indexType, size)); 132684dfe8aSAlex Zinenko } 133684dfe8aSAlex Zinenko 134684dfe8aSAlex Zinenko // Strides: iterate sizes in reverse order and multiply. 135684dfe8aSAlex Zinenko int64_t stride = 1; 136620e2bb2SNicolas Vasilache Value runningStride = createIndexAttrConstant(rewriter, loc, indexType, 1); 137684dfe8aSAlex Zinenko strides.resize(memRefType.getRank()); 138684dfe8aSAlex Zinenko for (auto i = memRefType.getRank(); i-- > 0;) { 139684dfe8aSAlex Zinenko strides[i] = runningStride; 140684dfe8aSAlex Zinenko 141041f1abeSFabian Mora int64_t staticSize = memRefType.getShape()[i]; 142684dfe8aSAlex Zinenko bool useSizeAsStride = stride == 1; 143041f1abeSFabian Mora if (staticSize == ShapedType::kDynamic) 144399638f9SAliia Khasanova stride = ShapedType::kDynamic; 145399638f9SAliia Khasanova if (stride != ShapedType::kDynamic) 146041f1abeSFabian Mora stride *= staticSize; 147684dfe8aSAlex Zinenko 148684dfe8aSAlex Zinenko if (useSizeAsStride) 149684dfe8aSAlex Zinenko runningStride = sizes[i]; 150399638f9SAliia Khasanova else if (stride == ShapedType::kDynamic) 151684dfe8aSAlex Zinenko runningStride = 152684dfe8aSAlex Zinenko rewriter.create<LLVM::MulOp>(loc, runningStride, sizes[i]); 153684dfe8aSAlex Zinenko else 154620e2bb2SNicolas Vasilache runningStride = createIndexAttrConstant(rewriter, loc, indexType, stride); 155684dfe8aSAlex Zinenko } 156041f1abeSFabian Mora if (sizeInBytes) { 157684dfe8aSAlex Zinenko // Buffer size in bytes. 15850ea17b8SMarkus Böck Type elementType = typeConverter->convertType(memRefType.getElementType()); 15997a238e8SChristian Ulmann auto elementPtrType = LLVM::LLVMPointerType::get(rewriter.getContext()); 16085175eddSTobias Gysi Value nullPtr = rewriter.create<LLVM::ZeroOp>(loc, elementPtrType); 161041f1abeSFabian Mora Value gepPtr = rewriter.create<LLVM::GEPOp>( 162041f1abeSFabian Mora loc, elementPtrType, elementType, nullPtr, runningStride); 163041f1abeSFabian Mora size = rewriter.create<LLVM::PtrToIntOp>(loc, getIndexType(), gepPtr); 164041f1abeSFabian Mora } else { 165041f1abeSFabian Mora size = runningStride; 166041f1abeSFabian Mora } 167684dfe8aSAlex Zinenko } 168684dfe8aSAlex Zinenko 169684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::getSizeInBytes( 170684dfe8aSAlex Zinenko Location loc, Type type, ConversionPatternRewriter &rewriter) const { 171684dfe8aSAlex Zinenko // Compute the size of an individual element. This emits the MLIR equivalent 172684dfe8aSAlex Zinenko // of the following sizeof(...) implementation in LLVM IR: 173684dfe8aSAlex Zinenko // %0 = getelementptr %elementType* null, %indexType 1 174684dfe8aSAlex Zinenko // %1 = ptrtoint %elementType* %0 to %indexType 175684dfe8aSAlex Zinenko // which is a common pattern of getting the size of a type in bytes. 17650ea17b8SMarkus Böck Type llvmType = typeConverter->convertType(type); 17797a238e8SChristian Ulmann auto convertedPtrType = LLVM::LLVMPointerType::get(rewriter.getContext()); 17885175eddSTobias Gysi auto nullPtr = rewriter.create<LLVM::ZeroOp>(loc, convertedPtrType); 17950ea17b8SMarkus Böck auto gep = rewriter.create<LLVM::GEPOp>(loc, convertedPtrType, llvmType, 18050ea17b8SMarkus Böck nullPtr, ArrayRef<LLVM::GEPArg>{1}); 181684dfe8aSAlex Zinenko return rewriter.create<LLVM::PtrToIntOp>(loc, getIndexType(), gep); 182684dfe8aSAlex Zinenko } 183684dfe8aSAlex Zinenko 184684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::getNumElements( 185041f1abeSFabian Mora Location loc, MemRefType memRefType, ValueRange dynamicSizes, 186684dfe8aSAlex Zinenko ConversionPatternRewriter &rewriter) const { 187041f1abeSFabian Mora assert(count(memRefType.getShape(), ShapedType::kDynamic) == 188041f1abeSFabian Mora static_cast<ssize_t>(dynamicSizes.size()) && 189041f1abeSFabian Mora "dynamicSizes size doesn't match dynamic sizes count in memref shape"); 190041f1abeSFabian Mora 191e98e5995SAlex Zinenko Type indexType = getIndexType(); 192041f1abeSFabian Mora Value numElements = memRefType.getRank() == 0 193620e2bb2SNicolas Vasilache ? createIndexAttrConstant(rewriter, loc, indexType, 1) 194041f1abeSFabian Mora : nullptr; 195041f1abeSFabian Mora unsigned dynamicIndex = 0; 196041f1abeSFabian Mora 197684dfe8aSAlex Zinenko // Compute the total number of memref elements. 198041f1abeSFabian Mora for (int64_t staticSize : memRefType.getShape()) { 199041f1abeSFabian Mora if (numElements) { 200620e2bb2SNicolas Vasilache Value size = 201620e2bb2SNicolas Vasilache staticSize == ShapedType::kDynamic 202041f1abeSFabian Mora ? dynamicSizes[dynamicIndex++] 203620e2bb2SNicolas Vasilache : createIndexAttrConstant(rewriter, loc, indexType, staticSize); 204041f1abeSFabian Mora numElements = rewriter.create<LLVM::MulOp>(loc, numElements, size); 205041f1abeSFabian Mora } else { 206620e2bb2SNicolas Vasilache numElements = 207620e2bb2SNicolas Vasilache staticSize == ShapedType::kDynamic 208041f1abeSFabian Mora ? dynamicSizes[dynamicIndex++] 209620e2bb2SNicolas Vasilache : createIndexAttrConstant(rewriter, loc, indexType, staticSize); 210041f1abeSFabian Mora } 211041f1abeSFabian Mora } 212684dfe8aSAlex Zinenko return numElements; 213684dfe8aSAlex Zinenko } 214684dfe8aSAlex Zinenko 215684dfe8aSAlex Zinenko /// Creates and populates the memref descriptor struct given all its fields. 216684dfe8aSAlex Zinenko MemRefDescriptor ConvertToLLVMPattern::createMemRefDescriptor( 217684dfe8aSAlex Zinenko Location loc, MemRefType memRefType, Value allocatedPtr, Value alignedPtr, 218684dfe8aSAlex Zinenko ArrayRef<Value> sizes, ArrayRef<Value> strides, 219684dfe8aSAlex Zinenko ConversionPatternRewriter &rewriter) const { 220684dfe8aSAlex Zinenko auto structType = typeConverter->convertType(memRefType); 221684dfe8aSAlex Zinenko auto memRefDescriptor = MemRefDescriptor::undef(rewriter, loc, structType); 222684dfe8aSAlex Zinenko 223684dfe8aSAlex Zinenko // Field 1: Allocated pointer, used for malloc/free. 224684dfe8aSAlex Zinenko memRefDescriptor.setAllocatedPtr(rewriter, loc, allocatedPtr); 225684dfe8aSAlex Zinenko 226684dfe8aSAlex Zinenko // Field 2: Actual aligned pointer to payload. 227684dfe8aSAlex Zinenko memRefDescriptor.setAlignedPtr(rewriter, loc, alignedPtr); 228684dfe8aSAlex Zinenko 229684dfe8aSAlex Zinenko // Field 3: Offset in aligned pointer. 230e98e5995SAlex Zinenko Type indexType = getIndexType(); 231620e2bb2SNicolas Vasilache memRefDescriptor.setOffset( 232620e2bb2SNicolas Vasilache rewriter, loc, createIndexAttrConstant(rewriter, loc, indexType, 0)); 233684dfe8aSAlex Zinenko 234684dfe8aSAlex Zinenko // Fields 4: Sizes. 235e4853be2SMehdi Amini for (const auto &en : llvm::enumerate(sizes)) 236684dfe8aSAlex Zinenko memRefDescriptor.setSize(rewriter, loc, en.index(), en.value()); 237684dfe8aSAlex Zinenko 238684dfe8aSAlex Zinenko // Field 5: Strides. 239e4853be2SMehdi Amini for (const auto &en : llvm::enumerate(strides)) 240684dfe8aSAlex Zinenko memRefDescriptor.setStride(rewriter, loc, en.index(), en.value()); 241684dfe8aSAlex Zinenko 242684dfe8aSAlex Zinenko return memRefDescriptor; 243684dfe8aSAlex Zinenko } 244684dfe8aSAlex Zinenko 245ed1f149bSFrederik Gossen LogicalResult ConvertToLLVMPattern::copyUnrankedDescriptors( 246ed1f149bSFrederik Gossen OpBuilder &builder, Location loc, TypeRange origTypes, 247ed1f149bSFrederik Gossen SmallVectorImpl<Value> &operands, bool toDynamic) const { 248ed1f149bSFrederik Gossen assert(origTypes.size() == operands.size() && 249ed1f149bSFrederik Gossen "expected as may original types as operands"); 250ed1f149bSFrederik Gossen 251ed1f149bSFrederik Gossen // Find operands of unranked memref type and store them. 252d0f19ce7SKrzysztof Drewniak SmallVector<UnrankedMemRefDescriptor> unrankedMemrefs; 253d0f19ce7SKrzysztof Drewniak SmallVector<unsigned> unrankedAddressSpaces; 254d0f19ce7SKrzysztof Drewniak for (unsigned i = 0, e = operands.size(); i < e; ++i) { 2555550c821STres Popp if (auto memRefType = dyn_cast<UnrankedMemRefType>(origTypes[i])) { 256ed1f149bSFrederik Gossen unrankedMemrefs.emplace_back(operands[i]); 257d0f19ce7SKrzysztof Drewniak FailureOr<unsigned> addressSpace = 258d0f19ce7SKrzysztof Drewniak getTypeConverter()->getMemRefAddressSpace(memRefType); 259d0f19ce7SKrzysztof Drewniak if (failed(addressSpace)) 260d0f19ce7SKrzysztof Drewniak return failure(); 261d0f19ce7SKrzysztof Drewniak unrankedAddressSpaces.emplace_back(*addressSpace); 262d0f19ce7SKrzysztof Drewniak } 263d0f19ce7SKrzysztof Drewniak } 264ed1f149bSFrederik Gossen 265ed1f149bSFrederik Gossen if (unrankedMemrefs.empty()) 266ed1f149bSFrederik Gossen return success(); 267ed1f149bSFrederik Gossen 268ed1f149bSFrederik Gossen // Compute allocation sizes. 269d0f19ce7SKrzysztof Drewniak SmallVector<Value> sizes; 270ed1f149bSFrederik Gossen UnrankedMemRefDescriptor::computeSizes(builder, loc, *getTypeConverter(), 271d0f19ce7SKrzysztof Drewniak unrankedMemrefs, unrankedAddressSpaces, 272d0f19ce7SKrzysztof Drewniak sizes); 273ed1f149bSFrederik Gossen 274ed1f149bSFrederik Gossen // Get frequently used types. 275ed1f149bSFrederik Gossen Type indexType = getTypeConverter()->getIndexType(); 276ed1f149bSFrederik Gossen 277ed1f149bSFrederik Gossen // Find the malloc and free, or declare them if necessary. 278ed1f149bSFrederik Gossen auto module = builder.getInsertionPoint()->getParentOfType<ModuleOp>(); 279*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp> freeFunc, mallocFunc; 280*e84f6b6aSLuohao Wang if (toDynamic) { 28197a238e8SChristian Ulmann mallocFunc = LLVM::lookupOrCreateMallocFn(module, indexType); 282*e84f6b6aSLuohao Wang if (failed(mallocFunc)) 283*e84f6b6aSLuohao Wang return failure(); 284*e84f6b6aSLuohao Wang } 285*e84f6b6aSLuohao Wang if (!toDynamic) { 28697a238e8SChristian Ulmann freeFunc = LLVM::lookupOrCreateFreeFn(module); 287*e84f6b6aSLuohao Wang if (failed(freeFunc)) 288*e84f6b6aSLuohao Wang return failure(); 289*e84f6b6aSLuohao Wang } 290ed1f149bSFrederik Gossen 291ed1f149bSFrederik Gossen unsigned unrankedMemrefPos = 0; 292ed1f149bSFrederik Gossen for (unsigned i = 0, e = operands.size(); i < e; ++i) { 293ed1f149bSFrederik Gossen Type type = origTypes[i]; 2945550c821STres Popp if (!isa<UnrankedMemRefType>(type)) 295ed1f149bSFrederik Gossen continue; 296ed1f149bSFrederik Gossen Value allocationSize = sizes[unrankedMemrefPos++]; 297ed1f149bSFrederik Gossen UnrankedMemRefDescriptor desc(operands[i]); 298ed1f149bSFrederik Gossen 299ed1f149bSFrederik Gossen // Allocate memory, copy, and free the source if necessary. 300ed1f149bSFrederik Gossen Value memory = 301ed1f149bSFrederik Gossen toDynamic 302*e84f6b6aSLuohao Wang ? builder 303*e84f6b6aSLuohao Wang .create<LLVM::CallOp>(loc, mallocFunc.value(), allocationSize) 3045e0c3b43SJeff Niu .getResult() 30550ea17b8SMarkus Böck : builder.create<LLVM::AllocaOp>(loc, getVoidPtrType(), 306a85bd1b1SMarkus Böck IntegerType::get(getContext(), 8), 307a85bd1b1SMarkus Böck allocationSize, 308ed1f149bSFrederik Gossen /*alignment=*/0); 309ed1f149bSFrederik Gossen Value source = desc.memRefDescPtr(builder, loc); 31048b126e3SChristian Ulmann builder.create<LLVM::MemcpyOp>(loc, memory, source, allocationSize, false); 311ed1f149bSFrederik Gossen if (!toDynamic) 312*e84f6b6aSLuohao Wang builder.create<LLVM::CallOp>(loc, freeFunc.value(), source); 313ed1f149bSFrederik Gossen 314ed1f149bSFrederik Gossen // Create a new descriptor. The same descriptor can be returned multiple 315ed1f149bSFrederik Gossen // times, attempting to modify its pointer can lead to memory leaks 316ed1f149bSFrederik Gossen // (allocated twice and overwritten) or double frees (the caller does not 317ed1f149bSFrederik Gossen // know if the descriptor points to the same memory). 318ed1f149bSFrederik Gossen Type descriptorType = getTypeConverter()->convertType(type); 319ed1f149bSFrederik Gossen if (!descriptorType) 320ed1f149bSFrederik Gossen return failure(); 321ed1f149bSFrederik Gossen auto updatedDesc = 322ed1f149bSFrederik Gossen UnrankedMemRefDescriptor::undef(builder, loc, descriptorType); 323ed1f149bSFrederik Gossen Value rank = desc.rank(builder, loc); 324ed1f149bSFrederik Gossen updatedDesc.setRank(builder, loc, rank); 325ed1f149bSFrederik Gossen updatedDesc.setMemRefDescPtr(builder, loc, memory); 326ed1f149bSFrederik Gossen 327ed1f149bSFrederik Gossen operands[i] = updatedDesc; 328ed1f149bSFrederik Gossen } 329ed1f149bSFrederik Gossen 330ed1f149bSFrederik Gossen return success(); 331ed1f149bSFrederik Gossen } 332ed1f149bSFrederik Gossen 333684dfe8aSAlex Zinenko //===----------------------------------------------------------------------===// 334684dfe8aSAlex Zinenko // Detail methods 335684dfe8aSAlex Zinenko //===----------------------------------------------------------------------===// 336684dfe8aSAlex Zinenko 337e553ac4dSJeff Niu void LLVM::detail::setNativeProperties(Operation *op, 338e553ac4dSJeff Niu IntegerOverflowFlags overflowFlags) { 339e553ac4dSJeff Niu if (auto iface = dyn_cast<IntegerOverflowFlagsInterface>(op)) 340e553ac4dSJeff Niu iface.setOverflowFlags(overflowFlags); 341e553ac4dSJeff Niu } 342e553ac4dSJeff Niu 343684dfe8aSAlex Zinenko /// Replaces the given operation "op" with a new operation of type "targetOp" 344684dfe8aSAlex Zinenko /// and given operands. 345e553ac4dSJeff Niu LogicalResult LLVM::detail::oneToOneRewrite( 346e553ac4dSJeff Niu Operation *op, StringRef targetOp, ValueRange operands, 347ce254598SMatthias Springer ArrayRef<NamedAttribute> targetAttrs, 348e553ac4dSJeff Niu const LLVMTypeConverter &typeConverter, ConversionPatternRewriter &rewriter, 349e553ac4dSJeff Niu IntegerOverflowFlags overflowFlags) { 350684dfe8aSAlex Zinenko unsigned numResults = op->getNumResults(); 351684dfe8aSAlex Zinenko 352a2100dafSJeff Niu SmallVector<Type> resultTypes; 353684dfe8aSAlex Zinenko if (numResults != 0) { 354a2100dafSJeff Niu resultTypes.push_back( 35576ba5ed0SAlex Zinenko typeConverter.packOperationResults(op->getResultTypes())); 356a2100dafSJeff Niu if (!resultTypes.back()) 357684dfe8aSAlex Zinenko return failure(); 358684dfe8aSAlex Zinenko } 359684dfe8aSAlex Zinenko 360684dfe8aSAlex Zinenko // Create the operation through state since we don't know its C++ type. 36114ecafd0SChia-hung Duan Operation *newOp = 36214ecafd0SChia-hung Duan rewriter.create(op->getLoc(), rewriter.getStringAttr(targetOp), operands, 363b56e65d3SJeremy Furtek resultTypes, targetAttrs); 364684dfe8aSAlex Zinenko 365e553ac4dSJeff Niu setNativeProperties(newOp, overflowFlags); 366e553ac4dSJeff Niu 367684dfe8aSAlex Zinenko // If the operation produced 0 or 1 result, return them immediately. 368684dfe8aSAlex Zinenko if (numResults == 0) 369684dfe8aSAlex Zinenko return rewriter.eraseOp(op), success(); 370684dfe8aSAlex Zinenko if (numResults == 1) 371684dfe8aSAlex Zinenko return rewriter.replaceOp(op, newOp->getResult(0)), success(); 372684dfe8aSAlex Zinenko 373684dfe8aSAlex Zinenko // Otherwise, it had been converted to an operation producing a structure. 374684dfe8aSAlex Zinenko // Extract individual results from the structure and return them as list. 375684dfe8aSAlex Zinenko SmallVector<Value, 4> results; 376684dfe8aSAlex Zinenko results.reserve(numResults); 377684dfe8aSAlex Zinenko for (unsigned i = 0; i < numResults; ++i) { 378684dfe8aSAlex Zinenko results.push_back(rewriter.create<LLVM::ExtractValueOp>( 3795c5af910SJeff Niu op->getLoc(), newOp->getResult(0), i)); 380684dfe8aSAlex Zinenko } 381684dfe8aSAlex Zinenko rewriter.replaceOp(op, results); 382684dfe8aSAlex Zinenko return success(); 383684dfe8aSAlex Zinenko } 384