1 //===- MemRefBuilder.h - Helper for LLVM MemRef equivalents -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Provides a convenience API for emitting IR that inspects or constructs values
10 // of LLVM dialect structure type that correspond to ranked or unranked memref.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_CONVERSION_LLVMCOMMON_MEMREFBUILDER_H
15 #define MLIR_CONVERSION_LLVMCOMMON_MEMREFBUILDER_H
16 
17 #include "mlir/Conversion/LLVMCommon/StructBuilder.h"
18 #include "mlir/IR/OperationSupport.h"
19 
20 namespace mlir {
21 
22 class LLVMTypeConverter;
23 class MemRefType;
24 class UnrankedMemRefType;
25 
26 namespace LLVM {
27 class LLVMPointerType;
28 } // namespace LLVM
29 
30 /// Helper class to produce LLVM dialect operations extracting or inserting
31 /// elements of a MemRef descriptor. Wraps a Value pointing to the descriptor.
32 /// The Value may be null, in which case none of the operations are valid.
33 class MemRefDescriptor : public StructBuilder {
34 public:
35   /// Construct a helper for the given descriptor value.
36   explicit MemRefDescriptor(Value descriptor);
37   /// Builds IR creating an `undef` value of the descriptor type.
38   static MemRefDescriptor undef(OpBuilder &builder, Location loc,
39                                 Type descriptorType);
40   /// Builds IR creating a MemRef descriptor that represents `type` and
41   /// populates it with static shape and stride information extracted from the
42   /// type.
43   static MemRefDescriptor fromStaticShape(OpBuilder &builder, Location loc,
44                                           LLVMTypeConverter &typeConverter,
45                                           MemRefType type, Value memory);
46 
47   /// Builds IR extracting the allocated pointer from the descriptor.
48   Value allocatedPtr(OpBuilder &builder, Location loc);
49   /// Builds IR inserting the allocated pointer into the descriptor.
50   void setAllocatedPtr(OpBuilder &builder, Location loc, Value ptr);
51 
52   /// Builds IR extracting the aligned pointer from the descriptor.
53   Value alignedPtr(OpBuilder &builder, Location loc);
54 
55   /// Builds IR inserting the aligned pointer into the descriptor.
56   void setAlignedPtr(OpBuilder &builder, Location loc, Value ptr);
57 
58   /// Builds IR extracting the offset from the descriptor.
59   Value offset(OpBuilder &builder, Location loc);
60 
61   /// Builds IR inserting the offset into the descriptor.
62   void setOffset(OpBuilder &builder, Location loc, Value offset);
63   void setConstantOffset(OpBuilder &builder, Location loc, uint64_t offset);
64 
65   /// Builds IR extracting the pos-th size from the descriptor.
66   Value size(OpBuilder &builder, Location loc, unsigned pos);
67   Value size(OpBuilder &builder, Location loc, Value pos, int64_t rank);
68 
69   /// Builds IR inserting the pos-th size into the descriptor
70   void setSize(OpBuilder &builder, Location loc, unsigned pos, Value size);
71   void setConstantSize(OpBuilder &builder, Location loc, unsigned pos,
72                        uint64_t size);
73 
74   /// Builds IR extracting the pos-th size from the descriptor.
75   Value stride(OpBuilder &builder, Location loc, unsigned pos);
76 
77   /// Builds IR inserting the pos-th stride into the descriptor
78   void setStride(OpBuilder &builder, Location loc, unsigned pos, Value stride);
79   void setConstantStride(OpBuilder &builder, Location loc, unsigned pos,
80                          uint64_t stride);
81 
82   /// Returns the type of array element in this descriptor.
getIndexType()83   Type getIndexType() { return indexType; };
84 
85   /// Returns the (LLVM) pointer type this descriptor contains.
86   LLVM::LLVMPointerType getElementPtrType();
87 
88   /// Builds IR populating a MemRef descriptor structure from a list of
89   /// individual values composing that descriptor, in the following order:
90   /// - allocated pointer;
91   /// - aligned pointer;
92   /// - offset;
93   /// - <rank> sizes;
94   /// - <rank> shapes;
95   /// where <rank> is the MemRef rank as provided in `type`.
96   static Value pack(OpBuilder &builder, Location loc,
97                     LLVMTypeConverter &converter, MemRefType type,
98                     ValueRange values);
99 
100   /// Builds IR extracting individual elements of a MemRef descriptor structure
101   /// and returning them as `results` list.
102   static void unpack(OpBuilder &builder, Location loc, Value packed,
103                      MemRefType type, SmallVectorImpl<Value> &results);
104 
105   /// Returns the number of non-aggregate values that would be produced by
106   /// `unpack`.
107   static unsigned getNumUnpackedValues(MemRefType type);
108 
109 private:
110   // Cached index type.
111   Type indexType;
112 };
113 
114 /// Helper class allowing the user to access a range of Values that correspond
115 /// to an unpacked memref descriptor using named accessors. This does not own
116 /// the values.
117 class MemRefDescriptorView {
118 public:
119   /// Constructs the view from a range of values. Infers the rank from the size
120   /// of the range.
121   explicit MemRefDescriptorView(ValueRange range);
122 
123   /// Returns the allocated pointer Value.
124   Value allocatedPtr();
125 
126   /// Returns the aligned pointer Value.
127   Value alignedPtr();
128 
129   /// Returns the offset Value.
130   Value offset();
131 
132   /// Returns the pos-th size Value.
133   Value size(unsigned pos);
134 
135   /// Returns the pos-th stride Value.
136   Value stride(unsigned pos);
137 
138 private:
139   /// Rank of the memref the descriptor is pointing to.
140   int rank;
141   /// Underlying range of Values.
142   ValueRange elements;
143 };
144 
145 class UnrankedMemRefDescriptor : public StructBuilder {
146 public:
147   /// Construct a helper for the given descriptor value.
148   explicit UnrankedMemRefDescriptor(Value descriptor);
149   /// Builds IR creating an `undef` value of the descriptor type.
150   static UnrankedMemRefDescriptor undef(OpBuilder &builder, Location loc,
151                                         Type descriptorType);
152 
153   /// Builds IR extracting the rank from the descriptor
154   Value rank(OpBuilder &builder, Location loc);
155   /// Builds IR setting the rank in the descriptor
156   void setRank(OpBuilder &builder, Location loc, Value value);
157   /// Builds IR extracting ranked memref descriptor ptr
158   Value memRefDescPtr(OpBuilder &builder, Location loc);
159   /// Builds IR setting ranked memref descriptor ptr
160   void setMemRefDescPtr(OpBuilder &builder, Location loc, Value value);
161 
162   /// Builds IR populating an unranked MemRef descriptor structure from a list
163   /// of individual constituent values in the following order:
164   /// - rank of the memref;
165   /// - pointer to the memref descriptor.
166   static Value pack(OpBuilder &builder, Location loc,
167                     LLVMTypeConverter &converter, UnrankedMemRefType type,
168                     ValueRange values);
169 
170   /// Builds IR extracting individual elements that compose an unranked memref
171   /// descriptor and returns them as `results` list.
172   static void unpack(OpBuilder &builder, Location loc, Value packed,
173                      SmallVectorImpl<Value> &results);
174 
175   /// Returns the number of non-aggregate values that would be produced by
176   /// `unpack`.
getNumUnpackedValues()177   static unsigned getNumUnpackedValues() { return 2; }
178 
179   /// Builds IR computing the sizes in bytes (suitable for opaque allocation)
180   /// and appends the corresponding values into `sizes`.
181   static void computeSizes(OpBuilder &builder, Location loc,
182                            LLVMTypeConverter &typeConverter,
183                            ArrayRef<UnrankedMemRefDescriptor> values,
184                            SmallVectorImpl<Value> &sizes);
185 
186   /// TODO: The following accessors don't take alignment rules between elements
187   /// of the descriptor struct into account. For some architectures, it might be
188   /// necessary to extend them and to use `llvm::DataLayout` contained in
189   /// `LLVMTypeConverter`.
190 
191   /// Builds IR extracting the allocated pointer from the descriptor.
192   static Value allocatedPtr(OpBuilder &builder, Location loc,
193                             Value memRefDescPtr, Type elemPtrPtrType);
194   /// Builds IR inserting the allocated pointer into the descriptor.
195   static void setAllocatedPtr(OpBuilder &builder, Location loc,
196                               Value memRefDescPtr, Type elemPtrPtrType,
197                               Value allocatedPtr);
198 
199   /// Builds IR extracting the aligned pointer from the descriptor.
200   static Value alignedPtr(OpBuilder &builder, Location loc,
201                           LLVMTypeConverter &typeConverter, Value memRefDescPtr,
202                           Type elemPtrPtrType);
203   /// Builds IR inserting the aligned pointer into the descriptor.
204   static void setAlignedPtr(OpBuilder &builder, Location loc,
205                             LLVMTypeConverter &typeConverter,
206                             Value memRefDescPtr, Type elemPtrPtrType,
207                             Value alignedPtr);
208 
209   /// Builds IR extracting the offset from the descriptor.
210   static Value offset(OpBuilder &builder, Location loc,
211                       LLVMTypeConverter &typeConverter, Value memRefDescPtr,
212                       Type elemPtrPtrType);
213   /// Builds IR inserting the offset into the descriptor.
214   static void setOffset(OpBuilder &builder, Location loc,
215                         LLVMTypeConverter &typeConverter, Value memRefDescPtr,
216                         Type elemPtrPtrType, Value offset);
217 
218   /// Builds IR extracting the pointer to the first element of the size array.
219   static Value sizeBasePtr(OpBuilder &builder, Location loc,
220                            LLVMTypeConverter &typeConverter,
221                            Value memRefDescPtr,
222                            LLVM::LLVMPointerType elemPtrPtrType);
223   /// Builds IR extracting the size[index] from the descriptor.
224   static Value size(OpBuilder &builder, Location loc,
225                     LLVMTypeConverter &typeConverter, Value sizeBasePtr,
226                     Value index);
227   /// Builds IR inserting the size[index] into the descriptor.
228   static void setSize(OpBuilder &builder, Location loc,
229                       LLVMTypeConverter &typeConverter, Value sizeBasePtr,
230                       Value index, Value size);
231 
232   /// Builds IR extracting the pointer to the first element of the stride array.
233   static Value strideBasePtr(OpBuilder &builder, Location loc,
234                              LLVMTypeConverter &typeConverter,
235                              Value sizeBasePtr, Value rank);
236   /// Builds IR extracting the stride[index] from the descriptor.
237   static Value stride(OpBuilder &builder, Location loc,
238                       LLVMTypeConverter &typeConverter, Value strideBasePtr,
239                       Value index, Value stride);
240   /// Builds IR inserting the stride[index] into the descriptor.
241   static void setStride(OpBuilder &builder, Location loc,
242                         LLVMTypeConverter &typeConverter, Value strideBasePtr,
243                         Value index, Value stride);
244 };
245 
246 } // namespace mlir
247 
248 #endif // MLIR_CONVERSION_LLVMCOMMON_MEMREFBUILDER_H
249