@@ -287,13 +287,6 @@ class RuntimeLibcallEmitter {
287
287
void run (raw_ostream &OS);
288
288
};
289
289
290
- // / Helper struct for the name hash table.
291
- struct LookupEntry {
292
- StringRef FuncName;
293
- uint64_t Hash = 0 ;
294
- unsigned TableValue = 0 ;
295
- };
296
-
297
290
} // End anonymous namespace.
298
291
299
292
void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum (raw_ostream &OS) const {
@@ -339,14 +332,17 @@ static void emitHashFunction(raw_ostream &OS) {
339
332
// / Return the table size, maximum number of collisions for the set of hashes
340
333
static std::pair<int , int >
341
334
computePerfectHashParameters (ArrayRef<uint64_t > Hashes) {
342
- const int SizeOverhead = 10 ;
343
- const int NumHashes = Hashes. size () ;
335
+ // Chosen based on experimentation with llvm/benchmarks/RuntimeLibcalls.cpp
336
+ const int SizeOverhead = 4 ;
344
337
345
338
// Index derived from hash -> number of collisions.
346
339
DenseMap<uint64_t , int > Table;
347
340
341
+ unsigned NumHashes = Hashes.size ();
342
+
348
343
for (int MaxCollisions = 1 ;; ++MaxCollisions) {
349
- for (int N = NumHashes; N < SizeOverhead * NumHashes; ++N) {
344
+ for (unsigned N = NextPowerOf2 (NumHashes - 1 ); N < SizeOverhead * NumHashes;
345
+ N <<= 1 ) {
350
346
Table.clear ();
351
347
352
348
bool NeedResize = false ;
@@ -365,41 +361,29 @@ computePerfectHashParameters(ArrayRef<uint64_t> Hashes) {
365
361
}
366
362
}
367
363
368
- static std::vector<LookupEntry >
364
+ static std::vector<unsigned >
369
365
constructPerfectHashTable (ArrayRef<RuntimeLibcallImpl> Keywords,
370
- ArrayRef<uint64_t > Hashes, int Size, int Collisions,
371
- StringToOffsetTable &OffsetTable) {
372
- DenseSet<StringRef> Seen;
373
- std::vector<LookupEntry> Lookup (Size * Collisions);
374
-
375
- for (const RuntimeLibcallImpl &LibCallImpl : Keywords) {
376
- StringRef ImplName = LibCallImpl.getLibcallFuncName ();
377
-
378
- // We do not want to add repeated entries for cases with the same name, only
379
- // an entry for the first, with the name collision enum values immediately
380
- // following.
381
- if (!Seen.insert (ImplName).second )
382
- continue ;
383
-
384
- uint64_t HashValue = Hashes[LibCallImpl.getEnumVal () - 1 ];
366
+ ArrayRef<uint64_t > Hashes,
367
+ ArrayRef<unsigned > TableValues, int Size,
368
+ int Collisions, StringToOffsetTable &OffsetTable) {
369
+ std::vector<unsigned > Lookup (Size * Collisions);
385
370
371
+ for (auto [HashValue, TableValue] : zip (Hashes, TableValues)) {
386
372
uint64_t Idx = (HashValue % static_cast <uint64_t >(Size)) *
387
373
static_cast <uint64_t >(Collisions);
388
374
389
375
bool Found = false ;
390
376
for (int J = 0 ; J < Collisions; ++J) {
391
- LookupEntry &Entry = Lookup[Idx + J];
392
- if (Entry.TableValue == 0 ) {
393
- Entry.FuncName = ImplName;
394
- Entry.TableValue = LibCallImpl.getEnumVal ();
395
- Entry.Hash = HashValue;
377
+ unsigned &Entry = Lookup[Idx + J];
378
+ if (Entry == 0 ) {
379
+ Entry = TableValue;
396
380
Found = true ;
397
381
break ;
398
382
}
399
383
}
400
384
401
385
if (!Found)
402
- reportFatalInternalError (" failure to hash " + ImplName );
386
+ reportFatalInternalError (" failure to hash" );
403
387
}
404
388
405
389
return Lookup;
@@ -409,15 +393,25 @@ constructPerfectHashTable(ArrayRef<RuntimeLibcallImpl> Keywords,
409
393
void RuntimeLibcallEmitter::emitNameMatchHashTable (
410
394
raw_ostream &OS, StringToOffsetTable &OffsetTable) const {
411
395
std::vector<uint64_t > Hashes (RuntimeLibcallImplDefList.size ());
396
+ std::vector<unsigned > TableValues (RuntimeLibcallImplDefList.size ());
397
+ DenseSet<StringRef> SeenFuncNames;
412
398
413
399
size_t MaxFuncNameSize = 0 ;
414
400
size_t Index = 0 ;
401
+
415
402
for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
416
403
StringRef ImplName = LibCallImpl.getLibcallFuncName ();
417
- MaxFuncNameSize = std::max (MaxFuncNameSize, ImplName.size ());
418
- Hashes[Index++] = hash (ImplName);
404
+ if (SeenFuncNames.insert (ImplName).second ) {
405
+ MaxFuncNameSize = std::max (MaxFuncNameSize, ImplName.size ());
406
+ TableValues[Index] = LibCallImpl.getEnumVal ();
407
+ Hashes[Index++] = hash (ImplName);
408
+ }
419
409
}
420
410
411
+ // Trim excess elements from non-unique entries.
412
+ Hashes.resize (SeenFuncNames.size ());
413
+ TableValues.resize (SeenFuncNames.size ());
414
+
421
415
LLVM_DEBUG ({
422
416
for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
423
417
StringRef ImplName = LibCallImpl.getLibcallFuncName ();
@@ -447,8 +441,9 @@ void RuntimeLibcallEmitter::emitNameMatchHashTable(
447
441
" #endif\n " ;
448
442
449
443
auto [Size, Collisions] = computePerfectHashParameters (Hashes);
450
- std::vector<LookupEntry> Lookup = constructPerfectHashTable (
451
- RuntimeLibcallImplDefList, Hashes, Size, Collisions, OffsetTable);
444
+ std::vector<unsigned > Lookup =
445
+ constructPerfectHashTable (RuntimeLibcallImplDefList, Hashes, TableValues,
446
+ Size, Collisions, OffsetTable);
452
447
453
448
LLVM_DEBUG (dbgs () << " Runtime libcall perfect hashing parameters: Size = "
454
449
<< Size << " , maximum collisions = " << Collisions << ' \n ' );
@@ -463,13 +458,8 @@ void RuntimeLibcallEmitter::emitNameMatchHashTable(
463
458
OS << " static constexpr uint16_t HashTableNameToEnum[" << Lookup.size ()
464
459
<< " ] = {\n " ;
465
460
466
- for (auto [FuncName, Hash, TableVal] : Lookup) {
467
- OS << " " << TableVal << ' ,' ;
468
- if (TableVal != 0 )
469
- OS << " // " << format_hex (Hash, 16 ) << " , " << FuncName;
470
-
471
- OS << ' \n ' ;
472
- }
461
+ for (unsigned TableVal : Lookup)
462
+ OS << " " << TableVal << " ,\n " ;
473
463
474
464
OS << " };\n\n " ;
475
465
0 commit comments