blob: e59b59cd7e7c6589095dd6fdf29b8049049f1ed5 [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 Lattnerff0d5902018-07-05 09:12:11 -070026#include "mlir/IR/OperationSet.h"
27#include "mlir/IR/StandardOps.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070028#include "mlir/IR/Types.h"
Chris Lattner36b4ed12018-07-04 10:43:29 -070029#include "mlir/Support/STLExtras.h"
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -070030#include "third_party/llvm/llvm/include/llvm/ADT/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 Lattner95865062018-08-01 10:18:59 -070033#include "llvm/ADT/Twine.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070034#include "llvm/Support/Allocator.h"
Chris Lattner95865062018-08-01 10:18:59 -070035#include "llvm/Support/raw_ostream.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070036using namespace mlir;
37using namespace llvm;
38
39namespace {
James Molloy87d81022018-07-23 11:44:40 -070040struct FunctionTypeKeyInfo : DenseMapInfo<FunctionType *> {
Chris Lattnerf7e22732018-06-22 22:03:48 -070041 // Functions are uniqued based on their inputs and results.
James Molloy87d81022018-07-23 11:44:40 -070042 using KeyTy = std::pair<ArrayRef<Type *>, ArrayRef<Type *>>;
43 using DenseMapInfo<FunctionType *>::getHashValue;
44 using DenseMapInfo<FunctionType *>::isEqual;
Chris Lattnerf7e22732018-06-22 22:03:48 -070045
46 static unsigned getHashValue(KeyTy key) {
James Molloy87d81022018-07-23 11:44:40 -070047 return hash_combine(
48 hash_combine_range(key.first.begin(), key.first.end()),
49 hash_combine_range(key.second.begin(), key.second.end()));
Chris Lattnerf7e22732018-06-22 22:03:48 -070050 }
51
52 static bool isEqual(const KeyTy &lhs, const FunctionType *rhs) {
53 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
54 return false;
55 return lhs == KeyTy(rhs->getInputs(), rhs->getResults());
56 }
57};
Uday Bondhugula015cbb12018-07-03 20:16:08 -070058
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070059struct AffineMapKeyInfo : DenseMapInfo<AffineMap *> {
Uday Bondhugula015cbb12018-07-03 20:16:08 -070060 // Affine maps are uniqued based on their dim/symbol counts and affine
61 // expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -070062 using KeyTy = std::tuple<unsigned, unsigned, ArrayRef<AffineExpr *>,
63 ArrayRef<AffineExpr *>>;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070064 using DenseMapInfo<AffineMap *>::getHashValue;
65 using DenseMapInfo<AffineMap *>::isEqual;
66
67 static unsigned getHashValue(KeyTy key) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -070068 return hash_combine(
Chris Lattner36b4ed12018-07-04 10:43:29 -070069 std::get<0>(key), std::get<1>(key),
Uday Bondhugula0115dbb2018-07-11 21:31:07 -070070 hash_combine_range(std::get<2>(key).begin(), std::get<2>(key).end()),
71 hash_combine_range(std::get<3>(key).begin(), std::get<3>(key).end()));
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070072 }
73
Uday Bondhugula015cbb12018-07-03 20:16:08 -070074 static bool isEqual(const KeyTy &lhs, const AffineMap *rhs) {
75 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
76 return false;
Chris Lattner36b4ed12018-07-04 10:43:29 -070077 return lhs == std::make_tuple(rhs->getNumDims(), rhs->getNumSymbols(),
Uday Bondhugula0115dbb2018-07-11 21:31:07 -070078 rhs->getResults(), rhs->getRangeSizes());
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070079 }
80};
81
James Molloy87d81022018-07-23 11:44:40 -070082struct VectorTypeKeyInfo : DenseMapInfo<VectorType *> {
Chris Lattnerf7e22732018-06-22 22:03:48 -070083 // Vectors are uniqued based on their element type and shape.
James Molloy87d81022018-07-23 11:44:40 -070084 using KeyTy = std::pair<Type *, ArrayRef<unsigned>>;
85 using DenseMapInfo<VectorType *>::getHashValue;
86 using DenseMapInfo<VectorType *>::isEqual;
Chris Lattnerf7e22732018-06-22 22:03:48 -070087
88 static unsigned getHashValue(KeyTy key) {
James Molloy87d81022018-07-23 11:44:40 -070089 return hash_combine(
90 DenseMapInfo<Type *>::getHashValue(key.first),
91 hash_combine_range(key.second.begin(), key.second.end()));
Chris Lattnerf7e22732018-06-22 22:03:48 -070092 }
93
94 static bool isEqual(const KeyTy &lhs, const VectorType *rhs) {
95 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
96 return false;
97 return lhs == KeyTy(rhs->getElementType(), rhs->getShape());
98 }
99};
Chris Lattner36b4ed12018-07-04 10:43:29 -0700100
James Molloy87d81022018-07-23 11:44:40 -0700101struct RankedTensorTypeKeyInfo : DenseMapInfo<RankedTensorType *> {
MLIR Team355ec862018-06-23 18:09:09 -0700102 // Ranked tensors are uniqued based on their element type and shape.
James Molloy87d81022018-07-23 11:44:40 -0700103 using KeyTy = std::pair<Type *, ArrayRef<int>>;
104 using DenseMapInfo<RankedTensorType *>::getHashValue;
105 using DenseMapInfo<RankedTensorType *>::isEqual;
MLIR Team355ec862018-06-23 18:09:09 -0700106
107 static unsigned getHashValue(KeyTy key) {
James Molloy87d81022018-07-23 11:44:40 -0700108 return hash_combine(
109 DenseMapInfo<Type *>::getHashValue(key.first),
110 hash_combine_range(key.second.begin(), key.second.end()));
MLIR Team355ec862018-06-23 18:09:09 -0700111 }
112
113 static bool isEqual(const KeyTy &lhs, const RankedTensorType *rhs) {
114 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
115 return false;
116 return lhs == KeyTy(rhs->getElementType(), rhs->getShape());
117 }
118};
Chris Lattner36b4ed12018-07-04 10:43:29 -0700119
James Molloy87d81022018-07-23 11:44:40 -0700120struct MemRefTypeKeyInfo : DenseMapInfo<MemRefType *> {
MLIR Team718c82f2018-07-16 09:45:22 -0700121 // MemRefs are uniqued based on their element type, shape, affine map
122 // composition, and memory space.
James Molloy87d81022018-07-23 11:44:40 -0700123 using KeyTy =
124 std::tuple<Type *, ArrayRef<int>, ArrayRef<AffineMap *>, unsigned>;
125 using DenseMapInfo<MemRefType *>::getHashValue;
126 using DenseMapInfo<MemRefType *>::isEqual;
MLIR Team718c82f2018-07-16 09:45:22 -0700127
128 static unsigned getHashValue(KeyTy key) {
129 return hash_combine(
James Molloy87d81022018-07-23 11:44:40 -0700130 DenseMapInfo<Type *>::getHashValue(std::get<0>(key)),
MLIR Team718c82f2018-07-16 09:45:22 -0700131 hash_combine_range(std::get<1>(key).begin(), std::get<1>(key).end()),
132 hash_combine_range(std::get<2>(key).begin(), std::get<2>(key).end()),
133 std::get<3>(key));
134 }
135
136 static bool isEqual(const KeyTy &lhs, const MemRefType *rhs) {
137 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
138 return false;
139 return lhs == std::make_tuple(rhs->getElementType(), rhs->getShape(),
140 rhs->getAffineMaps(), rhs->getMemorySpace());
141 }
142};
143
James Molloy87d81022018-07-23 11:44:40 -0700144struct ArrayAttrKeyInfo : DenseMapInfo<ArrayAttr *> {
Chris Lattner36b4ed12018-07-04 10:43:29 -0700145 // Array attributes are uniqued based on their elements.
James Molloy87d81022018-07-23 11:44:40 -0700146 using KeyTy = ArrayRef<Attribute *>;
147 using DenseMapInfo<ArrayAttr *>::getHashValue;
148 using DenseMapInfo<ArrayAttr *>::isEqual;
Chris Lattner36b4ed12018-07-04 10:43:29 -0700149
150 static unsigned getHashValue(KeyTy key) {
151 return hash_combine_range(key.begin(), key.end());
152 }
153
154 static bool isEqual(const KeyTy &lhs, const ArrayAttr *rhs) {
155 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
156 return false;
157 return lhs == rhs->getValue();
158 }
159};
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700160
161struct AttributeListKeyInfo : DenseMapInfo<AttributeListStorage *> {
162 // Array attributes are uniqued based on their elements.
163 using KeyTy = ArrayRef<NamedAttribute>;
164 using DenseMapInfo<AttributeListStorage *>::getHashValue;
165 using DenseMapInfo<AttributeListStorage *>::isEqual;
166
167 static unsigned getHashValue(KeyTy key) {
168 return hash_combine_range(key.begin(), key.end());
169 }
170
171 static bool isEqual(const KeyTy &lhs, const AttributeListStorage *rhs) {
172 if (rhs == getEmptyKey() || rhs == getTombstoneKey())
173 return false;
174 return lhs == rhs->getElements();
175 }
176};
177
Chris Lattnerf7e22732018-06-22 22:03:48 -0700178} // end anonymous namespace.
179
Chris Lattnerf7e22732018-06-22 22:03:48 -0700180namespace mlir {
181/// This is the implementation of the MLIRContext class, using the pImpl idiom.
182/// This class is completely private to this file, so everything is public.
183class MLIRContextImpl {
184public:
185 /// We put immortal objects into this allocator.
186 llvm::BumpPtrAllocator allocator;
187
Chris Lattnerff0d5902018-07-05 09:12:11 -0700188 /// This is the set of all operations that are registered with the system.
189 OperationSet operationSet;
190
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700191 /// This is the handler to use to report diagnostics, or null if not
192 /// registered.
193 MLIRContext::DiagnosticHandlerTy diagnosticHandler;
Chris Lattner95865062018-08-01 10:18:59 -0700194
Chris Lattnered65a732018-06-28 20:45:33 -0700195 /// These are identifiers uniqued into this MLIRContext.
James Molloy87d81022018-07-23 11:44:40 -0700196 llvm::StringMap<char, llvm::BumpPtrAllocator &> identifiers;
Chris Lattnered65a732018-06-28 20:45:33 -0700197
Chris Lattnerc3251192018-07-27 13:09:58 -0700198 // Uniquing table for 'other' types.
199 OtherType *otherTypes[int(Type::Kind::LAST_OTHER_TYPE) -
200 int(Type::Kind::FIRST_OTHER_TYPE) + 1] = {nullptr};
201
202 // Uniquing table for 'float' types.
203 FloatType *floatTypes[int(Type::Kind::LAST_FLOATING_POINT_TYPE) -
204 int(Type::Kind::FIRST_FLOATING_POINT_TYPE) + 1] = {
James Molloy87d81022018-07-23 11:44:40 -0700205 nullptr};
Chris Lattnerf7e22732018-06-22 22:03:48 -0700206
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700207 // Affine map uniquing.
208 using AffineMapSet = DenseSet<AffineMap *, AffineMapKeyInfo>;
209 AffineMapSet affineMaps;
210
Uday Bondhugula0b80a162018-07-03 21:34:58 -0700211 // Affine binary op expression uniquing. Figure out uniquing of dimensional
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700212 // or symbolic identifiers.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700213 DenseMap<std::tuple<unsigned, AffineExpr *, AffineExpr *>, AffineExpr *>
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700214 affineExprs;
215
Uday Bondhugula4e5078b2018-07-24 22:34:09 -0700216 // Uniqui'ing of AffineDimExpr, AffineSymbolExpr's by their position.
217 std::vector<AffineDimExpr *> dimExprs;
218 std::vector<AffineSymbolExpr *> symbolExprs;
219
220 // Uniqui'ing of AffineConstantExpr using constant value as key.
221 DenseMap<int64_t, AffineConstantExpr *> constExprs;
222
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700223 /// Integer type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700224 DenseMap<unsigned, IntegerType *> integers;
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700225
Chris Lattnerf7e22732018-06-22 22:03:48 -0700226 /// Function type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700227 using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>;
Chris Lattnerf7e22732018-06-22 22:03:48 -0700228 FunctionTypeSet functions;
229
230 /// Vector type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700231 using VectorTypeSet = DenseSet<VectorType *, VectorTypeKeyInfo>;
Chris Lattnerf7e22732018-06-22 22:03:48 -0700232 VectorTypeSet vectors;
233
MLIR Team355ec862018-06-23 18:09:09 -0700234 /// Ranked tensor type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700235 using RankedTensorTypeSet =
236 DenseSet<RankedTensorType *, RankedTensorTypeKeyInfo>;
MLIR Team355ec862018-06-23 18:09:09 -0700237 RankedTensorTypeSet rankedTensors;
238
239 /// Unranked tensor type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700240 DenseMap<Type *, UnrankedTensorType *> unrankedTensors;
MLIR Team355ec862018-06-23 18:09:09 -0700241
MLIR Team718c82f2018-07-16 09:45:22 -0700242 /// MemRef type uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700243 using MemRefTypeSet = DenseSet<MemRefType *, MemRefTypeKeyInfo>;
MLIR Team718c82f2018-07-16 09:45:22 -0700244 MemRefTypeSet memrefs;
245
Chris Lattner36b4ed12018-07-04 10:43:29 -0700246 // Attribute uniquing.
James Molloy87d81022018-07-23 11:44:40 -0700247 BoolAttr *boolAttrs[2] = {nullptr};
248 DenseMap<int64_t, IntegerAttr *> integerAttrs;
249 DenseMap<int64_t, FloatAttr *> floatAttrs;
250 StringMap<StringAttr *> stringAttrs;
251 using ArrayAttrSet = DenseSet<ArrayAttr *, ArrayAttrKeyInfo>;
Chris Lattner36b4ed12018-07-04 10:43:29 -0700252 ArrayAttrSet arrayAttrs;
James Molloy87d81022018-07-23 11:44:40 -0700253 DenseMap<AffineMap *, AffineMapAttr *> affineMapAttrs;
James Molloyf0d2f442018-08-03 01:54:46 -0700254 DenseMap<Type *, TypeAttr *> typeAttrs;
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700255 using AttributeListSet =
256 DenseSet<AttributeListStorage *, AttributeListKeyInfo>;
257 AttributeListSet attributeLists;
Chris Lattner1aa46322018-08-21 17:55:22 -0700258 DenseMap<const Function *, FunctionAttr *> functionAttrs;
Chris Lattnerf7e22732018-06-22 22:03:48 -0700259
260public:
Chris Lattnerff0d5902018-07-05 09:12:11 -0700261 MLIRContextImpl() : identifiers(allocator) {
262 registerStandardOperations(operationSet);
263 }
Chris Lattnered65a732018-06-28 20:45:33 -0700264
Chris Lattnerf7e22732018-06-22 22:03:48 -0700265 /// Copy the specified array of elements into memory managed by our bump
266 /// pointer allocator. This assumes the elements are all PODs.
James Molloy72b0cbe2018-08-01 12:55:27 -0700267 template <typename T>
268 ArrayRef<T> copyInto(ArrayRef<T> elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700269 auto result = allocator.Allocate<T>(elements.size());
270 std::uninitialized_copy(elements.begin(), elements.end(), result);
271 return ArrayRef<T>(result, elements.size());
272 }
273};
274} // end namespace mlir
275
James Molloy87d81022018-07-23 11:44:40 -0700276MLIRContext::MLIRContext() : impl(new MLIRContextImpl()) {}
Chris Lattnerf7e22732018-06-22 22:03:48 -0700277
James Molloy87d81022018-07-23 11:44:40 -0700278MLIRContext::~MLIRContext() {}
Chris Lattnerf7e22732018-06-22 22:03:48 -0700279
Chris Lattner95865062018-08-01 10:18:59 -0700280/// Register an issue handler with this LLVM context. The issue handler is
281/// passed location information if present (nullptr if not) along with a
282/// message and a boolean that indicates whether this is an error or warning.
283void MLIRContext::registerDiagnosticHandler(
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700284 const DiagnosticHandlerTy &handler) {
285 getImpl().diagnosticHandler = handler;
Chris Lattner95865062018-08-01 10:18:59 -0700286}
287
Chris Lattnerea5c3dc2018-08-21 08:42:19 -0700288/// Return the current diagnostic handler, or null if none is present.
289auto MLIRContext::getDiagnosticHandler() const -> DiagnosticHandlerTy {
290 return getImpl().diagnosticHandler;
291}
292
Chris Lattner95865062018-08-01 10:18:59 -0700293/// This emits a diagnostic using the registered issue handle if present, or
294/// with the default behavior if not. The MLIR compiler should not generally
295/// interact with this, it should use methods on Operation instead.
296void MLIRContext::emitDiagnostic(Attribute *location,
297 const llvm::Twine &message,
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700298 DiagnosticKind kind) const {
Chris Lattner95865062018-08-01 10:18:59 -0700299 // If we had a handler registered, emit the diagnostic using it.
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700300 auto handler = getImpl().diagnosticHandler;
301 if (handler && location)
302 return handler(location, message.str(), kind);
Chris Lattner95865062018-08-01 10:18:59 -0700303
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700304 // The default behavior for notes and warnings is to ignore them.
305 if (kind != DiagnosticKind::Error)
Chris Lattner95865062018-08-01 10:18:59 -0700306 return;
307
308 // The default behavior for errors is to emit them to stderr and exit.
309 llvm::errs() << message.str() << "\n";
310 llvm::errs().flush();
311 exit(1);
312}
313
Chris Lattnerff0d5902018-07-05 09:12:11 -0700314/// Return the operation set associated with the specified MLIRContext object.
315OperationSet &OperationSet::get(MLIRContext *context) {
316 return context->getImpl().operationSet;
317}
Chris Lattnerf7e22732018-06-22 22:03:48 -0700318
Chris Lattner21e67f62018-07-06 10:46:19 -0700319/// If this operation has a registered operation description in the
320/// OperationSet, return it. Otherwise return null.
Chris Lattner95865062018-08-01 10:18:59 -0700321const AbstractOperation *Operation::getAbstractOperation() const {
322 return OperationSet::get(getContext()).lookup(getName().str());
Chris Lattner21e67f62018-07-06 10:46:19 -0700323}
324
Chris Lattnered65a732018-06-28 20:45:33 -0700325//===----------------------------------------------------------------------===//
Chris Lattner36b4ed12018-07-04 10:43:29 -0700326// Identifier uniquing
Chris Lattnered65a732018-06-28 20:45:33 -0700327//===----------------------------------------------------------------------===//
328
329/// Return an identifier for the specified string.
330Identifier Identifier::get(StringRef str, const MLIRContext *context) {
331 assert(!str.empty() && "Cannot create an empty identifier");
332 assert(str.find('\0') == StringRef::npos &&
333 "Cannot create an identifier with a nul character");
334
335 auto &impl = context->getImpl();
336 auto it = impl.identifiers.insert({str, char()}).first;
337 return Identifier(it->getKeyData());
338}
339
Chris Lattnered65a732018-06-28 20:45:33 -0700340//===----------------------------------------------------------------------===//
Chris Lattner36b4ed12018-07-04 10:43:29 -0700341// Type uniquing
Chris Lattnered65a732018-06-28 20:45:33 -0700342//===----------------------------------------------------------------------===//
343
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700344IntegerType *IntegerType::get(unsigned width, MLIRContext *context) {
345 auto &impl = context->getImpl();
346
347 auto *&result = impl.integers[width];
348 if (!result) {
349 result = impl.allocator.Allocate<IntegerType>();
350 new (result) IntegerType(width, context);
351 }
352
353 return result;
Chris Lattnerf7e22732018-06-22 22:03:48 -0700354}
355
Chris Lattnerc3251192018-07-27 13:09:58 -0700356FloatType *FloatType::get(Kind kind, MLIRContext *context) {
357 assert(kind >= Kind::FIRST_FLOATING_POINT_TYPE &&
358 kind <= Kind::LAST_FLOATING_POINT_TYPE && "Not an FP type kind");
359 auto &impl = context->getImpl();
360
361 // We normally have these types.
362 auto *&entry =
363 impl.floatTypes[(int)kind - int(Kind::FIRST_FLOATING_POINT_TYPE)];
364 if (entry)
365 return entry;
366
367 // On the first use, we allocate them into the bump pointer.
368 auto *ptr = impl.allocator.Allocate<FloatType>();
369
370 // Initialize the memory using placement new.
371 new (ptr) FloatType(kind, context);
372
373 // Cache and return it.
374 return entry = ptr;
375}
376
377OtherType *OtherType::get(Kind kind, MLIRContext *context) {
378 assert(kind >= Kind::FIRST_OTHER_TYPE && kind <= Kind::LAST_OTHER_TYPE &&
379 "Not an 'other' type kind");
380 auto &impl = context->getImpl();
381
382 // We normally have these types.
383 auto *&entry = impl.otherTypes[(int)kind - int(Kind::FIRST_OTHER_TYPE)];
384 if (entry)
385 return entry;
386
387 // On the first use, we allocate them into the bump pointer.
388 auto *ptr = impl.allocator.Allocate<OtherType>();
389
390 // Initialize the memory using placement new.
391 new (ptr) OtherType(kind, context);
392
393 // Cache and return it.
394 return entry = ptr;
395}
396
James Molloy87d81022018-07-23 11:44:40 -0700397FunctionType *FunctionType::get(ArrayRef<Type *> inputs,
398 ArrayRef<Type *> results,
Chris Lattnerf7e22732018-06-22 22:03:48 -0700399 MLIRContext *context) {
400 auto &impl = context->getImpl();
401
402 // Look to see if we already have this function type.
403 FunctionTypeKeyInfo::KeyTy key(inputs, results);
404 auto existing = impl.functions.insert_as(nullptr, key);
405
406 // If we already have it, return that value.
407 if (!existing.second)
408 return *existing.first;
409
410 // On the first use, we allocate them into the bump pointer.
411 auto *result = impl.allocator.Allocate<FunctionType>();
412
413 // Copy the inputs and results into the bump pointer.
James Molloy87d81022018-07-23 11:44:40 -0700414 SmallVector<Type *, 16> types;
415 types.reserve(inputs.size() + results.size());
Chris Lattnerf7e22732018-06-22 22:03:48 -0700416 types.append(inputs.begin(), inputs.end());
417 types.append(results.begin(), results.end());
James Molloy87d81022018-07-23 11:44:40 -0700418 auto typesList = impl.copyInto(ArrayRef<Type *>(types));
Chris Lattnerf7e22732018-06-22 22:03:48 -0700419
420 // Initialize the memory using placement new.
James Molloy87d81022018-07-23 11:44:40 -0700421 new (result)
422 FunctionType(typesList.data(), inputs.size(), results.size(), context);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700423
424 // Cache and return it.
425 return *existing.first = result;
426}
427
Chris Lattnerf7e22732018-06-22 22:03:48 -0700428VectorType *VectorType::get(ArrayRef<unsigned> shape, Type *elementType) {
429 assert(!shape.empty() && "vector types must have at least one dimension");
Chris Lattnerc3251192018-07-27 13:09:58 -0700430 assert((isa<FloatType>(elementType) || isa<IntegerType>(elementType)) &&
Chris Lattnerf7e22732018-06-22 22:03:48 -0700431 "vectors elements must be primitives");
432
433 auto *context = elementType->getContext();
434 auto &impl = context->getImpl();
435
436 // Look to see if we already have this vector type.
437 VectorTypeKeyInfo::KeyTy key(elementType, shape);
438 auto existing = impl.vectors.insert_as(nullptr, key);
439
440 // If we already have it, return that value.
441 if (!existing.second)
442 return *existing.first;
443
444 // On the first use, we allocate them into the bump pointer.
445 auto *result = impl.allocator.Allocate<VectorType>();
446
447 // Copy the shape into the bump pointer.
448 shape = impl.copyInto(shape);
449
450 // Initialize the memory using placement new.
Jacques Pienaar3cdb8542018-07-23 11:48:22 -0700451 new (result) VectorType(shape, elementType, context);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700452
453 // Cache and return it.
454 return *existing.first = result;
455}
MLIR Team355ec862018-06-23 18:09:09 -0700456
James Molloy72b0cbe2018-08-01 12:55:27 -0700457static bool isValidTensorElementType(Type *type, MLIRContext *context) {
458 return isa<FloatType>(type) || isa<VectorType>(type) ||
459 isa<IntegerType>(type) || type == Type::getTFString(context);
460}
461
Chris Lattnereee1a2d2018-07-04 09:13:39 -0700462TensorType::TensorType(Kind kind, Type *elementType, MLIRContext *context)
James Molloy87d81022018-07-23 11:44:40 -0700463 : Type(kind, context), elementType(elementType) {
James Molloy72b0cbe2018-08-01 12:55:27 -0700464 assert(isValidTensorElementType(elementType, context));
MLIR Team355ec862018-06-23 18:09:09 -0700465 assert(isa<TensorType>(this));
466}
467
MLIR Team355ec862018-06-23 18:09:09 -0700468RankedTensorType *RankedTensorType::get(ArrayRef<int> shape,
469 Type *elementType) {
470 auto *context = elementType->getContext();
471 auto &impl = context->getImpl();
472
473 // Look to see if we already have this ranked tensor type.
474 RankedTensorTypeKeyInfo::KeyTy key(elementType, shape);
475 auto existing = impl.rankedTensors.insert_as(nullptr, key);
476
477 // If we already have it, return that value.
478 if (!existing.second)
479 return *existing.first;
480
481 // On the first use, we allocate them into the bump pointer.
482 auto *result = impl.allocator.Allocate<RankedTensorType>();
483
484 // Copy the shape into the bump pointer.
485 shape = impl.copyInto(shape);
486
487 // Initialize the memory using placement new.
488 new (result) RankedTensorType(shape, elementType, context);
489
490 // Cache and return it.
491 return *existing.first = result;
492}
493
494UnrankedTensorType *UnrankedTensorType::get(Type *elementType) {
495 auto *context = elementType->getContext();
496 auto &impl = context->getImpl();
497
498 // Look to see if we already have this unranked tensor type.
Chris Lattner36b4ed12018-07-04 10:43:29 -0700499 auto *&result = impl.unrankedTensors[elementType];
MLIR Team355ec862018-06-23 18:09:09 -0700500
501 // If we already have it, return that value.
Chris Lattner36b4ed12018-07-04 10:43:29 -0700502 if (result)
503 return result;
MLIR Team355ec862018-06-23 18:09:09 -0700504
505 // On the first use, we allocate them into the bump pointer.
Chris Lattner36b4ed12018-07-04 10:43:29 -0700506 result = impl.allocator.Allocate<UnrankedTensorType>();
MLIR Team355ec862018-06-23 18:09:09 -0700507
508 // Initialize the memory using placement new.
509 new (result) UnrankedTensorType(elementType, context);
Chris Lattner36b4ed12018-07-04 10:43:29 -0700510 return result;
511}
512
MLIR Team718c82f2018-07-16 09:45:22 -0700513MemRefType *MemRefType::get(ArrayRef<int> shape, Type *elementType,
James Molloy87d81022018-07-23 11:44:40 -0700514 ArrayRef<AffineMap *> affineMapComposition,
MLIR Team718c82f2018-07-16 09:45:22 -0700515 unsigned memorySpace) {
516 auto *context = elementType->getContext();
517 auto &impl = context->getImpl();
518
519 // Look to see if we already have this memref type.
James Molloy87d81022018-07-23 11:44:40 -0700520 auto key =
521 std::make_tuple(elementType, shape, affineMapComposition, memorySpace);
MLIR Team718c82f2018-07-16 09:45:22 -0700522 auto existing = impl.memrefs.insert_as(nullptr, key);
523
524 // If we already have it, return that value.
525 if (!existing.second)
526 return *existing.first;
527
528 // On the first use, we allocate them into the bump pointer.
529 auto *result = impl.allocator.Allocate<MemRefType>();
530
531 // Copy the shape into the bump pointer.
532 shape = impl.copyInto(shape);
533
534 // Copy the affine map composition into the bump pointer.
535 // TODO(andydavis) Assert that the structure of the composition is valid.
James Molloy87d81022018-07-23 11:44:40 -0700536 affineMapComposition =
537 impl.copyInto(ArrayRef<AffineMap *>(affineMapComposition));
MLIR Team718c82f2018-07-16 09:45:22 -0700538
539 // Initialize the memory using placement new.
540 new (result) MemRefType(shape, elementType, affineMapComposition, memorySpace,
541 context);
542 // Cache and return it.
543 return *existing.first = result;
544}
545
Chris Lattner36b4ed12018-07-04 10:43:29 -0700546//===----------------------------------------------------------------------===//
547// Attribute uniquing
548//===----------------------------------------------------------------------===//
549
550BoolAttr *BoolAttr::get(bool value, MLIRContext *context) {
551 auto *&result = context->getImpl().boolAttrs[value];
552 if (result)
553 return result;
554
555 result = context->getImpl().allocator.Allocate<BoolAttr>();
556 new (result) BoolAttr(value);
557 return result;
558}
559
560IntegerAttr *IntegerAttr::get(int64_t value, MLIRContext *context) {
561 auto *&result = context->getImpl().integerAttrs[value];
562 if (result)
563 return result;
564
565 result = context->getImpl().allocator.Allocate<IntegerAttr>();
566 new (result) IntegerAttr(value);
567 return result;
568}
569
570FloatAttr *FloatAttr::get(double value, MLIRContext *context) {
571 // We hash based on the bit representation of the double to ensure we don't
572 // merge things like -0.0 and 0.0 in the hash comparison.
573 union {
574 double floatValue;
575 int64_t intValue;
576 };
577 floatValue = value;
578
579 auto *&result = context->getImpl().floatAttrs[intValue];
580 if (result)
581 return result;
582
583 result = context->getImpl().allocator.Allocate<FloatAttr>();
584 new (result) FloatAttr(value);
585 return result;
586}
587
588StringAttr *StringAttr::get(StringRef bytes, MLIRContext *context) {
589 auto it = context->getImpl().stringAttrs.insert({bytes, nullptr}).first;
590
591 if (it->second)
592 return it->second;
593
594 auto result = context->getImpl().allocator.Allocate<StringAttr>();
595 new (result) StringAttr(it->first());
596 it->second = result;
597 return result;
598}
599
James Molloy87d81022018-07-23 11:44:40 -0700600ArrayAttr *ArrayAttr::get(ArrayRef<Attribute *> value, MLIRContext *context) {
Chris Lattner36b4ed12018-07-04 10:43:29 -0700601 auto &impl = context->getImpl();
602
603 // Look to see if we already have this.
604 auto existing = impl.arrayAttrs.insert_as(nullptr, value);
605
606 // If we already have it, return that value.
607 if (!existing.second)
608 return *existing.first;
609
610 // On the first use, we allocate them into the bump pointer.
611 auto *result = impl.allocator.Allocate<ArrayAttr>();
612
613 // Copy the elements into the bump pointer.
614 value = impl.copyInto(value);
615
Chris Lattnerea5c3dc2018-08-21 08:42:19 -0700616 // Check to see if any of the elements have a function attr.
617 bool hasFunctionAttr = false;
618 for (auto *elt : value)
619 if (elt->isOrContainsFunction()) {
620 hasFunctionAttr = true;
621 break;
622 }
623
Chris Lattner36b4ed12018-07-04 10:43:29 -0700624 // Initialize the memory using placement new.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -0700625 new (result) ArrayAttr(value, hasFunctionAttr);
MLIR Team355ec862018-06-23 18:09:09 -0700626
627 // Cache and return it.
Chris Lattner36b4ed12018-07-04 10:43:29 -0700628 return *existing.first = result;
MLIR Team355ec862018-06-23 18:09:09 -0700629}
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700630
James Molloy87d81022018-07-23 11:44:40 -0700631AffineMapAttr *AffineMapAttr::get(AffineMap *value, MLIRContext *context) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700632 auto *&result = context->getImpl().affineMapAttrs[value];
633 if (result)
634 return result;
635
636 result = context->getImpl().allocator.Allocate<AffineMapAttr>();
637 new (result) AffineMapAttr(value);
638 return result;
639}
640
James Molloyf0d2f442018-08-03 01:54:46 -0700641TypeAttr *TypeAttr::get(Type *type, MLIRContext *context) {
642 auto *&result = context->getImpl().typeAttrs[type];
643 if (result)
644 return result;
645
646 result = context->getImpl().allocator.Allocate<TypeAttr>();
647 new (result) TypeAttr(type);
648 return result;
649}
650
Chris Lattner1aa46322018-08-21 17:55:22 -0700651FunctionAttr *FunctionAttr::get(const Function *value, MLIRContext *context) {
652 assert(value && "Cannot get FunctionAttr for a null function");
653
Chris Lattner4613d9e2018-08-19 21:17:22 -0700654 auto *&result = context->getImpl().functionAttrs[value];
655 if (result)
656 return result;
657
658 result = context->getImpl().allocator.Allocate<FunctionAttr>();
Chris Lattner1aa46322018-08-21 17:55:22 -0700659 new (result) FunctionAttr(const_cast<Function *>(value));
Chris Lattner4613d9e2018-08-19 21:17:22 -0700660 return result;
661}
662
Chris Lattner1aa46322018-08-21 17:55:22 -0700663FunctionType *FunctionAttr::getType() const { return getValue()->getType(); }
664
Chris Lattner4613d9e2018-08-19 21:17:22 -0700665/// This function is used by the internals of the Function class to null out
666/// attributes refering to functions that are about to be deleted.
667void FunctionAttr::dropFunctionReference(Function *value) {
668 // Check to see if there was an attribute referring to this function.
669 auto &functionAttrs = value->getContext()->getImpl().functionAttrs;
670
671 // If not, then we're done.
672 auto it = functionAttrs.find(value);
673 if (it == functionAttrs.end())
674 return;
675
676 // If so, null out the function reference in the attribute (to avoid dangling
677 // pointers) and remove the entry from the map so the map doesn't contain
678 // dangling keys.
679 it->second->value = nullptr;
680 functionAttrs.erase(it);
681}
682
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700683/// Perform a three-way comparison between the names of the specified
684/// NamedAttributes.
685static int compareNamedAttributes(const NamedAttribute *lhs,
686 const NamedAttribute *rhs) {
687 return lhs->first.str().compare(rhs->first.str());
688}
689
690/// Given a list of NamedAttribute's, canonicalize the list (sorting
691/// by name) and return the unique'd result. Note that the empty list is
692/// represented with a null pointer.
693AttributeListStorage *AttributeListStorage::get(ArrayRef<NamedAttribute> attrs,
694 MLIRContext *context) {
695 // We need to sort the element list to canonicalize it, but we also don't want
696 // to do a ton of work in the super common case where the element list is
697 // already sorted.
698 SmallVector<NamedAttribute, 8> storage;
699 switch (attrs.size()) {
700 case 0:
701 // An empty list is represented with a null pointer.
702 return nullptr;
703 case 1:
704 // A single element is already sorted.
705 break;
706 case 2:
707 // Don't invoke a general sort for two element case.
708 if (attrs[0].first.str() > attrs[1].first.str()) {
709 storage.push_back(attrs[1]);
710 storage.push_back(attrs[0]);
711 attrs = storage;
712 }
713 break;
714 default:
715 // Check to see they are sorted already.
716 bool isSorted = true;
717 for (unsigned i = 0, e = attrs.size() - 1; i != e; ++i) {
718 if (attrs[i].first.str() > attrs[i + 1].first.str()) {
719 isSorted = false;
720 break;
721 }
722 }
723 // If not, do a general sort.
724 if (!isSorted) {
725 storage.append(attrs.begin(), attrs.end());
726 llvm::array_pod_sort(storage.begin(), storage.end(),
727 compareNamedAttributes);
728 attrs = storage;
729 }
730 }
731
732 // Ok, now that we've canonicalized our attributes, unique them.
733 auto &impl = context->getImpl();
734
735 // Look to see if we already have this.
736 auto existing = impl.attributeLists.insert_as(nullptr, attrs);
737
738 // If we already have it, return that value.
739 if (!existing.second)
740 return *existing.first;
741
742 // Otherwise, allocate a new AttributeListStorage, unique it and return it.
743 auto byteSize =
744 AttributeListStorage::totalSizeToAlloc<NamedAttribute>(attrs.size());
745 auto rawMem = impl.allocator.Allocate(byteSize, alignof(NamedAttribute));
746
747 // Placement initialize the AggregateSymbolicValue.
748 auto result = ::new (rawMem) AttributeListStorage(attrs.size());
749 std::uninitialized_copy(attrs.begin(), attrs.end(),
750 result->getTrailingObjects<NamedAttribute>());
751 return *existing.first = result;
752}
753
Chris Lattner36b4ed12018-07-04 10:43:29 -0700754//===----------------------------------------------------------------------===//
755// AffineMap and AffineExpr uniquing
756//===----------------------------------------------------------------------===//
757
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700758AffineMap *AffineMap::get(unsigned dimCount, unsigned symbolCount,
759 ArrayRef<AffineExpr *> results,
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700760 ArrayRef<AffineExpr *> rangeSizes,
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700761 MLIRContext *context) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700762 // The number of results can't be zero.
763 assert(!results.empty());
764
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700765 assert(rangeSizes.empty() || results.size() == rangeSizes.size());
766
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700767 auto &impl = context->getImpl();
768
769 // Check if we already have this affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700770 auto key = std::make_tuple(dimCount, symbolCount, results, rangeSizes);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700771 auto existing = impl.affineMaps.insert_as(nullptr, key);
772
773 // If we already have it, return that value.
774 if (!existing.second)
775 return *existing.first;
776
777 // On the first use, we allocate them into the bump pointer.
778 auto *res = impl.allocator.Allocate<AffineMap>();
779
Uday Bondhugula1e500b42018-07-12 18:04:04 -0700780 // Copy the results and range sizes into the bump pointer.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700781 results = impl.copyInto(ArrayRef<AffineExpr *>(results));
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700782 rangeSizes = impl.copyInto(ArrayRef<AffineExpr *>(rangeSizes));
783
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700784 // Initialize the memory using placement new.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700785 new (res) AffineMap(dimCount, symbolCount, results.size(), results.data(),
786 rangeSizes.empty() ? nullptr : rangeSizes.data());
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700787
788 // Cache and return it.
789 return *existing.first = res;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700790}
791
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700792/// Return a binary affine op expression with the specified op type and
793/// operands: if it doesn't exist, create it and store it; if it is already
794/// present, return from the list. The stored expressions are unique: they are
795/// constructed and stored in a simplified/canonicalized form. The result after
796/// simplification could be any form of affine expression.
797AffineExpr *AffineBinaryOpExpr::get(AffineExpr::Kind kind, AffineExpr *lhs,
798 AffineExpr *rhs, MLIRContext *context) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700799 auto &impl = context->getImpl();
800
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700801 // Check if we already have this affine expression, and return it if we do.
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700802 auto keyValue = std::make_tuple((unsigned)kind, lhs, rhs);
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700803 auto cached = impl.affineExprs.find(keyValue);
804 if (cached != impl.affineExprs.end())
805 return cached->second;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700806
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700807 // Simplify the expression if possible.
808 AffineExpr *simplified;
809 switch (kind) {
810 case Kind::Add:
811 simplified = AffineBinaryOpExpr::simplifyAdd(lhs, rhs, context);
812 break;
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700813 case Kind::Mul:
814 simplified = AffineBinaryOpExpr::simplifyMul(lhs, rhs, context);
815 break;
816 case Kind::FloorDiv:
817 simplified = AffineBinaryOpExpr::simplifyFloorDiv(lhs, rhs, context);
818 break;
819 case Kind::CeilDiv:
820 simplified = AffineBinaryOpExpr::simplifyCeilDiv(lhs, rhs, context);
821 break;
822 case Kind::Mod:
823 simplified = AffineBinaryOpExpr::simplifyMod(lhs, rhs, context);
824 break;
825 default:
826 llvm_unreachable("unexpected binary affine expr");
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700827 }
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700828
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700829 // The simplified one would have already been cached; just return it.
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700830 if (simplified)
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700831 return simplified;
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700832
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700833 // An expression with these operands will already be in the
834 // simplified/canonical form. Create and store it.
835 auto *result = impl.allocator.Allocate<AffineBinaryOpExpr>();
Uday Bondhugulae082aad2018-07-11 21:19:31 -0700836 // Initialize the memory using placement new.
Uday Bondhugula0dd940c2018-07-26 00:19:21 -0700837 new (result) AffineBinaryOpExpr(kind, lhs, rhs);
838 bool inserted = impl.affineExprs.insert({keyValue, result}).second;
839 assert(inserted && "the expression shouldn't already exist in the map");
840 (void)inserted;
841 return result;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700842}
843
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700844AffineDimExpr *AffineDimExpr::get(unsigned position, MLIRContext *context) {
Uday Bondhugula4e5078b2018-07-24 22:34:09 -0700845 auto &impl = context->getImpl();
846
847 // Check if we need to resize.
848 if (position >= impl.dimExprs.size())
849 impl.dimExprs.resize(position + 1, nullptr);
850
851 auto *&result = impl.dimExprs[position];
852 if (result)
853 return result;
854
855 result = impl.allocator.Allocate<AffineDimExpr>();
856 // Initialize the memory using placement new.
857 new (result) AffineDimExpr(position);
858 return result;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700859}
860
861AffineSymbolExpr *AffineSymbolExpr::get(unsigned position,
862 MLIRContext *context) {
Uday Bondhugula4e5078b2018-07-24 22:34:09 -0700863 auto &impl = context->getImpl();
864
865 // Check if we need to resize.
866 if (position >= impl.symbolExprs.size())
867 impl.symbolExprs.resize(position + 1, nullptr);
868
869 auto *&result = impl.symbolExprs[position];
870 if (result)
871 return result;
872
873 result = impl.allocator.Allocate<AffineSymbolExpr>();
874 // Initialize the memory using placement new.
875 new (result) AffineSymbolExpr(position);
876 return result;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700877}
878
879AffineConstantExpr *AffineConstantExpr::get(int64_t constant,
880 MLIRContext *context) {
Uday Bondhugula4e5078b2018-07-24 22:34:09 -0700881 auto &impl = context->getImpl();
882 auto *&result = impl.constExprs[constant];
883
884 if (result)
885 return result;
886
887 result = impl.allocator.Allocate<AffineConstantExpr>();
888 // Initialize the memory using placement new.
889 new (result) AffineConstantExpr(constant);
890 return result;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700891}
Uday Bondhugulabc535622018-08-07 14:24:38 -0700892
893//===----------------------------------------------------------------------===//
894// Integer Sets: these are allocated into the bump pointer, and are immutable.
895// But they aren't uniqued like AffineMap's; there isn't an advantage to.
896//===----------------------------------------------------------------------===//
897
898IntegerSet *IntegerSet::get(unsigned dimCount, unsigned symbolCount,
899 ArrayRef<AffineExpr *> constraints,
900 ArrayRef<bool> eqFlags, MLIRContext *context) {
901 assert(eqFlags.size() == constraints.size());
902
903 auto &impl = context->getImpl();
904
905 // Allocate them into the bump pointer.
906 auto *res = impl.allocator.Allocate<IntegerSet>();
907
908 // Copy the equalities and inequalities into the bump pointer.
909 constraints = impl.copyInto(ArrayRef<AffineExpr *>(constraints));
910 eqFlags = impl.copyInto(ArrayRef<bool>(eqFlags));
911
912 // Initialize the memory using placement new.
913 return new (res) IntegerSet(dimCount, symbolCount, constraints.size(),
914 constraints.data(), eqFlags.data());
915}