[lld] e1b6b5b - [ELF] Avoid referencing SectionBase::repl after ICF
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 24 12:09:53 PST 2021
Author: Fangrui Song
Date: 2021-12-24T12:09:48-08:00
New Revision: e1b6b5be462ee2f197737162fc2a7d23e9a2eab6
URL: https://github.com/llvm/llvm-project/commit/e1b6b5be462ee2f197737162fc2a7d23e9a2eab6
DIFF: https://github.com/llvm/llvm-project/commit/e1b6b5be462ee2f197737162fc2a7d23e9a2eab6.diff
LOG: [ELF] Avoid referencing SectionBase::repl after ICF
It is fairly easy to forget SectionBase::repl after ICF.
Let ICF rewrite a Defined symbol's `section` field to avoid references to
SectionBase::repl in subsequent passes. This slightly improves the --icf=none
performance due to less indirection (maybe for --icf={safe,all} as well if most
symbols are Defined).
With this change, there is only one reference to `repl` (--gdb-index D89751).
We can undo f4fb5fd7523f8e3c3b3966d43c0a28457b59d1d8 (`Move Repl to SectionBase.`)
but move `repl` to `InputSection` instead.
Reviewed By: ikudrin
Differential Revision: https://reviews.llvm.org/D116093
Added:
Modified:
lld/ELF/CallGraphSort.cpp
lld/ELF/ICF.cpp
lld/ELF/InputSection.cpp
lld/ELF/InputSection.h
lld/ELF/Relocations.cpp
lld/ELF/Symbols.cpp
lld/ELF/Symbols.h
lld/ELF/SyntheticSections.cpp
lld/ELF/Writer.cpp
Removed:
################################################################################
diff --git a/lld/ELF/CallGraphSort.cpp b/lld/ELF/CallGraphSort.cpp
index aa00d6eadbf98..5b07f0e18c8ab 100644
--- a/lld/ELF/CallGraphSort.cpp
+++ b/lld/ELF/CallGraphSort.cpp
@@ -114,8 +114,8 @@ CallGraphSort::CallGraphSort() {
// Create the graph.
for (std::pair<SectionPair, uint64_t> &c : profile) {
- const auto *fromSB = cast<InputSectionBase>(c.first.first->repl);
- const auto *toSB = cast<InputSectionBase>(c.first.second->repl);
+ const auto *fromSB = cast<InputSectionBase>(c.first.first);
+ const auto *toSB = cast<InputSectionBase>(c.first.second);
uint64_t weight = c.second;
// Ignore edges between input sections belonging to
diff erent output
diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp
index 0ec748e8f9901..ec63d2ef4d6f9 100644
--- a/lld/ELF/ICF.cpp
+++ b/lld/ELF/ICF.cpp
@@ -550,6 +550,22 @@ template <class ELFT> void ICF<ELFT>::run() {
}
});
+ // Change Defined symbol's section field to the canonical one.
+ auto fold = [](Symbol *sym) {
+ if (auto *d = dyn_cast<Defined>(sym))
+ if (auto *sec = dyn_cast_or_null<InputSection>(d->section))
+ if (sec->repl != d->section) {
+ d->section = sec->repl;
+ d->folded = true;
+ }
+ };
+ for (Symbol *sym : symtab->symbols())
+ fold(sym);
+ parallelForEach(objectFiles, [&](ELFFileBase *file) {
+ for (Symbol *sym : file->getLocalSymbols())
+ fold(sym);
+ });
+
// InputSectionDescription::sections is populated by processSectionCommands().
// ICF may fold some input sections assigned to output sections. Remove them.
for (SectionCommand *cmd : script->sectionCommands)
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index df8cc5f221a0b..e3871260fe5bc 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -442,7 +442,7 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
p->setSymbolAndType(0, 0, false);
continue;
}
- SectionBase *section = d->section->repl;
+ SectionBase *section = d->section;
if (!section->isLive()) {
p->setSymbolAndType(0, 0, false);
continue;
@@ -948,10 +948,10 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
//
// If the referenced symbol is discarded (made Undefined), or the
// section defining the referenced symbol is garbage collected,
- // sym.getOutputSection() is nullptr. `ds->section->repl != ds->section`
- // catches the ICF folded case. However, resolving a relocation in
- // .debug_line to -1 would stop debugger users from setting breakpoints on
- // the folded-in function, so exclude .debug_line.
+ // sym.getOutputSection() is nullptr. `ds->folded` catches the ICF folded
+ // case. However, resolving a relocation in .debug_line to -1 would stop
+ // debugger users from setting breakpoints on the folded-in function, so
+ // exclude .debug_line.
//
// For pre-DWARF-v5 .debug_loc and .debug_ranges, -1 is a reserved value
// (base address selection entry), use 1 (which is used by GNU ld for
@@ -960,8 +960,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
// TODO To reduce disruption, we use 0 instead of -1 as the tombstone
// value. Enable -1 in a future release.
auto *ds = dyn_cast<Defined>(&sym);
- if (!sym.getOutputSection() ||
- (ds && ds->section->repl != ds->section && !isDebugLine)) {
+ if (!sym.getOutputSection() || (ds && ds->folded && !isDebugLine)) {
// If -z dead-reloc-in-nonalloc= is specified, respect it.
const uint64_t value = tombstone ? SignExtend64<bits>(*tombstone)
: (isDebugLocOrRanges ? 1 : 0);
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index 5a0dd78f0e559..5319830b5d802 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -52,13 +52,6 @@ class SectionBase {
StringRef name;
- // This pointer points to the "real" instance of this instance.
- // Usually Repl == this. However, if ICF merges two sections,
- // Repl pointer of one section points to another section. So,
- // if you need to get a pointer to this instance, do not use
- // this but instead this->Repl.
- SectionBase *repl;
-
uint8_t sectionKind : 3;
// The next two bit fields are only used by InputSectionBase, but we
@@ -102,9 +95,9 @@ class SectionBase {
constexpr SectionBase(Kind sectionKind, StringRef name, uint64_t flags,
uint32_t entsize, uint32_t alignment, uint32_t type,
uint32_t info, uint32_t link)
- : name(name), repl(this), sectionKind(sectionKind), bss(false),
- keepUnique(false), partition(0), alignment(alignment), flags(flags),
- entsize(entsize), type(type), link(link), info(info) {}
+ : name(name), sectionKind(sectionKind), bss(false), keepUnique(false),
+ partition(0), alignment(alignment), flags(flags), entsize(entsize),
+ type(type), link(link), info(info) {}
};
// This corresponds to a section of an input file.
@@ -367,6 +360,10 @@ class InputSection : public InputSectionBase {
template <class ELFT, class RelTy>
void relocateNonAlloc(uint8_t *buf, llvm::ArrayRef<RelTy> rels);
+ // Points to the canonical section. If ICF folds two sections, repl pointer of
+ // one section points to the other.
+ InputSection *repl = this;
+
// Used by ICF.
uint32_t eqClass[2] = {0, 0};
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index c4438be0cb593..38e0d84e6271d 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -2004,8 +2004,8 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
// non-Thunk target, so we cannot fold offset + addend.
if (auto *d = dyn_cast<Defined>(rel.sym))
if (!d->isInPlt() && d->section)
- thunkVec = &thunkedSymbolsBySectionAndAddend[{
- {d->section->repl, d->value}, keyAddend}];
+ thunkVec = &thunkedSymbolsBySectionAndAddend[{{d->section, d->value},
+ keyAddend}];
if (!thunkVec)
thunkVec = &thunkedSymbols[{rel.sym, keyAddend}];
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index f6f0ad0087d74..23f8d3ef545ee 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -78,7 +78,6 @@ static uint64_t getSymVA(const Symbol &sym, int64_t addend) {
return d.value;
assert(isec != &InputSection::discarded);
- isec = isec->repl;
uint64_t offset = d.value;
@@ -348,7 +347,7 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
report(": unable to order absolute symbol: ");
else if (d && isa<OutputSection>(d->section))
report(": unable to order synthetic symbol: ");
- else if (d && !d->section->repl->isLive())
+ else if (d && !d->section->isLive())
report(": unable to order discarded symbol: ");
}
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index beb45ec141470..e5fe53c6c4961 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -248,8 +248,9 @@ class Symbol {
exportDynamic(isExportDynamic(k, visibility)), inDynamicList(false),
canInline(false), referenced(false), traced(false), isInIplt(false),
gotInIgot(false), isPreemptible(false), used(!config->gcSections),
- needsTocRestore(false), scriptDefined(false), needsCopy(false),
- needsGot(false), needsPlt(false), hasDirectReloc(false) {}
+ folded(false), needsTocRestore(false), scriptDefined(false),
+ needsCopy(false), needsGot(false), needsPlt(false),
+ hasDirectReloc(false) {}
public:
// True if this symbol is in the Iplt sub-section of the Plt and the Igot
@@ -269,6 +270,9 @@ class Symbol {
// which are referenced by relocations when -r or --emit-relocs is given.
uint8_t used : 1;
+ // True if defined relative to a section discarded by ICF.
+ uint8_t folded : 1;
+
// True if a call to this symbol needs to be followed by a restore of the
// PPC64 toc pointer.
uint8_t needsTocRestore : 1;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 872dd0e612afc..e480118f5ae9c 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -391,7 +391,7 @@ Defined *EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) {
// FDEs for garbage-collected or merged-by-ICF sections, or sections in
// another partition, are dead.
if (auto *d = dyn_cast<Defined>(&b))
- if (d->section && d->section->partition == partition)
+ if (!d->folded && d->section && d->section->partition == partition)
return d;
return nullptr;
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 221601d15c2f7..497e56886b720 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -679,7 +679,6 @@ static bool includeInSymtab(const Symbol &b) {
SectionBase *sec = d->section;
if (!sec)
return true;
- sec = sec->repl;
// Exclude symbols pointing to garbage-collected sections.
if (isa<InputSectionBase>(sec) && !sec->isLive())
@@ -1302,7 +1301,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
if (auto *d = dyn_cast<Defined>(&sym)) {
if (auto *sec = dyn_cast_or_null<InputSectionBase>(d->section)) {
- int &priority = sectionOrder[cast<InputSectionBase>(sec->repl)];
+ int &priority = sectionOrder[cast<InputSectionBase>(sec)];
priority = std::min(priority, ent.priority);
}
}
@@ -1725,7 +1724,7 @@ static void fixSymbolsAfterShrinking() {
if (!sec)
return;
- const InputSectionBase *inputSec = dyn_cast<InputSectionBase>(sec->repl);
+ const InputSectionBase *inputSec = dyn_cast<InputSectionBase>(sec);
if (!inputSec || !inputSec->bytesDropped)
return;
More information about the llvm-commits
mailing list