[lld] r336559 - [PPC64] Add TLS local dynamic to local exec relaxation

Zaara Syeda via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 9 09:35:51 PDT 2018


Author: syzaara
Date: Mon Jul  9 09:35:51 2018
New Revision: 336559

URL: http://llvm.org/viewvc/llvm-project?rev=336559&view=rev
Log:
[PPC64] Add TLS local dynamic to local exec relaxation

This patch adds the target call back relaxTlsLdToLe to support TLS relaxation
from local dynamic to local exec model.

Differential Revision: https://reviews.llvm.org/D48293

Added:
    lld/trunk/test/ELF/ppc64-tls-ld-le.s
Modified:
    lld/trunk/ELF/Arch/PPC64.cpp
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h

Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=336559&r1=336558&r2=336559&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Mon Jul  9 09:35:51 2018
@@ -55,6 +55,7 @@ public:
                           RelExpr Expr) const override;
   void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
   void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+  void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
 };
 } // namespace
 
@@ -165,6 +166,52 @@ void PPC64::relaxTlsGdToLe(uint8_t *Loc,
   }
 }
 
+
+void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
+  // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement.
+  // The local dynamic code sequence for a global `x` will look like:
+  // Instruction                    Relocation                Symbol
+  // addis r3, r2, x at got@tlsld at ha   R_PPC64_GOT_TLSLD16_HA      x
+  // addi  r3, r3, x at got@tlsld at l    R_PPC64_GOT_TLSLD16_LO      x
+  // bl __tls_get_addr(x at tlsgd)     R_PPC64_TLSLD               x
+  //                                R_PPC64_REL24               __tls_get_addr
+  // nop                            None                       None
+
+  // Relaxing to local exec entails converting:
+  // addis r3, r2, x at got@tlsld at ha   into      nop
+  // addi  r3, r3, x at got@tlsld at l    into      addis r3, r13, 0
+  // bl __tls_get_addr(x at tlsgd)     into      nop
+  // nop                            into      addi r3, r3, 4096
+
+  uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
+  switch (Type) {
+  case R_PPC64_GOT_TLSLD16_HA:
+    write32(Loc - EndianOffset, 0x60000000); // nop
+    break;
+  case R_PPC64_GOT_TLSLD16_LO:
+    write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13, 0
+    break;
+  case R_PPC64_TLSLD:
+    write32(Loc, 0x60000000);     // nop
+    write32(Loc + 4, 0x38631000); // addi r3, r3, 4096
+    break;
+  case R_PPC64_DTPREL16:
+  case R_PPC64_DTPREL16_HA:
+  case R_PPC64_DTPREL16_HI:
+  case R_PPC64_DTPREL16_DS:
+  case R_PPC64_DTPREL16_LO:
+  case R_PPC64_DTPREL16_LO_DS:
+  case R_PPC64_GOT_DTPREL16_HA:
+  case R_PPC64_GOT_DTPREL16_LO_DS:
+  case R_PPC64_GOT_DTPREL16_DS:
+  case R_PPC64_GOT_DTPREL16_HI:
+    relocateOne(Loc, Type, Val);
+    break;
+  default:
+    llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
+  }
+}
+
 RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
                           const uint8_t *Loc) const {
   switch (Type) {
@@ -230,6 +277,7 @@ RelExpr PPC64::getRelExpr(RelType Type,
   case R_PPC64_TLSGD:
     return R_TLSDESC_CALL;
   case R_PPC64_TLSLD:
+    return R_TLSLD_HINT;
   case R_PPC64_TLS:
     return R_HINT;
   default:
@@ -431,6 +479,8 @@ RelExpr PPC64::adjustRelaxExpr(RelType T
                                RelExpr Expr) const {
   if (Expr == R_RELAX_TLS_GD_TO_IE)
     return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
+  if (Expr == R_RELAX_TLS_LD_TO_LE)
+    return R_RELAX_TLS_LD_TO_LE_ABS;
   return Expr;
 }
 

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=336559&r1=336558&r2=336559&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon Jul  9 09:35:51 2018
@@ -483,6 +483,7 @@ static uint64_t getRelocTargetVA(const I
   case R_INVALID:
     return 0;
   case R_ABS:
+  case R_RELAX_TLS_LD_TO_LE_ABS:
   case R_RELAX_GOT_PC_NOPIC:
     return Sym.getVA(A);
   case R_ADDEND:
@@ -516,6 +517,7 @@ static uint64_t getRelocTargetVA(const I
   case R_HINT:
   case R_NONE:
   case R_TLSDESC_CALL:
+  case R_TLSLD_HINT:
     llvm_unreachable("cannot relocate hint relocs");
   case R_MIPS_GOTREL:
     return Sym.getVA(A) - InX::MipsGot->getGp(File);
@@ -767,6 +769,7 @@ void InputSectionBase::relocateAlloc(uin
       Target->relaxTlsIeToLe(BufLoc, Type, TargetVA);
       break;
     case R_RELAX_TLS_LD_TO_LE:
+    case R_RELAX_TLS_LD_TO_LE_ABS:
       Target->relaxTlsLdToLe(BufLoc, Type, TargetVA);
       break;
     case R_RELAX_TLS_GD_TO_LE:

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=336559&r1=336558&r2=336559&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Mon Jul  9 09:35:51 2018
@@ -188,13 +188,17 @@ handleTlsRelocation(RelType Type, Symbol
     return 1;
   }
 
-  if (isRelExprOneOf<R_TLSLD_GOT, R_TLSLD_GOT_FROM_END, R_TLSLD_PC>(Expr)) {
+  if (isRelExprOneOf<R_TLSLD_GOT, R_TLSLD_GOT_FROM_END, R_TLSLD_PC,
+                     R_TLSLD_HINT>(Expr)) {
     // Local-Dynamic relocs can be relaxed to Local-Exec.
     if (!Config->Shared) {
       C.Relocations.push_back(
-          {R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
-      return 2;
+          {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,
+           Offset, Addend, &Sym});
+      return Target->TlsGdRelaxSkip;
     }
+    if (Expr == R_TLSLD_HINT)
+      return 1;
     if (InX::Got->addTlsIndex())
       InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, InX::Got,
                              InX::Got->getTlsIndexOff(), nullptr);
@@ -203,9 +207,10 @@ handleTlsRelocation(RelType Type, Symbol
   }
 
   // Local-Dynamic relocs can be relaxed to Local-Exec.
-  if (isRelExprOneOf<R_ABS, R_TLSLD_GOT_FROM_END, R_TLSLD_PC>(Expr) &&
-      !Config->Shared) {
-    C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
+  if (Expr == R_ABS && !Config->Shared) {
+    C.Relocations.push_back(
+        {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,
+         Offset, Addend, &Sym});
     return 1;
   }
 
@@ -357,8 +362,8 @@ static bool isStaticLinkTimeConstant(Rel
           R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
           R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
           R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOT_FROM_END,
-          R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(
-          E))
+          R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT,
+          R_TLSLD_HINT>(E))
     return true;
 
   // These never do, except if the entire file is position dependent or if

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=336559&r1=336558&r2=336559&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Mon Jul  9 09:35:51 2018
@@ -73,6 +73,7 @@ enum RelExpr {
   R_RELAX_TLS_GD_TO_LE_NEG,
   R_RELAX_TLS_IE_TO_LE,
   R_RELAX_TLS_LD_TO_LE,
+  R_RELAX_TLS_LD_TO_LE_ABS,
   R_SIZE,
   R_TLS,
   R_TLSDESC,
@@ -84,6 +85,7 @@ enum RelExpr {
   R_TLSLD_GOT,
   R_TLSLD_GOT_FROM_END,
   R_TLSLD_GOT_OFF,
+  R_TLSLD_HINT,
   R_TLSLD_PC,
 };
 

Added: lld/trunk/test/ELF/ppc64-tls-ld-le.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-tls-ld-le.s?rev=336559&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-tls-ld-le.s (added)
+++ lld/trunk/test/ELF/ppc64-tls-ld-le.s Mon Jul  9 09:35:51 2018
@@ -0,0 +1,84 @@
+// REQUIRES: ppc
+
+// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
+// RUN: ld.lld  %t.o -o %t
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
+// RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s
+
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
+// RUN: ld.lld  %t.o -o %t
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
+// RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s
+
+	.text
+	.abiversion 2
+	.globl	_start                    # -- Begin function _start
+	.p2align	4
+	.type	_start, at function
+_start:                                   # @_start
+.Lfunc_begin0:
+.Lfunc_gep0:
+	addis 2, 12, .TOC.-.Lfunc_gep0 at ha
+	addi 2, 2, .TOC.-.Lfunc_gep0 at l
+.Lfunc_lep0:
+	.localentry	_start, .Lfunc_lep0-.Lfunc_gep0
+# %bb.0:                                # %entry
+	mflr 0
+	std 31, -8(1)
+	std 0, 16(1)
+	stdu 1, -64(1)
+	mr 31, 1
+	std 30, 48(31)                  # 8-byte Folded Spill
+	li 3, 0
+	stw 3, 44(31)
+	addis 3, 2, a at got@tlsld at ha
+	addi 3, 3, a at got@tlsld at l
+	bl __tls_get_addr(a at tlsld)
+	nop
+	addis 3, 3, a at dtprel@ha
+	addi 3, 3, a at dtprel@l
+	lwz 30, 0(3)
+	extsw 3, 30
+	ld 30, 48(31)                   # 8-byte Folded Reload
+	addi 1, 1, 64
+	ld 0, 16(1)
+	ld 31, -8(1)
+	mtlr 0
+	blr
+	.long	0
+	.quad	0
+.Lfunc_end0:
+	.size	_start, .Lfunc_end0-.Lfunc_begin0
+                                        # -- End function
+.globl __tls_get_addr
+.type __tls_get_addr, at function
+__tls_get_addr:
+	.type	a, at object               # @a
+	.section	.tdata,"awT", at progbits
+	.p2align	2
+a:
+	.long	2                       # 0x2
+	.size	a, 4
+
+// Verify that the input has local-dynamic tls relocation types
+// InputRelocs:  Relocation section '.rela.text'
+// InputRelocs: R_PPC64_GOT_TLSLD16_HA  {{0+}}  a + 0
+// InputRelocs: R_PPC64_GOT_TLSLD16_LO  {{0+}}  a + 0
+// InputRelocs: R_PPC64_TLSLD           {{0+}}  a + 0
+
+// Verify that the local-dynamic sequence is relaxed to local exec.
+// Dis: _start:
+// Dis: nop
+// Dis: addis 3, 13, 0
+// Dis: nop
+// Dis: addi 3, 3, 4096
+
+// #ha(a at dtprel) --> (0x0 -0x8000 + 0x8000) >> 16 = 0
+// #lo(a at dtprel) --> (0x0 -0x8000) = -0x8000 = -32768
+// Dis: addis 3, 3, 0
+// Dis: addi 3, 3, -32768
+
+// Verify that no local-dynamic relocations exist for the dynamic linker.
+// OutputRelocs-NOT: R_PPC64_DTPMOD64




More information about the llvm-commits mailing list