[lld] r302528 - Use a simpler heuristic for placing orphans.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue May 9 06:58:47 PDT 2017


Author: rafael
Date: Tue May  9 08:58:46 2017
New Revision: 302528

URL: http://llvm.org/viewvc/llvm-project?rev=302528&view=rev
Log:
Use a simpler heuristic for placing orphans.

This is a bit easier to read and a lot faster in some cases. A version
of many-sections.s with linker scripts goes from 0m41.232s to
0m19.575s.

Modified:
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=302528&r1=302527&r2=302528&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue May  9 08:58:46 2017
@@ -975,6 +975,34 @@ static bool canSharePtLoad(const OutputS
   return (S1.Flags & SHF_EXECINSTR) == (S2.Flags & SHF_EXECINSTR);
 }
 
+// We assume, like createPhdrs that all allocs are at the start.
+template <typename ELFT>
+static std::vector<OutputSection *>::iterator
+findOrphanPos(std::vector<OutputSection *>::iterator B,
+              std::vector<OutputSection *>::iterator E) {
+  OutputSection *Sec = *E;
+
+  // If it is not allocatable, just leave it at the end.
+  if (!(Sec->Flags & SHF_ALLOC))
+    return E;
+
+  // Find the first sharable.
+  auto Pos = std::find_if(
+      B, E, [=](OutputSection *S) { return canSharePtLoad(*S, *Sec); });
+  if (Pos != E) {
+    // Ony consider the sharable range.
+    B = Pos;
+    E = std::find_if(
+        B, E, [=](OutputSection *S) { return !canSharePtLoad(*S, *Sec); });
+    assert(B != E);
+  }
+
+  // Find the fist position that Sec compares less to.
+  return std::find_if(B, E, [=](OutputSection *S) {
+    return compareSectionsNonScript<ELFT>(Sec, S);
+  });
+}
+
 template <class ELFT> void Writer<ELFT>::sortSections() {
   // Don't sort if using -r. It is not necessary and we want to preserve the
   // relative order for SHF_LINK_ORDER sections.
@@ -1018,33 +1046,8 @@ template <class ELFT> void Writer<ELFT>:
   auto NonScriptI =
       std::find_if(OutputSections.begin(), E,
                    [](OutputSection *S) { return S->SectionIndex == INT_MAX; });
-  while (NonScriptI != E) {
-    auto BestPos = std::max_element(
-        I, NonScriptI, [&](OutputSection *&A, OutputSection *&B) {
-          bool ACanSharePtLoad = canSharePtLoad(**NonScriptI, *A);
-          bool BCanSharePtLoad = canSharePtLoad(**NonScriptI, *B);
-          if (ACanSharePtLoad != BCanSharePtLoad)
-            return BCanSharePtLoad;
-
-          bool ACmp = compareSectionsNonScript<ELFT>(*NonScriptI, A);
-          bool BCmp = compareSectionsNonScript<ELFT>(*NonScriptI, B);
-          if (ACmp != BCmp)
-            return BCmp; // FIXME: missing test
-
-          size_t PosA = &A - &OutputSections[0];
-          size_t PosB = &B - &OutputSections[0];
-          return ACmp ? PosA > PosB : PosA < PosB;
-        });
-
-    // max_element only returns NonScriptI if the range is empty. If the range
-    // is not empty we should consider moving the the element forward one
-    // position.
-    if (BestPos != NonScriptI &&
-        !compareSectionsNonScript<ELFT>(*NonScriptI, *BestPos))
-      ++BestPos;
-    std::rotate(BestPos, NonScriptI, NonScriptI + 1);
-    ++NonScriptI;
-  }
+  for (; NonScriptI != E; ++NonScriptI)
+    std::rotate(findOrphanPos<ELFT>(I, NonScriptI), NonScriptI, NonScriptI + 1);
 
   Script->adjustSectionsAfterSorting();
 }




More information about the llvm-commits mailing list