[lld] r319600 - Cache modulo values for the .gnu.hash section.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 1 16:37:13 PST 2017


Author: ruiu
Date: Fri Dec  1 16:37:13 2017
New Revision: 319600

URL: http://llvm.org/viewvc/llvm-project?rev=319600&view=rev
Log:
Cache modulo values for the .gnu.hash section.

This change actually makes the linker slightly faster. My observation
is that, with this patch, link time of clang without debug is about 1%
faster.

Differential Revision: https://reviews.llvm.org/D40697

Modified:
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=319600&r1=319599&r2=319600&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Fri Dec  1 16:37:13 2017
@@ -1745,7 +1745,7 @@ void GnuHashTableSection::writeHashTable
   // Group symbols by hash value.
   std::vector<std::vector<Entry>> Syms(NBuckets);
   for (const Entry &Ent : Symbols)
-    Syms[Ent.Hash % NBuckets].push_back(Ent);
+    Syms[Ent.BucketIdx].push_back(Ent);
 
   // Write hash buckets. Hash buckets contain indices in the following
   // hash value table.
@@ -1792,21 +1792,22 @@ void GnuHashTableSection::addSymbols(std
   if (Mid == V.end())
     return;
 
-  for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) {
-    Symbol *B = Ent.Sym;
-    Symbols.push_back({B, Ent.StrTabOffset, hashGnu(B->getName())});
-  }
-
   // We chose load factor 4 for the on-disk hash table. For each hash
   // collision, the dynamic linker will compare a uint32_t hash value.
   // Since the integer comparison is quite fast, we believe we can make
   // the load factor even larger. 4 is just a conservative choice.
-  NBuckets = std::max<size_t>(Symbols.size() / 4, 1);
+  NBuckets = std::max<size_t>((V.end() - Mid) / 4, 1);
+
+  for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) {
+    Symbol *B = Ent.Sym;
+    uint32_t Hash = hashGnu(B->getName());
+    uint32_t BucketIdx = Hash % NBuckets;
+    Symbols.push_back({B, Ent.StrTabOffset, Hash, BucketIdx});
+  }
 
-  std::stable_sort(Symbols.begin(), Symbols.end(),
-                   [&](const Entry &L, const Entry &R) {
-                     return L.Hash % NBuckets < R.Hash % NBuckets;
-                   });
+  std::stable_sort(
+      Symbols.begin(), Symbols.end(),
+      [](const Entry &L, const Entry &R) { return L.BucketIdx < R.BucketIdx; });
 
   V.erase(Mid, V.end());
   for (const Entry &Ent : Symbols)

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=319600&r1=319599&r2=319600&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Fri Dec  1 16:37:13 2017
@@ -465,6 +465,7 @@ private:
     Symbol *Sym;
     size_t StrTabOffset;
     uint32_t Hash;
+    uint32_t BucketIdx;
   };
 
   std::vector<Entry> Symbols;




More information about the llvm-commits mailing list