[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