[lld] ELF,SystemZ: Don't sort relocations for TLS GD/LD optimization; support CREL (PR #149640)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 18 23:49:11 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
The General dynamic and Local Dynamic TLS models call
`__tls_get_offset`, which is eliminated after optimization. To avoid an
unneeded PLT entry and its .dynsym entry, #<!-- -->75643 sorted the relocations.
However, sorting relocations does not play well with CREL. Since GNU ld
has a false dependency on `__tls_get_offset` as well, let's remove the
relocation sorting. Fix #<!-- -->149511
---
Full diff: https://github.com/llvm/llvm-project/pull/149640.diff
5 Files Affected:
- (modified) lld/ELF/Arch/SystemZ.cpp (+3-24)
- (modified) lld/ELF/Relocations.cpp (+1-1)
- (modified) lld/test/ELF/systemz-plt.s (+1-1)
- (modified) lld/test/ELF/systemz-tls-gd.s (+25-21)
- (modified) lld/test/ELF/systemz-tls-ld.s (+3)
``````````diff
diff --git a/lld/ELF/Arch/SystemZ.cpp b/lld/ELF/Arch/SystemZ.cpp
index a9125806c0952..6771ff01dae58 100644
--- a/lld/ELF/Arch/SystemZ.cpp
+++ b/lld/ELF/Arch/SystemZ.cpp
@@ -23,7 +23,6 @@ namespace {
class SystemZ : public TargetInfo {
public:
SystemZ(Ctx &);
- int getTlsGdRelaxSkip(RelType type) const override;
RelExpr getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const override;
RelType getDynRel(RelType type) const override;
@@ -277,29 +276,6 @@ RelExpr SystemZ::adjustTlsExpr(RelType type, RelExpr expr) const {
return expr;
}
-int SystemZ::getTlsGdRelaxSkip(RelType type) const {
- // A __tls_get_offset call instruction is marked with 2 relocations:
- //
- // R_390_TLS_GDCALL / R_390_TLS_LDCALL: marker relocation
- // R_390_PLT32DBL: __tls_get_offset
- //
- // After the relaxation we no longer call __tls_get_offset and should skip
- // both relocations to not create a false dependence on __tls_get_offset
- // being defined.
- //
- // Note that this mechanism only works correctly if the R_390_TLS_[GL]DCALL
- // is seen immediately *before* the R_390_PLT32DBL. Unfortunately, current
- // compilers on the platform will typically generate the inverse sequence.
- // To fix this, we sort relocations by offset in RelocationScanner::scan;
- // this ensures the correct sequence as the R_390_TLS_[GL]DCALL applies to
- // the first byte of the brasl instruction, while the R_390_PLT32DBL applies
- // to its third byte (the relative displacement).
-
- if (type == R_390_TLS_GDCALL || type == R_390_TLS_LDCALL)
- return 2;
- return 1;
-}
-
void SystemZ::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
// The general-dynamic code sequence for a global `x`:
@@ -320,6 +296,9 @@ void SystemZ::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
// Relaxing to initial-exec entails:
// 1) Replacing the call by a load from the GOT.
// 2) Replacing the relocation on the constant LC0 by R_390_TLS_GOTIE64.
+ //
+ // While we no longer call __tls_get_offset after optimization, we still
+ // generate an unused PLT entry. This simple behavior matches GNU ld.
switch (rel.type) {
case R_390_TLS_GDCALL:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 4333b032c9d4e..845ce199b62f2 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1657,7 +1657,7 @@ void RelocationScanner::scan(Relocs<RelTy> rels) {
// On SystemZ, all sections need to be sorted by r_offset, to allow TLS
// relaxation to be handled correctly - see SystemZ::getTlsGdRelaxSkip.
SmallVector<RelTy, 0> storage;
- if (isa<EhInputSection>(sec) || ctx.arg.emachine == EM_S390)
+ if (isa<EhInputSection>(sec))
rels = sortRels(rels, storage);
if constexpr (RelTy::IsCrel) {
diff --git a/lld/test/ELF/systemz-plt.s b/lld/test/ELF/systemz-plt.s
index 717343ce4c4d5..1207f0704db8e 100644
--- a/lld/test/ELF/systemz-plt.s
+++ b/lld/test/ELF/systemz-plt.s
@@ -3,7 +3,7 @@
# RUN: llvm-mc -filetype=obj -triple=s390x-unknown-linux %t1.s -o %t1.o
# RUN: ld.lld -shared %t1.o -soname=t1.so -o %t1.so
-# RUN: llvm-mc -filetype=obj -triple=s390x-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=s390x-unknown-linux --crel %s -o %t.o
# RUN: ld.lld %t.o %t1.so -z separate-code -o %t
# RUN: llvm-readelf -S -s -r -x .got.plt %t | FileCheck %s
# RUN: llvm-objdump -d %t | FileCheck --check-prefixes=DIS %s
diff --git a/lld/test/ELF/systemz-tls-gd.s b/lld/test/ELF/systemz-tls-gd.s
index 742797e2d62e4..0042127eea153 100644
--- a/lld/test/ELF/systemz-tls-gd.s
+++ b/lld/test/ELF/systemz-tls-gd.s
@@ -1,6 +1,7 @@
# REQUIRES: systemz
# RUN: llvm-mc -filetype=obj -triple=s390x-unknown-linux %s -o %t.o
-# RUN: echo '.tbss; .globl b, c; b: .zero 4; c:' | llvm-mc -filetype=obj -triple=s390x-unknown-linux - -o %t1.o
+# RUN: echo '.globl __tls_get_offset; __tls_get_offset:; .tbss; .globl b, c; b: .zero 4; c:' | \
+# RUN: llvm-mc -filetype=obj -triple=s390x-unknown-linux - -o %t1.o
# RUN: ld.lld -shared -soname=t1.so %t1.o -o %t1.so
# RUN: ld.lld -shared %t.o %t1.o -o %t.so
@@ -19,12 +20,12 @@
# RUN: llvm-objdump --section .data.rel.ro --full-contents %t.ie | FileCheck --check-prefix=IE-DATA %s
# GD-REL: Relocation section '.rela.dyn' at offset {{.*}} contains 6 entries:
-# GD-REL: 0000000000002570 0000000200000036 R_390_TLS_DTPMOD 0000000000000008 a + 0
-# GD-REL-NEXT: 0000000000002578 0000000200000037 R_390_TLS_DTPOFF 0000000000000008 a + 0
-# GD-REL-NEXT: 0000000000002580 0000000300000036 R_390_TLS_DTPMOD 000000000000000c b + 0
-# GD-REL-NEXT: 0000000000002588 0000000300000037 R_390_TLS_DTPOFF 000000000000000c b + 0
-# GD-REL-NEXT: 0000000000002590 0000000400000036 R_390_TLS_DTPMOD 0000000000000010 c + 0
-# GD-REL-NEXT: 0000000000002598 0000000400000037 R_390_TLS_DTPOFF 0000000000000010 c + 0
+# GD-REL: 0000000000002570 {{.*}} R_390_TLS_DTPMOD 0000000000000008 a + 0
+# GD-REL-NEXT: 0000000000002578 {{.*}} R_390_TLS_DTPOFF 0000000000000008 a + 0
+# GD-REL-NEXT: 0000000000002580 {{.*}} R_390_TLS_DTPMOD 000000000000000c b + 0
+# GD-REL-NEXT: 0000000000002588 {{.*}} R_390_TLS_DTPOFF 000000000000000c b + 0
+# GD-REL-NEXT: 0000000000002590 {{.*}} R_390_TLS_DTPMOD 0000000000000010 c + 0
+# GD-REL-NEXT: 0000000000002598 {{.*}} R_390_TLS_DTPOFF 0000000000000010 c + 0
## _GLOBAL_OFFSET_TABLE is at 0x2558
# GD: larl %r12, 0x2558
@@ -80,33 +81,36 @@
# IE-REL: Relocation section '.rela.dyn' at offset {{.*}} contains 2 entries:
-# IE-REL: 0000000001002430 0000000200000038 R_390_TLS_TPOFF 0000000000000000 b + 0
-# IE-REL-NEXT: 0000000001002438 0000000300000038 R_390_TLS_TPOFF 0000000000000000 c + 0
+# IE-REL: 0000000001002500 {{.*}} R_390_TLS_TPOFF 0000000000000000 b + 0
+# IE-REL-NEXT: 0000000001002508 {{.*}} R_390_TLS_TPOFF 0000000000000000 c + 0
+## Benign false dependency on __tls_get_offset
+# IE-REL: Relocation section '.rela.plt' at offset {{.*}} contains 1
+# IE-REL: R_390_JMP_SLOT 0000000000000000 __tls_get_offset
-## _GLOBAL_OFFSET_TABLE is at 0x1002418
-# IE: larl %r12, 0x1002418
+## _GLOBAL_OFFSET_TABLE
+# IE: larl %r12, 0x10024e8
-## TP offset of a is at 0x1002340
-# IE-NEXT: lgrl %r2, 0x1002340
+## TP offset of a
+# IE-NEXT: lgrl %r2, 0x10023d0
# IE-NEXT: jgnop
# IE-NEXT: lgf %r2, 0(%r2,%r7)
-## GOT offset of the TP offset for b is at 0x1002348
-# IE-NEXT: lgrl %r2, 0x1002348
+## GOT offset of the TP offset for b
+# IE-NEXT: lgrl %r2, 0x10023d8
# IE-NEXT: lg %r2, 0(%r2,%r12)
# IE-NEXT: lgf %r2, 0(%r2,%r7)
-## GOT offset of the TP offset for c is at 0x1002350
-# IE-NEXT: lgrl %r2, 0x1002350
+## GOT offset of the TP offset for c
+# IE-NEXT: lgrl %r2, 0x10023e0
# IE-NEXT: lg %r2, 0(%r2,%r12)
# IE-NEXT: lgf %r2, 0(%r2,%r7)
## TP offsets (a) / GOT offset of TP offsets (b, c)
# a: -4
-# b: 0x1002430 / 0x18
-# c: 0x1002438 / 0x20
-# IE-DATA: 1002340 ffffffff fffffffc 00000000 00000018
-# IE-DATA-NEXT: 1002350 00000000 00000020
+# b: 0x10023d0 / 0x18
+# c: 0x10023e0 / 0x20
+# IE-DATA: 10023d0 ffffffff fffffffc 00000000 00000018
+# IE-DATA-NEXT: 10023e0 00000000 00000020
ear %r7,%a0
diff --git a/lld/test/ELF/systemz-tls-ld.s b/lld/test/ELF/systemz-tls-ld.s
index ef104b82644ce..fc96f3a558a1f 100644
--- a/lld/test/ELF/systemz-tls-ld.s
+++ b/lld/test/ELF/systemz-tls-ld.s
@@ -91,6 +91,9 @@ lgf %r1,0(%r1,%r2)
lgrl %r1, .LC3
lgf %r1,0(%r1,%r2)
+.globl __tls_get_offset
+__tls_get_offset:
+
.section .data.rel.ro,"aw"
.align 8
.LC0:
``````````
</details>
https://github.com/llvm/llvm-project/pull/149640
More information about the llvm-commits
mailing list