From 2f7bd4fa97232dfab7f2347c745005eb9e2ffd2d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 2 Apr 2026 22:00:15 -0700 Subject: [PATCH] [ELF] Enable parallel relocation scanning for -z nocombreloc and PPC64 (#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. --- lld/ELF/Arch/PPC64.cpp | 4 +++- lld/ELF/Relocations.cpp | 8 +++----- lld/ELF/SyntheticSections.cpp | 2 +- lld/test/ELF/combreloc.s | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 80087e9ee59b..9f49605d89c5 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -1196,8 +1196,10 @@ void PPC64::scanSectionImpl(InputSectionBase &sec, Relocs rels) { case R_PPC64_TOC16_LO: // Record the TOC entry (.toc + addend) as not relaxable. if (sym.isSection() && isa(sym) && - cast(sym).section->name == ".toc") + cast(sym).section->name == ".toc") { + std::lock_guard 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 0000f1b4d905..7b4d7217e045 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1184,11 +1184,9 @@ template 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 2da3f1afeb82..3c08c392ff21 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4564,7 +4564,7 @@ template void elf::createSyntheticSections(Ctx &ctx) { ctx, relaDynName, threadCount); else part.relaDyn = std::make_unique>( - 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 08e404c66676..8e76de912bb4 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: 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: 0x33F8 R_X86_64_64 aaa 0x0 +# NOCOMB-NEXT: 0x3410 R_X86_64_64 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