[lld] [ELF] Retain .got for revertible no-PIC GOTPCRELX optimization (PR #212077)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 25 17:49:45 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/212077
Commit 9d6ec280fc537b55ef8641ea85d3522426bc5766 (2023) sets
GotSection::hasGotOffRel when adjustGotPcExpr returns R_RELAX_GOT_PC,
keeping .got alive for an optimization that X86_64::relaxOnce may
revert.
R_RELAX_GOT_PC_NOPIC (e.g. `addq`) in -no-pie mode has the same issue.
>From 35ae548308ed975d976d681ca74b2789dd18ee21 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 25 Jul 2026 17:18:16 -0700
Subject: [PATCH] [ELF] Retain .got for revertible no-PIC GOTPCRELX
optimization
Commit 9d6ec280fc537b55ef8641ea85d3522426bc5766 (2023) sets
GotSection::hasGotOffRel when adjustGotPcExpr returns R_RELAX_GOT_PC,
keeping .got alive for an optimization that X86_64::relaxOnce may
revert.
R_RELAX_GOT_PC_NOPIC (e.g. `addq`) in -no-pie mode has the same issue.
---
lld/ELF/Relocations.cpp | 6 +++---
lld/test/ELF/x86-64-gotpc-relax-too-far.s | 16 ++++++++++++++++
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 4702d941d28ca..ff06fe1602d95 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -927,9 +927,9 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
} else if (!isAbsoluteOrTls(sym)) {
expr = ctx.target->adjustGotPcExpr(type, addend,
sec->content().data() + offset);
- // If the target adjusted the expression to R_RELAX_GOT_PC, we may end up
- // needing the GOT if we can't relax everything.
- if (expr == R_RELAX_GOT_PC)
+ // If the target adjusted the expression to an optimizable form, we may
+ // end up needing the GOT if we can't optimize everything.
+ if (expr == R_RELAX_GOT_PC || expr == R_RELAX_GOT_PC_NOPIC)
ctx.in.got->hasGotOffRel.store(true, std::memory_order_relaxed);
}
}
diff --git a/lld/test/ELF/x86-64-gotpc-relax-too-far.s b/lld/test/ELF/x86-64-gotpc-relax-too-far.s
index 0318d73ec2db2..2019b8c51d050 100644
--- a/lld/test/ELF/x86-64-gotpc-relax-too-far.s
+++ b/lld/test/ELF/x86-64-gotpc-relax-too-far.s
@@ -11,6 +11,10 @@
# RUN: llvm-readelf -S %t/bin3 | FileCheck --check-prefixes=UNNECESSARY-GOT %s
# RUN: ld.lld -T %t/lds4 %t/a.o -o %t/bin4
# RUN: llvm-objdump -d %t/bin4 | FileCheck --check-prefix=DISASM4 %s
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/b.s -o %t/b.o
+# RUN: ld.lld -T %t/lds1 %t/b.o -o %t/bin5
+# RUN: llvm-objdump -d %t/bin5 | FileCheck --check-prefix=DISASM5 %s
+# RUN: llvm-readelf -S %t/bin5 | FileCheck --check-prefixes=GOT5 %s
# DISASM: <_foo>:
# DISASM-NEXT: movl 0x1ffffa(%rip), %eax
@@ -27,10 +31,14 @@
# DISASM4-NEXT: addq 0x1ff3(%rip), %rax
# DISASM4-NEXT: addq $0x7fffffff, %rax
+# DISASM5: <_start>:
+# DISASM5-NEXT: addq 0xffff9(%rip), %rax
+
# In our implementation, .got is retained even if all GOT-generating relocations are optimized.
# Make sure .got still exists with the right size.
# UNNECESSARY-GOT: .got PROGBITS 0000000000300000 101020 000000 00 WA 0 0 8
# GOT: .got PROGBITS 0000000000300000 102000 000018 00 WA 0 0 8
+# GOT5: .got PROGBITS 0000000000300000 002000 000008 00 WA 0 0 8
#--- a.s
.section .text.foo,"ax"
@@ -91,3 +99,11 @@ SECTIONS {
foo 0x7fffffff : { *(foo) }
data 0x80001000 : { *(data) }
}
+
+#--- b.s
+.globl _start
+_start:
+ addq __stop_data at GOTPCREL(%rip), %rax # out of range
+
+.section data,"aw", at progbits
+.space 13
More information about the llvm-commits
mailing list