9#ifndef LLVM_ADT_CONCURRENTHASHTABLE_H
10#define LLVM_ADT_CONCURRENTHASHTABLE_H
74template <
typename KeyTy,
typename KeyDataTy,
typename AllocatorTy>
88 static inline const KeyTy &
getKey(
const KeyDataTy &KeyData) {
89 return KeyData.getKey();
98template <
typename KeyTy,
typename KeyDataTy,
typename AllocatorTy,
100 ConcurrentHashTableInfoByPtr<KeyTy, KeyDataTy, AllocatorTy>>
106 size_t InitialNumberOfBuckets = 128)
108 assert((ThreadsNum > 0) &&
"ThreadsNum must be greater than 0");
109 assert((InitialNumberOfBuckets > 0) &&
110 "InitialNumberOfBuckets must be greater than 0");
113 uint64_t EstimatedNumberOfBuckets = ThreadsNum;
114 if (ThreadsNum > 1) {
115 EstimatedNumberOfBuckets *= InitialNumberOfBuckets;
116 EstimatedNumberOfBuckets *= std::max(
121 EstimatedNumberOfBuckets =
PowerOf2Ceil(EstimatedNumberOfBuckets);
123 std::min(EstimatedNumberOfBuckets, (
uint64_t)(1Ull << 31));
153 MaxBucketSize = 1Ull << (std::min((
size_t)31, LeadingZerosNumber));
171 std::pair<KeyDataTy *, bool>
insert(
const KeyTy &NewValue) {
173 uint64_t Hash = Info::getHashValue(NewValue);
177#if LLVM_ENABLE_THREADS
179 CurBucket.Guard.lock();
187 uint32_t CurEntryHashBits = BucketHashes[CurEntryIdx];
189 if (CurEntryHashBits == 0 && BucketEntries[CurEntryIdx] ==
nullptr) {
192 BucketEntries[CurEntryIdx] = NewData;
193 BucketHashes[CurEntryIdx] = ExtHashBits;
198#if LLVM_ENABLE_THREADS
199 CurBucket.Guard.unlock();
202 return {NewData,
true};
205 if (CurEntryHashBits == ExtHashBits) {
207 KeyDataTy *EntryData = BucketEntries[CurEntryIdx];
208 if (Info::isEqual(Info::getKey(*EntryData), NewValue)) {
210#if LLVM_ENABLE_THREADS
211 CurBucket.Guard.unlock();
214 return {EntryData,
false};
219 CurEntryIdx &= (CurBucket.
Size - 1);
228 OS <<
"\n--- HashTable statistic:\n";
232 uint64_t NumberOfNonEmptyBuckets = 0;
233 uint64_t NumberOfEntriesPlusEmpty = 0;
234 uint64_t OverallNumberOfEntries = 0;
243 BucketSizesMap[CurBucket.
Size]++;
246 NumberOfNonEmptyBuckets++;
247 NumberOfEntriesPlusEmpty += CurBucket.
Size;
253 OS <<
"\nOverall number of entries = " << OverallNumberOfEntries;
254 OS <<
"\nOverall number of non empty buckets = " << NumberOfNonEmptyBuckets;
255 for (
auto &BucketSize : BucketSizesMap)
256 OS <<
"\n Number of buckets with size " << BucketSize.first <<
": "
257 << BucketSize.second;
259 std::stringstream stream;
260 stream << std::fixed << std::setprecision(2)
261 << ((float)OverallNumberOfEntries / (
float)NumberOfEntriesPlusEmpty);
262 std::string str = stream.str();
264 OS <<
"\nLoad factor = " << str;
265 OS <<
"\nOverall allocated size = " << OverallSize;
291#if LLVM_ENABLE_THREADS
299 assert((CurBucket.
Size > 0) &&
"Uninitialised bucket");
309 "New bucket size less than size of current bucket");
317 memset(DestHashes, 0,
sizeof(
ExtHashBitsTy) * NewBucketSize);
320 memset(DestEntries, 0,
sizeof(
EntryDataTy) * NewBucketSize);
323 for (
uint32_t CurSrcEntryIdx = 0; CurSrcEntryIdx < CurBucket.
Size;
325 uint32_t CurSrcEntryHashBits = SrcHashes[CurSrcEntryIdx];
328 if (CurSrcEntryHashBits == 0 && SrcEntries[CurSrcEntryIdx] ==
nullptr)
335 uint32_t CurDestEntryHashBits = DestHashes[StartDestIdx];
337 if (CurDestEntryHashBits == 0 && DestEntries[StartDestIdx] ==
nullptr) {
339 DestHashes[StartDestIdx] = CurSrcEntryHashBits;
340 DestEntries[StartDestIdx] = SrcEntries[CurSrcEntryIdx];
345 StartDestIdx = StartDestIdx & (NewBucketSize - 1);
350 CurBucket.
Hashes = DestHashes;
351 CurBucket.
Entries = DestEntries;
352 CurBucket.
Size = NewBucketSize;
355 if (SrcHashes !=
nullptr)
357 if (SrcEntries !=
nullptr)
368 assert((BucketSize > 0) &&
"Empty bucket");
370 return ExtHashBits & (BucketSize - 1);
This file defines the BumpPtrAllocator interface.
Analysis containing CSE Info
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
std::pair< KeyDataTy *, bool > insert(const KeyTy &NewValue)
Insert new value NewValue or return already existing entry.
uint32_t getStartIdx(uint32_t ExtHashBits, uint32_t BucketSize)
virtual ~ConcurrentHashTableByPtr()
std::unique_ptr< Bucket[]> BucketsArray
uint32_t getBucketIdx(hash_code Hash)
void printStatistic(raw_ostream &OS)
Print information about current state of hash table structures.
void RehashBucket(Bucket &CurBucket)
uint32_t InitialBucketSize
uint32_t getExtHashBits(uint64_t Hash)
ConcurrentHashTableByPtr(AllocatorTy &Allocator, uint64_t EstimatedSize=100000, size_t ThreadsNum=parallel::strategy.compute_thread_count(), size_t InitialNumberOfBuckets=128)
AllocatorTy & MultiThreadAllocator
ConcurrentHashTable - is a resizeable concurrent hashtable.
static KeyDataTy * create(const KeyTy &Key, AllocatorTy &Allocator)
static const KeyTy & getKey(const KeyDataTy &KeyData)
static bool isEqual(const KeyTy &LHS, const KeyTy &RHS)
static uint64_t getHashValue(const KeyTy &Key)
An opaque object representing a hash code.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ThreadPoolStrategy strategy
This is an optimization pass for GlobalISel generic memory operations.
uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.