[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