Skip to content

Commit d565980

Browse files
committed
[AIX][TLS] Generate 64-bit local-exec access code sequence
This patch adds support for the TLS local-exec access model on AIX to allow for the ability to generate the 64-bit (specifically, non-optimized) code sequence. For this patch in particular, the sequence that is generated involves a load of the variable offset, followed by an add of the loaded variable offset to r13 (which is thread pointer, respectively). This code sequence looks like the following: ``` ld reg1,var[TC](2) add reg2, reg1, r13 // r13 contains the thread pointer ``` The TOC (.tc pseudo-op) entries generated in the assembly files are also changed where we add the @le relocation for the variable offset. Differential Revision: https://reviews.llvm.org/D149722
1 parent 706b547 commit d565980

15 files changed

+1796
-14
lines changed

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_TLSGD, // symbol@tlsgd
300300
VK_PPC_AIX_TLSGD, // symbol@gd
301301
VK_PPC_AIX_TLSGDM, // symbol@m
302+
VK_PPC_AIX_TLSLE, // symbol@le
302303
VK_PPC_GOT_TLSLD, // symbol@got@tlsld
303304
VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l
304305
VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h

llvm/lib/MC/MCExpr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
327327
return "gd";
328328
case VK_PPC_AIX_TLSGDM:
329329
return "m";
330+
case VK_PPC_AIX_TLSLE:
331+
return "le";
330332
case VK_PPC_GOT_TLSLD: return "got@tlsld";
331333
case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
332334
case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,11 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
147147
MCSymbolXCOFF *TCSym =
148148
cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
149149
->getQualNameSymbol();
150-
// If the variant kind is VK_PPC_AIX_TLSGDM the entry represents the
151-
// region handle for the symbol, we add the relocation specifier @m.
152-
// If the variant kind is VK_PPC_AIX_TLSGD the entry represents the
153-
// variable offset for the symbol, we add the relocation specifier @gd.
150+
// On AIX, we have a region handle (symbol@m) and the variable offset
151+
// (symbol@{gd|le}) for TLS variables, depending on the TLS model.
154152
if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD ||
155-
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM)
153+
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
154+
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE)
156155
OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
157156
<< MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
158157
else

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
108108
return {XCOFF::RelocationType::R_TLS, SignAndSizeForFKData};
109109
case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM:
110110
return {XCOFF::RelocationType::R_TLSM, SignAndSizeForFKData};
111+
case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
112+
return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData};
111113
case MCSymbolRefExpr::VK_None:
112114
return {XCOFF::RelocationType::R_POS, SignAndSizeForFKData};
113115
}

llvm/lib/Target/PowerPC/PPC.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@ class ModulePass;
127127
/// General Dynamic model for AIX.
128128
MO_TLSGD_FLAG = 32,
129129

130-
/// MO_TPREL_FLAG - If this bit is set the symbol reference is relative to
131-
/// TLS Initial Exec model.
130+
/// MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to
131+
/// the thread pointer and the symbol can be used for the TLS Initial Exec
132+
/// and Local Exec models.
132133
MO_TPREL_FLAG = 64,
133134

134135
/// MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,18 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
813813
return Expr;
814814
};
815815
auto GetVKForMO = [&](const MachineOperand &MO) {
816+
// For TLS local-exec accesses on AIX, we have one TOC entry for the symbol
817+
// (with the variable offset), which is differentiated by MO_TPREL_FLAG.
818+
if (MO.getTargetFlags() & PPCII::MO_TPREL_FLAG) {
819+
// TODO: Update the query and the comment above to add a check for initial
820+
// exec when this TLS model is supported on AIX in the future, as both
821+
// local-exec and initial-exec can use MO_TPREL_FLAG.
822+
assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");
823+
TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());
824+
if (Model == TLSModel::LocalExec)
825+
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
826+
llvm_unreachable("Only expecting local-exec accesses!");
827+
}
816828
// For GD TLS access on AIX, we have two TOC entries for the symbol (one for
817829
// the variable offset and the other for the region handle). They are
818830
// differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG.

llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3326,9 +3326,31 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
33263326
SDLoc dl(GA);
33273327
const GlobalValue *GV = GA->getGlobal();
33283328
EVT PtrVT = getPointerTy(DAG.getDataLayout());
3329+
bool Is64Bit = Subtarget.isPPC64();
3330+
TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
33293331

3330-
// The general-dynamic model is the only access model supported for now, so
3331-
// all the GlobalTLSAddress nodes are lowered with this model.
3332+
if (Model == TLSModel::LocalExec) {
3333+
if (Is64Bit) {
3334+
// For local-exec on AIX (64-bit), the sequence that is generated involves
3335+
// a load of the variable offset (from the TOC), followed by an add of the
3336+
// loaded variable offset to R13 (the thread pointer).
3337+
// This code sequence looks like:
3338+
// ld reg1,var[TC](2)
3339+
// add reg2, reg1, r13 // r13 contains the thread pointer
3340+
SDValue TLSReg = DAG.getRegister(PPC::X13, MVT::i64);
3341+
SDValue VariableOffsetTGA =
3342+
DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TPREL_FLAG);
3343+
SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3344+
return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
3345+
} else {
3346+
report_fatal_error("On AIX, the local-exec TLS model is only supported "
3347+
"on PPC64 for now.");
3348+
}
3349+
}
3350+
3351+
// The Local-Exec and General-Dynamic TLS models are currently the only
3352+
// supported access models. If Local-exec is not possible or specified, all
3353+
// GlobalTLSAddress nodes are lowered using the general-dynamic model.
33323354
// We need to generate two TOC entries, one for the variable offset, one for
33333355
// the region handle. The global address for the TOC entry of the region
33343356
// handle is created with the MO_TLSGDM_FLAG flag and the global address

llvm/lib/Target/PowerPC/PPCISelLowering.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,11 +332,11 @@ namespace llvm {
332332
/// finds the offset of "sym" relative to the thread pointer.
333333
LD_GOT_TPREL_L,
334334

335-
/// G8RC = ADD_TLS G8RReg, Symbol - Used by the initial-exec TLS
336-
/// model, produces an ADD instruction that adds the contents of
337-
/// G8RReg to the thread pointer. Symbol contains a relocation
338-
/// sym\@tls which is to be replaced by the thread pointer and
339-
/// identifies to the linker that the instruction is part of a
335+
/// G8RC = ADD_TLS G8RReg, Symbol - Can be used by the initial-exec
336+
/// and local-exec TLS models, produces an ADD instruction that adds
337+
/// the contents of G8RReg to the thread pointer. Symbol contains a
338+
/// relocation sym\@tls which is to be replaced by the thread pointer
339+
/// and identifies to the linker that the instruction is part of a
340340
/// TLS sequence.
341341
ADD_TLS,
342342

llvm/lib/Target/PowerPC/PPCInstr64Bit.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,9 +1910,20 @@ def : Pat<(add i64:$in, (PPChi tblockaddress:$g, 0)),
19101910
(ADDIS8 $in, tblockaddress:$g)>;
19111911

19121912
// AIX 64-bit small code model TLS access.
1913+
// This is used for global dynamic accesses when loading the region handle and
1914+
// variable offset, and also for local-exec accesses to load the offset of a
1915+
// TLS variable from the TOC, prior to adding it to r13.
19131916
def : Pat<(i64 (PPCtoc_entry tglobaltlsaddr:$disp, i64:$reg)),
19141917
(i64 (LDtoc tglobaltlsaddr:$disp, i64:$reg))>;
19151918

1919+
// The following pattern matches 64-bit local-exec TLS accesses on AIX.
1920+
// PPCaddTls is used in local-exec accesses in order to:
1921+
// - Get the address of a variable (adding the variable offset to the thread
1922+
// pointer in r13).
1923+
// - Create an opportunity to optimize the user of the loaded address.
1924+
def : Pat<(PPCaddTls i64:$in, i64:$addr),
1925+
(ADD8TLS $in, $addr)>;
1926+
19161927
// 64-bits atomic loads and stores
19171928
def : Pat<(atomic_load_64 DSForm:$src), (LD memrix:$src)>;
19181929
def : Pat<(atomic_load_64 XForm:$src), (LDX memrr:$src)>;

0 commit comments

Comments
 (0)