From 9a23f96e919ba91587d077b1d399246dde4002dd Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 30 Aug 2017 20:35:35 +0930 Subject: PowerPC TPREL16_HA/LO reloc optimization In the TLS GD/LD to LE optimization, ld replaces a sequence like addi 3,2,x@got@tlsgd R_PPC64_GOT_TLSGD16 x bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x R_PPC64_REL24 __tls_get_addr nop with addis 3,13,x@tprel@ha R_PPC64_TPREL16_HA x addi 3,3,x@tprel@l R_PPC64_TPREL16_LO x nop When the tprel offset is small, this can be further optimized to nop addi 3,13,x@tprel nop bfd/ * elf64-ppc.c (struct ppc_link_hash_table): Add do_tls_opt. (ppc64_elf_tls_optimize): Set it. (ppc64_elf_relocate_section): Nop addis on TPREL16_HA, and convert insn on TPREL16_LO and TPREL16_LO_DS relocs to use r13 when addis would add zero. * elf32-ppc.c (struct ppc_elf_link_hash_table): Add do_tls_opt. (ppc_elf_tls_optimize): Set it. (ppc_elf_relocate_section): Nop addis on TPREL16_HA, and convert insn on TPREL16_LO relocs to use r2 when addis would add zero. gold/ * powerpc.cc (Target_powerpc::Relocate::relocate): Nop addis on TPREL16_HA, and convert insn on TPREL16_LO and TPREL16_LO_DS relocs to use r2/r13 when addis would add zero. ld/ * testsuite/ld-powerpc/tls.s: Add calls with tls markers. * testsuite/ld-powerpc/tls32.s: Likewise. * testsuite/ld-powerpc/powerpc.exp: Run tls marker tests. * testsuite/ld-powerpc/tls.d: Adjust for TPREL16_HA/LO optimization. * testsuite/ld-powerpc/tlsexe.d: Likewise. * testsuite/ld-powerpc/tlsexetoc.d: Likewise. * testsuite/ld-powerpc/tlsld.d: Likewise. * testsuite/ld-powerpc/tlsmark.d: Likewise. * testsuite/ld-powerpc/tlsopt4.d: Likewise. * testsuite/ld-powerpc/tlstoc.d: Likewise. --- gold/ChangeLog | 6 ++++++ gold/powerpc.cc | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) (limited to 'gold') diff --git a/gold/ChangeLog b/gold/ChangeLog index 9359493..2343215 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,9 @@ +2017-08-30 Alan Modra + + * powerpc.cc (Target_powerpc::Relocate::relocate): Nop addis on + TPREL16_HA, and convert insn on TPREL16_LO and TPREL16_LO_DS + relocs to use r2/r13 when addis would add zero. + 2017-08-29 Alan Modra * options.h (tls_get_addr_optimize): New option. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 7f3f025..ff116e3 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -8974,6 +8974,38 @@ Target_powerpc::Relocate::relocate( } break; + case elfcpp::R_POWERPC_TPREL16_HA: + if (parameters->options().tls_optimize() && value + 0x8000 < 0x10000) + { + Insn* iview = reinterpret_cast(view - d_offset); + Insn insn = elfcpp::Swap<32, big_endian>::readval(iview); + if ((insn & ((0x3f << 26) | 0x1f << 16)) + != ((15u << 26) | ((size == 32 ? 2 : 13) << 16))) + ; + else + { + elfcpp::Swap<32, big_endian>::writeval(iview, nop); + return true; + } + } + break; + + case elfcpp::R_PPC64_TPREL16_LO_DS: + if (size == 32) + // R_PPC_TLSGD, R_PPC_TLSLD + break; + // Fall through. + case elfcpp::R_POWERPC_TPREL16_LO: + if (parameters->options().tls_optimize() && value + 0x8000 < 0x10000) + { + Insn* iview = reinterpret_cast(view - d_offset); + Insn insn = elfcpp::Swap<32, big_endian>::readval(iview); + insn &= ~(0x1f << 16); + insn |= (size == 32 ? 2 : 13) << 16; + elfcpp::Swap<32, big_endian>::writeval(iview, insn); + } + break; + case elfcpp::R_PPC64_ENTRY: value = (target->got_section()->output_section()->address() + object->toc_base_offset()); -- cgit v1.1