Close the gap between ELF and COFF ICF implementations. NFC.
authorRui Ueyama <ruiu@google.com>
Wed, 24 May 2017 19:56:29 +0000 (19:56 +0000)
committerRui Ueyama <ruiu@google.com>
Wed, 24 May 2017 19:56:29 +0000 (19:56 +0000)
We originally wrote the ICF code for COFF and ported it to ELF.
They started diverging since then. This patch closes the gap.

llvm-svn: 303801

lld/COFF/ICF.cpp

index aa08095..2e26eb0 100644 (file)
@@ -56,7 +56,6 @@ private:
 
   std::vector<SectionChunk *> Chunks;
   int Cnt = 0;
-  std::atomic<uint32_t> NextId = {1};
   std::atomic<bool> Repeat = {false};
 };
 
@@ -98,10 +97,10 @@ void ICF::segregate(size_t Begin, size_t End, bool Constant) {
         });
     size_t Mid = Bound - Chunks.begin();
 
-    // Split [Begin, End) into [Begin, Mid) and [Mid, End).
-    uint32_t Id = NextId++;
+    // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an
+    // equivalence class ID because every group ends with a unique index.
     for (size_t I = Begin; I < Mid; ++I)
-      Chunks[I]->Class[(Cnt + 1) % 2] = Id;
+      Chunks[I]->Class[(Cnt + 1) % 2] = Mid;
 
     // If we created a group, we need to iterate the main loop again.
     if (Mid != End)
@@ -186,6 +185,7 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
   // call Fn sequentially.
   if (Chunks.size() < 1024) {
     forEachClassRange(0, Chunks.size(), Fn);
+    ++Cnt;
     return;
   }
 
@@ -196,6 +196,7 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
     size_t End = (I == NumShards - 1) ? Chunks.size() : (I + 1) * Step;
     forEachClassRange(I * Step, End, Fn);
   });
+  ++Cnt;
 }
 
 // Merge identical COMDAT sections.
@@ -203,22 +204,15 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
 // contents and relocations are all the same.
 void ICF::run(const std::vector<Chunk *> &Vec) {
   // Collect only mergeable sections and group by hash value.
-  for (Chunk *C : Vec) {
-    auto *SC = dyn_cast<SectionChunk>(C);
-    if (!SC)
-      continue;
-
-    if (isEligible(SC)) {
-      // Set MSB to 1 to avoid collisions with non-hash classs.
-      SC->Class[0] = getHash(SC) | (1 << 31);
-      Chunks.push_back(SC);
-    } else {
-      SC->Class[0] = NextId++;
-    }
-  }
+  for (Chunk *C : Vec)
+    if (auto *SC = dyn_cast<SectionChunk>(C))
+      if (isEligible(SC))
+        Chunks.push_back(SC);
 
-  if (Chunks.empty())
-    return;
+  // Initially, we use hash values to partition sections.
+  for (SectionChunk *SC : Chunks)
+    // Set MSB to 1 to avoid collisions with non-hash classs.
+    SC->Class[0] = getHash(SC) | (1 << 31);
 
   // From now on, sections in Chunks are ordered so that sections in
   // the same group are consecutive in the vector.
@@ -229,14 +223,12 @@ void ICF::run(const std::vector<Chunk *> &Vec) {
 
   // Compare static contents and assign unique IDs for each static content.
   forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); });
-  ++Cnt;
 
   // Split groups by comparing relocations until convergence is obtained.
   do {
     Repeat = false;
     forEachClass(
         [&](size_t Begin, size_t End) { segregate(Begin, End, false); });
-    ++Cnt;
   } while (Repeat);
 
   log("ICF needed " + Twine(Cnt) + " iterations");