[ELF] Guard relocation section handling behind copyRelocs in addOrphanSections. NFC (#188409)

In addOrphanSections, getRelocatedSection() only returns non-null for -r
or --emit-relocs links. Guard code blocks with `copyRelocs` to skip
unnecessary dyn_cast + getRelocatedSection calls per section in the
common case. Hoist copyRelocs and relocatable to local variables so the
compiler does not reload them through ctx on every loop iteration.

"Assign sections" decreases by 1ms.
This commit is contained in:
Fangrui Song 2026-03-24 21:59:03 -07:00 committed by GitHub
parent 665c2e91e2
commit f599bfcd27
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -50,8 +50,11 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
// This is for --emit-relocs and -r. If .text.foo is emitted as .text.bar, we
// want to emit .rela.text.foo as .rela.text.bar for consistency (this is not
// technically required, but not doing it is odd). This code guarantees that.
if (auto *isec = dyn_cast<InputSection>(s)) {
if (InputSectionBase *rel = isec->getRelocatedSection()) {
if (LLVM_UNLIKELY(ctx.arg.copyRelocs)) {
InputSectionBase *rel = nullptr;
if (auto *isec = dyn_cast<InputSection>(s))
rel = isec->getRelocatedSection();
if (rel) {
OutputSection *out = rel->getOutputSection();
if (!out) {
assert(ctx.arg.relocatable && (rel->flags & SHF_LINK_ORDER));
@ -64,11 +67,10 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
return ss.save(".rela" + out->name);
return ss.save(".rel" + out->name);
}
if (ctx.arg.relocatable)
return s->name;
}
if (ctx.arg.relocatable)
return s->name;
// A BssSection created for a common symbol is identified as "COMMON" in
// linker scripts. It should go to .bss section.
if (s->name == "COMMON")
@ -1021,32 +1023,36 @@ void LinkerScript::addOrphanSections() {
}
};
const bool copyRelocs = ctx.arg.copyRelocs;
const bool relocatable = ctx.arg.relocatable;
size_t n = 0;
for (InputSectionBase *isec : ctx.inputSections) {
// Process InputSection and MergeInputSection.
if (LLVM_LIKELY(isa<InputSection>(isec)))
ctx.inputSections[n++] = isec;
// In -r links, SHF_LINK_ORDER sections are added while adding their parent
// sections because we need to know the parent's output section before we
// can select an output section for the SHF_LINK_ORDER section.
if (ctx.arg.relocatable && (isec->flags & SHF_LINK_ORDER))
continue;
if (LLVM_UNLIKELY(copyRelocs)) {
// In -r links, SHF_LINK_ORDER sections are added while adding their
// parent sections because we need to know the parent's output section
// before we can select an output section for the SHF_LINK_ORDER section.
if (relocatable && (isec->flags & SHF_LINK_ORDER))
continue;
if (auto *sec = dyn_cast<InputSection>(isec)) {
if (InputSectionBase *relocated = sec->getRelocatedSection()) {
// For --emit-relocs and -r, ensure the output section for .text.foo
// is created before the output section for .rela.text.foo.
add(relocated);
// EhInputSection sections are not added to ctx.inputSections. If we see
// .rela.eh_frame, ensure the output section for the synthetic
// EhFrameSection is created first.
if (auto *p = dyn_cast_or_null<InputSectionBase>(relocated->parent))
add(p);
}
if (auto *sec = dyn_cast<InputSection>(isec))
if (InputSectionBase *relocated = sec->getRelocatedSection()) {
// For --emit-relocs and -r, ensure the output section for .text.foo
// is created before the output section for .rela.text.foo.
add(relocated);
// EhInputSection sections are not added to ctx.inputSections. If we
// see .rela.eh_frame, ensure the output section for the synthetic
// EhFrameSection is created first.
if (auto *p = dyn_cast_or_null<InputSectionBase>(relocated->parent))
add(p);
}
}
add(isec);
if (ctx.arg.relocatable)
if (LLVM_UNLIKELY(relocatable))
for (InputSectionBase *depSec : isec->dependentSections)
if (depSec->flags & SHF_LINK_ORDER)
add(depSec);