diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index c2f91ce8e6b96..80b187eaf6062 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -3235,7 +3235,8 @@ def PPC32GOT: PPCEmitTimePseudo<(outs gprc:$rD), (ins), "#PPC32GOT", // Get the _GLOBAL_OFFSET_TABLE_ in PIC mode. // This uses two output registers, the first as the real output, the second as a -// temporary register, used internally in code generation. +// temporary register, used internally in code generation. A "bl" also clobbers LR. +let Defs = [LR] in def PPC32PICGOT: PPCEmitTimePseudo<(outs gprc:$rD, gprc:$rT), (ins), "#PPC32PICGOT", []>, NoEncode<"$rT">; diff --git a/llvm/test/CodeGen/PowerPC/tls-picgot.ll b/llvm/test/CodeGen/PowerPC/tls-picgot.ll new file mode 100644 index 0000000000000..6562d864d1ba7 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/tls-picgot.ll @@ -0,0 +1,31 @@ +; RUN: llc -verify-machineinstrs -relocation-model=pic < %s | FileCheck %s + +target triple = "powerpc-unknown-linux-gnu" + +; Test that LR is preserved when PPC32PICGOT clobbers it with a local "bl". + +@TLS = external thread_local global i8 + +; CHECK-LABEL: tls_addr: +; CHECK: mflr [[SAVED_REG:[0-9]+]] + +; CHECK: bl [[JUMP:\.L[[:alnum:]_]+]] +; CHECK-NEXT: [[OFFSET:\.L[[:alnum:]_]+]]: +; CHECK-NEXT: .long _GLOBAL_OFFSET_TABLE_-[[OFFSET]] +; CHECK-NEXT: [[JUMP]] +; CHECK-NEXT: mflr {{[0-9]+}} + +; CHECK: mtlr [[SAVED_REG]] +; CHECK-NEXT: blr + +define ptr @tls_addr() unnamed_addr { + %1 = call ptr @llvm.threadlocal.address.p0(ptr @TLS) + ret ptr %1 +} + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 8, !"PIC Level", i32 2} +!1 = !{i32 7, !"PIE Level", i32 2}