Page MenuHomePhabricator

0001-Add-GD-to-IE-TLS-relax-optimization.patch

Authored By
zatrazz
Mar 17 2016, 12:15 PM
Size
6 KB
Subscribers
None

0001-Add-GD-to-IE-TLS-relax-optimization.patch

From 72f761d2feea47f18859f2556bfe66aec0ee8766 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed, 9 Mar 2016 03:52:14 +0000
Subject: [PATCH] Add GD to IE TLS relax optimization
This patch add the TLS Global-Dynamic to Initial-Exec TLS optimization
for AArch64. Similar of GD to LE, the idea is to optimize TLS access
to global symbols that can preempted by emitting a GOT entry and
a dynamic relocation (R_AARCH64_TLS_TPREL64).
---
ELF/Target.cpp | 65 ++++++++++++++++++++++++++++++++++++----
test/ELF/Inputs/aarch64-tls-ie.s | 2 --
test/ELF/aarch64-tls-gdie.s | 30 +++++++++++++++++++
3 files changed, 90 insertions(+), 7 deletions(-)
create mode 100644 test/ELF/aarch64-tls-gdie.s
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index c968cbe..a5fbfa3 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -190,6 +190,8 @@ public:
private:
void relocateTlsGdToLe(uint32_t Type, uint8_t *Loc, uint8_t *BufEnd,
uint64_t P, uint64_t SA) const;
+ void relocateTlsGdToIe(uint32_t Type, uint8_t *Loc, uint8_t *BufEnd,
+ uint64_t P, uint64_t SA) const;
void relocateTlsIeToLe(uint32_t Type, uint8_t *Loc, uint8_t *BufEnd,
uint64_t P, uint64_t SA) const;
@@ -1318,6 +1320,15 @@ bool AArch64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
}
}
+bool AArch64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
+ if (Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC ||
+ Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
+ return true;
+ if (isTlsDescRel(Type, S))
+ return S.isPreemptible();
+ return refersToGotEntry(Type) || needsPlt<ELF64LE>(Type, S);
+}
+
bool AArch64TargetInfo::needsPltImpl(uint32_t Type) const {
switch (Type) {
default:
@@ -1462,13 +1473,12 @@ size_t AArch64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
case R_AARCH64_TLSDESC_ADR_PAGE21:
case R_AARCH64_TLSDESC_LD64_LO12_NC:
case R_AARCH64_TLSDESC_ADD_LO12_NC:
- case R_AARCH64_TLSDESC_CALL: {
+ case R_AARCH64_TLSDESC_CALL:
if (S.isPreemptible())
- fatal("unsupported TLS optimization");
- uint64_t X = S.getVA<ELF64LE>();
- relocateTlsGdToLe(Type, Loc, BufEnd, P, X);
+ relocateTlsGdToIe(Type, Loc, BufEnd, P, SA);
+ else
+ relocateTlsGdToLe(Type, Loc, BufEnd, P, SA);
return 0;
- }
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
relocateTlsIeToLe(Type, Loc, BufEnd, P, S.getVA<ELF64LE>());
@@ -1518,6 +1528,51 @@ void AArch64TargetInfo::relocateTlsGdToLe(uint32_t Type, uint8_t *Loc,
write32le(Loc, NewInst);
}
+// Global-Dynamic relocations can be relaxed to Initial-Exec if both binary is
+// an executable and target is not final (can be preempted).
+void AArch64TargetInfo::relocateTlsGdToIe(uint32_t Type, uint8_t *Loc,
+ uint8_t *BufEnd, uint64_t P,
+ uint64_t SA) const {
+ // TLSDESC Global-Dynamic relocation are in the form:
+ // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]
+ // ldr x1, [x0, #:tlsdesc_lo12:v] [R_AARCH64_TLSDESC_LD64_LO12_NC]
+ // add x0, x0, :tlsdesc_los:v [R_AARCH64_TLSDESC_ADD_LO12_NC]
+ // .tlsdesccall [R_AARCH64_TLSDESC_CALL]
+ // And it can optimized to:
+ // adrp x0, :tlsie:v
+ // ldr x0, [x0, :tlsie_lo12:v]
+ // nop
+ // nop
+
+ // For Initial-Exec from Global-Dynamic TLS relax the idea is to emit
+ // a R_AARCH64_TLS_TPREL64 dynamic relocation and thus adjust the
+ // tlsdesc call to access the GOT slot adjusted by dynamic linker.
+ checkUInt<32>(SA, Type);
+
+ switch (Type) {
+ case R_AARCH64_TLSDESC_ADD_LO12_NC:
+ case R_AARCH64_TLSDESC_CALL:
+ // nop
+ write32le(Loc, 0xD503201F);
+ break;
+ case R_AARCH64_TLSDESC_ADR_PAGE21: {
+ // adrp
+ uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
+ updateAArch64Addr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
+ return;
+ }
+ case R_AARCH64_TLSDESC_LD64_LO12_NC: {
+ // ldr with target register being 'x0'
+ uint32_t NewInst = read32le(Loc) & 0xFFFFFFE0;
+ NewInst |= (SA & 0xFF8) << 7;
+ write32le(Loc, NewInst);
+ break;
+ }
+ default:
+ llvm_unreachable("Unsupported relocation for TLS GD to IE relaxation");
+ }
+}
+
// Initial-Exec relocations can be relaxed to Local-Exec if symbol is final
// (can not be preempted).
void AArch64TargetInfo::relocateTlsIeToLe(uint32_t Type, uint8_t *Loc,
diff --git a/test/ELF/Inputs/aarch64-tls-ie.s b/test/ELF/Inputs/aarch64-tls-ie.s
index c5e853b..969bb59 100644
--- a/test/ELF/Inputs/aarch64-tls-ie.s
+++ b/test/ELF/Inputs/aarch64-tls-ie.s
@@ -1,4 +1,3 @@
-.text
.global foo
.section .tdata,"awT",%progbits
.align 2
@@ -8,7 +7,6 @@ foo:
.word 5
.text
-.text
.global bar
.section .tdata,"awT",%progbits
.align 2
diff --git a/test/ELF/aarch64-tls-gdie.s b/test/ELF/aarch64-tls-gdie.s
new file mode 100644
index 0000000..d6e0e0f
--- /dev/null
+++ b/test/ELF/aarch64-tls-gdie.s
@@ -0,0 +1,30 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o
+# RUN: ld.lld -shared %ttlsie.o -o %t.so
+# RUN: ld.lld %tmain.o -o %tout %t.so
+# RUN: llvm-objdump -d %tout | FileCheck %s
+# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
+
+# Global-Dynamic to Initial-Exec relax creates a R_AARCH64_TPREL64
+# RELOC: Relocations [
+# RELOC-NEXT: Section ({{.*}}) .rela.dyn {
+# RELOC-NEXT: {{.*}} R_AARCH64_TLS_TPREL64 foo 0x0
+# RELOC-NEXT: }
+# RELOC-NEXT: ]
+
+# CHECK: Disassembly of section .text:
+# CHECK: _start:
+# CHECK: 11000: 00 00 00 b0 adrp x0, #4096
+# CHECK: 11004: 00 58 40 f9 ldr x0, [x0, #176]
+# CHECK: 11008: 1f 20 03 d5 nop
+# CHECK: 1100c: 1f 20 03 d5 nop
+
+.text
+.globl _start
+_start:
+ adrp x0, :tlsdesc:foo
+ ldr x1, [x0, :tlsdesc_lo12:foo]
+ add x0, x0, :tlsdesc_lo12:foo
+ .tlsdesccall foo
+ blr x1
--
1.9.1

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1444923

Event Timeline