[lld] [ELF] Parallelize ICF's section sort. NFC (PR #223216)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 12 23:46:00 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/223216
All candidate sections are sorted by a serial stable_sort, which is a
scalability bottleneck. Switch to parallel sort using Schwartzian
transform. Linking Chromium with --icf=all (--threads=8) drops from
4.47s to 3.18s.
>From c3c1cdc521c3ace063fee982c6aac48d7e989dff Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 12 Sep 2026 23:16:43 -0700
Subject: [PATCH] [ELF] Parallelize ICF's section sort. NFC
All candidate sections are sorted by a serial stable_sort, which is a
scalability bottleneck. Switch to parallel sort using Schwartzian
transform. Linking Chromium with --icf=all (--threads=8) drops from
4.47s to 3.18s.
---
lld/ELF/ICF.cpp | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp
index b64f49ec8b0bd..62c42bdbb550d 100644
--- a/lld/ELF/ICF.cpp
+++ b/lld/ELF/ICF.cpp
@@ -510,9 +510,16 @@ template <class ELFT> void ICF<ELFT>::run() {
// From now on, sections in Sections vector are ordered so that sections
// in the same equivalence class are consecutive in the vector.
- llvm::stable_sort(sections, [](const InputSection *a, const InputSection *b) {
- return a->eqClass[0] < b->eqClass[0];
+ SmallVector<uint64_t, 0> keys(sections.size());
+ parallelFor(0, sections.size(), [&](size_t i) {
+ keys[i] = uint64_t(sections[i]->eqClass[0]) << 32 | i;
});
+ parallelSort(keys.begin(), keys.end());
+ SmallVector<InputSection *, 0> sorted;
+ sorted.reserve(keys.size());
+ for (uint64_t k : keys)
+ sorted.push_back(sections[uint32_t(k)]);
+ sections = std::move(sorted);
// Compare static contents and assign unique equivalence class IDs for each
// static content. Use a base offset for these IDs to ensure no overlap with
More information about the llvm-commits
mailing list