diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h index bf1f32bb91ba7..49bd6883d4297 100644 --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -299,6 +299,7 @@ class MCSymbolRefExpr : public MCExpr { VK_PPC_TLSGD, // symbol@tlsgd VK_PPC_AIX_TLSGD, // symbol@gd VK_PPC_AIX_TLSGDM, // symbol@m + VK_PPC_AIX_TLSLE, // symbol@le VK_PPC_GOT_TLSLD, // symbol@got@tlsld VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index d5b5aa8fba4e0..c2ecc00b5796c 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -327,6 +327,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { return "gd"; case VK_PPC_AIX_TLSGDM: return "m"; + case VK_PPC_AIX_TLSLE: + return "le"; case VK_PPC_GOT_TLSLD: return "got@tlsld"; case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index 37bb90ab2c248..271f7ab757e16 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -147,12 +147,11 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer { MCSymbolXCOFF *TCSym = cast(Streamer.getCurrentSectionOnly()) ->getQualNameSymbol(); - // If the variant kind is VK_PPC_AIX_TLSGDM the entry represents the - // region handle for the symbol, we add the relocation specifier @m. - // If the variant kind is VK_PPC_AIX_TLSGD the entry represents the - // variable offset for the symbol, we add the relocation specifier @gd. + // On AIX, we have a region handle (symbol@m) and the variable offset + // (symbol@{gd|le}) for TLS variables, depending on the TLS model. if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD || - Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM) + Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM || + Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE) OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@" << MCSymbolRefExpr::getVariantKindName(Kind) << '\n'; else diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp index b6e749b781804..df671f53cbd8c 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp @@ -108,6 +108,8 @@ std::pair PPCXCOFFObjectWriter::getRelocTypeAndSignSize( return {XCOFF::RelocationType::R_TLS, SignAndSizeForFKData}; case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM: return {XCOFF::RelocationType::R_TLSM, SignAndSizeForFKData}; + case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: + return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData}; case MCSymbolRefExpr::VK_None: return {XCOFF::RelocationType::R_POS, SignAndSizeForFKData}; } diff --git a/llvm/lib/Target/PowerPC/PPC.h b/llvm/lib/Target/PowerPC/PPC.h index 8f84ae7efc246..0d3d71742bfb7 100644 --- a/llvm/lib/Target/PowerPC/PPC.h +++ b/llvm/lib/Target/PowerPC/PPC.h @@ -127,8 +127,9 @@ class ModulePass; /// General Dynamic model for AIX. MO_TLSGD_FLAG = 32, - /// MO_TPREL_FLAG - If this bit is set the symbol reference is relative to - /// TLS Initial Exec model. + /// MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to + /// the thread pointer and the symbol can be used for the TLS Initial Exec + /// and Local Exec models. MO_TPREL_FLAG = 64, /// MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index caaea40ae5169..2a192e6555912 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -813,6 +813,18 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { return Expr; }; auto GetVKForMO = [&](const MachineOperand &MO) { + // For TLS local-exec accesses on AIX, we have one TOC entry for the symbol + // (with the variable offset), which is differentiated by MO_TPREL_FLAG. + if (MO.getTargetFlags() & PPCII::MO_TPREL_FLAG) { + // TODO: Update the query and the comment above to add a check for initial + // exec when this TLS model is supported on AIX in the future, as both + // local-exec and initial-exec can use MO_TPREL_FLAG. + assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n"); + TLSModel::Model Model = TM.getTLSModel(MO.getGlobal()); + if (Model == TLSModel::LocalExec) + return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE; + llvm_unreachable("Only expecting local-exec accesses!"); + } // For GD TLS access on AIX, we have two TOC entries for the symbol (one for // the variable offset and the other for the region handle). They are // differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG. diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 012052a1be1d3..f4eb89dda19ce 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -3326,9 +3326,31 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, SDLoc dl(GA); const GlobalValue *GV = GA->getGlobal(); EVT PtrVT = getPointerTy(DAG.getDataLayout()); + bool Is64Bit = Subtarget.isPPC64(); + TLSModel::Model Model = getTargetMachine().getTLSModel(GV); - // The general-dynamic model is the only access model supported for now, so - // all the GlobalTLSAddress nodes are lowered with this model. + if (Model == TLSModel::LocalExec) { + if (Is64Bit) { + // For local-exec on AIX (64-bit), the sequence that is generated involves + // a load of the variable offset (from the TOC), followed by an add of the + // loaded variable offset to R13 (the thread pointer). + // This code sequence looks like: + // ld reg1,var[TC](2) + // add reg2, reg1, r13 // r13 contains the thread pointer + SDValue TLSReg = DAG.getRegister(PPC::X13, MVT::i64); + SDValue VariableOffsetTGA = + DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TPREL_FLAG); + SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA); + return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset); + } else { + report_fatal_error("On AIX, the local-exec TLS model is only supported " + "on PPC64 for now."); + } + } + + // The Local-Exec and General-Dynamic TLS models are currently the only + // supported access models. If Local-exec is not possible or specified, all + // GlobalTLSAddress nodes are lowered using the general-dynamic model. // We need to generate two TOC entries, one for the variable offset, one for // the region handle. The global address for the TOC entry of the region // handle is created with the MO_TLSGDM_FLAG flag and the global address diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index 02f7147dfd6bb..2e2514a5e34a4 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -332,11 +332,11 @@ namespace llvm { /// finds the offset of "sym" relative to the thread pointer. LD_GOT_TPREL_L, - /// G8RC = ADD_TLS G8RReg, Symbol - Used by the initial-exec TLS - /// model, produces an ADD instruction that adds the contents of - /// G8RReg to the thread pointer. Symbol contains a relocation - /// sym\@tls which is to be replaced by the thread pointer and - /// identifies to the linker that the instruction is part of a + /// G8RC = ADD_TLS G8RReg, Symbol - Can be used by the initial-exec + /// and local-exec TLS models, produces an ADD instruction that adds + /// the contents of G8RReg to the thread pointer. Symbol contains a + /// relocation sym\@tls which is to be replaced by the thread pointer + /// and identifies to the linker that the instruction is part of a /// TLS sequence. ADD_TLS, diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 4487082a3bb8c..f4f058aff237f 100644 --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1910,9 +1910,20 @@ def : Pat<(add i64:$in, (PPChi tblockaddress:$g, 0)), (ADDIS8 $in, tblockaddress:$g)>; // AIX 64-bit small code model TLS access. +// This is used for global dynamic accesses when loading the region handle and +// variable offset, and also for local-exec accesses to load the offset of a +// TLS variable from the TOC, prior to adding it to r13. def : Pat<(i64 (PPCtoc_entry tglobaltlsaddr:$disp, i64:$reg)), (i64 (LDtoc tglobaltlsaddr:$disp, i64:$reg))>; +// The following pattern matches 64-bit local-exec TLS accesses on AIX. +// PPCaddTls is used in local-exec accesses in order to: +// - Get the address of a variable (adding the variable offset to the thread +// pointer in r13). +// - Create an opportunity to optimize the user of the loaded address. +def : Pat<(PPCaddTls i64:$in, i64:$addr), + (ADD8TLS $in, $addr)>; + // 64-bits atomic loads and stores def : Pat<(atomic_load_64 DSForm:$src), (LD memrix:$src)>; def : Pat<(atomic_load_64 XForm:$src), (LDX memrr:$src)>; diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-double.ll b/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-double.ll new file mode 100644 index 0000000000000..2e0697d347226 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-double.ll @@ -0,0 +1,328 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s \ +; RUN: --check-prefix=SMALL64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large < %s \ +; RUN: | FileCheck %s --check-prefix=LARGE64 + +@ThreadLocalVarInit = thread_local(localexec) global double 0x4021947AE147AE14, align 8 +@VarInit = global double 8.787000e+01, align 8 +@IThreadLocalVarUninit = internal thread_local(localexec) global double 0.000000e+00, align 8 +@IThreadLocalVarInit = internal thread_local(localexec) global double 5.870000e+00, align 8 +@ThreadLocalVarUninit = thread_local(localexec) global double 0.000000e+00, align 8 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1 + +define void @storeITLUninit(double noundef %x) { +; SMALL64-LABEL: storeITLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: stfd f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeITLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: stfd f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarUninit) + store double %x, ptr %0, align 8 + ret void +} + +define void @storeITLInit(double noundef %x) { +; SMALL64-LABEL: storeITLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: stfd f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeITLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: stfd f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarInit) + store double %x, ptr %0, align 8 + ret void +} + +define void @storeTLUninit(double noundef %x) { +; SMALL64-LABEL: storeTLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: stfd f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeTLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: stfd f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarUninit) + store double %x, ptr %0, align 8 + ret void +} + +define void @storeTLInit(double noundef %x) { +; SMALL64-LABEL: storeTLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: stfd f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeTLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: stfd f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarInit) + store double %x, ptr %0, align 8 + ret void +} + +define double @loadITLUninit() { +; SMALL64-LABEL: loadITLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfd f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfd f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarUninit) + %1 = load double, ptr %0, align 8 + ret double %1 +} + +define double @loadITLUninit2() { +; SMALL64-LABEL: loadITLUninit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfd f1, 0(r4) +; SMALL64-NEXT: lfd f0, 0(r3) +; SMALL64-NEXT: xsadddp f1, f0, f1 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLUninit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfd f1, 0(r4) +; LARGE64-NEXT: lfd f0, 0(r3) +; LARGE64-NEXT: xsadddp f1, f0, f1 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarUninit) + %1 = load double, ptr %0, align 8 + %2 = load double, ptr @VarInit, align 8 + %add = fadd double %1, %2 + ret double %add +} + +define double @loadITLInit() { +; SMALL64-LABEL: loadITLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfd f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfd f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarInit) + %1 = load double, ptr %0, align 8 + ret double %1 +} + +define double @loadITLInit2() { +; SMALL64-LABEL: loadITLInit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfd f1, 0(r4) +; SMALL64-NEXT: lfd f0, 0(r3) +; SMALL64-NEXT: xsadddp f1, f0, f1 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLInit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfd f1, 0(r4) +; LARGE64-NEXT: lfd f0, 0(r3) +; LARGE64-NEXT: xsadddp f1, f0, f1 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarInit) + %1 = load double, ptr %0, align 8 + %2 = load double, ptr @VarInit, align 8 + %add = fadd double %1, %2 + ret double %add +} + +define double @loadTLUninit() { +; SMALL64-LABEL: loadTLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfd f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfd f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarUninit) + %1 = load double, ptr %0, align 8 + ret double %1 +} + +define double @loadTLUninit2() { +; SMALL64-LABEL: loadTLUninit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfd f1, 0(r4) +; SMALL64-NEXT: lfd f0, 0(r3) +; SMALL64-NEXT: xsadddp f1, f0, f1 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLUninit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfd f1, 0(r4) +; LARGE64-NEXT: lfd f0, 0(r3) +; LARGE64-NEXT: xsadddp f1, f0, f1 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarUninit) + %1 = load double, ptr %0, align 8 + %2 = load double, ptr @VarInit, align 8 + %add = fadd double %1, %2 + ret double %add +} + +define double @loadTLInit() { +; SMALL64-LABEL: loadTLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfd f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfd f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarInit) + %1 = load double, ptr %0, align 8 + ret double %1 +} + +define double @loadTLInit2() { +; SMALL64-LABEL: loadTLInit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfd f1, 0(r4) +; SMALL64-NEXT: lfd f0, 0(r3) +; SMALL64-NEXT: xsadddp f1, f0, f1 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLInit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfd f1, 0(r4) +; LARGE64-NEXT: lfd f0, 0(r3) +; LARGE64-NEXT: xsadddp f1, f0, f1 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarInit) + %1 = load double, ptr %0, align 8 + %2 = load double, ptr @VarInit, align 8 + %add = fadd double %1, %2 + ret double %add +} + +; TOC Entry Checks. + +; SMALL64-LABEL: .toc +; SMALL64-LABEL: L..C0: +; SMALL64-NEXT: .tc IThreadLocalVarUninit[TC],IThreadLocalVarUninit[UL]@le +; SMALL64-LABEL: L..C1: +; SMALL64-NEXT: .tc IThreadLocalVarInit[TC],IThreadLocalVarInit[TL]@le +; SMALL64-LABEL: L..C2: +; SMALL64-NEXT: .tc ThreadLocalVarUninit[TC],ThreadLocalVarUninit[TL]@le +; SMALL64-LABEL: L..C3: +; SMALL64-NEXT: .tc ThreadLocalVarInit[TC],ThreadLocalVarInit[TL]@le +; SMALL64-LABEL: L..C4: +; SMALL64-NEXT: .tc VarInit[TC],VarInit[RW] + +; LARGE64-LABEL: .toc +; LARGE64-LABEL: L..C0: +; LARGE64-NEXT: .tc IThreadLocalVarUninit[TE],IThreadLocalVarUninit[UL]@le +; LARGE64-LABEL: L..C1: +; LARGE64-NEXT: .tc IThreadLocalVarInit[TE],IThreadLocalVarInit[TL]@le +; LARGE64-LABEL: L..C2: +; LARGE64-NEXT: .tc ThreadLocalVarUninit[TE],ThreadLocalVarUninit[TL]@le +; LARGE64-LABEL: L..C3: +; LARGE64-NEXT: .tc ThreadLocalVarInit[TE],ThreadLocalVarInit[TL]@le +; LARGE64-LABEL: L..C4: +; LARGE64-NEXT: .tc VarInit[TE],VarInit[RW] diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-float.ll b/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-float.ll new file mode 100644 index 0000000000000..2b93616bfe8bd --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-float.ll @@ -0,0 +1,328 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s \ +; RUN: --check-prefix=SMALL64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large < %s \ +; RUN: | FileCheck %s --check-prefix=LARGE64 + +@ThreadLocalVarInit = thread_local(localexec) global float 0x401D333340000000, align 4 +@VarInit = global float 0x4021666660000000, align 4 +@IThreadLocalVarUninit = internal thread_local(localexec) global float 0.000000e+00, align 4 +@IThreadLocalVarInit = internal thread_local(localexec) global float 0x4018CCCCC0000000, align 4 +@ThreadLocalVarUninit = thread_local(localexec) global float 0.000000e+00, align 4 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1 + +define void @storeITLUninit(float noundef %x) { +; SMALL64-LABEL: storeITLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: stfs f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeITLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: stfs f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarUninit) + store float %x, ptr %0, align 4 + ret void +} + +define void @storeITLInit(float noundef %x) { +; SMALL64-LABEL: storeITLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: stfs f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeITLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: stfs f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarInit) + store float %x, ptr %0, align 4 + ret void +} + +define void @storeTLUninit(float noundef %x) { +; SMALL64-LABEL: storeTLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: stfs f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeTLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: stfs f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarUninit) + store float %x, ptr %0, align 4 + ret void +} + +define void @storeTLInit(float noundef %x) { +; SMALL64-LABEL: storeTLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: stfs f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeTLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: stfs f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarInit) + store float %x, ptr %0, align 4 + ret void +} + +define float @loadITLUninit() { +; SMALL64-LABEL: loadITLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfs f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfs f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarUninit) + %1 = load float, ptr %0, align 4 + ret float %1 +} + +define float @loadITLUninit2() { +; SMALL64-LABEL: loadITLUninit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfs f1, 0(r4) +; SMALL64-NEXT: lfs f0, 0(r3) +; SMALL64-NEXT: fadds f1, f0, f1 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLUninit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfs f1, 0(r4) +; LARGE64-NEXT: lfs f0, 0(r3) +; LARGE64-NEXT: fadds f1, f0, f1 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarUninit) + %1 = load float, ptr %0, align 4 + %2 = load float, ptr @VarInit, align 4 + %add = fadd float %1, %2 + ret float %add +} + +define float @loadITLInit() { +; SMALL64-LABEL: loadITLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfs f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfs f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarInit) + %1 = load float, ptr %0, align 4 + ret float %1 +} + +define float @loadITLInit2() { +; SMALL64-LABEL: loadITLInit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfs f1, 0(r4) +; SMALL64-NEXT: lfs f0, 0(r3) +; SMALL64-NEXT: fadds f1, f0, f1 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLInit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfs f1, 0(r4) +; LARGE64-NEXT: lfs f0, 0(r3) +; LARGE64-NEXT: fadds f1, f0, f1 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarInit) + %1 = load float, ptr %0, align 4 + %2 = load float, ptr @VarInit, align 4 + %add = fadd float %1, %2 + ret float %add +} + +define float @loadTLUninit() { +; SMALL64-LABEL: loadTLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfs f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfs f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarUninit) + %1 = load float, ptr %0, align 4 + ret float %1 +} + +define float @loadTLUninit2() { +; SMALL64-LABEL: loadTLUninit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfs f1, 0(r4) +; SMALL64-NEXT: lfs f0, 0(r3) +; SMALL64-NEXT: fadds f1, f0, f1 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLUninit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfs f1, 0(r4) +; LARGE64-NEXT: lfs f0, 0(r3) +; LARGE64-NEXT: fadds f1, f0, f1 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarUninit) + %1 = load float, ptr %0, align 4 + %2 = load float, ptr @VarInit, align 4 + %add = fadd float %1, %2 + ret float %add +} + +define float @loadTLInit() { +; SMALL64-LABEL: loadTLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfs f1, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfs f1, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarInit) + %1 = load float, ptr %0, align 4 + ret float %1 +} + +define float @loadTLInit2() { +; SMALL64-LABEL: loadTLInit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lfs f1, 0(r4) +; SMALL64-NEXT: lfs f0, 0(r3) +; SMALL64-NEXT: fadds f1, f0, f1 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLInit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lfs f1, 0(r4) +; LARGE64-NEXT: lfs f0, 0(r3) +; LARGE64-NEXT: fadds f1, f0, f1 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarInit) + %1 = load float, ptr %0, align 4 + %2 = load float, ptr @VarInit, align 4 + %add = fadd float %1, %2 + ret float %add +} + +; TOC Entry Checks. + +; SMALL64-LABEL: .toc +; SMALL64-LABEL: L..C0: +; SMALL64-NEXT: .tc IThreadLocalVarUninit[TC],IThreadLocalVarUninit[UL]@le +; SMALL64-LABEL: L..C1: +; SMALL64-NEXT: .tc IThreadLocalVarInit[TC],IThreadLocalVarInit[TL]@le +; SMALL64-LABEL: L..C2: +; SMALL64-NEXT: .tc ThreadLocalVarUninit[TC],ThreadLocalVarUninit[TL]@le +; SMALL64-LABEL: L..C3: +; SMALL64-NEXT: .tc ThreadLocalVarInit[TC],ThreadLocalVarInit[TL]@le +; SMALL64-LABEL: L..C4: +; SMALL64-NEXT: .tc VarInit[TC],VarInit[RW] + +; LARGE64-LABEL: .toc +; LARGE64-LABEL: L..C0: +; LARGE64-NEXT: .tc IThreadLocalVarUninit[TE],IThreadLocalVarUninit[UL]@le +; LARGE64-LABEL: L..C1: +; LARGE64-NEXT: .tc IThreadLocalVarInit[TE],IThreadLocalVarInit[TL]@le +; LARGE64-LABEL: L..C2: +; LARGE64-NEXT: .tc ThreadLocalVarUninit[TE],ThreadLocalVarUninit[TL]@le +; LARGE64-LABEL: L..C3: +; LARGE64-NEXT: .tc ThreadLocalVarInit[TE],ThreadLocalVarInit[TL]@le +; LARGE64-LABEL: L..C4: +; LARGE64-NEXT: .tc VarInit[TE],VarInit[RW] diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-int.ll b/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-int.ll new file mode 100644 index 0000000000000..1df848481da4b --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-int.ll @@ -0,0 +1,336 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s \ +; RUN: --check-prefix=SMALL64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large < %s \ +; RUN: | FileCheck %s --check-prefix=LARGE64 + +@ThreadLocalVarInit = thread_local(localexec) global i32 1, align 4 +@VarInit = global i32 87, align 4 +@IThreadLocalVarUninit = internal thread_local(localexec) global i32 0, align 4 +@IThreadLocalVarInit = internal thread_local(localexec) global i32 1, align 4 +@ThreadLocalVarUninit = thread_local(localexec) global i32 0, align 4 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1 + +define void @storeITLUninit(i32 noundef signext %x) { +; SMALL64-LABEL: storeITLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r4, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: add r4, r13, r4 +; SMALL64-NEXT: stw r3, 0(r4) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeITLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r4, L..C0@u(r2) +; LARGE64-NEXT: ld r4, L..C0@l(r4) +; LARGE64-NEXT: add r4, r13, r4 +; LARGE64-NEXT: stw r3, 0(r4) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarUninit) + store i32 %x, ptr %0, align 4 + ret void +} + +define void @storeITLInit(i32 noundef signext %x) { +; SMALL64-LABEL: storeITLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: add r4, r13, r4 +; SMALL64-NEXT: stw r3, 0(r4) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeITLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r4, L..C1@u(r2) +; LARGE64-NEXT: ld r4, L..C1@l(r4) +; LARGE64-NEXT: add r4, r13, r4 +; LARGE64-NEXT: stw r3, 0(r4) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarInit) + store i32 %x, ptr %0, align 4 + ret void +} + +define void @storeTLUninit(i32 noundef signext %x) { +; SMALL64-LABEL: storeTLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: add r4, r13, r4 +; SMALL64-NEXT: stw r3, 0(r4) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeTLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r4, L..C2@u(r2) +; LARGE64-NEXT: ld r4, L..C2@l(r4) +; LARGE64-NEXT: add r4, r13, r4 +; LARGE64-NEXT: stw r3, 0(r4) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarUninit) + store i32 %x, ptr %0, align 4 + ret void +} + +define void @storeTLInit(i32 noundef signext %x) { +; SMALL64-LABEL: storeTLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r4, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: add r4, r13, r4 +; SMALL64-NEXT: stw r3, 0(r4) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeTLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r4, L..C3@u(r2) +; LARGE64-NEXT: ld r4, L..C3@l(r4) +; LARGE64-NEXT: add r4, r13, r4 +; LARGE64-NEXT: stw r3, 0(r4) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarInit) + store i32 %x, ptr %0, align 4 + ret void +} + +define signext i32 @loadITLUninit() { +; SMALL64-LABEL: loadITLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lwa r3, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lwa r3, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarUninit) + %1 = load i32, ptr %0, align 4 + ret i32 %1 +} + +define signext i32 @loadITLUninit2() { +; SMALL64-LABEL: loadITLUninit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lwz r4, 0(r4) +; SMALL64-NEXT: lwz r3, 0(r3) +; SMALL64-NEXT: add r3, r4, r3 +; SMALL64-NEXT: extsw r3, r3 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLUninit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lwz r4, 0(r4) +; LARGE64-NEXT: lwz r3, 0(r3) +; LARGE64-NEXT: add r3, r4, r3 +; LARGE64-NEXT: extsw r3, r3 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarUninit) + %1 = load i32, ptr %0, align 4 + %2 = load i32, ptr @VarInit, align 4 + %add = add nsw i32 %2, %1 + ret i32 %add +} + +define signext i32 @loadITLInit() { +; SMALL64-LABEL: loadITLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lwa r3, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lwa r3, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarInit) + %1 = load i32, ptr %0, align 4 + ret i32 %1 +} + +define signext i32 @loadITLInit2() { +; SMALL64-LABEL: loadITLInit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lwz r4, 0(r4) +; SMALL64-NEXT: lwz r3, 0(r3) +; SMALL64-NEXT: add r3, r4, r3 +; SMALL64-NEXT: extsw r3, r3 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLInit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lwz r4, 0(r4) +; LARGE64-NEXT: lwz r3, 0(r3) +; LARGE64-NEXT: add r3, r4, r3 +; LARGE64-NEXT: extsw r3, r3 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarInit) + %1 = load i32, ptr %0, align 4 + %2 = load i32, ptr @VarInit, align 4 + %add = add nsw i32 %2, %1 + ret i32 %add +} + +define signext i32 @loadTLUninit() { +; SMALL64-LABEL: loadTLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lwa r3, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lwa r3, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarUninit) + %1 = load i32, ptr %0, align 4 + ret i32 %1 +} + +define signext i32 @loadTLUninit2() { +; SMALL64-LABEL: loadTLUninit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lwz r4, 0(r4) +; SMALL64-NEXT: lwz r3, 0(r3) +; SMALL64-NEXT: add r3, r4, r3 +; SMALL64-NEXT: extsw r3, r3 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLUninit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lwz r4, 0(r4) +; LARGE64-NEXT: lwz r3, 0(r3) +; LARGE64-NEXT: add r3, r4, r3 +; LARGE64-NEXT: extsw r3, r3 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarUninit) + %1 = load i32, ptr %0, align 4 + %2 = load i32, ptr @VarInit, align 4 + %add = add nsw i32 %2, %1 + ret i32 %add +} + +define signext i32 @loadTLInit() { +; SMALL64-LABEL: loadTLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lwa r3, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lwa r3, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarInit) + %1 = load i32, ptr %0, align 4 + ret i32 %1 +} + +define signext i32 @loadTLInit2() { +; SMALL64-LABEL: loadTLInit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: lwz r4, 0(r4) +; SMALL64-NEXT: lwz r3, 0(r3) +; SMALL64-NEXT: add r3, r4, r3 +; SMALL64-NEXT: extsw r3, r3 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLInit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: lwz r4, 0(r4) +; LARGE64-NEXT: lwz r3, 0(r3) +; LARGE64-NEXT: add r3, r4, r3 +; LARGE64-NEXT: extsw r3, r3 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarInit) + %1 = load i32, ptr %0, align 4 + %2 = load i32, ptr @VarInit, align 4 + %add = add nsw i32 %2, %1 + ret i32 %add +} + +; TOC Entry Checks. + +; SMALL64-LABEL: .toc +; SMALL64-LABEL: L..C0: +; SMALL64-NEXT: .tc IThreadLocalVarUninit[TC],IThreadLocalVarUninit[UL]@le +; SMALL64-LABEL: L..C1: +; SMALL64-NEXT: .tc IThreadLocalVarInit[TC],IThreadLocalVarInit[TL]@le +; SMALL64-LABEL: L..C2: +; SMALL64-NEXT: .tc ThreadLocalVarUninit[TC],ThreadLocalVarUninit[TL]@le +; SMALL64-LABEL: L..C3: +; SMALL64-NEXT: .tc ThreadLocalVarInit[TC],ThreadLocalVarInit[TL]@le +; SMALL64-LABEL: L..C4: +; SMALL64-NEXT: .tc VarInit[TC],VarInit[RW] + +; LARGE64-LABEL: .toc +; LARGE64-LABEL: L..C0: +; LARGE64-NEXT: .tc IThreadLocalVarUninit[TE],IThreadLocalVarUninit[UL]@le +; LARGE64-LABEL: L..C1: +; LARGE64-NEXT: .tc IThreadLocalVarInit[TE],IThreadLocalVarInit[TL]@le +; LARGE64-LABEL: L..C2: +; LARGE64-NEXT: .tc ThreadLocalVarUninit[TE],ThreadLocalVarUninit[TL]@le +; LARGE64-LABEL: L..C3: +; LARGE64-NEXT: .tc ThreadLocalVarInit[TE],ThreadLocalVarInit[TL]@le +; LARGE64-LABEL: L..C4: +; LARGE64-NEXT: .tc VarInit[TE],VarInit[RW] diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-longlong.ll b/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-longlong.ll new file mode 100644 index 0000000000000..8ef680909f91b --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-tls-le-ldst-longlong.ll @@ -0,0 +1,328 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s \ +; RUN: --check-prefix=SMALL64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large < %s \ +; RUN: | FileCheck %s --check-prefix=LARGE64 + +@ThreadLocalVarInit = thread_local(localexec) global i64 1, align 8 +@VarInit = global i64 87, align 8 +@IThreadLocalVarUninit = internal thread_local(localexec) global i64 0, align 8 +@IThreadLocalVarInit = internal thread_local(localexec) global i64 1, align 8 +@ThreadLocalVarUninit = thread_local(localexec) global i64 0, align 8 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1 + +define void @storeITLUninit(i64 noundef %x) { +; SMALL64-LABEL: storeITLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r4, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: add r4, r13, r4 +; SMALL64-NEXT: std r3, 0(r4) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeITLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r4, L..C0@u(r2) +; LARGE64-NEXT: ld r4, L..C0@l(r4) +; LARGE64-NEXT: add r4, r13, r4 +; LARGE64-NEXT: std r3, 0(r4) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarUninit) + store i64 %x, ptr %0, align 8 + ret void +} + +define void @storeITLInit(i64 noundef %x) { +; SMALL64-LABEL: storeITLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: add r4, r13, r4 +; SMALL64-NEXT: std r3, 0(r4) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeITLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r4, L..C1@u(r2) +; LARGE64-NEXT: ld r4, L..C1@l(r4) +; LARGE64-NEXT: add r4, r13, r4 +; LARGE64-NEXT: std r3, 0(r4) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarInit) + store i64 %x, ptr %0, align 8 + ret void +} + +define void @storeTLUninit(i64 noundef %x) { +; SMALL64-LABEL: storeTLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: add r4, r13, r4 +; SMALL64-NEXT: std r3, 0(r4) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeTLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r4, L..C2@u(r2) +; LARGE64-NEXT: ld r4, L..C2@l(r4) +; LARGE64-NEXT: add r4, r13, r4 +; LARGE64-NEXT: std r3, 0(r4) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarUninit) + store i64 %x, ptr %0, align 8 + ret void +} + +define void @storeTLInit(i64 noundef %x) { +; SMALL64-LABEL: storeTLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r4, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: add r4, r13, r4 +; SMALL64-NEXT: std r3, 0(r4) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: storeTLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r4, L..C3@u(r2) +; LARGE64-NEXT: ld r4, L..C3@l(r4) +; LARGE64-NEXT: add r4, r13, r4 +; LARGE64-NEXT: std r3, 0(r4) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarInit) + store i64 %x, ptr %0, align 8 + ret void +} + +define i64 @loadITLUninit() { +; SMALL64-LABEL: loadITLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: ld r3, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: ld r3, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarUninit) + %1 = load i64, ptr %0, align 8 + ret i64 %1 +} + +define i64 @loadITLUninit2() { +; SMALL64-LABEL: loadITLUninit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @IThreadLocalVarUninit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: ld r4, 0(r4) +; SMALL64-NEXT: ld r3, 0(r3) +; SMALL64-NEXT: add r3, r4, r3 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLUninit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C0@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C0@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: ld r4, 0(r4) +; LARGE64-NEXT: ld r3, 0(r3) +; LARGE64-NEXT: add r3, r4, r3 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarUninit) + %1 = load i64, ptr %0, align 8 + %2 = load i64, ptr @VarInit, align 8 + %add = add nsw i64 %2, %1 + ret i64 %add +} + +define i64 @loadITLInit() { +; SMALL64-LABEL: loadITLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: ld r3, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: ld r3, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarInit) + %1 = load i64, ptr %0, align 8 + ret i64 %1 +} + +define i64 @loadITLInit2() { +; SMALL64-LABEL: loadITLInit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @IThreadLocalVarInit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: ld r4, 0(r4) +; SMALL64-NEXT: ld r3, 0(r3) +; SMALL64-NEXT: add r3, r4, r3 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadITLInit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C1@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C1@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: ld r4, 0(r4) +; LARGE64-NEXT: ld r3, 0(r3) +; LARGE64-NEXT: add r3, r4, r3 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarInit) + %1 = load i64, ptr %0, align 8 + %2 = load i64, ptr @VarInit, align 8 + %add = add nsw i64 %2, %1 + ret i64 %add +} + +define i64 @loadTLUninit() { +; SMALL64-LABEL: loadTLUninit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: ld r3, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLUninit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: ld r3, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarUninit) + %1 = load i64, ptr %0, align 8 + ret i64 %1 +} + +define i64 @loadTLUninit2() { +; SMALL64-LABEL: loadTLUninit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @ThreadLocalVarUninit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: ld r4, 0(r4) +; SMALL64-NEXT: ld r3, 0(r3) +; SMALL64-NEXT: add r3, r4, r3 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLUninit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C2@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C2@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: ld r4, 0(r4) +; LARGE64-NEXT: ld r3, 0(r3) +; LARGE64-NEXT: add r3, r4, r3 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarUninit) + %1 = load i64, ptr %0, align 8 + %2 = load i64, ptr @VarInit, align 8 + %add = add nsw i64 %2, %1 + ret i64 %add +} + +define i64 @loadTLInit() { +; SMALL64-LABEL: loadTLInit: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: ld r3, 0(r3) +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLInit: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: ld r3, 0(r3) +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarInit) + %1 = load i64, ptr %0, align 8 + ret i64 %1 +} + +define i64 @loadTLInit2() { +; SMALL64-LABEL: loadTLInit2: +; SMALL64: # %bb.0: # %entry +; SMALL64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @ThreadLocalVarInit +; SMALL64-NEXT: ld r4, L..C4(r2) # @VarInit +; SMALL64-NEXT: add r3, r13, r3 +; SMALL64-NEXT: ld r4, 0(r4) +; SMALL64-NEXT: ld r3, 0(r3) +; SMALL64-NEXT: add r3, r4, r3 +; SMALL64-NEXT: blr +; +; LARGE64-LABEL: loadTLInit2: +; LARGE64: # %bb.0: # %entry +; LARGE64-NEXT: addis r3, L..C3@u(r2) +; LARGE64-NEXT: addis r4, L..C4@u(r2) +; LARGE64-NEXT: ld r3, L..C3@l(r3) +; LARGE64-NEXT: ld r4, L..C4@l(r4) +; LARGE64-NEXT: add r3, r13, r3 +; LARGE64-NEXT: ld r4, 0(r4) +; LARGE64-NEXT: ld r3, 0(r3) +; LARGE64-NEXT: add r3, r4, r3 +; LARGE64-NEXT: blr +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarInit) + %1 = load i64, ptr %0, align 8 + %2 = load i64, ptr @VarInit, align 8 + %add = add nsw i64 %2, %1 + ret i64 %add +} + +; TOC Entry Checks. + +; SMALL64-LABEL: .toc +; SMALL64-LABEL: L..C0: +; SMALL64-NEXT: .tc IThreadLocalVarUninit[TC],IThreadLocalVarUninit[UL]@le +; SMALL64-LABEL: L..C1: +; SMALL64-NEXT: .tc IThreadLocalVarInit[TC],IThreadLocalVarInit[TL]@le +; SMALL64-LABEL: L..C2: +; SMALL64-NEXT: .tc ThreadLocalVarUninit[TC],ThreadLocalVarUninit[TL]@le +; SMALL64-LABEL: L..C3: +; SMALL64-NEXT: .tc ThreadLocalVarInit[TC],ThreadLocalVarInit[TL]@le +; SMALL64-LABEL: L..C4: +; SMALL64-NEXT: .tc VarInit[TC],VarInit[RW] + +; LARGE64-LABEL: .toc +; LARGE64-LABEL: L..C0: +; LARGE64-NEXT: .tc IThreadLocalVarUninit[TE],IThreadLocalVarUninit[UL]@le +; LARGE64-LABEL: L..C1: +; LARGE64-NEXT: .tc IThreadLocalVarInit[TE],IThreadLocalVarInit[TL]@le +; LARGE64-LABEL: L..C2: +; LARGE64-NEXT: .tc ThreadLocalVarUninit[TE],ThreadLocalVarUninit[TL]@le +; LARGE64-LABEL: L..C3: +; LARGE64-NEXT: .tc ThreadLocalVarInit[TE],ThreadLocalVarInit[TL]@le +; LARGE64-LABEL: L..C4: +; LARGE64-NEXT: .tc VarInit[TE],VarInit[RW] diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-le-xcoff-reloc-large.ll b/llvm/test/CodeGen/PowerPC/aix-tls-le-xcoff-reloc-large.ll new file mode 100644 index 0000000000000..5404fdae4c03a --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-tls-le-xcoff-reloc-large.ll @@ -0,0 +1,218 @@ +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \ +; RUN: -xcoff-traceback-table=false --code-model=large -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck --check-prefix=RELOC %s +; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=SYM %s +; RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck --check-prefix=DIS %s + +@ThreadLocalVarInit = thread_local(localexec) global i64 1, align 8 +@VarInit = global i64 87, align 8 +@IThreadLocalVarUninit = internal thread_local(localexec) global i64 0, align 8 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +define void @storeITLUninit(i64 noundef %x) { +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @IThreadLocalVarUninit) + store i64 %x, ptr %0, align 8 + ret void +} + +define i64 @loadTLInit() { +entry: + %0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ThreadLocalVarInit) + %1 = load i64, ptr %0, align 8 + %2 = load i64, ptr @VarInit, align 8 + %add = add nsw i64 %2, %1 + ret i64 %add +} + +; RELOC: File: {{.*}}aix-tls-le-xcoff-reloc-large.ll.tmp.o +; RELOC-NEXT: Format: aix5coff64-rs6000 +; RELOC-NEXT: Arch: powerpc64 +; RELOC-NEXT: AddressSize: 64bit +; RELOC-NEXT: Relocations [ +; RELOC: Virtual Address: 0x2 +; RELOC-NEXT: Symbol: IThreadLocalVarUninit (15) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 16 +; RELOC-NEXT: Type: R_TOCU (0x30) +; RELOC-NEXT: } +; RELOC: Virtual Address: 0x6 +; RELOC-NEXT: Symbol: IThreadLocalVarUninit (15) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 16 +; RELOC-NEXT: Type: R_TOCL (0x31) +; RELOC-NEXT: } +; RELOC: Virtual Address: 0x22 +; RELOC-NEXT: Symbol: ThreadLocalVarInit (17) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 16 +; RELOC-NEXT: Type: R_TOCU (0x30) +; RELOC-NEXT: } +; RELOC: Virtual Address: 0x2A +; RELOC-NEXT: Symbol: ThreadLocalVarInit (17) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 16 +; RELOC-NEXT: Type: R_TOCL (0x31) +; RELOC-NEXT: } +; RELOC: Virtual Address: 0x80 +; RELOC-NEXT: Symbol: IThreadLocalVarUninit (23) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 64 +; RELOC-NEXT: Type: R_TLS_LE (0x23) +; RELOC-NEXT: } +; RELOC: Virtual Address: 0x88 +; RELOC-NEXT: Symbol: ThreadLocalVarInit (21) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 64 +; RELOC-NEXT: Type: R_TLS_LE (0x23) +; RELOC-NEXT: } + +; SYM: File: {{.*}}aix-tls-le-xcoff-reloc-large.ll.tmp.o +; SYM-NEXT: Format: aix5coff64-rs6000 +; SYM-NEXT: Arch: powerpc64 +; SYM-NEXT: AddressSize: 64bit +; SYM-NEXT: Symbols [ +; SYM: Index: 15 +; SYM-NEXT: Name: IThreadLocalVarUninit +; SYM-NEXT: Value (RelocatableAddress): 0x80 +; SYM-NEXT: Section: .data +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 16 +; SYM-NEXT: SectionLen: 8 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 3 +; SYM-NEXT: SymbolType: XTY_SD (0x1) +; SYM-NEXT: StorageMappingClass: XMC_TE (0x16) +; SYM-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYM-NEXT: } +; SYM-NEXT: } +; SYM: Index: 17 +; SYM-NEXT: Name: ThreadLocalVarInit +; SYM-NEXT: Value (RelocatableAddress): 0x88 +; SYM-NEXT: Section: .data +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 18 +; SYM-NEXT: SectionLen: 8 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 3 +; SYM-NEXT: SymbolType: XTY_SD (0x1) +; SYM-NEXT: StorageMappingClass: XMC_TE (0x16) +; SYM-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYM-NEXT: } +; SYM-NEXT: } +; SYM: Index: 21 +; SYM-NEXT: Name: ThreadLocalVarInit +; SYM-NEXT: Value (RelocatableAddress): 0x0 +; SYM-NEXT: Section: .tdata +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_EXT (0x2) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 22 +; SYM-NEXT: SectionLen: 8 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 3 +; SYM-NEXT: SymbolType: XTY_SD (0x1) +; SYM-NEXT: StorageMappingClass: XMC_TL (0x14) +; SYM-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYM-NEXT: } +; SYM-NEXT: } +; SYM: Index: 23 +; SYM-NEXT: Name: IThreadLocalVarUninit +; SYM-NEXT: Value (RelocatableAddress): 0x8 +; SYM-NEXT: Section: .tbss +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 24 +; SYM-NEXT: SectionLen: 8 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 3 +; SYM-NEXT: SymbolType: XTY_CM (0x3) +; SYM-NEXT: StorageMappingClass: XMC_UL (0x15) +; SYM-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYM-NEXT: } +; SYM-NEXT: } + +; DIS: {{.*}}aix-tls-le-xcoff-reloc-large.ll.tmp.o: file format aix5coff64-rs6000 +; DIS: Disassembly of section .text: +; DIS: 0000000000000000 (idx: 3) .storeITLUninit: +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 4, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: 15) IThreadLocalVarUninit[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 4, 0(4) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: 15) IThreadLocalVarUninit[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 4, 13, 4 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 3, 0(4) +; DIS-NEXT: blr +; DIS: 0000000000000020 (idx: 5) .loadTLInit: +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: 17) ThreadLocalVarInit[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 4, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: 19) VarInit[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 8(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: 17) ThreadLocalVarInit[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 4, 16(4) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: 19) VarInit[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 13, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 4, 0(4) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 0(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 4, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} blr + +; DIS: Disassembly of section .data: +; DIS: 0000000000000048 (idx: 7) VarInit[RW]: +; DIS-NEXT: 48: 00 00 00 00 +; DIS-NEXT: 4c: 00 00 00 57 +; DIS: 0000000000000050 (idx: 9) storeITLUninit[DS]: +; DIS-NEXT: 50: 00 00 00 00 +; DIS-NEXT: 0000000000000050: R_POS (idx: 3) .storeITLUninit +; DIS-NEXT: 54: 00 00 00 00 +; DIS-NEXT: 58: 00 00 00 00 +; DIS-NEXT: 0000000000000058: R_POS (idx: 13) TOC[TC0] +; DIS-NEXT: 5c: 00 00 00 80 +; DIS: 0000000000000068 (idx: 11) loadTLInit[DS]: +; DIS-NEXT: 68: 00 00 00 00 +; DIS-NEXT: 0000000000000068: R_POS (idx: 5) .loadTLInit +; DIS-NEXT: 6c: 00 00 00 20 +; DIS-NEXT: 70: 00 00 00 00 +; DIS-NEXT: 0000000000000070: R_POS (idx: 13) TOC[TC0] +; DIS-NEXT: 74: 00 00 00 80 +; DIS: 0000000000000080 (idx: 15) IThreadLocalVarUninit[TE]: +; DIS-NEXT: 80: 00 00 00 00 +; DIS-NEXT: 0000000000000080: R_TLS_LE (idx: 23) IThreadLocalVarUninit[UL] +; DIS-NEXT: 84: 00 00 00 00 +; DIS: 0000000000000088 (idx: 17) ThreadLocalVarInit[TE]: +; DIS-NEXT: 88: 00 00 00 00 +; DIS-NEXT: 0000000000000088: R_TLS_LE (idx: 21) ThreadLocalVarInit[TL] +; DIS-NEXT: 8c: 00 00 00 00 +; DIS: 0000000000000090 (idx: 19) VarInit[TE]: +; DIS-NEXT: 90: 00 00 00 00 +; DIS-NEXT: 0000000000000090: R_POS (idx: 7) VarInit[RW] +; DIS-NEXT: 94: 00 00 00 48 + +; DIS: Disassembly of section .tdata: +; DIS: 0000000000000000 (idx: 21) ThreadLocalVarInit[TL]: +; DIS-NEXT: 0: 00 00 00 00 +; DIS-NEXT: 4: 00 00 00 01 + +; DIS: Disassembly of section .tbss: +; DIS: 0000000000000008 (idx: 23) IThreadLocalVarUninit[UL]: +; DIS-NEXT: ... + diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-le-xcoff-reloc.ll b/llvm/test/CodeGen/PowerPC/aix-tls-le-xcoff-reloc.ll new file mode 100644 index 0000000000000..73a81a3d6f681 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-tls-le-xcoff-reloc.ll @@ -0,0 +1,194 @@ +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \ +; RUN: -xcoff-traceback-table=false -data-sections=false -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck --check-prefix=RELOC %s +; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=SYM %s +; RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck --check-prefix=DIS %s + +@ThreadLocalVarInit = thread_local(localexec) global i32 1, align 4 +@VarInit = global i32 87, align 4 +@IThreadLocalVarUninit = internal thread_local(localexec) global i32 0, align 4 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +define void @storeITLUninit(i32 noundef signext %x) { +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @IThreadLocalVarUninit) + store i32 %x, ptr %0, align 4 + ret void +} + +define signext i32 @loadTLInit() { +entry: + %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalVarInit) + %1 = load i32, ptr %0, align 4 + %2 = load i32, ptr @VarInit, align 4 + %add = add nsw i32 %2, %1 + ret i32 %add +} + +; RELOC: File: {{.*}}aix-tls-le-xcoff-reloc.ll.tmp.o +; RELOC-NEXT: Format: aix5coff64-rs6000 +; RELOC-NEXT: Arch: powerpc64 +; RELOC-NEXT: AddressSize: 64bit +; RELOC-NEXT: Relocations [ +; RELOC: Virtual Address: 0x2 +; RELOC-NEXT: Symbol: IThreadLocalVarUninit (17) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 16 +; RELOC-NEXT: Type: R_TOC (0x3) +; RELOC-NEXT: } +; RELOC: Virtual Address: 0x12 +; RELOC-NEXT: Symbol: ThreadLocalVarInit (19) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 16 +; RELOC-NEXT: Type: R_TOC (0x3) +; RELOC-NEXT: } +; RELOC: Virtual Address: 0x68 +; RELOC-NEXT: Symbol: IThreadLocalVarUninit (27) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 64 +; RELOC-NEXT: Type: R_TLS_LE (0x23) +; RELOC-NEXT: } +; RELOC: Virtual Address: 0x70 +; RELOC-NEXT: Symbol: ThreadLocalVarInit (25) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 64 +; RELOC-NEXT: Type: R_TLS_LE (0x23) +; RELOC-NEXT: } + +; SYM: File: {{.*}}aix-tls-le-xcoff-reloc.ll.tmp.o +; SYM-NEXT: Format: aix5coff64-rs6000 +; SYM-NEXT: Arch: powerpc64 +; SYM-NEXT: AddressSize: 64bit +; SYM-NEXT: Symbols [ +; SYM: Index: 17 +; SYM-NEXT: Name: IThreadLocalVarUninit +; SYM-NEXT: Value (RelocatableAddress): 0x68 +; SYM-NEXT: Section: .data +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 18 +; SYM-NEXT: SectionLen: 8 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 3 +; SYM-NEXT: SymbolType: XTY_SD (0x1) +; SYM-NEXT: StorageMappingClass: XMC_TC (0x3) +; SYM-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYM-NEXT: } +; SYM-NEXT: } +; SYM: Index: 19 +; SYM-NEXT: Name: ThreadLocalVarInit +; SYM-NEXT: Value (RelocatableAddress): 0x70 +; SYM-NEXT: Section: .data +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 20 +; SYM-NEXT: SectionLen: 8 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 3 +; SYM-NEXT: SymbolType: XTY_SD (0x1) +; SYM-NEXT: StorageMappingClass: XMC_TC (0x3) +; SYM-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYM-NEXT: } +; SYM-NEXT: } +; SYM: Index: 25 +; SYM-NEXT: Name: ThreadLocalVarInit +; SYM-NEXT: Value (RelocatableAddress): 0x0 +; SYM-NEXT: Section: .tdata +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_EXT (0x2) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 26 +; SYM-NEXT: ContainingCsectSymbolIndex: 23 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 0 +; SYM-NEXT: SymbolType: XTY_LD (0x2) +; SYM-NEXT: StorageMappingClass: XMC_TL (0x14) +; SYM-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYM-NEXT: } +; SYM-NEXT: } +; SYM: Index: 27 +; SYM-NEXT: Name: IThreadLocalVarUninit +; SYM-NEXT: Value (RelocatableAddress): 0x4 +; SYM-NEXT: Section: .tbss +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 28 +; SYM-NEXT: SectionLen: 4 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 2 +; SYM-NEXT: SymbolType: XTY_CM (0x3) +; SYM-NEXT: StorageMappingClass: XMC_UL (0x15) +; SYM-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYM-NEXT: } +; SYM-NEXT: } + +; DIS: {{.*}}aix-tls-le-xcoff-reloc.ll.tmp.o: file format aix5coff64-rs6000 +; DIS: Disassembly of section .text: +; DIS: 0000000000000000 (idx: 3) .storeITLUninit: +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 4, 0(2) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOC (idx: 17) IThreadLocalVarUninit[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 4, 13, 4 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 0(4) +; DIS-NEXT: blr +; DIS: 0000000000000010 (idx: 5) .loadTLInit: +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 8(2) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOC (idx: 19) ThreadLocalVarInit[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 4, 16(2) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOC (idx: 21) VarInit[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 13, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} lwz 4, 0(4) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} lwz 3, 0(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 4, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} extsw 3, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} blr + +; DIS: Disassembly of section .data: +; DIS: 0000000000000030 (idx: 9) VarInit: +; DIS-NEXT: 30: 00 00 00 57 +; DIS: 0000000000000038 (idx: 11) storeITLUninit[DS]: +; DIS-NEXT: 8: 00 00 00 00 +; DIS-NEXT: 0000000000000038: R_POS (idx: 3) .storeITLUninit +; DIS-NEXT: 3c: 00 00 00 00 +; DIS-NEXT: 40: 00 00 00 00 +; DIS-NEXT: 0000000000000040: R_POS (idx: 15) TOC[TC0] +; DIS-NEXT: 44: 00 00 00 68 +; DIS: 0000000000000050 (idx: 13) loadTLInit[DS]: +; DIS-NEXT: 50: 00 00 00 00 +; DIS-NEXT: 0000000000000050: R_POS (idx: 5) .loadTLInit +; DIS-NEXT: 54: 00 00 00 10 +; DIS-NEXT: 58: 00 00 00 00 +; DIS-NEXT: 0000000000000058: R_POS (idx: 15) TOC[TC0] +; DIS-NEXT: 5c: 00 00 00 68 +; DIS: 0000000000000068 (idx: 17) IThreadLocalVarUninit[TC]: +; DIS-NEXT: 68: 00 00 00 00 +; DIS-NEXT: 0000000000000068: R_TLS_LE (idx: 27) IThreadLocalVarUninit[UL] +; DIS: 0000000000000070 (idx: 19) ThreadLocalVarInit[TC]: +; DIS-NEXT: 70: 00 00 00 00 +; DIS-NEXT: 0000000000000070: R_TLS_LE (idx: 25) ThreadLocalVarInit +; DIS: 0000000000000078 (idx: 21) VarInit[TC]: +; DIS-NEXT: 78: 00 00 00 00 +; DIS-NEXT: 0000000000000078: R_POS (idx: 9) VarInit + +; DIS: Disassembly of section .tdata: +; DIS: 0000000000000000 (idx: 25) ThreadLocalVarInit: +; DIS-NEXT: 0: 00 00 00 01 + +; DIS: Disassembly of section .tbss: +; DIS: 0000000000000004 (idx: 27) IThreadLocalVarUninit[UL]: +; DIS-NEXT: ... +