Skip to content

Commit b74b80b

Browse files
committed
[PowerPC][PCRelative] Thread Local Storage Support for General Dynamic
This patch is the initial support for the General Dynamic Thread Local Local Storage model to produce code sequence and relocations correct to the ABI for the model when using PC relative memory operations. Patch by: NeHuang Reviewed By: stefanp Differential Revision: https://reviews.llvm.org/D82315
1 parent d9b062a commit b74b80b

19 files changed

+205
-20
lines changed

llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
#undef R_PPC64_PCREL_OPT
101101
#undef R_PPC64_PCREL34
102102
#undef R_PPC64_GOT_PCREL34
103+
#undef R_PPC64_GOT_TLSGD_PCREL34
103104
#undef R_PPC64_IRELATIVE
104105
#undef R_PPC64_REL16
105106
#undef R_PPC64_REL16_LO
@@ -198,6 +199,7 @@ ELF_RELOC(R_PPC64_REL24_NOTOC, 116)
198199
ELF_RELOC(R_PPC64_PCREL_OPT, 123)
199200
ELF_RELOC(R_PPC64_PCREL34, 132)
200201
ELF_RELOC(R_PPC64_GOT_PCREL34, 133)
202+
ELF_RELOC(R_PPC64_GOT_TLSGD_PCREL34, 148)
201203
ELF_RELOC(R_PPC64_IRELATIVE, 248)
202204
ELF_RELOC(R_PPC64_REL16, 249)
203205
ELF_RELOC(R_PPC64_REL16_LO, 250)

llvm/include/llvm/MC/MCExpr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ class MCSymbolRefExpr : public MCExpr {
299299
VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h
300300
VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha
301301
VK_PPC_GOT_PCREL, // symbol@got@pcrel
302+
VK_PPC_GOT_TLSGD_PCREL, // symbol@got@tlsgd@pcrel
302303
VK_PPC_TLSLD, // symbol@tlsld
303304
VK_PPC_LOCAL, // symbol@local
304305
VK_PPC_NOTOC, // symbol@notoc

llvm/lib/MC/MCExpr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
322322
case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";
323323
case VK_PPC_GOT_PCREL:
324324
return "got@pcrel";
325+
case VK_PPC_GOT_TLSGD_PCREL:
326+
return "got@tlsgd@pcrel";
325327
case VK_PPC_TLSLD: return "tlsld";
326328
case VK_PPC_LOCAL: return "local";
327329
case VK_PPC_NOTOC: return "notoc";
@@ -454,6 +456,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
454456
.Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)
455457
.Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)
456458
.Case("got@pcrel", VK_PPC_GOT_PCREL)
459+
.Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL)
457460
.Case("notoc", VK_PPC_NOTOC)
458461
.Case("gdgot", VK_Hexagon_GD_GOT)
459462
.Case("gdplt", VK_Hexagon_GD_PLT)

llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
138138
case MCSymbolRefExpr::VK_PPC_GOT_PCREL:
139139
Type = ELF::R_PPC64_GOT_PCREL34;
140140
break;
141+
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL:
142+
Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
143+
break;
141144
}
142145
break;
143146
case FK_Data_4:

llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,10 +531,17 @@ void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
531531
RefExp = cast<MCSymbolRefExpr>(Op.getExpr());
532532

533533
O << RefExp->getSymbol().getName();
534+
// The variant kind VK_PPC_NOTOC needs to be handled as a special case
535+
// because we do not want the assembly to print out the @notoc at the
536+
// end like __tls_get_addr(x@tlsgd)@notoc. Instead we want it to look
537+
// like __tls_get_addr@notoc(x@tlsgd).
538+
if (RefExp->getKind() == MCSymbolRefExpr::VK_PPC_NOTOC)
539+
O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind());
534540
O << '(';
535541
printOperand(MI, OpNo+1, O);
536542
O << ')';
537-
if (RefExp->getKind() != MCSymbolRefExpr::VK_None)
543+
if (RefExp->getKind() != MCSymbolRefExpr::VK_None &&
544+
RefExp->getKind() != MCSymbolRefExpr::VK_PPC_NOTOC)
538545
O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind());
539546
if (ConstExp != nullptr)
540547
O << '+' << ConstExp->getValue();

llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
4444
SmallVectorImpl<MCFixup> &Fixups,
4545
const MCSubtargetInfo &STI) const {
4646
const MCOperand &MO = MI.getOperand(OpNo);
47-
if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
4847

48+
if (MO.isReg() || MO.isImm())
49+
return getMachineOpValue(MI, MO, Fixups, STI);
4950
// Add a fixup for the branch target.
5051
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
51-
((MI.getOpcode() == PPC::BL8_NOTOC)
52+
((MI.getOpcode() == PPC::BL8_NOTOC ||
53+
MI.getOpcode() == PPC::BL8_NOTOC_TLS)
5254
? (MCFixupKind)PPC::fixup_ppc_br24_notoc
5355
: (MCFixupKind)PPC::fixup_ppc_br24)));
5456
return 0;
@@ -229,8 +231,10 @@ PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
229231
(void)SRE;
230232
// Currently these are the only valid PCRelative Relocations.
231233
assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
232-
SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) &&
233-
"VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL");
234+
SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL ||
235+
SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL) &&
236+
"VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or "
237+
"VK_PPC_GOT_TLSGD_PCREL");
234238
// Generate the fixup for the relocation.
235239
Fixups.push_back(
236240
MCFixup::create(0, Expr,

llvm/lib/Target/PowerPC/PPC.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,15 @@ namespace llvm {
109109
// PC Relative linker optimization.
110110
MO_PCREL_OPT_FLAG = 16,
111111

112+
/// MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to
113+
/// TLS General Dynamic model.
114+
MO_TLSGD_FLAG = 32,
115+
116+
/// MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set
117+
/// they should produce the relocation @got@tlsgd@pcrel.
118+
/// Fix up is VK_PPC_GOT_TLSGD_PCREL
119+
MO_GOT_TLSGD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSGD_FLAG,
120+
112121
/// The next are not flags but distinct values.
113122
MO_ACCESS_MASK = 0xf00,
114123

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,13 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
488488
StringRef Name = "__tls_get_addr";
489489
MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol(Name);
490490
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
491+
unsigned Opcode = PPC::BL8_NOP_TLS;
492+
493+
assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI");
494+
if (MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) {
495+
Kind = MCSymbolRefExpr::VK_PPC_NOTOC;
496+
Opcode = PPC::BL8_NOTOC_TLS;
497+
}
491498
const Module *M = MF->getFunction().getParent();
492499

493500
assert(MI->getOperand(0).isReg() &&
@@ -515,10 +522,9 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
515522
MCSymbol *MOSymbol = getSymbol(GValue);
516523
const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
517524
EmitToStreamer(*OutStreamer,
518-
MCInstBuilder(Subtarget->isPPC64() ?
519-
PPC::BL8_NOP_TLS : PPC::BL_TLS)
520-
.addExpr(TlsRef)
521-
.addExpr(SymVar));
525+
MCInstBuilder(Subtarget->isPPC64() ? Opcode : PPC::BL_TLS)
526+
.addExpr(TlsRef)
527+
.addExpr(SymVar));
522528
}
523529

524530
/// Map a machine operand for a TOC pseudo-machine instruction to its

llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,8 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
14721472
case PPCISD::LD_VSX_LH: return "PPCISD::LD_VSX_LH";
14731473
case PPCISD::FP_EXTEND_HALF: return "PPCISD::FP_EXTEND_HALF";
14741474
case PPCISD::MAT_PCREL_ADDR: return "PPCISD::MAT_PCREL_ADDR";
1475+
case PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR:
1476+
return "PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR";
14751477
case PPCISD::LD_SPLAT: return "PPCISD::LD_SPLAT";
14761478
case PPCISD::FNMSUB: return "PPCISD::FNMSUB";
14771479
case PPCISD::STRICT_FCTIDZ:
@@ -2999,6 +3001,12 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
29993001
}
30003002

30013003
if (Model == TLSModel::GeneralDynamic) {
3004+
if (Subtarget.isUsingPCRelativeCalls()) {
3005+
SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,
3006+
PPCII::MO_GOT_TLSGD_PCREL_FLAG);
3007+
return DAG.getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3008+
}
3009+
30023010
SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0);
30033011
SDValue GOTPtr;
30043012
if (is64bit) {

llvm/lib/Target/PowerPC/PPCISelLowering.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,11 @@ namespace llvm {
436436
/// PLD.
437437
MAT_PCREL_ADDR,
438438

439+
/// TLS_DYNAMIC_MAT_PCREL_ADDR = Materialize a PC Relative address for
440+
/// TLS global address when using dynamic access models. This can be done
441+
/// through an add like PADDI.
442+
TLS_DYNAMIC_MAT_PCREL_ADDR,
443+
439444
// Constrained conversion from floating point to int
440445
STRICT_FCTIDZ = ISD::FIRST_TARGET_STRICTFP_OPCODE,
441446
STRICT_FCTIWZ,

llvm/lib/Target/PowerPC/PPCInstr64Bit.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ let isCall = 1, PPC970_Unit = 7, Defs = [LR8] in {
148148
def BL8_NOTOC : IForm<18, 0, 1, (outs),
149149
(ins calltarget:$func),
150150
"bl $func", IIC_BrB, []>;
151+
def BL8_NOTOC_TLS : IForm<18, 0, 1, (outs),
152+
(ins tlscall:$func),
153+
"bl $func", IIC_BrB, []>;
151154
}
152155
}
153156
let Uses = [CTR8, RM] in {

llvm/lib/Target/PowerPC/PPCInstrInfo.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2272,7 +2272,9 @@ PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
22722272
{MO_PIC_FLAG, "ppc-pic"},
22732273
{MO_PCREL_FLAG, "ppc-pcrel"},
22742274
{MO_GOT_FLAG, "ppc-got"},
2275-
{MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"}};
2275+
{MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"},
2276+
{MO_TLSGD_FLAG, "ppc-tlsgd"},
2277+
{MO_GOT_TLSGD_PCREL_FLAG, "ppc-got-tlsgd-pcrel"}};
22762278
return makeArrayRef(TargetFlags);
22772279
}
22782280

llvm/lib/Target/PowerPC/PPCInstrInfo.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ def PPCprobedalloca : SDNode<"PPCISD::PROBED_ALLOCA", SDTDynOp, [SDNPHasChain]>;
339339

340340
// PC Relative Specific Nodes
341341
def PPCmatpcreladdr : SDNode<"PPCISD::MAT_PCREL_ADDR", SDTIntUnaryOp, []>;
342+
def PPCtlsdynamatpcreladdr : SDNode<"PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR",
343+
SDTIntUnaryOp, []>;
342344

343345
//===----------------------------------------------------------------------===//
344346
// PowerPC specific transformation functions and pattern fragments.

llvm/lib/Target/PowerPC/PPCInstrPrefix.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,9 @@ let Predicates = [PCRelativeMemops], AddedComplexity = 500 in {
811811
// If the PPCmatpcreladdr node is not caught by any other pattern it should be
812812
// caught here and turned into a paddi instruction to materialize the address.
813813
def : Pat<(PPCmatpcreladdr pcreladdr:$addr), (PADDI8pc 0, $addr)>;
814+
// PPCtlsdynamatpcreladdr node is used for TLS dynamic models to materialize
815+
// tls global address with paddi instruction.
816+
def : Pat<(PPCtlsdynamatpcreladdr pcreladdr:$addr), (PADDI8pc 0, $addr)>;
814817
}
815818

816819
let Predicates = [PrefixInstrs] in {

llvm/lib/Target/PowerPC/PPCMCInstLower.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
8484
RefKind = MCSymbolRefExpr::VK_PCREL;
8585
else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG))
8686
RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL;
87+
else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG)
88+
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL;
8789

8890
const MachineInstr *MI = MO.getParent();
8991
const MachineFunction *MF = MI->getMF();

llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,17 @@ namespace {
5050
bool Changed = false;
5151
bool NeedFence = true;
5252
bool Is64Bit = MBB.getParent()->getSubtarget<PPCSubtarget>().isPPC64();
53+
bool IsTLSGDPCREL = false;
5354

5455
for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
5556
I != IE;) {
5657
MachineInstr &MI = *I;
58+
IsTLSGDPCREL = isTLSGDPCREL(MI);
5759

5860
if (MI.getOpcode() != PPC::ADDItlsgdLADDR &&
5961
MI.getOpcode() != PPC::ADDItlsldLADDR &&
6062
MI.getOpcode() != PPC::ADDItlsgdLADDR32 &&
61-
MI.getOpcode() != PPC::ADDItlsldLADDR32) {
62-
63+
MI.getOpcode() != PPC::ADDItlsldLADDR32 && !IsTLSGDPCREL) {
6364
// Although we create ADJCALLSTACKDOWN and ADJCALLSTACKUP
6465
// as scheduling fences, we skip creating fences if we already
6566
// have existing ADJCALLSTACKDOWN/UP to avoid nesting,
@@ -76,12 +77,16 @@ namespace {
7677
LLVM_DEBUG(dbgs() << "TLS Dynamic Call Fixup:\n " << MI);
7778

7879
Register OutReg = MI.getOperand(0).getReg();
79-
Register InReg = MI.getOperand(1).getReg();
80-
DebugLoc DL = MI.getDebugLoc();
80+
Register InReg = PPC::NoRegister;
8181
Register GPR3 = Is64Bit ? PPC::X3 : PPC::R3;
82-
unsigned Opc1, Opc2;
83-
const Register OrigRegs[] = {OutReg, InReg, GPR3};
82+
SmallVector<Register, 3> OrigRegs = {OutReg, GPR3};
83+
if (!IsTLSGDPCREL) {
84+
InReg = MI.getOperand(1).getReg();
85+
OrigRegs.push_back(InReg);
86+
}
87+
DebugLoc DL = MI.getDebugLoc();
8488

89+
unsigned Opc1, Opc2;
8590
switch (MI.getOpcode()) {
8691
default:
8792
llvm_unreachable("Opcode inconsistency error");
@@ -101,6 +106,10 @@ namespace {
101106
Opc1 = PPC::ADDItlsldL32;
102107
Opc2 = PPC::GETtlsldADDR32;
103108
break;
109+
case PPC::PADDI8pc:
110+
assert(IsTLSGDPCREL && "Expecting General Dynamic PCRel");
111+
Opc1 = PPC::PADDI8pc;
112+
Opc2 = PPC::GETtlsADDR;
104113
}
105114

106115
// We create ADJCALLSTACKUP and ADJCALLSTACKDOWN around _tls_get_addr
@@ -113,9 +122,15 @@ namespace {
113122
BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKDOWN)).addImm(0)
114123
.addImm(0);
115124

116-
// Expand into two ops built prior to the existing instruction.
117-
MachineInstr *Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3)
118-
.addReg(InReg);
125+
MachineInstr *Addi;
126+
if (IsTLSGDPCREL) {
127+
Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3).addImm(0);
128+
} else {
129+
// Expand into two ops built prior to the existing instruction.
130+
assert(InReg != PPC::NoRegister && "Operand must be a register");
131+
Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3).addReg(InReg);
132+
}
133+
119134
Addi->addOperand(MI.getOperand(2));
120135

121136
// The ADDItls* instruction is the first instruction in the
@@ -125,7 +140,10 @@ namespace {
125140

126141
MachineInstr *Call = (BuildMI(MBB, I, DL, TII->get(Opc2), GPR3)
127142
.addReg(GPR3));
128-
Call->addOperand(MI.getOperand(3));
143+
if (IsTLSGDPCREL)
144+
Call->addOperand(MI.getOperand(2));
145+
else
146+
Call->addOperand(MI.getOperand(3));
129147

130148
if (NeedFence)
131149
BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKUP)).addImm(0).addImm(0);
@@ -150,6 +168,11 @@ namespace {
150168
}
151169

152170
public:
171+
bool isTLSGDPCREL(const MachineInstr &MI) {
172+
return (MI.getOpcode() == PPC::PADDI8pc) &&
173+
(MI.getOperand(2).getTargetFlags() ==
174+
PPCII::MO_GOT_TLSGD_PCREL_FLAG);
175+
}
153176
bool runOnMachineFunction(MachineFunction &MF) override {
154177
TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo();
155178
LIS = &getAnalysis<LiveIntervals>();
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
2+
; RUN: --relocation-model=pic -mcpu=pwr10 -ppc-asm-full-reg-names \
3+
; RUN: -enable-ppc-pcrel-tls < %s | FileCheck %s --check-prefix=CHECK-S
4+
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
5+
; RUN: --relocation-model=pic -mcpu=pwr10 -ppc-asm-full-reg-names \
6+
; RUN: -enable-ppc-pcrel-tls --filetype=obj < %s | \
7+
; RUN: llvm-objdump --mcpu=pwr10 -dr - | FileCheck %s --check-prefix=CHECK-O
8+
9+
; These test cases are to ensure that when using pc relative memory operations
10+
; ABI correct code and relocations are produced for General Dynamic TLS Model.
11+
12+
@x = external thread_local global i32, align 4
13+
14+
define nonnull i32* @GeneralDynamicAddressLoad() {
15+
; CHECK-S-LABEL: GeneralDynamicAddressLoad:
16+
; CHECK-S: paddi r3, 0, x@got@tlsgd@pcrel, 1
17+
; CHECK-S-NEXT: bl __tls_get_addr@notoc(x@tlsgd)
18+
; CHECK-S-NEXT: addi r1, r1, 32
19+
; CHECK-S-NEXT: ld r0, 16(r1)
20+
; CHECK-S-NEXT: mtlr r0
21+
; CHECK-S-NEXT: blr
22+
; CHECK-O-LABEL: <GeneralDynamicAddressLoad>:
23+
; CHECK-O: c: 00 00 10 06 00 00 60 38 paddi 3, 0, 0, 1
24+
; CHECK-O-NEXT: 000000000000000c: R_PPC64_GOT_TLSGD_PCREL34 x
25+
; CHECK-O-NEXT: 14: 01 00 00 48 bl 0x14
26+
; CHECK-O-NEXT: 0000000000000014: R_PPC64_TLSGD x
27+
; CHECK-O-NEXT: 0000000000000014: R_PPC64_REL24_NOTOC __tls_get_addr
28+
entry:
29+
ret i32* @x
30+
}
31+
32+
define i32 @GeneralDynamicValueLoad() {
33+
; CHECK-S-LABEL: GeneralDynamicValueLoad:
34+
; CHECK-S: paddi r3, 0, x@got@tlsgd@pcrel, 1
35+
; CHECK-S-NEXT: bl __tls_get_addr@notoc(x@tlsgd)
36+
; CHECK-S-NEXT: lwz r3, 0(r3)
37+
; CHECK-S-NEXT: addi r1, r1, 32
38+
; CHECK-S-NEXT: ld r0, 16(r1)
39+
; CHECK-S-NEXT: mtlr r0
40+
; CHECK-S-NEXT: blr
41+
; CHECK-O-LABEL: <GeneralDynamicValueLoad>:
42+
; CHECK-O: 4c: 00 00 10 06 00 00 60 38 paddi 3, 0, 0, 1
43+
; CHECK-O-NEXT: 000000000000004c: R_PPC64_GOT_TLSGD_PCREL34 x
44+
; CHECK-O-NEXT: 54: 01 00 00 48 bl 0x54
45+
; CHECK-O-NEXT: 0000000000000054: R_PPC64_TLSGD x
46+
; CHECK-O-NEXT: 0000000000000054: R_PPC64_REL24_NOTOC __tls_get_addr
47+
; CHECK-O-NEXT: 58: 00 00 63 80 lwz 3, 0(3)
48+
entry:
49+
%0 = load i32, i32* @x, align 4
50+
ret i32 %0
51+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s 2>&1 | \
2+
# RUN: FileCheck %s -check-prefix=MC
3+
# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \
4+
# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=READOBJ
5+
6+
# This test checks that on Power PC we can correctly convert @got@tlsgd@pcrel
7+
# x@tlsgd and __tls_get_addr@notoc into R_PPC64_GOT_TLSGD_PCREL34, R_PPC64_TLSGD
8+
# and R_PPC64_REL24_NOTOC for general dynamic relocations with address loaded
9+
10+
# MC-NOT: error: invalid variant
11+
12+
# READOBJ: 0xC R_PPC64_GOT_TLSGD_PCREL34 x 0x0
13+
# READOBJ-NEXT: 0x14 R_PPC64_TLSGD x 0x0
14+
# READOBJ-NEXT: 0x14 R_PPC64_REL24_NOTOC __tls_get_addr 0x0
15+
16+
GeneralDynamicAddrLoad: # @GeneralDynamicAddrLoad
17+
mflr 0
18+
std 0, 16(1)
19+
stdu 1, -32(1)
20+
paddi 3, 0, x@got@tlsgd@pcrel, 1
21+
bl __tls_get_addr@notoc(x@tlsgd)
22+
addi 1, 1, 32
23+
ld 0, 16(1)
24+
mtlr 0
25+
blr

0 commit comments

Comments
 (0)