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"
14*14ecafd0SChia-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 
ConvertToLLVMPattern(StringRef rootOpName,MLIRContext * context,LLVMTypeConverter & typeConverter,PatternBenefit benefit)22684dfe8aSAlex Zinenko ConvertToLLVMPattern::ConvertToLLVMPattern(StringRef rootOpName,
23684dfe8aSAlex Zinenko                                            MLIRContext *context,
24684dfe8aSAlex Zinenko                                            LLVMTypeConverter &typeConverter,
25684dfe8aSAlex Zinenko                                            PatternBenefit benefit)
26684dfe8aSAlex Zinenko     : ConversionPattern(typeConverter, rootOpName, benefit, context) {}
27684dfe8aSAlex Zinenko 
getTypeConverter() const28684dfe8aSAlex Zinenko LLVMTypeConverter *ConvertToLLVMPattern::getTypeConverter() const {
29684dfe8aSAlex Zinenko   return static_cast<LLVMTypeConverter *>(
30684dfe8aSAlex Zinenko       ConversionPattern::getTypeConverter());
31684dfe8aSAlex Zinenko }
32684dfe8aSAlex Zinenko 
getDialect() const33684dfe8aSAlex Zinenko LLVM::LLVMDialect &ConvertToLLVMPattern::getDialect() const {
34684dfe8aSAlex Zinenko   return *getTypeConverter()->getDialect();
35684dfe8aSAlex Zinenko }
36684dfe8aSAlex Zinenko 
getIndexType() const37684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getIndexType() const {
38684dfe8aSAlex Zinenko   return getTypeConverter()->getIndexType();
39684dfe8aSAlex Zinenko }
40684dfe8aSAlex Zinenko 
getIntPtrType(unsigned addressSpace) const41684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getIntPtrType(unsigned addressSpace) const {
42684dfe8aSAlex Zinenko   return IntegerType::get(&getTypeConverter()->getContext(),
43684dfe8aSAlex Zinenko                           getTypeConverter()->getPointerBitwidth(addressSpace));
44684dfe8aSAlex Zinenko }
45684dfe8aSAlex Zinenko 
getVoidType() const46684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getVoidType() const {
47684dfe8aSAlex Zinenko   return LLVM::LLVMVoidType::get(&getTypeConverter()->getContext());
48684dfe8aSAlex Zinenko }
49684dfe8aSAlex Zinenko 
getVoidPtrType() const50684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getVoidPtrType() const {
51684dfe8aSAlex Zinenko   return LLVM::LLVMPointerType::get(
52684dfe8aSAlex Zinenko       IntegerType::get(&getTypeConverter()->getContext(), 8));
53684dfe8aSAlex Zinenko }
54684dfe8aSAlex Zinenko 
createIndexAttrConstant(OpBuilder & builder,Location loc,Type resultType,int64_t value)55684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::createIndexAttrConstant(OpBuilder &builder,
56684dfe8aSAlex Zinenko                                                     Location loc,
57684dfe8aSAlex Zinenko                                                     Type resultType,
58684dfe8aSAlex Zinenko                                                     int64_t value) {
59684dfe8aSAlex Zinenko   return builder.create<LLVM::ConstantOp>(
60684dfe8aSAlex Zinenko       loc, resultType, builder.getIntegerAttr(builder.getIndexType(), value));
61684dfe8aSAlex Zinenko }
62684dfe8aSAlex Zinenko 
createIndexConstant(ConversionPatternRewriter & builder,Location loc,uint64_t value) const63684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::createIndexConstant(
64684dfe8aSAlex Zinenko     ConversionPatternRewriter &builder, Location loc, uint64_t value) const {
65684dfe8aSAlex Zinenko   return createIndexAttrConstant(builder, loc, getIndexType(), value);
66684dfe8aSAlex Zinenko }
67684dfe8aSAlex Zinenko 
getStridedElementPtr(Location loc,MemRefType type,Value memRefDesc,ValueRange indices,ConversionPatternRewriter & rewriter) const68684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::getStridedElementPtr(
69684dfe8aSAlex Zinenko     Location loc, MemRefType type, Value memRefDesc, ValueRange indices,
70684dfe8aSAlex Zinenko     ConversionPatternRewriter &rewriter) const {
71684dfe8aSAlex Zinenko 
72684dfe8aSAlex Zinenko   int64_t offset;
73684dfe8aSAlex Zinenko   SmallVector<int64_t, 4> strides;
74684dfe8aSAlex Zinenko   auto successStrides = getStridesAndOffset(type, strides, offset);
75684dfe8aSAlex Zinenko   assert(succeeded(successStrides) && "unexpected non-strided memref");
76684dfe8aSAlex Zinenko   (void)successStrides;
77684dfe8aSAlex Zinenko 
78684dfe8aSAlex Zinenko   MemRefDescriptor memRefDescriptor(memRefDesc);
79684dfe8aSAlex Zinenko   Value base = memRefDescriptor.alignedPtr(rewriter, loc);
80684dfe8aSAlex Zinenko 
81684dfe8aSAlex Zinenko   Value index;
82684dfe8aSAlex Zinenko   if (offset != 0) // Skip if offset is zero.
83676bfb2aSRiver Riddle     index = ShapedType::isDynamicStrideOrOffset(offset)
84684dfe8aSAlex Zinenko                 ? memRefDescriptor.offset(rewriter, loc)
85684dfe8aSAlex Zinenko                 : createIndexConstant(rewriter, loc, offset);
86684dfe8aSAlex Zinenko 
87684dfe8aSAlex Zinenko   for (int i = 0, e = indices.size(); i < e; ++i) {
88684dfe8aSAlex Zinenko     Value increment = indices[i];
89684dfe8aSAlex Zinenko     if (strides[i] != 1) { // Skip if stride is 1.
90676bfb2aSRiver Riddle       Value stride = ShapedType::isDynamicStrideOrOffset(strides[i])
91684dfe8aSAlex Zinenko                          ? memRefDescriptor.stride(rewriter, loc, i)
92684dfe8aSAlex Zinenko                          : createIndexConstant(rewriter, loc, strides[i]);
93684dfe8aSAlex Zinenko       increment = rewriter.create<LLVM::MulOp>(loc, increment, stride);
94684dfe8aSAlex Zinenko     }
95684dfe8aSAlex Zinenko     index =
96684dfe8aSAlex Zinenko         index ? rewriter.create<LLVM::AddOp>(loc, index, increment) : increment;
97684dfe8aSAlex Zinenko   }
98684dfe8aSAlex Zinenko 
99684dfe8aSAlex Zinenko   Type elementPtrType = memRefDescriptor.getElementPtrType();
100684dfe8aSAlex Zinenko   return index ? rewriter.create<LLVM::GEPOp>(loc, elementPtrType, base, index)
101684dfe8aSAlex Zinenko                : base;
102684dfe8aSAlex Zinenko }
103684dfe8aSAlex Zinenko 
104684dfe8aSAlex Zinenko // Check if the MemRefType `type` is supported by the lowering. We currently
105684dfe8aSAlex Zinenko // only support memrefs with identity maps.
isConvertibleAndHasIdentityMaps(MemRefType type) const106684dfe8aSAlex Zinenko bool ConvertToLLVMPattern::isConvertibleAndHasIdentityMaps(
107684dfe8aSAlex Zinenko     MemRefType type) const {
108684dfe8aSAlex Zinenko   if (!typeConverter->convertType(type.getElementType()))
109684dfe8aSAlex Zinenko     return false;
110e41ebbecSVladislav Vinogradov   return type.getLayout().isIdentity();
111684dfe8aSAlex Zinenko }
112684dfe8aSAlex Zinenko 
getElementPtrType(MemRefType type) const113684dfe8aSAlex Zinenko Type ConvertToLLVMPattern::getElementPtrType(MemRefType type) const {
114684dfe8aSAlex Zinenko   auto elementType = type.getElementType();
115684dfe8aSAlex Zinenko   auto structElementType = typeConverter->convertType(elementType);
116684dfe8aSAlex Zinenko   return LLVM::LLVMPointerType::get(structElementType,
117684dfe8aSAlex Zinenko                                     type.getMemorySpaceAsInt());
118684dfe8aSAlex Zinenko }
119684dfe8aSAlex Zinenko 
getMemRefDescriptorSizes(Location loc,MemRefType memRefType,ValueRange dynamicSizes,ConversionPatternRewriter & rewriter,SmallVectorImpl<Value> & sizes,SmallVectorImpl<Value> & strides,Value & sizeBytes) const120684dfe8aSAlex Zinenko void ConvertToLLVMPattern::getMemRefDescriptorSizes(
121684dfe8aSAlex Zinenko     Location loc, MemRefType memRefType, ValueRange dynamicSizes,
122684dfe8aSAlex Zinenko     ConversionPatternRewriter &rewriter, SmallVectorImpl<Value> &sizes,
123684dfe8aSAlex Zinenko     SmallVectorImpl<Value> &strides, Value &sizeBytes) const {
124684dfe8aSAlex Zinenko   assert(isConvertibleAndHasIdentityMaps(memRefType) &&
125684dfe8aSAlex Zinenko          "layout maps must have been normalized away");
126684dfe8aSAlex Zinenko   assert(count(memRefType.getShape(), ShapedType::kDynamicSize) ==
127684dfe8aSAlex Zinenko              static_cast<ssize_t>(dynamicSizes.size()) &&
128684dfe8aSAlex Zinenko          "dynamicSizes size doesn't match dynamic sizes count in memref shape");
129684dfe8aSAlex Zinenko 
130684dfe8aSAlex Zinenko   sizes.reserve(memRefType.getRank());
131684dfe8aSAlex Zinenko   unsigned dynamicIndex = 0;
132684dfe8aSAlex Zinenko   for (int64_t size : memRefType.getShape()) {
133684dfe8aSAlex Zinenko     sizes.push_back(size == ShapedType::kDynamicSize
134684dfe8aSAlex Zinenko                         ? dynamicSizes[dynamicIndex++]
135684dfe8aSAlex Zinenko                         : createIndexConstant(rewriter, loc, size));
136684dfe8aSAlex Zinenko   }
137684dfe8aSAlex Zinenko 
138684dfe8aSAlex Zinenko   // Strides: iterate sizes in reverse order and multiply.
139684dfe8aSAlex Zinenko   int64_t stride = 1;
140684dfe8aSAlex Zinenko   Value runningStride = createIndexConstant(rewriter, loc, 1);
141684dfe8aSAlex Zinenko   strides.resize(memRefType.getRank());
142684dfe8aSAlex Zinenko   for (auto i = memRefType.getRank(); i-- > 0;) {
143684dfe8aSAlex Zinenko     strides[i] = runningStride;
144684dfe8aSAlex Zinenko 
145684dfe8aSAlex Zinenko     int64_t size = memRefType.getShape()[i];
146684dfe8aSAlex Zinenko     if (size == 0)
147684dfe8aSAlex Zinenko       continue;
148684dfe8aSAlex Zinenko     bool useSizeAsStride = stride == 1;
149684dfe8aSAlex Zinenko     if (size == ShapedType::kDynamicSize)
150684dfe8aSAlex Zinenko       stride = ShapedType::kDynamicSize;
151684dfe8aSAlex Zinenko     if (stride != ShapedType::kDynamicSize)
152684dfe8aSAlex Zinenko       stride *= size;
153684dfe8aSAlex Zinenko 
154684dfe8aSAlex Zinenko     if (useSizeAsStride)
155684dfe8aSAlex Zinenko       runningStride = sizes[i];
156684dfe8aSAlex Zinenko     else if (stride == ShapedType::kDynamicSize)
157684dfe8aSAlex Zinenko       runningStride =
158684dfe8aSAlex Zinenko           rewriter.create<LLVM::MulOp>(loc, runningStride, sizes[i]);
159684dfe8aSAlex Zinenko     else
160684dfe8aSAlex Zinenko       runningStride = createIndexConstant(rewriter, loc, stride);
161684dfe8aSAlex Zinenko   }
162684dfe8aSAlex Zinenko 
163684dfe8aSAlex Zinenko   // Buffer size in bytes.
164684dfe8aSAlex Zinenko   Type elementPtrType = getElementPtrType(memRefType);
165684dfe8aSAlex Zinenko   Value nullPtr = rewriter.create<LLVM::NullOp>(loc, elementPtrType);
166cafaa350SAlex Zinenko   Value gepPtr = rewriter.create<LLVM::GEPOp>(loc, elementPtrType, nullPtr,
167cafaa350SAlex Zinenko                                               ArrayRef<Value>{runningStride});
168684dfe8aSAlex Zinenko   sizeBytes = rewriter.create<LLVM::PtrToIntOp>(loc, getIndexType(), gepPtr);
169684dfe8aSAlex Zinenko }
170684dfe8aSAlex Zinenko 
getSizeInBytes(Location loc,Type type,ConversionPatternRewriter & rewriter) const171684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::getSizeInBytes(
172684dfe8aSAlex Zinenko     Location loc, Type type, ConversionPatternRewriter &rewriter) const {
173684dfe8aSAlex Zinenko   // Compute the size of an individual element. This emits the MLIR equivalent
174684dfe8aSAlex Zinenko   // of the following sizeof(...) implementation in LLVM IR:
175684dfe8aSAlex Zinenko   //   %0 = getelementptr %elementType* null, %indexType 1
176684dfe8aSAlex Zinenko   //   %1 = ptrtoint %elementType* %0 to %indexType
177684dfe8aSAlex Zinenko   // which is a common pattern of getting the size of a type in bytes.
178684dfe8aSAlex Zinenko   auto convertedPtrType =
179684dfe8aSAlex Zinenko       LLVM::LLVMPointerType::get(typeConverter->convertType(type));
180684dfe8aSAlex Zinenko   auto nullPtr = rewriter.create<LLVM::NullOp>(loc, convertedPtrType);
181684dfe8aSAlex Zinenko   auto gep = rewriter.create<LLVM::GEPOp>(
182cafaa350SAlex Zinenko       loc, convertedPtrType, nullPtr,
183cafaa350SAlex Zinenko       ArrayRef<Value>{createIndexConstant(rewriter, loc, 1)});
184684dfe8aSAlex Zinenko   return rewriter.create<LLVM::PtrToIntOp>(loc, getIndexType(), gep);
185684dfe8aSAlex Zinenko }
186684dfe8aSAlex Zinenko 
getNumElements(Location loc,ArrayRef<Value> shape,ConversionPatternRewriter & rewriter) const187684dfe8aSAlex Zinenko Value ConvertToLLVMPattern::getNumElements(
188684dfe8aSAlex Zinenko     Location loc, ArrayRef<Value> shape,
189684dfe8aSAlex Zinenko     ConversionPatternRewriter &rewriter) const {
190684dfe8aSAlex Zinenko   // Compute the total number of memref elements.
191684dfe8aSAlex Zinenko   Value numElements =
192684dfe8aSAlex Zinenko       shape.empty() ? createIndexConstant(rewriter, loc, 1) : shape.front();
193684dfe8aSAlex Zinenko   for (unsigned i = 1, e = shape.size(); i < e; ++i)
194684dfe8aSAlex Zinenko     numElements = rewriter.create<LLVM::MulOp>(loc, numElements, shape[i]);
195684dfe8aSAlex Zinenko   return numElements;
196684dfe8aSAlex Zinenko }
197684dfe8aSAlex Zinenko 
198684dfe8aSAlex Zinenko /// Creates and populates the memref descriptor struct given all its fields.
createMemRefDescriptor(Location loc,MemRefType memRefType,Value allocatedPtr,Value alignedPtr,ArrayRef<Value> sizes,ArrayRef<Value> strides,ConversionPatternRewriter & rewriter) const199684dfe8aSAlex Zinenko MemRefDescriptor ConvertToLLVMPattern::createMemRefDescriptor(
200684dfe8aSAlex Zinenko     Location loc, MemRefType memRefType, Value allocatedPtr, Value alignedPtr,
201684dfe8aSAlex Zinenko     ArrayRef<Value> sizes, ArrayRef<Value> strides,
202684dfe8aSAlex Zinenko     ConversionPatternRewriter &rewriter) const {
203684dfe8aSAlex Zinenko   auto structType = typeConverter->convertType(memRefType);
204684dfe8aSAlex Zinenko   auto memRefDescriptor = MemRefDescriptor::undef(rewriter, loc, structType);
205684dfe8aSAlex Zinenko 
206684dfe8aSAlex Zinenko   // Field 1: Allocated pointer, used for malloc/free.
207684dfe8aSAlex Zinenko   memRefDescriptor.setAllocatedPtr(rewriter, loc, allocatedPtr);
208684dfe8aSAlex Zinenko 
209684dfe8aSAlex Zinenko   // Field 2: Actual aligned pointer to payload.
210684dfe8aSAlex Zinenko   memRefDescriptor.setAlignedPtr(rewriter, loc, alignedPtr);
211684dfe8aSAlex Zinenko 
212684dfe8aSAlex Zinenko   // Field 3: Offset in aligned pointer.
213684dfe8aSAlex Zinenko   memRefDescriptor.setOffset(rewriter, loc,
214684dfe8aSAlex Zinenko                              createIndexConstant(rewriter, loc, 0));
215684dfe8aSAlex Zinenko 
216684dfe8aSAlex Zinenko   // Fields 4: Sizes.
217e4853be2SMehdi Amini   for (const auto &en : llvm::enumerate(sizes))
218684dfe8aSAlex Zinenko     memRefDescriptor.setSize(rewriter, loc, en.index(), en.value());
219684dfe8aSAlex Zinenko 
220684dfe8aSAlex Zinenko   // Field 5: Strides.
221e4853be2SMehdi Amini   for (const auto &en : llvm::enumerate(strides))
222684dfe8aSAlex Zinenko     memRefDescriptor.setStride(rewriter, loc, en.index(), en.value());
223684dfe8aSAlex Zinenko 
224684dfe8aSAlex Zinenko   return memRefDescriptor;
225684dfe8aSAlex Zinenko }
226684dfe8aSAlex Zinenko 
copyUnrankedDescriptors(OpBuilder & builder,Location loc,TypeRange origTypes,SmallVectorImpl<Value> & operands,bool toDynamic) const227ed1f149bSFrederik Gossen LogicalResult ConvertToLLVMPattern::copyUnrankedDescriptors(
228ed1f149bSFrederik Gossen     OpBuilder &builder, Location loc, TypeRange origTypes,
229ed1f149bSFrederik Gossen     SmallVectorImpl<Value> &operands, bool toDynamic) const {
230ed1f149bSFrederik Gossen   assert(origTypes.size() == operands.size() &&
231ed1f149bSFrederik Gossen          "expected as may original types as operands");
232ed1f149bSFrederik Gossen 
233ed1f149bSFrederik Gossen   // Find operands of unranked memref type and store them.
234ed1f149bSFrederik Gossen   SmallVector<UnrankedMemRefDescriptor, 4> unrankedMemrefs;
235ed1f149bSFrederik Gossen   for (unsigned i = 0, e = operands.size(); i < e; ++i)
236ed1f149bSFrederik Gossen     if (origTypes[i].isa<UnrankedMemRefType>())
237ed1f149bSFrederik Gossen       unrankedMemrefs.emplace_back(operands[i]);
238ed1f149bSFrederik Gossen 
239ed1f149bSFrederik Gossen   if (unrankedMemrefs.empty())
240ed1f149bSFrederik Gossen     return success();
241ed1f149bSFrederik Gossen 
242ed1f149bSFrederik Gossen   // Compute allocation sizes.
243ed1f149bSFrederik Gossen   SmallVector<Value, 4> sizes;
244ed1f149bSFrederik Gossen   UnrankedMemRefDescriptor::computeSizes(builder, loc, *getTypeConverter(),
245ed1f149bSFrederik Gossen                                          unrankedMemrefs, sizes);
246ed1f149bSFrederik Gossen 
247ed1f149bSFrederik Gossen   // Get frequently used types.
248ed1f149bSFrederik Gossen   MLIRContext *context = builder.getContext();
249ed1f149bSFrederik Gossen   Type voidPtrType = LLVM::LLVMPointerType::get(IntegerType::get(context, 8));
250ed1f149bSFrederik Gossen   auto i1Type = IntegerType::get(context, 1);
251ed1f149bSFrederik Gossen   Type indexType = getTypeConverter()->getIndexType();
252ed1f149bSFrederik Gossen 
253ed1f149bSFrederik Gossen   // Find the malloc and free, or declare them if necessary.
254ed1f149bSFrederik Gossen   auto module = builder.getInsertionPoint()->getParentOfType<ModuleOp>();
255ed1f149bSFrederik Gossen   LLVM::LLVMFuncOp freeFunc, mallocFunc;
256ed1f149bSFrederik Gossen   if (toDynamic)
257ed1f149bSFrederik Gossen     mallocFunc = LLVM::lookupOrCreateMallocFn(module, indexType);
258ed1f149bSFrederik Gossen   if (!toDynamic)
259ed1f149bSFrederik Gossen     freeFunc = LLVM::lookupOrCreateFreeFn(module);
260ed1f149bSFrederik Gossen 
261ed1f149bSFrederik Gossen   // Initialize shared constants.
262ed1f149bSFrederik Gossen   Value zero =
263ed1f149bSFrederik Gossen       builder.create<LLVM::ConstantOp>(loc, i1Type, builder.getBoolAttr(false));
264ed1f149bSFrederik Gossen 
265ed1f149bSFrederik Gossen   unsigned unrankedMemrefPos = 0;
266ed1f149bSFrederik Gossen   for (unsigned i = 0, e = operands.size(); i < e; ++i) {
267ed1f149bSFrederik Gossen     Type type = origTypes[i];
268ed1f149bSFrederik Gossen     if (!type.isa<UnrankedMemRefType>())
269ed1f149bSFrederik Gossen       continue;
270ed1f149bSFrederik Gossen     Value allocationSize = sizes[unrankedMemrefPos++];
271ed1f149bSFrederik Gossen     UnrankedMemRefDescriptor desc(operands[i]);
272ed1f149bSFrederik Gossen 
273ed1f149bSFrederik Gossen     // Allocate memory, copy, and free the source if necessary.
274ed1f149bSFrederik Gossen     Value memory =
275ed1f149bSFrederik Gossen         toDynamic
276ed1f149bSFrederik Gossen             ? builder.create<LLVM::CallOp>(loc, mallocFunc, allocationSize)
277ed1f149bSFrederik Gossen                   .getResult(0)
278ed1f149bSFrederik Gossen             : builder.create<LLVM::AllocaOp>(loc, voidPtrType, allocationSize,
279ed1f149bSFrederik Gossen                                              /*alignment=*/0);
280ed1f149bSFrederik Gossen     Value source = desc.memRefDescPtr(builder, loc);
281ed1f149bSFrederik Gossen     builder.create<LLVM::MemcpyOp>(loc, memory, source, allocationSize, zero);
282ed1f149bSFrederik Gossen     if (!toDynamic)
283ed1f149bSFrederik Gossen       builder.create<LLVM::CallOp>(loc, freeFunc, source);
284ed1f149bSFrederik Gossen 
285ed1f149bSFrederik Gossen     // Create a new descriptor. The same descriptor can be returned multiple
286ed1f149bSFrederik Gossen     // times, attempting to modify its pointer can lead to memory leaks
287ed1f149bSFrederik Gossen     // (allocated twice and overwritten) or double frees (the caller does not
288ed1f149bSFrederik Gossen     // know if the descriptor points to the same memory).
289ed1f149bSFrederik Gossen     Type descriptorType = getTypeConverter()->convertType(type);
290ed1f149bSFrederik Gossen     if (!descriptorType)
291ed1f149bSFrederik Gossen       return failure();
292ed1f149bSFrederik Gossen     auto updatedDesc =
293ed1f149bSFrederik Gossen         UnrankedMemRefDescriptor::undef(builder, loc, descriptorType);
294ed1f149bSFrederik Gossen     Value rank = desc.rank(builder, loc);
295ed1f149bSFrederik Gossen     updatedDesc.setRank(builder, loc, rank);
296ed1f149bSFrederik Gossen     updatedDesc.setMemRefDescPtr(builder, loc, memory);
297ed1f149bSFrederik Gossen 
298ed1f149bSFrederik Gossen     operands[i] = updatedDesc;
299ed1f149bSFrederik Gossen   }
300ed1f149bSFrederik Gossen 
301ed1f149bSFrederik Gossen   return success();
302ed1f149bSFrederik Gossen }
303ed1f149bSFrederik Gossen 
304684dfe8aSAlex Zinenko //===----------------------------------------------------------------------===//
305684dfe8aSAlex Zinenko // Detail methods
306684dfe8aSAlex Zinenko //===----------------------------------------------------------------------===//
307684dfe8aSAlex Zinenko 
308684dfe8aSAlex Zinenko /// Replaces the given operation "op" with a new operation of type "targetOp"
309684dfe8aSAlex Zinenko /// and given operands.
oneToOneRewrite(Operation * op,StringRef targetOp,ValueRange operands,LLVMTypeConverter & typeConverter,ConversionPatternRewriter & rewriter)310684dfe8aSAlex Zinenko LogicalResult LLVM::detail::oneToOneRewrite(
311684dfe8aSAlex Zinenko     Operation *op, StringRef targetOp, ValueRange operands,
312684dfe8aSAlex Zinenko     LLVMTypeConverter &typeConverter, ConversionPatternRewriter &rewriter) {
313684dfe8aSAlex Zinenko   unsigned numResults = op->getNumResults();
314684dfe8aSAlex Zinenko 
315684dfe8aSAlex Zinenko   Type packedType;
316684dfe8aSAlex Zinenko   if (numResults != 0) {
317684dfe8aSAlex Zinenko     packedType = typeConverter.packFunctionResults(op->getResultTypes());
318684dfe8aSAlex Zinenko     if (!packedType)
319684dfe8aSAlex Zinenko       return failure();
320684dfe8aSAlex Zinenko   }
321684dfe8aSAlex Zinenko 
322684dfe8aSAlex Zinenko   // Create the operation through state since we don't know its C++ type.
323*14ecafd0SChia-hung Duan   Operation *newOp =
324*14ecafd0SChia-hung Duan       rewriter.create(op->getLoc(), rewriter.getStringAttr(targetOp), operands,
325*14ecafd0SChia-hung Duan                       packedType, op->getAttrs());
326684dfe8aSAlex Zinenko 
327684dfe8aSAlex Zinenko   // If the operation produced 0 or 1 result, return them immediately.
328684dfe8aSAlex Zinenko   if (numResults == 0)
329684dfe8aSAlex Zinenko     return rewriter.eraseOp(op), success();
330684dfe8aSAlex Zinenko   if (numResults == 1)
331684dfe8aSAlex Zinenko     return rewriter.replaceOp(op, newOp->getResult(0)), success();
332684dfe8aSAlex Zinenko 
333684dfe8aSAlex Zinenko   // Otherwise, it had been converted to an operation producing a structure.
334684dfe8aSAlex Zinenko   // Extract individual results from the structure and return them as list.
335684dfe8aSAlex Zinenko   SmallVector<Value, 4> results;
336684dfe8aSAlex Zinenko   results.reserve(numResults);
337684dfe8aSAlex Zinenko   for (unsigned i = 0; i < numResults; ++i) {
338684dfe8aSAlex Zinenko     auto type = typeConverter.convertType(op->getResult(i).getType());
339684dfe8aSAlex Zinenko     results.push_back(rewriter.create<LLVM::ExtractValueOp>(
340684dfe8aSAlex Zinenko         op->getLoc(), type, newOp->getResult(0), rewriter.getI64ArrayAttr(i)));
341684dfe8aSAlex Zinenko   }
342684dfe8aSAlex Zinenko   rewriter.replaceOp(op, results);
343684dfe8aSAlex Zinenko   return success();
344684dfe8aSAlex Zinenko }
345