[lld] 4374824 - [ELF] --gc-sections: combine two iterations over inputSections

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 23 09:53:14 PST 2021


Author: Fangrui Song
Date: 2021-12-23T09:53:08-08:00
New Revision: 4374824ccf6e7ae68264d996a9ae5bb5e3be7fc5

URL: https://github.com/llvm/llvm-project/commit/4374824ccf6e7ae68264d996a9ae5bb5e3be7fc5
DIFF: https://github.com/llvm/llvm-project/commit/4374824ccf6e7ae68264d996a9ae5bb5e3be7fc5.diff

LOG: [ELF] --gc-sections: combine two iterations over inputSections

There is a slight speed-up.

Added: 
    

Modified: 
    lld/ELF/MarkLive.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index 1a17f3bbfdc50..2c712ea964b15 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -244,8 +244,6 @@ template <class ELFT> void MarkLive<ELFT>::run() {
   for (StringRef s : script->referencedSymbols)
     markSymbol(symtab->find(s));
 
-  // Preserve special sections and those which are specified in linker
-  // script KEEP command.
   for (InputSectionBase *sec : inputSections) {
     // Mark .eh_frame sections as live because there are usually no relocations
     // that point to .eh_frames. Otherwise, the garbage collector would drop
@@ -259,6 +257,7 @@ template <class ELFT> void MarkLive<ELFT>::run() {
         scanEhFrameSection(*eh, rels.rels);
       else if (rels.relas.size())
         scanEhFrameSection(*eh, rels.relas);
+      continue;
     }
 
     if (sec->flags & SHF_GNU_RETAIN) {
@@ -268,6 +267,39 @@ template <class ELFT> void MarkLive<ELFT>::run() {
     if (sec->flags & SHF_LINK_ORDER)
       continue;
 
+    // Usually, non-SHF_ALLOC sections are not removed even if they are
+    // unreachable through relocations because reachability is not a good signal
+    // whether they are garbage or not (e.g. there is usually no section
+    // referring to a .comment section, but we want to keep it.) When a
+    // non-SHF_ALLOC section is retained, we also retain sections dependent on
+    // it.
+    //
+    // Note on SHF_LINK_ORDER: Such sections contain metadata and they
+    // have a reverse dependency on the InputSection they are linked with.
+    // We are able to garbage collect them.
+    //
+    // Note on SHF_REL{,A}: Such sections reach here only when -r
+    // or --emit-reloc were given. And they are subject of garbage
+    // collection because, if we remove a text section, we also
+    // remove its relocation section.
+    //
+    // Note on nextInSectionGroup: The ELF spec says that group sections are
+    // included or omitted as a unit. We take the interpretation that:
+    //
+    // - Group members (nextInSectionGroup != nullptr) are subject to garbage
+    //   collection.
+    // - Groups members are retained or discarded as a unit.
+    if (!(sec->flags & SHF_ALLOC)) {
+      bool isRel = sec->type == SHT_REL || sec->type == SHT_RELA;
+      if (!isRel && !sec->nextInSectionGroup) {
+        sec->markLive();
+        for (InputSection *isec : sec->dependentSections)
+          isec->markLive();
+      }
+    }
+
+    // Preserve special sections and those which are specified in linker
+    // script KEEP command.
     if (isReserved(sec) || script->shouldKeep(sec)) {
       enqueue(sec, 0);
     } else if ((!config->zStartStopGC || sec->name.startswith("__libc_")) &&
@@ -377,17 +409,6 @@ template <class ELFT> void elf::markLive() {
   // - Group members (nextInSectionGroup != nullptr) are subject to garbage
   //   collection.
   // - Groups members are retained or discarded as a unit.
-  for (InputSectionBase *sec : inputSections) {
-    bool isAlloc = (sec->flags & SHF_ALLOC);
-    bool isLinkOrder = (sec->flags & SHF_LINK_ORDER);
-    bool isRel = (sec->type == SHT_REL || sec->type == SHT_RELA);
-
-    if (!isAlloc && !isLinkOrder && !isRel && !sec->nextInSectionGroup) {
-      sec->markLive();
-      for (InputSection *isec : sec->dependentSections)
-        isec->markLive();
-    }
-  }
 
   // Follow the graph to mark all live sections.
   for (unsigned curPart = 1; curPart <= partitions.size(); ++curPart)


        


More information about the llvm-commits mailing list