blob: 2bfeb48d89430bf8730169495ef4df5c9c22dc42 [file] [log] [blame]
Chris Lattnerf7e22732018-06-22 22:03:48 -07001//===- MLIRContext.cpp - MLIR Type Classes --------------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17
18#include "mlir/IR/MLIRContext.h"
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -070019#include "AttributeListStorage.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070020#include "mlir/IR/AffineExpr.h"
21#include "mlir/IR/AffineMap.h"
Chris Lattner36b4ed12018-07-04 10:43:29 -070022#include "mlir/IR/Attributes.h"
Chris Lattner4613d9e2018-08-19 21:17:22 -070023#include "mlir/IR/Function.h"
Chris Lattner36b4ed12018-07-04 10:43:29 -070024#include "mlir/IR/Identifier.h"
Uday Bondhugulabc535622018-08-07 14:24:38 -070025#include "mlir/IR/IntegerSet.h"
Chris Lattnerfc647d52018-08-27 21:05:16 -070026#include "mlir/IR/Location.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070027#include "mlir/IR/OperationSet.h"
28#include "mlir/IR/StandardOps.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070029#include "mlir/IR/Types.h"
Chris Lattner36b4ed12018-07-04 10:43:29 -070030#include "mlir/Support/STLExtras.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070031#include "llvm/ADT/DenseSet.h"
Chris Lattnered65a732018-06-28 20:45:33 -070032#include "llvm/ADT/StringMap.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070033#include "llvm/Support/Allocator.h"
Chris Lattner95865062018-08-01 10:18:59 -070034#include "llvm/Support/raw_ostream.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070035using namespace mlir;
36using namespace llvm;
37
38namespace {
James Molloy87d81022018-07-23 11:44:40 -070039struct FunctionTypeKeyInfo : DenseMapInfo<FunctionType *> {
Chris Lattnerf7e22732018-06-22 22:03:48 -070040 // Functions are uniqued based on their inputs and results.
James Molloy87d81022018-07-23 11:44:40 -070041 using KeyTy = std::pair<ArrayRef<Type *>, ArrayRef<Type *>>;
42 using DenseMapInfo<FunctionType *>::getHashValue;
43 using DenseMapInfo<FunctionType *>::isEqual;
Chris Lattnerf7e22732018-06-22 22:03:48 -070044
45 static unsigned getHashValue(KeyTy key) {
James Molloy87d81022018-07-23 11:44:40 -070046 return hash_combine(
47 hash_combine_range(key.first.begin(), key.first.end()),
48 hash_combine_range(key.second.begin(), key.second.end()));
Chris Lattnerf7e22732018-06-22 22:03:48 -070049 }
50
51 static bool isEqual(const KeyTy &lhs, const FunctionType *rhs) {
52 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
53 return false;
54 return lhs == KeyTy(rhs->getInputs(), rhs->getResults());
55 }
56};
Uday Bondhugula015cbb12018-07-03 20:16:08 -070057
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070058struct AffineMapKeyInfo : DenseMapInfo<AffineMap *> {
Uday Bondhugula015cbb12018-07-03 20:16:08 -070059 // Affine maps are uniqued based on their dim/symbol counts and affine
60 // expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -070061 using KeyTy = std::tuple<unsigned, unsigned, ArrayRef<AffineExpr *>,
62 ArrayRef<AffineExpr *>>;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070063 using DenseMapInfo<AffineMap *>::getHashValue;
64 using DenseMapInfo<AffineMap *>::isEqual;
65
66 static unsigned getHashValue(KeyTy key) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -070067 return hash_combine(
Chris Lattner36b4ed12018-07-04 10:43:29 -070068 std::get<0>(key), std::get<1>(key),
Uday Bondhugula0115dbb2018-07-11 21:31:07 -070069 hash_combine_range(std::get<2>(key).begin(), std::get<2>(key).end()),
70 hash_combine_range(std::get<3>(key).begin(), std::get<3>(key).end()));
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070071 }
72
Uday Bondhugula015cbb12018-07-03 20:16:08 -070073 static bool isEqual(const KeyTy &lhs, const AffineMap *rhs) {
74 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
75 return false;
Chris Lattner36b4ed12018-07-04 10:43:29 -070076 return lhs == std::make_tuple(rhs->getNumDims(), rhs->getNumSymbols(),
Uday Bondhugula0115dbb2018-07-11 21:31:07 -070077 rhs->getResults(), rhs->getRangeSizes());
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070078 }
79};
80
James Molloy87d81022018-07-23 11:44:40 -070081struct VectorTypeKeyInfo : DenseMapInfo<VectorType *> {
Chris Lattnerf7e22732018-06-22 22:03:48 -070082 // Vectors are uniqued based on their element type and shape.
James Molloy87d81022018-07-23 11:44:40 -070083 using KeyTy = std::pair<Type *, ArrayRef<unsigned>>;
84 using DenseMapInfo<VectorType *>::getHashValue;
85 using DenseMapInfo<VectorType *>::isEqual;
Chris Lattnerf7e22732018-06-22 22:03:48 -070086
87 static unsigned getHashValue(KeyTy key) {
James Molloy87d81022018-07-23 11:44:40 -070088 return hash_combine(
89 DenseMapInfo<Type *>::getHashValue(key.first),
90 hash_combine_range(key.second.begin(), key.second.end()));
Chris Lattnerf7e22732018-06-22 22:03:48 -070091 }
92
93 static bool isEqual(const KeyTy &lhs, const VectorType *rhs) {
94 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
95 return false;
96 return lhs == KeyTy(rhs->getElementType(), rhs->getShape());
97 }
98};
Chris Lattner36b4ed12018-07-04 10:43:29 -070099
James Molloy87d81022018-07-23 11:44:40 -0700100struct RankedTensorTypeKeyInfo : DenseMapInfo<RankedTensorType *> {
MLIR Team355ec862018-06-23 18:09:09 -0700101 // Ranked tensors are uniqued based on their element type and shape.
James Molloy87d81022018-07-23 11:44:40 -0700102 using KeyTy = std::pair<Type *, ArrayRef<int>>;
103 using DenseMapInfo<RankedTensorType *>::getHashValue;
104 using DenseMapInfo<RankedTensorType *>::isEqual;
MLIR Team355ec862018-06-23 18:09:09 -0700105
106 static unsigned getHashValue(KeyTy key) {
James Molloy87d81022018-07-23 11:44:40 -0700107 return hash_combine(
108 DenseMapInfo<Type *>::getHashValue(key.first),
109 hash_combine_range(key.second.begin(), key.second.end()));
MLIR Team355ec862018-06-23 18:09:09 -0700110 }
111
112 static bool isEqual(const KeyTy &lhs, const RankedTensorType *rhs) {
113 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
114 return false;
115 return lhs == KeyTy(rhs->getElementType(), rhs->getShape());
116 }
117};
Chris Lattner36b4ed12018-07-04 10:43:29 -0700118
James Molloy87d81022018-07-23 11:44:40 -0700119struct MemRefTypeKeyInfo : DenseMapInfo<MemRefType *> {
MLIR Team718c82f2018-07-16 09:45:22 -0700120 // MemRefs are uniqued based on their element type, shape, affine map
121 // composition, and memory space.
James Molloy87d81022018-07-23 11:44:40 -0700122 using KeyTy =
123 std::tuple<Type *, ArrayRef<int>, ArrayRef<AffineMap *>, unsigned>;
124 using DenseMapInfo<MemRefType *>::getHashValue;
125 using DenseMapInfo<MemRefType *>::isEqual;
MLIR Team718c82f2018-07-16 09:45:22 -0700126
127 static unsigned getHashValue(KeyTy key) {
128 return hash_combine(
James Molloy87d81022018-07-23 11:44:40 -0700129 DenseMapInfo<Type *>::getHashValue(std::get<0>(key)),
MLIR Team718c82f2018-07-16 09:45:22 -0700130 hash_combine_range(std::get<1>(key).begin(), std::get<1>(key).end()),
131 hash_combine_range(std::get<2>(key).begin(), std::get<2>(key).end()),
132 std::get<3>(key));
133 }
134
135 static bool isEqual(const KeyTy &lhs, const MemRefType *rhs) {
136 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
137 return false;
138 return lhs == std::make_tuple(rhs->getElementType(), rhs->getShape(),
139 rhs->getAffineMaps(), rhs->getMemorySpace());
140 }
141};
142
James Molloy87d81022018-07-23 11:44:40 -0700143struct ArrayAttrKeyInfo : DenseMapInfo<ArrayAttr *> {
Chris Lattner36b4ed12018-07-04 10:43:29 -0700144 // Array attributes are uniqued based on their elements.
James Molloy87d81022018-07-23 11:44:40 -0700145 using KeyTy = ArrayRef<Attribute *>;
146 using DenseMapInfo<ArrayAttr *>::getHashValue;
147 using DenseMapInfo<ArrayAttr *>::isEqual;
Chris Lattner36b4ed12018-07-04 10:43:29 -0700148
149 static unsigned getHashValue(KeyTy key) {
150 return hash_combine_range(key.begin(), key.end());
151 }
152
153 static bool isEqual(const KeyTy &lhs, const ArrayAttr *rhs) {
154 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
155 return false;
156 return lhs == rhs->getValue();
157 }
158};
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700159
160struct AttributeListKeyInfo : DenseMapInfo<AttributeListStorage *> {
161 // Array attributes are uniqued based on their elements.
162 using KeyTy = ArrayRef<NamedAttribute>;
163 using DenseMapInfo<AttributeListStorage *>::getHashValue;
164 using DenseMapInfo<AttributeListStorage *>::isEqual;
165
166 static unsigned getHashValue(KeyTy key) {
167 return hash_combine_range(key.begin(), key.end());
168 }
169
170 static bool isEqual(const KeyTy &lhs, const AttributeListStorage *rhs) {
171 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
172 return false;
173 return lhs == rhs->getElements();
174 }
175};
176
Chris Lattnerf7e22732018-06-22 22:03:48 -0700177} // end anonymous namespace.
178
Chris Lattnerf7e22732018-06-22 22:03:48 -0700179namespace mlir {
180/// This is the implementation of the MLIRContext class, using the pImpl idiom.
181/// This class is completely private to this file, so everything is public.
182class MLIRContextImpl {
183public:
Chris Lattnerff0d5902018-07-05 09:12:11 -0700184 /// This is the set of all operations that are registered with the system.
185 OperationSet operationSet;
186
Chris Lattnerfc647d52018-08-27 21:05:16 -0700187 /// We put location info into this allocator, since it is generally not
188 /// touched by compiler passes.
189 llvm::BumpPtrAllocator locationAllocator;
190
191 /// The singleton for UnknownLoc.
192 UnknownLoc *theUnknownLoc = nullptr;
193
194 /// These are filename locations uniqued into this MLIRContext.
195 llvm::StringMap<char, llvm::BumpPtrAllocator &> filenames;
196
197 /// FileLineColLoc uniquing.
198 DenseMap<std::tuple<const char *, unsigned, unsigned>, FileLineColLoc *>
199 fileLineColLocs;
200
201 /// We put immortal objects into this allocator.
202 llvm::BumpPtrAllocator allocator;
203
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700204 /// This is the handler to use to report diagnostics, or null if not
205 /// registered.
206 MLIRContext::DiagnosticHandlerTy diagnosticHandler;
Chris Lattner95865062018-08-01 10:18:59 -0700207
Chris Lattnered65a732018-06-28 20:45:33 -0700208 /// These are identifiers uniqued into this MLIRContext.
James Molloy87d81022018-07-23 11:44:40 -0700209 llvm::StringMap<char, llvm::BumpPtrAllocator &> identifiers;
Chris Lattnered65a732018-06-28 20:45:33 -0700210
Chris Lattnerc3251192018-07-27 13:09:58 -0700211 // Uniquing table for 'other' types.
212 OtherType *otherTypes[int(Type::Kind::LAST_OTHER_TYPE) -
213 int(Type::Kind::FIRST_OTHER_TYPE) + 1] = {nullptr};
214
215 // Uniquing table for 'float' types.
216 FloatType *floatTypes[int(Type::Kind::LAST_FLOATING_POINT_TYPE) -
217 int(Type::Kind::FIRST_FLOATING_POINT_TYPE) + 1] = {
James Molloy87d81022018-07-23 11:44:40 -0700218 nullptr};
Chris Lattnerf7e22732018-06-22 22:03:48 -0700219
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700220 // Affine map uniquing.
221 using AffineMapSet = DenseSet<AffineMap *, AffineMapKeyInfo>;
222 AffineMapSet affineMaps;
223
Uday Bondhugula0b80a162018-07-03 21:34:58 -0700224 // Affine binary op expression uniquing. Figure out uniquing of dimensional
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700225 // or symbolic identifiers.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700226 DenseMap<std::tuple<unsigned, AffineExpr *, AffineExpr *>, AffineExpr *>
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700227 affineExprs;
228
Uday Bondhugula4e5078b2018-07-24 22:34:09 -0700229 // Uniqui'ing of AffineDimExpr, AffineSymbolExpr's by their position.
230 std::vector<AffineDimExpr *> dimExprs;
231 std::vector<AffineSymbolExpr *> symbolExprs;
232
233 // Uniqui'ing of AffineConstantExpr using constant value as key.
234 DenseMap<int64_t, AffineConstantExpr *> constExprs;
235
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700236 /// Integer type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700237 DenseMap<unsigned, IntegerType *> integers;
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700238
Chris Lattnerf7e22732018-06-22 22:03:48 -0700239 /// Function type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700240 using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>;
Chris Lattnerf7e22732018-06-22 22:03:48 -0700241 FunctionTypeSet functions;
242
243 /// Vector type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700244 using VectorTypeSet = DenseSet<VectorType *, VectorTypeKeyInfo>;
Chris Lattnerf7e22732018-06-22 22:03:48 -0700245 VectorTypeSet vectors;
246
MLIR Team355ec862018-06-23 18:09:09 -0700247 /// Ranked tensor type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700248 using RankedTensorTypeSet =
249 DenseSet<RankedTensorType *, RankedTensorTypeKeyInfo>;
MLIR Team355ec862018-06-23 18:09:09 -0700250 RankedTensorTypeSet rankedTensors;
251
252 /// Unranked tensor type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700253 DenseMap<Type *, UnrankedTensorType *> unrankedTensors;
MLIR Team355ec862018-06-23 18:09:09 -0700254
MLIR Team718c82f2018-07-16 09:45:22 -0700255 /// MemRef type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700256 using MemRefTypeSet = DenseSet<MemRefType *, MemRefTypeKeyInfo>;
MLIR Team718c82f2018-07-16 09:45:22 -0700257 MemRefTypeSet memrefs;
258
Chris Lattner36b4ed12018-07-04 10:43:29 -0700259 // Attribute uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700260 BoolAttr *boolAttrs[2] = {nullptr};
261 DenseMap<int64_t, IntegerAttr *> integerAttrs;
262 DenseMap<int64_t, FloatAttr *> floatAttrs;
263 StringMap<StringAttr *> stringAttrs;
264 using ArrayAttrSet = DenseSet<ArrayAttr *, ArrayAttrKeyInfo>;
Chris Lattner36b4ed12018-07-04 10:43:29 -0700265 ArrayAttrSet arrayAttrs;
James Molloy87d81022018-07-23 11:44:40 -0700266 DenseMap<AffineMap *, AffineMapAttr *> affineMapAttrs;
James Molloyf0d2f442018-08-03 01:54:46 -0700267 DenseMap<Type *, TypeAttr *> typeAttrs;
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700268 using AttributeListSet =
269 DenseSet<AttributeListStorage *, AttributeListKeyInfo>;
270 AttributeListSet attributeLists;
Chris Lattner1aa46322018-08-21 17:55:22 -0700271 DenseMap<const Function *, FunctionAttr *> functionAttrs;
Chris Lattnerf7e22732018-06-22 22:03:48 -0700272
273public:
Chris Lattnerfc647d52018-08-27 21:05:16 -0700274 MLIRContextImpl() : filenames(locationAllocator), identifiers(allocator) {
Chris Lattnerff0d5902018-07-05 09:12:11 -0700275 registerStandardOperations(operationSet);
276 }
Chris Lattnered65a732018-06-28 20:45:33 -0700277
Chris Lattnerf7e22732018-06-22 22:03:48 -0700278 /// Copy the specified array of elements into memory managed by our bump
279 /// pointer allocator. This assumes the elements are all PODs.
James Molloy72b0cbe2018-08-01 12:55:27 -0700280 template <typename T>
281 ArrayRef<T> copyInto(ArrayRef<T> elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700282 auto result = allocator.Allocate<T>(elements.size());
283 std::uninitialized_copy(elements.begin(), elements.end(), result);
284 return ArrayRef<T>(result, elements.size());
285 }
286};
287} // end namespace mlir
288
James Molloy87d81022018-07-23 11:44:40 -0700289MLIRContext::MLIRContext() : impl(new MLIRContextImpl()) {}
Chris Lattnerf7e22732018-06-22 22:03:48 -0700290
James Molloy87d81022018-07-23 11:44:40 -0700291MLIRContext::~MLIRContext() {}
Chris Lattnerf7e22732018-06-22 22:03:48 -0700292
Chris Lattner95865062018-08-01 10:18:59 -0700293/// Register an issue handler with this LLVM context. The issue handler is
294/// passed location information if present (nullptr if not) along with a
295/// message and a boolean that indicates whether this is an error or warning.
296void MLIRContext::registerDiagnosticHandler(
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700297 const DiagnosticHandlerTy &handler) {
298 getImpl().diagnosticHandler = handler;
Chris Lattner95865062018-08-01 10:18:59 -0700299}
300
Chris Lattnerea5c3dc2018-08-21 08:42:19 -0700301/// Return the current diagnostic handler, or null if none is present.
302auto MLIRContext::getDiagnosticHandler() const -> DiagnosticHandlerTy {
303 return getImpl().diagnosticHandler;
304}
305
Chris Lattner95865062018-08-01 10:18:59 -0700306/// This emits a diagnostic using the registered issue handle if present, or
307/// with the default behavior if not. The MLIR compiler should not generally
308/// interact with this, it should use methods on Operation instead.
Chris Lattnerfc647d52018-08-27 21:05:16 -0700309void MLIRContext::emitDiagnostic(Location *location, const llvm::Twine &message,
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700310 DiagnosticKind kind) const {
Chris Lattner95865062018-08-01 10:18:59 -0700311 // If we had a handler registered, emit the diagnostic using it.
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700312 auto handler = getImpl().diagnosticHandler;
313 if (handler && location)
314 return handler(location, message.str(), kind);
Chris Lattner95865062018-08-01 10:18:59 -0700315
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700316 // The default behavior for notes and warnings is to ignore them.
317 if (kind != DiagnosticKind::Error)
Chris Lattner95865062018-08-01 10:18:59 -0700318 return;
319
Chris Lattner7879f842018-09-02 22:01:45 -0700320 auto &os = llvm::errs();
321
322 if (auto fileLoc = dyn_cast<FileLineColLoc>(location))
323 os << fileLoc->getFilename() << ':' << fileLoc->getLine() << ':'
324 << fileLoc->getColumn() << ": ";
325
326 os << "error: ";
Chris Lattnerfc647d52018-08-27 21:05:16 -0700327
Chris Lattner95865062018-08-01 10:18:59 -0700328 // The default behavior for errors is to emit them to stderr and exit.
Chris Lattner7879f842018-09-02 22:01:45 -0700329 os << message.str() << '\n';
330 os.flush();
Chris Lattner95865062018-08-01 10:18:59 -0700331 exit(1);
332}
333
Chris Lattnerff0d5902018-07-05 09:12:11 -0700334/// Return the operation set associated with the specified MLIRContext object.
335OperationSet &OperationSet::get(MLIRContext *context) {
336 return context->getImpl().operationSet;
337}
Chris Lattnerf7e22732018-06-22 22:03:48 -0700338
Chris Lattner21e67f62018-07-06 10:46:19 -0700339/// If this operation has a registered operation description in the
340/// OperationSet, return it. Otherwise return null.
Chris Lattner95865062018-08-01 10:18:59 -0700341const AbstractOperation *Operation::getAbstractOperation() const {
342 return OperationSet::get(getContext()).lookup(getName().str());
Chris Lattner21e67f62018-07-06 10:46:19 -0700343}
344
Chris Lattnered65a732018-06-28 20:45:33 -0700345//===----------------------------------------------------------------------===//
Chris Lattner36b4ed12018-07-04 10:43:29 -0700346// Identifier uniquing
Chris Lattnered65a732018-06-28 20:45:33 -0700347//===----------------------------------------------------------------------===//
348
349/// Return an identifier for the specified string.
350Identifier Identifier::get(StringRef str, const MLIRContext *context) {
351 assert(!str.empty() && "Cannot create an empty identifier");
352 assert(str.find('\0') == StringRef::npos &&
353 "Cannot create an identifier with a nul character");
354
355 auto &impl = context->getImpl();
356 auto it = impl.identifiers.insert({str, char()}).first;
357 return Identifier(it->getKeyData());
358}
359
Chris Lattnered65a732018-06-28 20:45:33 -0700360//===----------------------------------------------------------------------===//
Chris Lattnerfc647d52018-08-27 21:05:16 -0700361// Location uniquing
362//===----------------------------------------------------------------------===//
363
364UnknownLoc *UnknownLoc::get(MLIRContext *context) {
365 auto &impl = context->getImpl();
366 if (auto *result = impl.theUnknownLoc)
367 return result;
368
369 impl.theUnknownLoc = impl.allocator.Allocate<UnknownLoc>();
370 new (impl.theUnknownLoc) UnknownLoc();
371 return impl.theUnknownLoc;
372}
373
374UniquedFilename UniquedFilename::get(StringRef filename, MLIRContext *context) {
375 auto &impl = context->getImpl();
376 auto it = impl.filenames.insert({filename, char()}).first;
377 return UniquedFilename(it->getKeyData());
378}
379
380FileLineColLoc *FileLineColLoc::get(UniquedFilename filename, unsigned line,
381 unsigned column, MLIRContext *context) {
382 auto &impl = context->getImpl();
383 auto &entry =
384 impl.fileLineColLocs[std::make_tuple(filename.data(), line, column)];
385 if (!entry) {
386 entry = impl.allocator.Allocate<FileLineColLoc>();
387 new (entry) FileLineColLoc(filename, line, column);
388 }
389
390 return entry;
391}
392
393//===----------------------------------------------------------------------===//
Chris Lattner36b4ed12018-07-04 10:43:29 -0700394// Type uniquing
Chris Lattnered65a732018-06-28 20:45:33 -0700395//===----------------------------------------------------------------------===//
396
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700397IntegerType *IntegerType::get(unsigned width, MLIRContext *context) {
398 auto &impl = context->getImpl();
399
400 auto *&result = impl.integers[width];
401 if (!result) {
402 result = impl.allocator.Allocate<IntegerType>();
403 new (result) IntegerType(width, context);
404 }
405
406 return result;
Chris Lattnerf7e22732018-06-22 22:03:48 -0700407}
408
Chris Lattnerc3251192018-07-27 13:09:58 -0700409FloatType *FloatType::get(Kind kind, MLIRContext *context) {
410 assert(kind >= Kind::FIRST_FLOATING_POINT_TYPE &&
411 kind <= Kind::LAST_FLOATING_POINT_TYPE && "Not an FP type kind");
412 auto &impl = context->getImpl();
413
414 // We normally have these types.
415 auto *&entry =
416 impl.floatTypes[(int)kind - int(Kind::FIRST_FLOATING_POINT_TYPE)];
417 if (entry)
418 return entry;
419
420 // On the first use, we allocate them into the bump pointer.
421 auto *ptr = impl.allocator.Allocate<FloatType>();
422
423 // Initialize the memory using placement new.
424 new (ptr) FloatType(kind, context);
425
426 // Cache and return it.
427 return entry = ptr;
428}
429
430OtherType *OtherType::get(Kind kind, MLIRContext *context) {
431 assert(kind >= Kind::FIRST_OTHER_TYPE && kind <= Kind::LAST_OTHER_TYPE &&
432 "Not an 'other' type kind");
433 auto &impl = context->getImpl();
434
435 // We normally have these types.
436 auto *&entry = impl.otherTypes[(int)kind - int(Kind::FIRST_OTHER_TYPE)];
437 if (entry)
438 return entry;
439
440 // On the first use, we allocate them into the bump pointer.
441 auto *ptr = impl.allocator.Allocate<OtherType>();
442
443 // Initialize the memory using placement new.
444 new (ptr) OtherType(kind, context);
445
446 // Cache and return it.
447 return entry = ptr;
448}
449
James Molloy87d81022018-07-23 11:44:40 -0700450FunctionType *FunctionType::get(ArrayRef<Type *> inputs,
451 ArrayRef<Type *> results,
Chris Lattnerf7e22732018-06-22 22:03:48 -0700452 MLIRContext *context) {
453 auto &impl = context->getImpl();
454
455 // Look to see if we already have this function type.
456 FunctionTypeKeyInfo::KeyTy key(inputs, results);
457 auto existing = impl.functions.insert_as(nullptr, key);
458
459 // If we already have it, return that value.
460 if (!existing.second)
461 return *existing.first;
462
463 // On the first use, we allocate them into the bump pointer.
464 auto *result = impl.allocator.Allocate<FunctionType>();
465
466 // Copy the inputs and results into the bump pointer.
James Molloy87d81022018-07-23 11:44:40 -0700467 SmallVector<Type *, 16> types;
468 types.reserve(inputs.size() + results.size());
Chris Lattnerf7e22732018-06-22 22:03:48 -0700469 types.append(inputs.begin(), inputs.end());
470 types.append(results.begin(), results.end());
James Molloy87d81022018-07-23 11:44:40 -0700471 auto typesList = impl.copyInto(ArrayRef<Type *>(types));
Chris Lattnerf7e22732018-06-22 22:03:48 -0700472
473 // Initialize the memory using placement new.
James Molloy87d81022018-07-23 11:44:40 -0700474 new (result)
475 FunctionType(typesList.data(), inputs.size(), results.size(), context);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700476
477 // Cache and return it.
478 return *existing.first = result;
479}
480
Chris Lattnerf7e22732018-06-22 22:03:48 -0700481VectorType *VectorType::get(ArrayRef<unsigned> shape, Type *elementType) {
482 assert(!shape.empty() && "vector types must have at least one dimension");
Chris Lattnerc3251192018-07-27 13:09:58 -0700483 assert((isa<FloatType>(elementType) || isa<IntegerType>(elementType)) &&
Chris Lattnerf7e22732018-06-22 22:03:48 -0700484 "vectors elements must be primitives");
485
486 auto *context = elementType->getContext();
487 auto &impl = context->getImpl();
488
489 // Look to see if we already have this vector type.
490 VectorTypeKeyInfo::KeyTy key(elementType, shape);
491 auto existing = impl.vectors.insert_as(nullptr, key);
492
493 // If we already have it, return that value.
494 if (!existing.second)
495 return *existing.first;
496
497 // On the first use, we allocate them into the bump pointer.
498 auto *result = impl.allocator.Allocate<VectorType>();
499
500 // Copy the shape into the bump pointer.
501 shape = impl.copyInto(shape);
502
503 // Initialize the memory using placement new.
Jacques Pienaar3cdb8542018-07-23 11:48:22 -0700504 new (result) VectorType(shape, elementType, context);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700505
506 // Cache and return it.
507 return *existing.first = result;
508}
MLIR Team355ec862018-06-23 18:09:09 -0700509
MLIR Team355ec862018-06-23 18:09:09 -0700510RankedTensorType *RankedTensorType::get(ArrayRef<int> shape,
511 Type *elementType) {
512 auto *context = elementType->getContext();
513 auto &impl = context->getImpl();
514
515 // Look to see if we already have this ranked tensor type.
516 RankedTensorTypeKeyInfo::KeyTy key(elementType, shape);
517 auto existing = impl.rankedTensors.insert_as(nullptr, key);
518
519 // If we already have it, return that value.
520 if (!existing.second)
521 return *existing.first;
522
523 // On the first use, we allocate them into the bump pointer.
524 auto *result = impl.allocator.Allocate<RankedTensorType>();
525
526 // Copy the shape into the bump pointer.
527 shape = impl.copyInto(shape);
528
529 // Initialize the memory using placement new.
530 new (result) RankedTensorType(shape, elementType, context);
531
532 // Cache and return it.
533 return *existing.first = result;
534}
535
536UnrankedTensorType *UnrankedTensorType::get(Type *elementType) {
537 auto *context = elementType->getContext();
538 auto &impl = context->getImpl();
539
540 // Look to see if we already have this unranked tensor type.
Chris Lattner36b4ed12018-07-04 10:43:29 -0700541 auto *&result = impl.unrankedTensors[elementType];
MLIR Team355ec862018-06-23 18:09:09 -0700542
543 // If we already have it, return that value.
Chris Lattner36b4ed12018-07-04 10:43:29 -0700544 if (result)
545 return result;
MLIR Team355ec862018-06-23 18:09:09 -0700546
547 // On the first use, we allocate them into the bump pointer.
Chris Lattner36b4ed12018-07-04 10:43:29 -0700548 result = impl.allocator.Allocate<UnrankedTensorType>();
MLIR Team355ec862018-06-23 18:09:09 -0700549
550 // Initialize the memory using placement new.
551 new (result) UnrankedTensorType(elementType, context);
Chris Lattner36b4ed12018-07-04 10:43:29 -0700552 return result;
553}
554
MLIR Team718c82f2018-07-16 09:45:22 -0700555MemRefType *MemRefType::get(ArrayRef<int> shape, Type *elementType,
James Molloy87d81022018-07-23 11:44:40 -0700556 ArrayRef<AffineMap *> affineMapComposition,
MLIR Team718c82f2018-07-16 09:45:22 -0700557 unsigned memorySpace) {
558 auto *context = elementType->getContext();
559 auto &impl = context->getImpl();
560
561 // Look to see if we already have this memref type.
James Molloy87d81022018-07-23 11:44:40 -0700562 auto key =
563 std::make_tuple(elementType, shape, affineMapComposition, memorySpace);
MLIR Team718c82f2018-07-16 09:45:22 -0700564 auto existing = impl.memrefs.insert_as(nullptr, key);
565
566 // If we already have it, return that value.
567 if (!existing.second)
568 return *existing.first;
569
570 // On the first use, we allocate them into the bump pointer.
571 auto *result = impl.allocator.Allocate<MemRefType>();
572
573 // Copy the shape into the bump pointer.
574 shape = impl.copyInto(shape);
575
576 // Copy the affine map composition into the bump pointer.
577 // TODO(andydavis) Assert that the structure of the composition is valid.
James Molloy87d81022018-07-23 11:44:40 -0700578 affineMapComposition =
579 impl.copyInto(ArrayRef<AffineMap *>(affineMapComposition));
MLIR Team718c82f2018-07-16 09:45:22 -0700580
581 // Initialize the memory using placement new.
582 new (result) MemRefType(shape, elementType, affineMapComposition, memorySpace,
583 context);
584 // Cache and return it.
585 return *existing.first = result;
586}
587
Chris Lattner36b4ed12018-07-04 10:43:29 -0700588//===----------------------------------------------------------------------===//
589// Attribute uniquing
590//===----------------------------------------------------------------------===//
591
592BoolAttr *BoolAttr::get(bool value, MLIRContext *context) {
593 auto *&result = context->getImpl().boolAttrs[value];
594 if (result)
595 return result;
596
597 result = context->getImpl().allocator.Allocate<BoolAttr>();
598 new (result) BoolAttr(value);
599 return result;
600}
601
602IntegerAttr *IntegerAttr::get(int64_t value, MLIRContext *context) {
603 auto *&result = context->getImpl().integerAttrs[value];
604 if (result)
605 return result;
606
607 result = context->getImpl().allocator.Allocate<IntegerAttr>();
608 new (result) IntegerAttr(value);
609 return result;
610}
611
612FloatAttr *FloatAttr::get(double value, MLIRContext *context) {
613 // We hash based on the bit representation of the double to ensure we don't
614 // merge things like -0.0 and 0.0 in the hash comparison.
615 union {
616 double floatValue;
617 int64_t intValue;
618 };
619 floatValue = value;
620
621 auto *&result = context->getImpl().floatAttrs[intValue];
622 if (result)
623 return result;
624
625 result = context->getImpl().allocator.Allocate<FloatAttr>();
626 new (result) FloatAttr(value);
627 return result;
628}
629
630StringAttr *StringAttr::get(StringRef bytes, MLIRContext *context) {
631 auto it = context->getImpl().stringAttrs.insert({bytes, nullptr}).first;
632
633 if (it->second)
634 return it->second;
635
636 auto result = context->getImpl().allocator.Allocate<StringAttr>();
637 new (result) StringAttr(it->first());
638 it->second = result;
639 return result;
640}
641
James Molloy87d81022018-07-23 11:44:40 -0700642ArrayAttr *ArrayAttr::get(ArrayRef<Attribute *> value, MLIRContext *context) {
Chris Lattner36b4ed12018-07-04 10:43:29 -0700643 auto &impl = context->getImpl();
644
645 // Look to see if we already have this.
646 auto existing = impl.arrayAttrs.insert_as(nullptr, value);
647
648 // If we already have it, return that value.
649 if (!existing.second)
650 return *existing.first;
651
652 // On the first use, we allocate them into the bump pointer.
653 auto *result = impl.allocator.Allocate<ArrayAttr>();
654
655 // Copy the elements into the bump pointer.
656 value = impl.copyInto(value);
657
Chris Lattnerea5c3dc2018-08-21 08:42:19 -0700658 // Check to see if any of the elements have a function attr.
659 bool hasFunctionAttr = false;
660 for (auto *elt : value)
661 if (elt->isOrContainsFunction()) {
662 hasFunctionAttr = true;
663 break;
664 }
665
Chris Lattner36b4ed12018-07-04 10:43:29 -0700666 // Initialize the memory using placement new.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -0700667 new (result) ArrayAttr(value, hasFunctionAttr);
MLIR Team355ec862018-06-23 18:09:09 -0700668
669 // Cache and return it.
Chris Lattner36b4ed12018-07-04 10:43:29 -0700670 return *existing.first = result;
MLIR Team355ec862018-06-23 18:09:09 -0700671}
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700672
James Molloy87d81022018-07-23 11:44:40 -0700673AffineMapAttr *AffineMapAttr::get(AffineMap *value, MLIRContext *context) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700674 auto *&result = context->getImpl().affineMapAttrs[value];
675 if (result)
676 return result;
677
678 result = context->getImpl().allocator.Allocate<AffineMapAttr>();
679 new (result) AffineMapAttr(value);
680 return result;
681}
682
James Molloyf0d2f442018-08-03 01:54:46 -0700683TypeAttr *TypeAttr::get(Type *type, MLIRContext *context) {
684 auto *&result = context->getImpl().typeAttrs[type];
685 if (result)
686 return result;
687
688 result = context->getImpl().allocator.Allocate<TypeAttr>();
689 new (result) TypeAttr(type);
690 return result;
691}
692
Chris Lattner1aa46322018-08-21 17:55:22 -0700693FunctionAttr *FunctionAttr::get(const Function *value, MLIRContext *context) {
694 assert(value && "Cannot get FunctionAttr for a null function");
695
Chris Lattner4613d9e2018-08-19 21:17:22 -0700696 auto *&result = context->getImpl().functionAttrs[value];
697 if (result)
698 return result;
699
700 result = context->getImpl().allocator.Allocate<FunctionAttr>();
Chris Lattner1aa46322018-08-21 17:55:22 -0700701 new (result) FunctionAttr(const_cast<Function *>(value));
Chris Lattner4613d9e2018-08-19 21:17:22 -0700702 return result;
703}
704
Chris Lattner1aa46322018-08-21 17:55:22 -0700705FunctionType *FunctionAttr::getType() const { return getValue()->getType(); }
706
Chris Lattner4613d9e2018-08-19 21:17:22 -0700707/// This function is used by the internals of the Function class to null out
708/// attributes refering to functions that are about to be deleted.
709void FunctionAttr::dropFunctionReference(Function *value) {
710 // Check to see if there was an attribute referring to this function.
711 auto &functionAttrs = value->getContext()->getImpl().functionAttrs;
712
713 // If not, then we're done.
714 auto it = functionAttrs.find(value);
715 if (it == functionAttrs.end())
716 return;
717
718 // If so, null out the function reference in the attribute (to avoid dangling
719 // pointers) and remove the entry from the map so the map doesn't contain
720 // dangling keys.
721 it->second->value = nullptr;
722 functionAttrs.erase(it);
723}
724
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700725/// Perform a three-way comparison between the names of the specified
726/// NamedAttributes.
727static int compareNamedAttributes(const NamedAttribute *lhs,
728 const NamedAttribute *rhs) {
729 return lhs->first.str().compare(rhs->first.str());
730}
731
732/// Given a list of NamedAttribute's, canonicalize the list (sorting
733/// by name) and return the unique'd result. Note that the empty list is
734/// represented with a null pointer.
735AttributeListStorage *AttributeListStorage::get(ArrayRef<NamedAttribute> attrs,
736 MLIRContext *context) {
737 // We need to sort the element list to canonicalize it, but we also don't want
738 // to do a ton of work in the super common case where the element list is
739 // already sorted.
740 SmallVector<NamedAttribute, 8> storage;
741 switch (attrs.size()) {
742 case 0:
743 // An empty list is represented with a null pointer.
744 return nullptr;
745 case 1:
746 // A single element is already sorted.
747 break;
748 case 2:
749 // Don't invoke a general sort for two element case.
750 if (attrs[0].first.str() > attrs[1].first.str()) {
751 storage.push_back(attrs[1]);
752 storage.push_back(attrs[0]);
753 attrs = storage;
754 }
755 break;
756 default:
757 // Check to see they are sorted already.
758 bool isSorted = true;
759 for (unsigned i = 0, e = attrs.size() - 1; i != e; ++i) {
760 if (attrs[i].first.str() > attrs[i + 1].first.str()) {
761 isSorted = false;
762 break;
763 }
764 }
765 // If not, do a general sort.
766 if (!isSorted) {
767 storage.append(attrs.begin(), attrs.end());
768 llvm::array_pod_sort(storage.begin(), storage.end(),
769 compareNamedAttributes);
770 attrs = storage;
771 }
772 }
773
774 // Ok, now that we've canonicalized our attributes, unique them.
775 auto &impl = context->getImpl();
776
777 // Look to see if we already have this.
778 auto existing = impl.attributeLists.insert_as(nullptr, attrs);
779
780 // If we already have it, return that value.
781 if (!existing.second)
782 return *existing.first;
783
784 // Otherwise, allocate a new AttributeListStorage, unique it and return it.
785 auto byteSize =
786 AttributeListStorage::totalSizeToAlloc<NamedAttribute>(attrs.size());
787 auto rawMem = impl.allocator.Allocate(byteSize, alignof(NamedAttribute));
788
789 // Placement initialize the AggregateSymbolicValue.
790 auto result = ::new (rawMem) AttributeListStorage(attrs.size());
791 std::uninitialized_copy(attrs.begin(), attrs.end(),
792 result->getTrailingObjects<NamedAttribute>());
793 return *existing.first = result;
794}
795
Chris Lattner36b4ed12018-07-04 10:43:29 -0700796//===----------------------------------------------------------------------===//
797// AffineMap and AffineExpr uniquing
798//===----------------------------------------------------------------------===//
799
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700800AffineMap *AffineMap::get(unsigned dimCount, unsigned symbolCount,
801 ArrayRef<AffineExpr *> results,
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700802 ArrayRef<AffineExpr *> rangeSizes,
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700803 MLIRContext *context) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700804 // The number of results can't be zero.
805 assert(!results.empty());
806
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700807 assert(rangeSizes.empty() || results.size() == rangeSizes.size());
808
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700809 auto &impl = context->getImpl();
810
811 // Check if we already have this affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700812 auto key = std::make_tuple(dimCount, symbolCount, results, rangeSizes);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700813 auto existing = impl.affineMaps.insert_as(nullptr, key);
814
815 // If we already have it, return that value.
816 if (!existing.second)
817 return *existing.first;
818
819 // On the first use, we allocate them into the bump pointer.
820 auto *res = impl.allocator.Allocate<AffineMap>();
821
Uday Bondhugula1e500b42018-07-12 18:04:04 -0700822 // Copy the results and range sizes into the bump pointer.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700823 results = impl.copyInto(ArrayRef<AffineExpr *>(results));
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700824 rangeSizes = impl.copyInto(ArrayRef<AffineExpr *>(rangeSizes));
825
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700826 // Initialize the memory using placement new.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700827 new (res) AffineMap(dimCount, symbolCount, results.size(), results.data(),
828 rangeSizes.empty() ? nullptr : rangeSizes.data());
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700829
830 // Cache and return it.
831 return *existing.first = res;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700832}
833
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700834/// Return a binary affine op expression with the specified op type and
835/// operands: if it doesn't exist, create it and store it; if it is already
836/// present, return from the list. The stored expressions are unique: they are
837/// constructed and stored in a simplified/canonicalized form. The result after
838/// simplification could be any form of affine expression.
839AffineExpr *AffineBinaryOpExpr::get(AffineExpr::Kind kind, AffineExpr *lhs,
840 AffineExpr *rhs, MLIRContext *context) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700841 auto &impl = context->getImpl();
842
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700843 // Check if we already have this affine expression, and return it if we do.
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700844 auto keyValue = std::make_tuple((unsigned)kind, lhs, rhs);
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700845 auto cached = impl.affineExprs.find(keyValue);
846 if (cached != impl.affineExprs.end())
847 return cached->second;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700848
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700849 // Simplify the expression if possible.
850 AffineExpr *simplified;
851 switch (kind) {
852 case Kind::Add:
853 simplified = AffineBinaryOpExpr::simplifyAdd(lhs, rhs, context);
854 break;
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700855 case Kind::Mul:
856 simplified = AffineBinaryOpExpr::simplifyMul(lhs, rhs, context);
857 break;
858 case Kind::FloorDiv:
859 simplified = AffineBinaryOpExpr::simplifyFloorDiv(lhs, rhs, context);
860 break;
861 case Kind::CeilDiv:
862 simplified = AffineBinaryOpExpr::simplifyCeilDiv(lhs, rhs, context);
863 break;
864 case Kind::Mod:
865 simplified = AffineBinaryOpExpr::simplifyMod(lhs, rhs, context);
866 break;
867 default:
868 llvm_unreachable("unexpected binary affine expr");
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700869 }
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700870
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700871 // The simplified one would have already been cached; just return it.
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700872 if (simplified)
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700873 return simplified;
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700874
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700875 // An expression with these operands will already be in the
876 // simplified/canonical form. Create and store it.
877 auto *result = impl.allocator.Allocate<AffineBinaryOpExpr>();
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700878 // Initialize the memory using placement new.
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700879 new (result) AffineBinaryOpExpr(kind, lhs, rhs);
880 bool inserted = impl.affineExprs.insert({keyValue, result}).second;
881 assert(inserted && "the expression shouldn't already exist in the map");
882 (void)inserted;
883 return result;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700884}
885
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700886AffineDimExpr *AffineDimExpr::get(unsigned position, MLIRContext *context) {
Uday Bondhugula4e5078b2018-07-24 22:34:09 -0700887 auto &impl = context->getImpl();
888
889 // Check if we need to resize.
890 if (position >= impl.dimExprs.size())
891 impl.dimExprs.resize(position + 1, nullptr);
892
893 auto *&result = impl.dimExprs[position];
894 if (result)
895 return result;
896
897 result = impl.allocator.Allocate<AffineDimExpr>();
898 // Initialize the memory using placement new.
899 new (result) AffineDimExpr(position);
900 return result;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700901}
902
903AffineSymbolExpr *AffineSymbolExpr::get(unsigned position,
904 MLIRContext *context) {
Uday Bondhugula4e5078b2018-07-24 22:34:09 -0700905 auto &impl = context->getImpl();
906
907 // Check if we need to resize.
908 if (position >= impl.symbolExprs.size())
909 impl.symbolExprs.resize(position + 1, nullptr);
910
911 auto *&result = impl.symbolExprs[position];
912 if (result)
913 return result;
914
915 result = impl.allocator.Allocate<AffineSymbolExpr>();
916 // Initialize the memory using placement new.
917 new (result) AffineSymbolExpr(position);
918 return result;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700919}
920
921AffineConstantExpr *AffineConstantExpr::get(int64_t constant,
922 MLIRContext *context) {
Uday Bondhugula4e5078b2018-07-24 22:34:09 -0700923 auto &impl = context->getImpl();
924 auto *&result = impl.constExprs[constant];
925
926 if (result)
927 return result;
928
929 result = impl.allocator.Allocate<AffineConstantExpr>();
930 // Initialize the memory using placement new.
931 new (result) AffineConstantExpr(constant);
932 return result;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700933}
Uday Bondhugulabc535622018-08-07 14:24:38 -0700934
935//===----------------------------------------------------------------------===//
936// Integer Sets: these are allocated into the bump pointer, and are immutable.
937// But they aren't uniqued like AffineMap's; there isn't an advantage to.
938//===----------------------------------------------------------------------===//
939
940IntegerSet *IntegerSet::get(unsigned dimCount, unsigned symbolCount,
941 ArrayRef<AffineExpr *> constraints,
942 ArrayRef<bool> eqFlags, MLIRContext *context) {
943 assert(eqFlags.size() == constraints.size());
944
945 auto &impl = context->getImpl();
946
947 // Allocate them into the bump pointer.
948 auto *res = impl.allocator.Allocate<IntegerSet>();
949
950 // Copy the equalities and inequalities into the bump pointer.
951 constraints = impl.copyInto(ArrayRef<AffineExpr *>(constraints));
952 eqFlags = impl.copyInto(ArrayRef<bool>(eqFlags));
953
954 // Initialize the memory using placement new.
955 return new (res) IntegerSet(dimCount, symbolCount, constraints.size(),
956 constraints.data(), eqFlags.data());
957}