[lld] [ELF] Parallelize demoteSymbolsAndComputeIsPreemptible (PR #207310)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 2 19:52:14 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/207310
Each symbol's demotion and isPreemptible bit is independent.
Linking clang release is 1.02x as fast on an x86-64 machine.
>From 76bae2d88b4a514270527fd7b746238d71cb073a Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 2 Jul 2026 00:21:22 -0700
Subject: [PATCH] [ELF] Parallelize demoteSymbolsAndComputeIsPreemptible
Each symbol's demotion and isPreemptible bit is independent.
Linking clang release is 1.02x as fast on an x86-64 machine.
---
lld/ELF/Writer.cpp | 40 +++++++++++++++++++++++-----------------
1 file changed, 23 insertions(+), 17 deletions(-)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 56cd9548a5f59..49d3f903b3743 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -261,25 +261,31 @@ static void demoteDefined(Defined &sym, DenseMap<SectionBase *, size_t> &map) {
// references to /DISCARD/ discarded symbols will lead to errors.
static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
llvm::TimeTraceScope timeScope("Demote symbols");
- DenseMap<InputFile *, DenseMap<SectionBase *, size_t>> sectionIndexMap;
- for (Symbol *sym : ctx.symtab->getSymbols()) {
- if (auto *d = dyn_cast<Defined>(sym)) {
- if (d->section && !d->section->isLive())
- demoteDefined(*d, sectionIndexMap[d->file]);
- } else {
- auto *s = dyn_cast<SharedSymbol>(sym);
- if (sym->isLazy() || (s && !cast<SharedFile>(s->file)->isNeeded)) {
- uint8_t binding = sym->isLazy() ? sym->binding : uint8_t(STB_WEAK);
- Undefined(ctx.internalFile, sym->getName(), binding, sym->stOther,
- sym->type)
- .overwrite(*sym);
- sym->versionId = VER_NDX_GLOBAL;
+ ArrayRef<Symbol *> syms = ctx.symtab->getSymbols();
+ constexpr size_t chunkSize = 4096;
+ parallelFor(0, (syms.size() + chunkSize - 1) / chunkSize, [&](size_t c) {
+ DenseMap<InputFile *, DenseMap<SectionBase *, size_t>> sectionIndexMap;
+ size_t begin = c * chunkSize;
+ for (Symbol *sym :
+ syms.slice(begin, std::min(chunkSize, syms.size() - begin))) {
+ if (auto *d = dyn_cast<Defined>(sym)) {
+ if (d->section && !d->section->isLive())
+ demoteDefined(*d, sectionIndexMap[d->file]);
+ } else {
+ auto *s = dyn_cast<SharedSymbol>(sym);
+ if (sym->isLazy() || (s && !cast<SharedFile>(s->file)->isNeeded)) {
+ uint8_t binding = sym->isLazy() ? sym->binding : uint8_t(STB_WEAK);
+ Undefined(ctx.internalFile, sym->getName(), binding, sym->stOther,
+ sym->type)
+ .overwrite(*sym);
+ sym->versionId = VER_NDX_GLOBAL;
+ }
}
- }
- sym->isPreemptible = (sym->isUndefined() || sym->isExported) &&
- computeIsPreemptible(ctx, *sym);
- }
+ sym->isPreemptible = (sym->isUndefined() || sym->isExported) &&
+ computeIsPreemptible(ctx, *sym);
+ }
+ });
}
static OutputSection *findSection(Ctx &ctx, StringRef name) {
More information about the llvm-commits
mailing list