xref: /llvm-project/mlir/lib/Conversion/LLVMCommon/Pattern.cpp (revision e84f6b6a88c1222d512edf0644c8f869dd12b8ef)
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