forked from OSchip/llvm-project
[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 f4fb5fd752
(`Move Repl to SectionBase.`)
but move `repl` to `InputSection` instead.
Reviewed By: ikudrin
Differential Revision: https://reviews.llvm.org/D116093
This commit is contained in:
parent
8ea64d5585
commit
e1b6b5be46
|
@ -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 different output
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -52,13 +52,6 @@ public:
|
|||
|
||||
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 @@ protected:
|
|||
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 @@ public:
|
|||
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};
|
||||
|
||||
|
|
|
@ -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}];
|
||||
|
||||
|
|
|
@ -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: ");
|
||||
}
|
||||
|
||||
|
|
|
@ -248,8 +248,9 @@ protected:
|
|||
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 @@ public:
|
|||
// 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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue