[lld] [ELF] Enable parallel relocation scanning for -z nocombreloc and PPC64 (PR #190309)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 2 22:00:15 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/190309
The `bool serial` condition in scanRelocations disabled parallelism for
three cases: -z nocombreloc, MIPS, and PPC64. Resolve two cases:
- nocombreloc: .rela.dyn is now always created with combreloc=true so
non-relative relocations are sorted deterministically. Since
#187964 already separates relative relocations unconditionally,
the only remaining effect of -z nocombreloc is suppressing
DT_RELACOUNT (gated on ctx.arg.zCombreloc in DynamicSection).
- PPC64: After #181496 moved scanning into scanSectionImpl, the
sole thread-unsafe access is ctx.ppc64noTocRelax (DenseSet::insert).
Protect it with ctx.relocMutex, which is already used for rare
operations during parallel scanning.
MIPS retains serial scanning due to `MipsGotSection` mutations.
>From 1b152400fa606f7dbebed18f5630e5e5218390e0 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 2 Apr 2026 21:20:01 -0700
Subject: [PATCH] [ELF] Enable parallel relocation scanning for -z nocombreloc
and PPC64
The `bool serial` condition in scanRelocations disabled parallelism for
three cases: -z nocombreloc, MIPS, and PPC64. Resolve two cases:
- nocombreloc: .rela.dyn is now always created with combreloc=true so
non-relative relocations are sorted deterministically. Since
#187964 already separates relative relocations unconditionally,
the only remaining effect of -z nocombreloc is suppressing
DT_RELACOUNT (gated on ctx.arg.zCombreloc in DynamicSection).
- PPC64: After #181496 moved scanning into scanSectionImpl, the
sole thread-unsafe access is ctx.ppc64noTocRelax (DenseSet::insert).
Protect it with ctx.relocMutex, which is already used for rare
operations during parallel scanning.
MIPS retains serial scanning due to `MipsGotSection` mutations.
---
lld/ELF/Arch/PPC64.cpp | 4 +++-
lld/ELF/Relocations.cpp | 8 +++-----
lld/ELF/SyntheticSections.cpp | 2 +-
lld/test/ELF/combreloc.s | 6 +++---
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp
index 80087e9ee59bd..9f49605d89c58 100644
--- a/lld/ELF/Arch/PPC64.cpp
+++ b/lld/ELF/Arch/PPC64.cpp
@@ -1196,8 +1196,10 @@ void PPC64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
case R_PPC64_TOC16_LO:
// Record the TOC entry (.toc + addend) as not relaxable.
if (sym.isSection() && isa<Defined>(sym) &&
- cast<Defined>(sym).section->name == ".toc")
+ cast<Defined>(sym).section->name == ".toc") {
+ std::lock_guard<std::mutex> lock(ctx.relocMutex);
ctx.ppc64noTocRelax.insert({&sym, addend});
+ }
expr = R_GOTREL;
break;
case R_PPC64_TOC16_HA:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 0000f1b4d9059..7b4d7217e0452 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1184,11 +1184,9 @@ template <class ELFT> void elf::scanRelocations(Ctx &ctx) {
// copy relocations, etc. Note that relocations for non-alloc sections are
// directly processed by InputSection::relocateNonAlloc.
- // Deterministic parallellism needs sorting relocations which is unsuitable
- // for -z nocombreloc. MIPS and PPC64 use global states which are not suitable
- // for parallelism.
- bool serial = !ctx.arg.zCombreloc || ctx.arg.emachine == EM_MIPS ||
- ctx.arg.emachine == EM_PPC64;
+ // MIPS modifies MipsGotSection during relocation scanning, which is not
+ // suitable for parallelism.
+ bool serial = ctx.arg.emachine == EM_MIPS;
parallel::TaskGroup tg;
auto outerFn = [&]() {
for (ELFFileBase *f : ctx.objectFiles) {
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2da3f1afeb821..3c08c392ff214 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -4564,7 +4564,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
ctx, relaDynName, threadCount);
else
part.relaDyn = std::make_unique<RelocationSection<ELFT>>(
- ctx, relaDynName, ctx.arg.zCombreloc, threadCount);
+ ctx, relaDynName, /*combreloc=*/true, threadCount);
if (ctx.hasDynsym) {
add(*part.dynSymTab);
diff --git a/lld/test/ELF/combreloc.s b/lld/test/ELF/combreloc.s
index 08e404c66676e..8e76de912bb4e 100644
--- a/lld/test/ELF/combreloc.s
+++ b/lld/test/ELF/combreloc.s
@@ -32,11 +32,11 @@
# NOCOMB: Relocations [
# NOCOMB-NEXT: Section ({{.*}}) .rela.dyn {
# NOCOMB-NEXT: 0x3418 R_X86_64_RELATIVE - 0x3420
+# NOCOMB-NEXT: 0x23F0 R_X86_64_GLOB_DAT aaa 0x0
# NOCOMB-NEXT: 0x33F8 R_X86_64_64 aaa 0x0
-# NOCOMB-NEXT: 0x3400 R_X86_64_64 ccc 0x0
-# NOCOMB-NEXT: 0x3408 R_X86_64_64 bbb 0x0
# NOCOMB-NEXT: 0x3410 R_X86_64_64 aaa 0x0
-# NOCOMB-NEXT: 0x23F0 R_X86_64_GLOB_DAT aaa 0x0
+# NOCOMB-NEXT: 0x3408 R_X86_64_64 bbb 0x0
+# NOCOMB-NEXT: 0x3400 R_X86_64_64 ccc 0x0
# NOCOMB-NEXT: }
.globl aaa, bbb, ccc
More information about the llvm-commits
mailing list