[lld] r358645 - [ELF] Place SectionPiece::{Live, Hash} bit fields together

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 18 00:46:09 PDT 2019


Author: maskray
Date: Thu Apr 18 00:46:09 2019
New Revision: 358645

URL: http://llvm.org/viewvc/llvm-project?rev=358645&view=rev
Log:
[ELF] Place SectionPiece::{Live,Hash} bit fields together

Summary:
We access Live and OutputOff (which may share the same memory location)
concurrently in 2 parallelForEachN loops. Separating them avoids subtle
data races like D41884/PR35788. This patch places Live and Hash
together.

2 reasons this is appealing:

1) Hash is immutable. Live is almost read-only - only written once in MarkLive.cpp where
   Hash is not accessed
2) we already discard low bits of Hash to decide ShardID. It doesn't
   matter much if we make 32-bit Hash to 31-bit.

   For a huge internal clang -O3 executable (1.6GiB),
   `Strings` in StringTableBuilder::finalizeStringTable contains at most 310253 elements.
   The expected number of pair-wise collisions 2^(-31) * C(310253,2) ~= 22.41 is too small to have a negative impact on performance.
   Actually, my benchmark shows there is actually a minor performance improvement.

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

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

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=358645&r1=358644&r2=358645&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Thu Apr 18 00:46:09 2019
@@ -227,13 +227,12 @@ protected:
 // be found by looking at the next one).
 struct SectionPiece {
   SectionPiece(size_t Off, uint32_t Hash, bool Live)
-      : InputOff(Off), Hash(Hash), OutputOff(0),
-        Live(Live || !Config->GcSections) {}
+      : InputOff(Off), Live(Live || !Config->GcSections), Hash(Hash >> 1) {}
 
   uint32_t InputOff;
-  uint32_t Hash;
-  int64_t OutputOff : 63;
-  uint64_t Live : 1;
+  uint32_t Live : 1;
+  uint32_t Hash : 31;
+  uint64_t OutputOff = 0;
 };
 
 static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big");

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=358645&r1=358644&r2=358645&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Apr 18 00:46:09 2019
@@ -2876,8 +2876,10 @@ void MergeNoTailSection::finalizeContent
   parallelForEachN(0, Concurrency, [&](size_t ThreadId) {
     for (MergeInputSection *Sec : Sections) {
       for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) {
+        if (!Sec->Pieces[I].Live)
+          continue;
         size_t ShardId = getShardId(Sec->Pieces[I].Hash);
-        if ((ShardId & (Concurrency - 1)) == ThreadId && Sec->Pieces[I].Live)
+        if ((ShardId & (Concurrency - 1)) == ThreadId)
           Sec->Pieces[I].OutputOff = Shards[ShardId].add(Sec->getData(I));
       }
     }

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=358645&r1=358644&r2=358645&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Apr 18 00:46:09 2019
@@ -859,7 +859,8 @@ private:
   // If we use lower bits, it significantly increases the probability of
   // hash collisons.
   size_t getShardId(uint32_t Hash) {
-    return Hash >> (32 - llvm::countTrailingZeros(NumShards));
+    assert((Hash >> 31) == 0);
+    return Hash >> (31 - llvm::countTrailingZeros(NumShards));
   }
 
   // Section size




More information about the llvm-commits mailing list