From 7cd0c45364f7767c81185f2f086fe416af0a165d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 30 Jan 2022 15:12:09 -0800 Subject: [PATCH] [ELF] Simplify SectionBase::partition handling and make it live by default. NFC Previously an InputSectionBase is dead (`partition==0`) by default. SyntheticSection calls markLive and BssSection overrides that with markDead. It is more natural to make InputSectionBase live by default and let --gc-sections mark InputSectionBase dead. When linking a Release build of clang: * --no-gc-sections:, the removed `inputSections` loop decreases markLive time from 4ms to 1ms. * --gc-sections: the extra `inputSections` loop increases markLive time from 0.181296s to 0.188526s. This is as of we lose the removing one `inputSections` loop optimization (4374824ccf6e7ae68264d996a9ae5bb5e3be7fc5). I believe the loss can be mitigated if we refactor markLive. --- lld/ELF/Driver.cpp | 1 - lld/ELF/InputSection.h | 6 +++--- lld/ELF/MarkLive.cpp | 6 +++--- lld/ELF/SyntheticSections.h | 4 +--- lld/ELF/Writer.cpp | 3 +-- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 4aae70d08018e..a1daae6e0e9b1 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1828,7 +1828,6 @@ static void replaceCommonSymbols() { auto *bss = make("COMMON", s->size, s->alignment); bss->file = s->file; - bss->markDead(); inputSections.push_back(bss); s->replace(Defined{s->file, s->getName(), s->binding, s->stOther, s->type, /*value=*/0, s->size, bss}); diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index adfc45ece9bcd..3105d27a07fbc 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -65,7 +65,7 @@ class SectionBase { // The 1-indexed partition that this section is assigned to by the garbage // collector, or 0 if this section is dead. Normally there is only one // partition, so this will either be 0 or 1. - uint8_t partition; + uint8_t partition = 1; elf::Partition &getPartition() const; // These corresponds to the fields in Elf_Shdr. @@ -96,8 +96,8 @@ class SectionBase { uint32_t entsize, uint32_t alignment, uint32_t type, uint32_t info, uint32_t link) : name(name), sectionKind(sectionKind), bss(false), keepUnique(false), - partition(0), alignment(alignment), flags(flags), entsize(entsize), - type(type), link(link), info(info) {} + alignment(alignment), flags(flags), entsize(entsize), type(type), + link(link), info(info) {} }; // This corresponds to a section of an input file. diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 597c0684b8b2b..017507c1abd04 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -371,9 +371,6 @@ template void elf::markLive() { llvm::TimeTraceScope timeScope("markLive"); // If --gc-sections is not given, retain all input sections. if (!config->gcSections) { - for (InputSectionBase *sec : inputSections) - sec->markLive(); - // If a DSO defines a symbol referenced in a regular object, it is needed. for (Symbol *sym : symtab->symbols()) if (auto *s = dyn_cast(sym)) @@ -382,6 +379,9 @@ template void elf::markLive() { return; } + for (InputSectionBase *sec : inputSections) + sec->markDead(); + // Follow the graph to mark all live sections. for (unsigned curPart = 1; curPart <= partitions.size(); ++curPart) MarkLive(curPart).run(); diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 4b55e1157276c..40c2382075676 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -40,9 +40,7 @@ class SyntheticSection : public InputSection { SyntheticSection(uint64_t flags, uint32_t type, uint32_t alignment, StringRef name) : InputSection(nullptr, flags, type, alignment, {}, name, - InputSectionBase::Synthetic) { - markLive(); - } + InputSectionBase::Synthetic) {} virtual ~SyntheticSection() = default; virtual void writeTo(uint8_t *buf) = 0; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 7541bd309e6e9..d689db2e6dc09 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -315,8 +315,7 @@ template void elf::createSyntheticSections() { // If there is a SECTIONS command and a .data.rel.ro section name use name // .data.rel.ro.bss so that we match in the .data.rel.ro output section. // This makes sure our relro is contiguous. - bool hasDataRelRo = - script->hasSectionsCommand && findSection(".data.rel.ro", 0); + bool hasDataRelRo = script->hasSectionsCommand && findSection(".data.rel.ro"); in.bssRelRo = std::make_unique( hasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1); add(*in.bssRelRo);