Skip to content

Commit 129d3ef

Browse files
author
git apple-llvm automerger
committed
Merge commit 'e45705ad5051' from llvm.org/main into next
2 parents 4f02556 + e45705a commit 129d3ef

File tree

5 files changed

+53
-147
lines changed

5 files changed

+53
-147
lines changed

mlir/include/mlir/IR/IntegerSet.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ class IntegerSet {
117117

118118
private:
119119
ImplType *set;
120-
/// Sets with constraints fewer than kUniquingThreshold are uniqued.
121-
constexpr static unsigned kUniquingThreshold = 4;
122120
};
123121

124122
// Make AffineExpr hashable.

mlir/lib/IR/AffineMapDetail.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515

1616
#include "mlir/IR/AffineExpr.h"
1717
#include "mlir/IR/AffineMap.h"
18+
#include "mlir/Support/StorageUniquer.h"
1819
#include "llvm/ADT/ArrayRef.h"
1920

2021
namespace mlir {
2122
namespace detail {
2223

23-
struct AffineMapStorage {
24+
struct AffineMapStorage : public StorageUniquer::BaseStorage {
25+
/// The hash key used for uniquing.
26+
using KeyTy = std::tuple<unsigned, unsigned, ArrayRef<AffineExpr>>;
27+
2428
unsigned numDims;
2529
unsigned numSymbols;
2630

@@ -29,6 +33,22 @@ struct AffineMapStorage {
2933
ArrayRef<AffineExpr> results;
3034

3135
MLIRContext *context;
36+
37+
bool operator==(const KeyTy &key) const {
38+
return std::get<0>(key) == numDims && std::get<1>(key) == numSymbols &&
39+
std::get<2>(key) == results;
40+
}
41+
42+
// Constructs an AffineMapStorage from a key. The context must be set by the
43+
// caller.
44+
static AffineMapStorage *
45+
construct(StorageUniquer::StorageAllocator &allocator, const KeyTy &key) {
46+
auto *res = new (allocator.allocate<AffineMapStorage>()) AffineMapStorage();
47+
res->numDims = std::get<0>(key);
48+
res->numSymbols = std::get<1>(key);
49+
res->results = allocator.copyInto(std::get<2>(key));
50+
return res;
51+
}
3252
};
3353

3454
} // end namespace detail

mlir/lib/IR/IntegerSet.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ unsigned IntegerSet::getNumInequalities() const {
3535
}
3636

3737
bool IntegerSet::isEmptyIntegerSet() const {
38-
// This will only work if uniquing is on.
39-
static_assert(kUniquingThreshold >= 1,
40-
"uniquing threshold should be at least one");
4138
return *this == getEmptySet(set->dimCount, set->symbolCount, getContext());
4239
}
4340

mlir/lib/IR/IntegerSetDetail.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@
1414
#define INTEGERSETDETAIL_H_
1515

1616
#include "mlir/IR/AffineExpr.h"
17+
#include "mlir/Support/StorageUniquer.h"
1718
#include "llvm/ADT/ArrayRef.h"
1819

1920
namespace mlir {
2021
namespace detail {
2122

22-
struct IntegerSetStorage {
23+
struct IntegerSetStorage : public StorageUniquer::BaseStorage {
24+
/// The hash key used for uniquing.
25+
using KeyTy =
26+
std::tuple<unsigned, unsigned, ArrayRef<AffineExpr>, ArrayRef<bool>>;
27+
2328
unsigned dimCount;
2429
unsigned symbolCount;
2530

@@ -29,6 +34,22 @@ struct IntegerSetStorage {
2934

3035
// Bits to check whether a constraint is an equality or an inequality.
3136
ArrayRef<bool> eqFlags;
37+
38+
bool operator==(const KeyTy &key) const {
39+
return std::get<0>(key) == dimCount && std::get<1>(key) == symbolCount &&
40+
std::get<2>(key) == constraints && std::get<3>(key) == eqFlags;
41+
}
42+
43+
static IntegerSetStorage *
44+
construct(StorageUniquer::StorageAllocator &allocator, const KeyTy &key) {
45+
auto *res =
46+
new (allocator.allocate<IntegerSetStorage>()) IntegerSetStorage();
47+
res->dimCount = std::get<0>(key);
48+
res->symbolCount = std::get<1>(key);
49+
res->constraints = allocator.copyInto(std::get<2>(key));
50+
res->eqFlags = allocator.copyInto(std::get<3>(key));
51+
return res;
52+
}
3253
};
3354

3455
} // end namespace detail

mlir/lib/IR/MLIRContext.cpp

Lines changed: 10 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -112,91 +112,6 @@ struct ScopedWriterLock {
112112
};
113113
} // end anonymous namespace.
114114

115-
//===----------------------------------------------------------------------===//
116-
// AffineMap and IntegerSet hashing
117-
//===----------------------------------------------------------------------===//
118-
119-
/// A utility function to safely get or create a uniqued instance within the
120-
/// given set container.
121-
template <typename ValueT, typename DenseInfoT, typename KeyT,
122-
typename ConstructorFn>
123-
static ValueT safeGetOrCreate(DenseSet<ValueT, DenseInfoT> &container,
124-
KeyT &&key, llvm::sys::SmartRWMutex<true> &mutex,
125-
bool threadingIsEnabled,
126-
ConstructorFn &&constructorFn) {
127-
// Check for an existing instance in read-only mode.
128-
if (threadingIsEnabled) {
129-
llvm::sys::SmartScopedReader<true> instanceLock(mutex);
130-
auto it = container.find_as(key);
131-
if (it != container.end())
132-
return *it;
133-
}
134-
135-
// Acquire a writer-lock so that we can safely create the new instance.
136-
ScopedWriterLock instanceLock(mutex, threadingIsEnabled);
137-
138-
// Check for an existing instance again here, because another writer thread
139-
// may have already created one. Otherwise, construct a new instance.
140-
auto existing = container.insert_as(ValueT(), key);
141-
if (existing.second)
142-
return *existing.first = constructorFn();
143-
return *existing.first;
144-
}
145-
146-
namespace {
147-
struct AffineMapKeyInfo : DenseMapInfo<AffineMap> {
148-
// Affine maps are uniqued based on their dim/symbol counts and affine
149-
// expressions.
150-
using KeyTy = std::tuple<unsigned, unsigned, ArrayRef<AffineExpr>>;
151-
using DenseMapInfo<AffineMap>::isEqual;
152-
153-
static unsigned getHashValue(const AffineMap &key) {
154-
return getHashValue(
155-
KeyTy(key.getNumDims(), key.getNumSymbols(), key.getResults()));
156-
}
157-
158-
static unsigned getHashValue(KeyTy key) {
159-
return hash_combine(
160-
std::get<0>(key), std::get<1>(key),
161-
hash_combine_range(std::get<2>(key).begin(), std::get<2>(key).end()));
162-
}
163-
164-
static bool isEqual(const KeyTy &lhs, AffineMap rhs) {
165-
if (rhs == getEmptyKey() || rhs == getTombstoneKey())
166-
return false;
167-
return lhs == std::make_tuple(rhs.getNumDims(), rhs.getNumSymbols(),
168-
rhs.getResults());
169-
}
170-
};
171-
172-
struct IntegerSetKeyInfo : DenseMapInfo<IntegerSet> {
173-
// Integer sets are uniqued based on their dim/symbol counts, affine
174-
// expressions appearing in the LHS of constraints, and eqFlags.
175-
using KeyTy =
176-
std::tuple<unsigned, unsigned, ArrayRef<AffineExpr>, ArrayRef<bool>>;
177-
using DenseMapInfo<IntegerSet>::isEqual;
178-
179-
static unsigned getHashValue(const IntegerSet &key) {
180-
return getHashValue(KeyTy(key.getNumDims(), key.getNumSymbols(),
181-
key.getConstraints(), key.getEqFlags()));
182-
}
183-
184-
static unsigned getHashValue(KeyTy key) {
185-
return hash_combine(
186-
std::get<0>(key), std::get<1>(key),
187-
hash_combine_range(std::get<2>(key).begin(), std::get<2>(key).end()),
188-
hash_combine_range(std::get<3>(key).begin(), std::get<3>(key).end()));
189-
}
190-
191-
static bool isEqual(const KeyTy &lhs, IntegerSet rhs) {
192-
if (rhs == getEmptyKey() || rhs == getTombstoneKey())
193-
return false;
194-
return lhs == std::make_tuple(rhs.getNumDims(), rhs.getNumSymbols(),
195-
rhs.getConstraints(), rhs.getEqFlags());
196-
}
197-
};
198-
} // end anonymous namespace.
199-
200115
//===----------------------------------------------------------------------===//
201116
// MLIRContextImpl
202117
//===----------------------------------------------------------------------===//
@@ -279,19 +194,7 @@ class MLIRContextImpl {
279194
// Affine uniquing
280195
//===--------------------------------------------------------------------===//
281196

282-
// Affine allocator and mutex for thread safety.
283-
llvm::BumpPtrAllocator affineAllocator;
284-
llvm::sys::SmartRWMutex<true> affineMutex;
285-
286-
// Affine map uniquing.
287-
using AffineMapSet = DenseSet<AffineMap, AffineMapKeyInfo>;
288-
AffineMapSet affineMaps;
289-
290-
// Integer set uniquing.
291-
using IntegerSets = DenseSet<IntegerSet, IntegerSetKeyInfo>;
292-
IntegerSets integerSets;
293-
294-
// Affine expression uniquing.
197+
// Affine expression, map and integer set uniquing.
295198
StorageUniquer affineUniquer;
296199

297200
//===--------------------------------------------------------------------===//
@@ -415,6 +318,8 @@ MLIRContext::MLIRContext(const DialectRegistry &registry, Threading setting)
415318
impl->affineUniquer
416319
.registerParametricStorageType<AffineConstantExprStorage>();
417320
impl->affineUniquer.registerParametricStorageType<AffineDimExprStorage>();
321+
impl->affineUniquer.registerParametricStorageType<AffineMapStorage>();
322+
impl->affineUniquer.registerParametricStorageType<IntegerSetStorage>();
418323
}
419324

420325
MLIRContext::~MLIRContext() {}
@@ -995,21 +900,10 @@ AffineMap AffineMap::getImpl(unsigned dimCount, unsigned symbolCount,
995900
ArrayRef<AffineExpr> results,
996901
MLIRContext *context) {
997902
auto &impl = context->getImpl();
998-
auto key = std::make_tuple(dimCount, symbolCount, results);
999-
1000-
// Safely get or create an AffineMap instance.
1001-
return safeGetOrCreate(
1002-
impl.affineMaps, key, impl.affineMutex, impl.threadingIsEnabled, [&] {
1003-
auto *res = impl.affineAllocator.Allocate<detail::AffineMapStorage>();
1004-
1005-
// Copy the results into the bump pointer.
1006-
results = copyArrayRefInto(impl.affineAllocator, results);
1007-
1008-
// Initialize the memory using placement new.
1009-
new (res)
1010-
detail::AffineMapStorage{dimCount, symbolCount, results, context};
1011-
return AffineMap(res);
1012-
});
903+
auto *storage = impl.affineUniquer.get<AffineMapStorage>(
904+
[&](AffineMapStorage *storage) { storage->context = context; }, dimCount,
905+
symbolCount, results);
906+
return AffineMap(storage);
1013907
}
1014908

1015909
/// Check whether the arguments passed to the AffineMap::get() are consistent.
@@ -1069,33 +963,9 @@ IntegerSet IntegerSet::get(unsigned dimCount, unsigned symbolCount,
1069963
assert(constraints.size() == eqFlags.size());
1070964

1071965
auto &impl = constraints[0].getContext()->getImpl();
1072-
1073-
// A utility function to construct a new IntegerSetStorage instance.
1074-
auto constructorFn = [&] {
1075-
auto *res = impl.affineAllocator.Allocate<detail::IntegerSetStorage>();
1076-
1077-
// Copy the results and equality flags into the bump pointer.
1078-
constraints = copyArrayRefInto(impl.affineAllocator, constraints);
1079-
eqFlags = copyArrayRefInto(impl.affineAllocator, eqFlags);
1080-
1081-
// Initialize the memory using placement new.
1082-
new (res)
1083-
detail::IntegerSetStorage{dimCount, symbolCount, constraints, eqFlags};
1084-
return IntegerSet(res);
1085-
};
1086-
1087-
// If this instance is uniqued, then we handle it separately so that multiple
1088-
// threads may simultaneously access existing instances.
1089-
if (constraints.size() < IntegerSet::kUniquingThreshold) {
1090-
auto key = std::make_tuple(dimCount, symbolCount, constraints, eqFlags);
1091-
return safeGetOrCreate(impl.integerSets, key, impl.affineMutex,
1092-
impl.threadingIsEnabled, constructorFn);
1093-
}
1094-
1095-
// Otherwise, acquire a writer-lock so that we can safely create the new
1096-
// instance.
1097-
ScopedWriterLock affineLock(impl.affineMutex, impl.threadingIsEnabled);
1098-
return constructorFn();
966+
auto *storage = impl.affineUniquer.get<IntegerSetStorage>(
967+
[](IntegerSetStorage *) {}, dimCount, symbolCount, constraints, eqFlags);
968+
return IntegerSet(storage);
1099969
}
1100970

1101971
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)