diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def @@ -101,7 +101,9 @@ #undef R_PPC64_PCREL34 #undef R_PPC64_GOT_PCREL34 #undef R_PPC64_TPREL34 +#undef R_PPC64_DTPREL34 #undef R_PPC64_GOT_TLSGD_PCREL34 +#undef R_PPC64_GOT_TLSLD_PCREL34 #undef R_PPC64_GOT_TPREL_PCREL34 #undef R_PPC64_IRELATIVE #undef R_PPC64_REL16 @@ -202,7 +204,9 @@ ELF_RELOC(R_PPC64_PCREL34, 132) ELF_RELOC(R_PPC64_GOT_PCREL34, 133) ELF_RELOC(R_PPC64_TPREL34, 146) +ELF_RELOC(R_PPC64_DTPREL34, 147) ELF_RELOC(R_PPC64_GOT_TLSGD_PCREL34, 148) +ELF_RELOC(R_PPC64_GOT_TLSLD_PCREL34, 149) ELF_RELOC(R_PPC64_GOT_TPREL_PCREL34, 150) ELF_RELOC(R_PPC64_IRELATIVE, 248) ELF_RELOC(R_PPC64_REL16, 249) diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -300,6 +300,7 @@ VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_GOT_PCREL, // symbol@got@pcrel VK_PPC_GOT_TLSGD_PCREL, // symbol@got@tlsgd@pcrel + VK_PPC_GOT_TLSLD_PCREL, // symbol@got@tlsld@pcrel VK_PPC_GOT_TPREL_PCREL, // symbol@got@tprel@pcrel VK_PPC_TLS_PCREL, // symbol@tls@pcrel VK_PPC_TLSLD, // symbol@tlsld diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -324,6 +324,8 @@ return "got@pcrel"; case VK_PPC_GOT_TLSGD_PCREL: return "got@tlsgd@pcrel"; + case VK_PPC_GOT_TLSLD_PCREL: + return "got@tlsld@pcrel"; case VK_PPC_GOT_TPREL_PCREL: return "got@tprel@pcrel"; case VK_PPC_TLS_PCREL: @@ -461,6 +463,7 @@ .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) .Case("got@pcrel", VK_PPC_GOT_PCREL) .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL) + .Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL) .Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL) .Case("tls@pcrel", VK_PPC_TLS_PCREL) .Case("notoc", VK_PPC_NOTOC) diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -141,6 +141,9 @@ case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL: Type = ELF::R_PPC64_GOT_TLSGD_PCREL34; break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL: + Type = ELF::R_PPC64_GOT_TLSLD_PCREL34; + break; case MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL: Type = ELF::R_PPC64_GOT_TPREL_PCREL34; break; @@ -422,6 +425,9 @@ switch (Modifier) { default: report_fatal_error("Unsupported Modifier for fixup_ppc_imm34."); + case MCSymbolRefExpr::VK_DTPREL: + Type = ELF::R_PPC64_DTPREL34; + break; case MCSymbolRefExpr::VK_TPREL: Type = ELF::R_PPC64_TPREL34; break; diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -233,9 +233,11 @@ assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL || SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL || SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL || + SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL || SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL) && "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or " - "VK_PPC_GOT_TLSGD_PCREL or VK_PPC_GOT_TPREL_PCREL"); + "VK_PPC_GOT_TLSGD_PCREL or VK_PPC_GOT_TLSLD_PCREL or " + "VK_PPC_GOT_TPREL_PCREL."); // Generate the fixup for the relocation. Fixups.push_back( MCFixup::create(0, Expr, diff --git a/llvm/lib/Target/PowerPC/PPC.h b/llvm/lib/Target/PowerPC/PPC.h --- a/llvm/lib/Target/PowerPC/PPC.h +++ b/llvm/lib/Target/PowerPC/PPC.h @@ -123,11 +123,20 @@ /// TLS Initial Exec model. MO_TPREL_FLAG = 64, + /// MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to + /// TLS Local Dynamic model. + MO_TLSLD_FLAG = 128, + /// MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set /// they should produce the relocation @got@tlsgd@pcrel. /// Fix up is VK_PPC_GOT_TLSGD_PCREL MO_GOT_TLSGD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSGD_FLAG, + /// MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set + /// they should produce the relocation @got@tlsld@pcrel. + /// Fix up is VK_PPC_GOT_TLSLD_PCREL + MO_GOT_TLSLD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSLD_FLAG, + /// MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set /// they should produce the relocation @got@tprel@pcrel. /// Fix up is VK_PPC_GOT_TPREL_PCREL diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -491,7 +491,8 @@ unsigned Opcode = PPC::BL8_NOP_TLS; assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI"); - if (MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) { + if (MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG || + MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) { Kind = MCSymbolRefExpr::VK_PPC_NOTOC; Opcode = PPC::BL8_NOTOC_TLS; } @@ -1146,6 +1147,21 @@ .addExpr(SymDtprel)); return; } + case PPC::PADDIdtprel: { + // Transform: %rd = PADDIdtprel %rs, @sym + // Into: %rd = PADDI8 %rs, sym@dtprel + const MachineOperand &MO = MI->getOperand(2); + const GlobalValue *GValue = MO.getGlobal(); + MCSymbol *MOSymbol = getSymbol(GValue); + const MCExpr *SymDtprel = MCSymbolRefExpr::create( + MOSymbol, MCSymbolRefExpr::VK_DTPREL, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8) + .addReg(MI->getOperand(0).getReg()) + .addReg(MI->getOperand(1).getReg()) + .addExpr(SymDtprel)); + return; + } + case PPC::ADDIdtprelL: // Transform: %xd = ADDIdtprelL %xs, @sym // Into: %xd = ADDI8 %xs, sym@dtprel@l diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -381,6 +381,10 @@ /// sym\@got\@dtprel\@l. ADDI_DTPREL_L, + /// G8RC = PADDI_DTPREL %x3, Symbol - For the pc-rel based local-dynamic TLS + /// model, produces a PADDI8 instruction that adds X3 to sym\@dtprel. + PADDI_DTPREL, + /// VRRC = VADD_SPLAT Elt, EltSize - Temporary node to be expanded /// during instruction selection to optimize a BUILD_VECTOR into /// operations on splats. This is necessary to avoid losing these diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1499,6 +1499,8 @@ case PPCISD::ADDI_TLSLD_L_ADDR: return "PPCISD::ADDI_TLSLD_L_ADDR"; case PPCISD::ADDIS_DTPREL_HA: return "PPCISD::ADDIS_DTPREL_HA"; case PPCISD::ADDI_DTPREL_L: return "PPCISD::ADDI_DTPREL_L"; + case PPCISD::PADDI_DTPREL: + return "PPCISD::PADDI_DTPREL"; case PPCISD::VADD_SPLAT: return "PPCISD::VADD_SPLAT"; case PPCISD::SC: return "PPCISD::SC"; case PPCISD::CLRBHRB: return "PPCISD::CLRBHRB"; @@ -3098,6 +3100,14 @@ } if (Model == TLSModel::LocalDynamic) { + if (Subtarget.isUsingPCRelativeCalls()) { + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, + PPCII::MO_GOT_TLSLD_PCREL_FLAG); + SDValue MatPCRel = + DAG.getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA); + return DAG.getNode(PPCISD::PADDI_DTPREL, dl, PtrVT, MatPCRel, TGA); + } + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0); SDValue GOTPtr; if (is64bit) { diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1332,6 +1332,11 @@ [(set i64:$rD, (PPCaddiDtprelL i64:$reg, tglobaltlsaddr:$disp))]>, isPPC64; +def PADDIdtprel : PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, s16imm64:$disp), + "#PADDIdtprel", + [(set i64:$rD, + (PPCpaddiDtprel i64:$reg, tglobaltlsaddr:$disp))]>, + isPPC64; let PPC970_Unit = 2 in { let Interpretation64Bit = 1, isCodeGenOnly = 1 in { diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -2380,8 +2380,10 @@ {MO_GOT_FLAG, "ppc-got"}, {MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"}, {MO_TLSGD_FLAG, "ppc-tlsgd"}, + {MO_TLSLD_FLAG, "ppc-tlsld"}, {MO_TPREL_FLAG, "ppc-tprel"}, {MO_GOT_TLSGD_PCREL_FLAG, "ppc-got-tlsgd-pcrel"}, + {MO_GOT_TLSLD_PCREL_FLAG, "ppc-got-tlsld-pcrel"}, {MO_GOT_TPREL_PCREL_FLAG, "ppc-got-tprel-pcrel"}}; return makeArrayRef(TargetFlags); } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -222,6 +222,7 @@ SDTCisSameAs<0, 3>, SDTCisInt<0> ]>>; def PPCaddisDtprelHA : SDNode<"PPCISD::ADDIS_DTPREL_HA", SDTIntBinOp>; def PPCaddiDtprelL : SDNode<"PPCISD::ADDI_DTPREL_L", SDTIntBinOp>; +def PPCpaddiDtprel : SDNode<"PPCISD::PADDI_DTPREL", SDTIntBinOp>; def PPCvperm : SDNode<"PPCISD::VPERM", SDT_PPCvperm, []>; def PPCxxsplt : SDNode<"PPCISD::XXSPLT", SDT_PPCVecSplat, []>; diff --git a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp --- a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp +++ b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -90,6 +90,8 @@ RefKind = MCSymbolRefExpr::VK_TPREL; else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; + else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) + RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; diff --git a/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp b/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp --- a/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp +++ b/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp @@ -50,17 +50,17 @@ bool Changed = false; bool NeedFence = true; bool Is64Bit = MBB.getParent()->getSubtarget().isPPC64(); - bool IsTLSGDPCREL = false; + bool IsPCREL = false; for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end(); I != IE;) { MachineInstr &MI = *I; - IsTLSGDPCREL = isTLSGDPCREL(MI); + IsPCREL = isPCREL(MI); if (MI.getOpcode() != PPC::ADDItlsgdLADDR && MI.getOpcode() != PPC::ADDItlsldLADDR && MI.getOpcode() != PPC::ADDItlsgdLADDR32 && - MI.getOpcode() != PPC::ADDItlsldLADDR32 && !IsTLSGDPCREL) { + MI.getOpcode() != PPC::ADDItlsldLADDR32 && !IsPCREL) { // Although we create ADJCALLSTACKDOWN and ADJCALLSTACKUP // as scheduling fences, we skip creating fences if we already // have existing ADJCALLSTACKDOWN/UP to avoid nesting, @@ -80,7 +80,7 @@ Register InReg = PPC::NoRegister; Register GPR3 = Is64Bit ? PPC::X3 : PPC::R3; SmallVector OrigRegs = {OutReg, GPR3}; - if (!IsTLSGDPCREL) { + if (!IsPCREL) { InReg = MI.getOperand(1).getReg(); OrigRegs.push_back(InReg); } @@ -107,9 +107,12 @@ Opc2 = PPC::GETtlsldADDR32; break; case PPC::PADDI8pc: - assert(IsTLSGDPCREL && "Expecting General Dynamic PCRel"); + assert(IsPCREL && "Expecting General/Local Dynamic PCRel"); Opc1 = PPC::PADDI8pc; - Opc2 = PPC::GETtlsADDR; + Opc2 = MI.getOperand(2).getTargetFlags() == + PPCII::MO_GOT_TLSGD_PCREL_FLAG + ? PPC::GETtlsADDR + : PPC::GETtlsldADDR; } // We create ADJCALLSTACKUP and ADJCALLSTACKDOWN around _tls_get_addr @@ -123,7 +126,7 @@ .addImm(0); MachineInstr *Addi; - if (IsTLSGDPCREL) { + if (IsPCREL) { Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3).addImm(0); } else { // Expand into two ops built prior to the existing instruction. @@ -140,7 +143,7 @@ MachineInstr *Call = (BuildMI(MBB, I, DL, TII->get(Opc2), GPR3) .addReg(GPR3)); - if (IsTLSGDPCREL) + if (IsPCREL) Call->addOperand(MI.getOperand(2)); else Call->addOperand(MI.getOperand(3)); @@ -168,11 +171,14 @@ } public: - bool isTLSGDPCREL(const MachineInstr &MI) { + bool isPCREL(const MachineInstr &MI) { return (MI.getOpcode() == PPC::PADDI8pc) && (MI.getOperand(2).getTargetFlags() == - PPCII::MO_GOT_TLSGD_PCREL_FLAG); + PPCII::MO_GOT_TLSGD_PCREL_FLAG || + MI.getOperand(2).getTargetFlags() == + PPCII::MO_GOT_TLSLD_PCREL_FLAG); } + bool runOnMachineFunction(MachineFunction &MF) override { TII = MF.getSubtarget().getInstrInfo(); LIS = &getAnalysis(); diff --git a/llvm/test/CodeGen/PowerPC/pcrel-tls-local-dynamic.ll b/llvm/test/CodeGen/PowerPC/pcrel-tls-local-dynamic.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/pcrel-tls-local-dynamic.ll @@ -0,0 +1,55 @@ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr10 \ +; RUN: -ppc-asm-full-reg-names --relocation-model=pic -enable-ppc-pcrel-tls < %s | FileCheck %s --check-prefix=CHECK-S +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr10 \ +; RUN: -ppc-asm-full-reg-names --relocation-model=pic -enable-ppc-pcrel-tls --filetype=obj < %s | \ +; RUN: llvm-objdump --mcpu=pwr10 --no-show-raw-insn -dr - | FileCheck %s --check-prefix=CHECK-O + +; These test cases are to ensure that when using pc relative memory operations +; ABI correct code and relocations are produced for Local Dynamic TLS Model. + +@x = hidden thread_local global i32 0, align 4 + +define nonnull i32* @LocalDynamicAddressLoad() { + ; CHECK-S-LABEL: LocalDynamicAddressLoad: + ; CHECK-S: paddi r3, 0, x@got@tlsld@pcrel, 1 + ; CHECK-S-NEXT: bl __tls_get_addr@notoc(x@tlsld) + ; CHECK-S-NEXT: paddi r3, r3, x@DTPREL, 0 + ; CHECK-S-NEXT: addi r1, r1, 32 + ; CHECK-S-NEXT: ld r0, 16(r1) + ; CHECK-S-NEXT: mtlr r0 + ; CHECK-S-NEXT: blr + ; CHECK-O-LABEL: : + ; CHECK-O: c: paddi 3, 0, 0, 1 + ; CHECK-O-NEXT: 000000000000000c: R_PPC64_GOT_TLSLD_PCREL34 x + ; CHECK-O-NEXT: 14: bl 0x14 + ; CHECK-O-NEXT: 0000000000000014: R_PPC64_TLSLD x + ; CHECK-O-NEXT: 0000000000000014: R_PPC64_REL24_NOTOC __tls_get_addr + ; CHECK-O-NEXT: 18: paddi 3, 3, 0, 0 + ; CHECK-O-NEXT: 0000000000000018: R_PPC64_DTPREL34 x + entry: + ret i32* @x +} + +define i32 @LocalDynamicValueLoad() { + ; CHECK-S-LABEL: LocalDynamicValueLoad: + ; CHECK-S: paddi r3, 0, x@got@tlsld@pcrel, 1 + ; CHECK-S-NEXT: bl __tls_get_addr@notoc(x@tlsld) + ; CHECK-S-NEXT: paddi r3, r3, x@DTPREL, 0 + ; CHECK-S-NEXT: lwz r3, 0(r3) + ; CHECK-S-NEXT: addi r1, r1, 32 + ; CHECK-S-NEXT: ld r0, 16(r1) + ; CHECK-S-NEXT: mtlr r0 + ; CHECK-S-NEXT: blr + ; CHECK-O-LABEL: : + ; CHECK-O: 4c: paddi 3, 0, 0, 1 + ; CHECK-O-NEXT: 000000000000004c: R_PPC64_GOT_TLSLD_PCREL34 x + ; CHECK-O-NEXT: 54: bl 0x54 + ; CHECK-O-NEXT: 0000000000000054: R_PPC64_TLSLD x + ; CHECK-O-NEXT: 0000000000000054: R_PPC64_REL24_NOTOC __tls_get_addr + ; CHECK-O-NEXT: 58: paddi 3, 3, 0, 0 + ; CHECK-O-NEXT: 0000000000000058: R_PPC64_DTPREL34 x + ; CHECK-O-NEXT: 60: lwz 3, 0(3) + entry: + %0 = load i32, i32* @x, align 4 + ret i32 %0 +} diff --git a/llvm/test/MC/PowerPC/pcrel-tls-local-dynamic-reloc.s b/llvm/test/MC/PowerPC/pcrel-tls-local-dynamic-reloc.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/PowerPC/pcrel-tls-local-dynamic-reloc.s @@ -0,0 +1,33 @@ +# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s 2>&1 | \ +# RUN: FileCheck %s -check-prefix=MC +# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \ +# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=READOBJ + +# This test checks that on Power PC we can correctly convert @got@tlsld@pcrel +# x@tlsld, __tls_get_addr@notoc and x@DTPREL into R_PPC64_GOT_TLSLD_PCREL34, +# R_PPC64_TLSLD, R_PPC64_REL24_NOTOC and R_PPC64_DTPREL34 for local dynamic +# relocations with address/value loaded + +# MC-NOT: error: invalid variant + +# READOBJ: 0x0 R_PPC64_GOT_TLSLD_PCREL34 x 0x0 +# READOBJ-NEXT: 0x8 R_PPC64_TLSLD x 0x0 +# READOBJ-NEXT: 0x8 R_PPC64_REL24_NOTOC __tls_get_addr 0x0 +# READOBJ-NEXT: 0xC R_PPC64_DTPREL34 x 0x0 +# READOBJ-NEXT: 0x18 R_PPC64_GOT_TLSLD_PCREL34 x 0x0 +# READOBJ-NEXT: 0x20 R_PPC64_TLSLD x 0x0 +# READOBJ-NEXT: 0x20 R_PPC64_REL24_NOTOC __tls_get_addr 0x0 +# READOBJ-NEXT: 0x24 R_PPC64_DTPREL34 x 0x0 + +LocalDynamicAddrLoad: + paddi 3, 0, x@got@tlsld@pcrel, 1 + bl __tls_get_addr@notoc(x@tlsld) + paddi 3, 3, x@DTPREL, 0 + blr + +LocalDynamicValueLoad: + paddi 3, 0, x@got@tlsld@pcrel, 1 + bl __tls_get_addr@notoc(x@tlsld) + paddi 3, 3, x@DTPREL, 0 + lwz 3, 0(3) + blr