diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -920,7 +920,15 @@ // that comes before it will already have computed the address of the // symbol. if (secondaryOp == 266) { - write32(loc - 1, NOP); + // Check if the add uses the same result register as the input register. + uint32_t RT = (tlsInstr & 0x03E00000) >> 21; // bits 6-10 + uint32_t RA = (tlsInstr & 0x001F0000) >> 16; // bits 11-15 + if (RA == RT) + write32(loc - 1, NOP); + else { + // mr RT, RA + write32(loc - 1, 0x7C000378 | (RT << 16) | (RA << 21) | (RA << 11)); + } } else { uint32_t dFormOp = getPPCDFormOp(secondaryOp); if (dFormOp == 0) diff --git a/lld/test/ELF/ppc64-tls-pcrel-ie.s b/lld/test/ELF/ppc64-tls-pcrel-ie.s --- a/lld/test/ELF/ppc64-tls-pcrel-ie.s +++ b/lld/test/ELF/ppc64-tls-pcrel-ie.s @@ -54,9 +54,9 @@ # LE-RELOC: There are no relocations in this file. -# LE-SYM: Symbol table '.symtab' contains 7 entries: -# LE-SYM: 5: 0000000000000000 0 TLS GLOBAL DEFAULT 6 x -# LE-SYM: 6: 0000000000000004 0 TLS GLOBAL DEFAULT 6 y +# LE-SYM: Symbol table '.symtab' contains 8 entries: +# LE-SYM: 6: 0000000000000000 0 TLS GLOBAL DEFAULT 6 x +# LE-SYM: 7: 0000000000000004 0 TLS GLOBAL DEFAULT 6 y # LE-GOT: could not find section '.got' @@ -74,6 +74,20 @@ add 3, 3, x@tls@pcrel blr +# IE-LABEL: : +# IE-NEXT: pld 3, 12488(0), 1 +# IE-NEXT: add 4, 3, 13 +# IE-NEXT: blr +# LE-LABEL: : +# LE-NEXT: paddi 3, 13, -28672, 0 +# LE-NEXT: mr 4, 3 +# LE-NEXT: blr +.section .text_addr, "ax", %progbits +IEAddrCopy: + pld 3, x@got@tprel@pcrel(0), 1 + add 4, 3, x@tls@pcrel + blr + # IE-LABEL: : # IE-NEXT: pld 3, 8408(0), 1 # IE-NEXT: lwzx 3, 3, 13