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-le-relax.s b/lld/test/ELF/ppc64-tls-le-relax.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc64-tls-le-relax.s @@ -0,0 +1,81 @@ +# REQUIRES: ppc +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/initexec -o %t/initexec.o +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/defs -o %t/defs.o +# RUN: ld.lld %t/initexec.o %t/defs.o -o %t/out +# RUN: llvm-objdump -d --mcpu=pwr10 --no-show-raw-insn %t/out | FileCheck %s + +# CHECK-LABEL: : +# CHECK: mflr 0 +# CHECK-NEXT: std 30, -16(1) +# CHECK-NEXT: std 0, 16(1) +# CHECK-NEXT: stdu 1, -48(1) +# CHECK-NEXT: paddi 3, 13, -28672, 0 +# CHECK-NEXT: mr 30, 3 +# CHECK-NEXT: mr 3, 30 +# CHECK-NEXT: bl +# CHECK-NEXT: mr 4, 30 +# CHECK-NEXT: addi 1, 1, 48 +# CHECK-NEXT: ld 0, 16(1) +# CHECK-NEXT: ld 30, -16(1) +# CHECK-NEXT: mtlr 0 +# CHECK-NEXT: b + +## Generated From: +## extern __thread unsigned TGlobal; +## unsigned getConst(unsigned*); +## unsigned addVal(unsigned, unsigned*); +## +## unsigned GetAddrT() { +## return addVal(getConst(&TGlobal), &TGlobal); +## } + +//--- initexec +GetAddrT: + mflr 0 + std 30, -16(1) + std 0, 16(1) + stdu 1, -48(1) + pld 3, TGlobal@got@tprel@pcrel(0), 1 + add 30, 3, TGlobal@tls@pcrel + mr 3, 30 + bl getConst@notoc + mr 4, 30 + addi 1, 1, 48 + ld 0, 16(1) + ld 30, -16(1) + mtlr 0 + b addVal@notoc + +## Generated From: +## __thread unsigned TGlobal; +## +## unsigned getConst(unsigned* A) { +## return *A + 3; +## } +## +## unsigned addVal(unsigned A, unsigned* B) { +## return A + *B; +## } + +//--- defs +.globl getConst +getConst: + lwz 3, 0(3) + addi 3, 3, 3 + clrldi 3, 3, 32 + blr + +.globl addVal +addVal: + lwz 4, 0(4) + add 3, 4, 3 + clrldi 3, 3, 32 + blr + +.section .tbss,"awT",@nobits +.globl TGlobal +.p2align 2 +TGlobal: + .long 0 + .size TGlobal, 4 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