[llvm] 21bea1a - [PowerPC] Support initial-exec TLS relocation on AIX

Qiu Chaofan via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 30 01:28:44 PDT 2023


Author: Qiu Chaofan
Date: 2023-08-30T16:22:16+08:00
New Revision: 21bea1a208692f26a7112b9f0f46edb21d706023

URL: https://github.com/llvm/llvm-project/commit/21bea1a208692f26a7112b9f0f46edb21d706023
DIFF: https://github.com/llvm/llvm-project/commit/21bea1a208692f26a7112b9f0f46edb21d706023.diff

LOG: [PowerPC] Support initial-exec TLS relocation on AIX

Add TLS_IE relocation type to XCOFF writer, and emit code sequence for
initial-exec TLS variables.

Reviewed By: lkail

Differential Revision: https://reviews.llvm.org/D156292

Added: 
    llvm/test/CodeGen/PowerPC/aix-tls-ie-ldst.ll
    llvm/test/CodeGen/PowerPC/aix-tls-ie-xcoff-reloc.ll

Modified: 
    llvm/include/llvm/MC/MCExpr.h
    llvm/lib/MC/MCExpr.cpp
    llvm/lib/MC/XCOFFObjectWriter.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/lib/Target/PowerPC/PPCISelLowering.h
    llvm/lib/Target/PowerPC/PPCInstr64Bit.td
    llvm/lib/Target/PowerPC/PPCInstrInfo.td

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 5bc5e04f79ffc3..67836292874f5f 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 at tlsgd
     VK_PPC_AIX_TLSGD,       // symbol at gd
     VK_PPC_AIX_TLSGDM,      // symbol at m
+    VK_PPC_AIX_TLSIE,       // symbol at ie
     VK_PPC_AIX_TLSLE,       // symbol at le
     VK_PPC_GOT_TLSLD,       // symbol at got@tlsld
     VK_PPC_GOT_TLSLD_LO,    // symbol at got@tlsld at l

diff  --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 392bc200ef30b4..73e6569f96e463 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_TLSIE:
+    return "ie";
   case VK_PPC_AIX_TLSLE:
     return "le";
   case VK_PPC_GOT_TLSLD: return "got at tlsld";

diff  --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index 036210d6b0efa2..2e8898cb6c5b38 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -697,7 +697,8 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
   const uint32_t Index = getIndex(SymA, SymASec);
   if (Type == XCOFF::RelocationType::R_POS ||
       Type == XCOFF::RelocationType::R_TLS ||
-      Type == XCOFF::RelocationType::R_TLS_LE)
+      Type == XCOFF::RelocationType::R_TLS_LE ||
+      Type == XCOFF::RelocationType::R_TLS_IE)
     // The FixedValue should be symbol's virtual address in this object file
     // plus any constant value that we might get.
     FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index 271f7ab757e164..3a1bda31282799 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -148,9 +148,10 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
           cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
               ->getQualNameSymbol();
       // On AIX, we have a region handle (symbol at m) and the variable offset
-      // (symbol@{gd|le}) for TLS variables, depending on the TLS model.
+      // (symbol@{gd|ie|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_TLSIE ||
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE)
         OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
            << MCSymbolRefExpr::getVariantKindName(Kind) << '\n';

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
index df671f53cbd8ce..ffdbfc4ddb0134 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
@@ -108,6 +108,8 @@ std::pair<uint8_t, uint8_t> 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_TLSIE:
+      return {XCOFF::RelocationType::R_TLS_IE, SignAndSizeForFKData};
     case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
       return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData};
     case MCSymbolRefExpr::VK_None:

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 37eb38363838f3..0e1d5911294eac 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -826,17 +826,17 @@ 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 
diff erentiated by MO_TPREL_FLAG.
+    // For TLS initial-exec and local-exec accesses on AIX, we have one TOC
+    // entry for the symbol (with the variable offset), which is 
diff erentiated
+    // 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!");
+      if (Model == TLSModel::InitialExec)
+        return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
+      llvm_unreachable("Only expecting local-exec or initial-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

diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 0f15ad12db19eb..384e437cf5d366 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3336,22 +3336,22 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
   bool Is64Bit = Subtarget.isPPC64();
   TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
 
-  if (Model == TLSModel::LocalExec) {
+  if (Model == TLSModel::LocalExec || Model == TLSModel::InitialExec) {
     SDValue VariableOffsetTGA =
         DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TPREL_FLAG);
     SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
     SDValue TLSReg;
     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).
+      // For local-exec and initial-exec on AIX (64-bit), the sequence 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
       TLSReg = DAG.getRegister(PPC::X13, MVT::i64);
     else
-      // For local-exec on AIX (32-bit), the sequence that is generated involves
-      // loading the variable offset from the TOC, generating a call to
+      // For local-exec and initial-exec on AIX (32-bit), the sequence generated
+      // involves loading the variable offset from the TOC, generating a call to
       // .__get_tpointer to get the thread pointer (which will be in R3), and
       // adding the two together:
       //    lwz reg1,var[TC](2)
@@ -3361,9 +3361,9 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
     return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
   }
 
-  // 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.
+  // Only Local-Exec, Initial-Exec and General-Dynamic TLS models are currently
+  // supported models. If Local- or Initial-exec are 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 e6ebc68008fb7b..6ef2d607ff9d3b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -356,9 +356,9 @@ namespace llvm {
     /// ADDIS_TLSGD_L_ADDR until after register assignment.
     GET_TLS_ADDR,
 
-    /// %x3 = GET_TPOINTER - Used for the local-exec TLS model on 32-bit AIX,
-    /// produces a call to .__get_tpointer to retrieve the thread pointer
-    /// At the end of the call, the thread pointer is found in R3.
+    /// %x3 = GET_TPOINTER - Used for the local- and initial-exec TLS model on
+    /// 32-bit AIX, produces a call to .__get_tpointer to retrieve the thread
+    /// pointer. At the end of the call, the thread pointer is found in R3.
     GET_TPOINTER,
 
     /// G8RC = ADDI_TLSGD_L_ADDR G8RReg, Symbol, Symbol - Op that

diff  --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index fd44efa1b3f4ec..7067239dd92802 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -1958,8 +1958,8 @@ def : Pat<(add i64:$in, (PPChi tblockaddress:$g, 0)),
 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:
+// The following pattern matches 64-bit local- and initial-exec TLS accesses on AIX.
+// PPCaddTls is used in local- and initial-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.

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 2992f78aa38ad7..4a8e36e8d242fe 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -3251,8 +3251,8 @@ def GETtlsTpointer32AIX : PPCEmitTimePseudo<(outs gprc:$rD), (ins),
                           "GETtlsTpointer32AIX",
                           [(set i32:$rD, (PPCgetTpointer))]>;
 
-// The following pattern matches local-exec TLS accesses on 32-bit AIX.
-// PPCaddTls is used in local-exec accesses in order to:
+// The following pattern matches local- and initial-exec TLS accesses on 32-bit AIX.
+// PPCaddTls is used in local- and initial-exec accesses in order to:
 //   - Get the address of a variable (add the variable offset to the thread
 //     pointer, retrieved by calling .__get_tpointer).
 //   - Create an opportunity to optimize the user of the loaded address.

diff  --git a/llvm/test/CodeGen/PowerPC/aix-tls-ie-ldst.ll b/llvm/test/CodeGen/PowerPC/aix-tls-ie-ldst.ll
new file mode 100644
index 00000000000000..adfdc94e764005
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-ie-ldst.ll
@@ -0,0 +1,1690 @@
+; 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 -code-model=large < %s | \
+; RUN:   FileCheck %s -check-prefix=LARGE64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \
+; RUN:   -mtriple powerpc64-ibm-aix-xcoff -code-model=small < %s | \
+; RUN:   FileCheck %s -check-prefix=SMALL64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \
+; RUN:   -mtriple powerpc-ibm-aix-xcoff -code-model=large < %s | \
+; RUN:   FileCheck %s -check-prefix=LARGE32
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \
+; RUN:   -mtriple powerpc-ibm-aix-xcoff -code-model=small < %s | \
+; RUN:   FileCheck %s -check-prefix=SMALL32
+
+ at global_int_zero = thread_local(initialexec) global i32 0, align 4
+ at global_int_nonzero = thread_local(initialexec) global i32 1, align 4
+ at intern_int_zero = internal thread_local(initialexec) global i32 0, align 4
+ at intern_int_nonzero = internal thread_local(initialexec) global i32 1, align 4
+
+ at global_long_zero = thread_local(initialexec) global i64 0, align 8
+ at global_long_nonzero = thread_local(initialexec) global i64 1, align 8
+ at intern_long_zero = internal thread_local(initialexec) global i64 0, align 8
+ at intern_long_nonzero = internal thread_local(initialexec) global i64 1, align 8
+
+ at global_float_zero = thread_local(initialexec) global float 0.000000, align 4
+ at global_float_nonzero = thread_local(initialexec) global float 1.000000, align 4
+ at intern_float_zero = internal thread_local(initialexec) global float 0.000000, align 4
+ at intern_float_nonzero = internal thread_local(initialexec) global float 1.000000, align 4
+
+ at global_double_zero = thread_local(initialexec) global double 0.000000, align 8
+ at global_double_nonzero = thread_local(initialexec) global double 1.000000, align 8
+ at intern_double_zero = internal thread_local(initialexec) global double 0.000000, align 8
+ at intern_double_nonzero = internal thread_local(initialexec) global double 1.000000, align 8
+
+define void @store_global_int_zero(i32 noundef signext %i) {
+; LARGE64-LABEL: store_global_int_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r4, L..C0 at u(r2)
+; LARGE64-NEXT:    ld r4, L..C0 at l(r4)
+; LARGE64-NEXT:    stwx r3, r13, r4
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_global_int_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r4, L..C0(r2) # target-flags(ppc-tprel) @global_int_zero
+; SMALL64-NEXT:    stwx r3, r13, r4
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_global_int_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    mr r4, r3
+; LARGE32-NEXT:    addis r3, L..C0 at u(r2)
+; LARGE32-NEXT:    lwz r5, L..C0 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stwx r4, r3, r5
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_global_int_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r5, L..C0(r2) # target-flags(ppc-tprel) @global_int_zero
+; SMALL32-NEXT:    mr r4, r3
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stwx r4, r3, r5
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_int_zero)
+  store i32 %i, ptr %addr, align 4
+  ret void
+}
+
+define void @store_global_int_nonzero(i32 noundef signext %i) {
+; LARGE64-LABEL: store_global_int_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r4, L..C1 at u(r2)
+; LARGE64-NEXT:    ld r4, L..C1 at l(r4)
+; LARGE64-NEXT:    stwx r3, r13, r4
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_global_int_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r4, L..C1(r2) # target-flags(ppc-tprel) @global_int_nonzero
+; SMALL64-NEXT:    stwx r3, r13, r4
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_global_int_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    mr r4, r3
+; LARGE32-NEXT:    addis r3, L..C1 at u(r2)
+; LARGE32-NEXT:    lwz r5, L..C1 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stwx r4, r3, r5
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_global_int_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r5, L..C1(r2) # target-flags(ppc-tprel) @global_int_nonzero
+; SMALL32-NEXT:    mr r4, r3
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stwx r4, r3, r5
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_int_nonzero)
+  store i32 %i, ptr %addr, align 4
+  ret void
+}
+
+define void @store_intern_int_zero(i32 noundef signext %i) {
+; LARGE64-LABEL: store_intern_int_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r4, L..C2 at u(r2)
+; LARGE64-NEXT:    ld r4, L..C2 at l(r4)
+; LARGE64-NEXT:    stwx r3, r13, r4
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_intern_int_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r4, L..C2(r2) # target-flags(ppc-tprel) @intern_int_zero
+; SMALL64-NEXT:    stwx r3, r13, r4
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_intern_int_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    mr r4, r3
+; LARGE32-NEXT:    addis r3, L..C2 at u(r2)
+; LARGE32-NEXT:    lwz r5, L..C2 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stwx r4, r3, r5
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_intern_int_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r5, L..C2(r2) # target-flags(ppc-tprel) @intern_int_zero
+; SMALL32-NEXT:    mr r4, r3
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stwx r4, r3, r5
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_int_zero)
+  store i32 %i, ptr %addr, align 4
+  ret void
+}
+
+define void @store_intern_int_nonzero(i32 noundef signext %i) {
+; LARGE64-LABEL: store_intern_int_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r4, L..C3 at u(r2)
+; LARGE64-NEXT:    ld r4, L..C3 at l(r4)
+; LARGE64-NEXT:    stwx r3, r13, r4
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_intern_int_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r4, L..C3(r2) # target-flags(ppc-tprel) @intern_int_nonzero
+; SMALL64-NEXT:    stwx r3, r13, r4
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_intern_int_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    mr r4, r3
+; LARGE32-NEXT:    addis r3, L..C3 at u(r2)
+; LARGE32-NEXT:    lwz r5, L..C3 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stwx r4, r3, r5
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_intern_int_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r5, L..C3(r2) # target-flags(ppc-tprel) @intern_int_nonzero
+; SMALL32-NEXT:    mr r4, r3
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stwx r4, r3, r5
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_int_nonzero)
+  store i32 %i, ptr %addr, align 4
+  ret void
+}
+
+define signext i32 @load_global_int_zero() {
+; LARGE64-LABEL: load_global_int_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C0 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C0 at l(r3)
+; LARGE64-NEXT:    lwax r3, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_global_int_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C0(r2) # target-flags(ppc-tprel) @global_int_zero
+; SMALL64-NEXT:    lwax r3, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_global_int_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C0 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C0 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lwzx r3, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_global_int_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C0(r2) # target-flags(ppc-tprel) @global_int_zero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lwzx r3, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_int_zero)
+  %val = load i32, ptr %addr, align 4
+  ret i32 %val
+}
+
+define signext i32 @load_global_int_nonzero() {
+; LARGE64-LABEL: load_global_int_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C1 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C1 at l(r3)
+; LARGE64-NEXT:    lwax r3, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_global_int_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C1(r2) # target-flags(ppc-tprel) @global_int_nonzero
+; SMALL64-NEXT:    lwax r3, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_global_int_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C1 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C1 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lwzx r3, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_global_int_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C1(r2) # target-flags(ppc-tprel) @global_int_nonzero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lwzx r3, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_int_nonzero)
+  %val = load i32, ptr %addr, align 4
+  ret i32 %val
+}
+
+define signext i32 @load_intern_int_zero() {
+; LARGE64-LABEL: load_intern_int_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C2 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C2 at l(r3)
+; LARGE64-NEXT:    lwax r3, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_intern_int_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C2(r2) # target-flags(ppc-tprel) @intern_int_zero
+; SMALL64-NEXT:    lwax r3, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_intern_int_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C2 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C2 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lwzx r3, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_intern_int_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C2(r2) # target-flags(ppc-tprel) @intern_int_zero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lwzx r3, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_int_zero)
+  %val = load i32, ptr %addr, align 4
+  ret i32 %val
+}
+
+define signext i32 @load_intern_int_nonzero() {
+; LARGE64-LABEL: load_intern_int_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C3 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C3 at l(r3)
+; LARGE64-NEXT:    lwax r3, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_intern_int_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C3(r2) # target-flags(ppc-tprel) @intern_int_nonzero
+; SMALL64-NEXT:    lwax r3, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_intern_int_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C3 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C3 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lwzx r3, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_intern_int_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C3(r2) # target-flags(ppc-tprel) @intern_int_nonzero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lwzx r3, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_int_nonzero)
+  %val = load i32, ptr %addr, align 4
+  ret i32 %val
+}
+
+define void @store_global_long_zero(i64 noundef %i) {
+; LARGE64-LABEL: store_global_long_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r4, L..C4 at u(r2)
+; LARGE64-NEXT:    ld r4, L..C4 at l(r4)
+; LARGE64-NEXT:    stdx r3, r13, r4
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_global_long_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r4, L..C4(r2) # target-flags(ppc-tprel) @global_long_zero
+; SMALL64-NEXT:    stdx r3, r13, r4
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_global_long_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    mr r5, r3
+; LARGE32-NEXT:    addis r3, L..C4 at u(r2)
+; LARGE32-NEXT:    lwz r6, L..C4 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    add r3, r3, r6
+; LARGE32-NEXT:    stw r4, 4(r3)
+; LARGE32-NEXT:    stw r5, 0(r3)
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_global_long_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r6, L..C4(r2) # target-flags(ppc-tprel) @global_long_zero
+; SMALL32-NEXT:    mr r5, r3
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    add r3, r3, r6
+; SMALL32-NEXT:    stw r4, 4(r3)
+; SMALL32-NEXT:    stw r5, 0(r3)
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @global_long_zero)
+  store i64 %i, ptr %addr, align 8
+  ret void
+}
+
+define void @store_global_long_nonzero(i64 noundef %i) {
+; LARGE64-LABEL: store_global_long_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r4, L..C5 at u(r2)
+; LARGE64-NEXT:    ld r4, L..C5 at l(r4)
+; LARGE64-NEXT:    stdx r3, r13, r4
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_global_long_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r4, L..C5(r2) # target-flags(ppc-tprel) @global_long_nonzero
+; SMALL64-NEXT:    stdx r3, r13, r4
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_global_long_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    mr r5, r3
+; LARGE32-NEXT:    addis r3, L..C5 at u(r2)
+; LARGE32-NEXT:    lwz r6, L..C5 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    add r3, r3, r6
+; LARGE32-NEXT:    stw r4, 4(r3)
+; LARGE32-NEXT:    stw r5, 0(r3)
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_global_long_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r6, L..C5(r2) # target-flags(ppc-tprel) @global_long_nonzero
+; SMALL32-NEXT:    mr r5, r3
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    add r3, r3, r6
+; SMALL32-NEXT:    stw r4, 4(r3)
+; SMALL32-NEXT:    stw r5, 0(r3)
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @global_long_nonzero)
+  store i64 %i, ptr %addr, align 8
+  ret void
+}
+
+define void @store_intern_long_zero(i64 noundef %i) {
+; LARGE64-LABEL: store_intern_long_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r4, L..C6 at u(r2)
+; LARGE64-NEXT:    ld r4, L..C6 at l(r4)
+; LARGE64-NEXT:    stdx r3, r13, r4
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_intern_long_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r4, L..C6(r2) # target-flags(ppc-tprel) @intern_long_zero
+; SMALL64-NEXT:    stdx r3, r13, r4
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_intern_long_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    mr r5, r3
+; LARGE32-NEXT:    addis r3, L..C6 at u(r2)
+; LARGE32-NEXT:    lwz r6, L..C6 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    add r3, r3, r6
+; LARGE32-NEXT:    stw r4, 4(r3)
+; LARGE32-NEXT:    stw r5, 0(r3)
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_intern_long_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r6, L..C6(r2) # target-flags(ppc-tprel) @intern_long_zero
+; SMALL32-NEXT:    mr r5, r3
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    add r3, r3, r6
+; SMALL32-NEXT:    stw r4, 4(r3)
+; SMALL32-NEXT:    stw r5, 0(r3)
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @intern_long_zero)
+  store i64 %i, ptr %addr, align 8
+  ret void
+}
+
+define void @store_intern_long_nonzero(i64 noundef %i) {
+; LARGE64-LABEL: store_intern_long_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r4, L..C7 at u(r2)
+; LARGE64-NEXT:    ld r4, L..C7 at l(r4)
+; LARGE64-NEXT:    stdx r3, r13, r4
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_intern_long_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r4, L..C7(r2) # target-flags(ppc-tprel) @intern_long_nonzero
+; SMALL64-NEXT:    stdx r3, r13, r4
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_intern_long_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    mr r5, r3
+; LARGE32-NEXT:    addis r3, L..C7 at u(r2)
+; LARGE32-NEXT:    lwz r6, L..C7 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    add r3, r3, r6
+; LARGE32-NEXT:    stw r4, 4(r3)
+; LARGE32-NEXT:    stw r5, 0(r3)
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_intern_long_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r6, L..C7(r2) # target-flags(ppc-tprel) @intern_long_nonzero
+; SMALL32-NEXT:    mr r5, r3
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    add r3, r3, r6
+; SMALL32-NEXT:    stw r4, 4(r3)
+; SMALL32-NEXT:    stw r5, 0(r3)
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @intern_long_nonzero)
+  store i64 %i, ptr %addr, align 8
+  ret void
+}
+
+define i64 @load_global_long_zero() {
+; LARGE64-LABEL: load_global_long_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C4 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C4 at l(r3)
+; LARGE64-NEXT:    ldx r3, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_global_long_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C4(r2) # target-flags(ppc-tprel) @global_long_zero
+; SMALL64-NEXT:    ldx r3, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_global_long_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C4 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C4 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    add r4, r3, r4
+; LARGE32-NEXT:    lwz r3, 0(r4)
+; LARGE32-NEXT:    lwz r4, 4(r4)
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_global_long_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C4(r2) # target-flags(ppc-tprel) @global_long_zero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    add r4, r3, r4
+; SMALL32-NEXT:    lwz r3, 0(r4)
+; SMALL32-NEXT:    lwz r4, 4(r4)
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @global_long_zero)
+  %val = load i64, ptr %addr, align 8
+  ret i64 %val
+}
+
+define i64 @load_global_long_nonzero() {
+; LARGE64-LABEL: load_global_long_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C5 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C5 at l(r3)
+; LARGE64-NEXT:    ldx r3, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_global_long_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C5(r2) # target-flags(ppc-tprel) @global_long_nonzero
+; SMALL64-NEXT:    ldx r3, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_global_long_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C5 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C5 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    add r4, r3, r4
+; LARGE32-NEXT:    lwz r3, 0(r4)
+; LARGE32-NEXT:    lwz r4, 4(r4)
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_global_long_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C5(r2) # target-flags(ppc-tprel) @global_long_nonzero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    add r4, r3, r4
+; SMALL32-NEXT:    lwz r3, 0(r4)
+; SMALL32-NEXT:    lwz r4, 4(r4)
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @global_long_nonzero)
+  %val = load i64, ptr %addr, align 8
+  ret i64 %val
+}
+
+define i64 @load_intern_long_zero() {
+; LARGE64-LABEL: load_intern_long_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C6 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C6 at l(r3)
+; LARGE64-NEXT:    ldx r3, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_intern_long_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C6(r2) # target-flags(ppc-tprel) @intern_long_zero
+; SMALL64-NEXT:    ldx r3, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_intern_long_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C6 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C6 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    add r4, r3, r4
+; LARGE32-NEXT:    lwz r3, 0(r4)
+; LARGE32-NEXT:    lwz r4, 4(r4)
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_intern_long_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C6(r2) # target-flags(ppc-tprel) @intern_long_zero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    add r4, r3, r4
+; SMALL32-NEXT:    lwz r3, 0(r4)
+; SMALL32-NEXT:    lwz r4, 4(r4)
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @intern_long_zero)
+  %val = load i64, ptr %addr, align 8
+  ret i64 %val
+}
+
+define i64 @load_intern_long_nonzero() {
+; LARGE64-LABEL: load_intern_long_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C7 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C7 at l(r3)
+; LARGE64-NEXT:    ldx r3, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_intern_long_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C7(r2) # target-flags(ppc-tprel) @intern_long_nonzero
+; SMALL64-NEXT:    ldx r3, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_intern_long_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C7 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C7 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    add r4, r3, r4
+; LARGE32-NEXT:    lwz r3, 0(r4)
+; LARGE32-NEXT:    lwz r4, 4(r4)
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_intern_long_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C7(r2) # target-flags(ppc-tprel) @intern_long_nonzero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    add r4, r3, r4
+; SMALL32-NEXT:    lwz r3, 0(r4)
+; SMALL32-NEXT:    lwz r4, 4(r4)
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @intern_long_nonzero)
+  %val = load i64, ptr %addr, align 8
+  ret i64 %val
+}
+
+define void @store_global_float_zero(float noundef %i) {
+; LARGE64-LABEL: store_global_float_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C8 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C8 at l(r3)
+; LARGE64-NEXT:    stfsx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_global_float_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C8(r2) # target-flags(ppc-tprel) @global_float_zero
+; SMALL64-NEXT:    stfsx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_global_float_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C8 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C8 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stfsx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_global_float_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C8(r2) # target-flags(ppc-tprel) @global_float_zero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stfsx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_float_zero)
+  store float %i, ptr %addr, align 4
+  ret void
+}
+
+define void @store_global_float_nonzero(float noundef %i) {
+; LARGE64-LABEL: store_global_float_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C9 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C9 at l(r3)
+; LARGE64-NEXT:    stfsx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_global_float_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C9(r2) # target-flags(ppc-tprel) @global_float_nonzero
+; SMALL64-NEXT:    stfsx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_global_float_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C9 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C9 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stfsx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_global_float_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C9(r2) # target-flags(ppc-tprel) @global_float_nonzero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stfsx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_float_nonzero)
+  store float %i, ptr %addr, align 4
+  ret void
+}
+
+define void @store_intern_float_zero(float noundef %i) {
+; LARGE64-LABEL: store_intern_float_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C10 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C10 at l(r3)
+; LARGE64-NEXT:    stfsx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_intern_float_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C10(r2) # target-flags(ppc-tprel) @intern_float_zero
+; SMALL64-NEXT:    stfsx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_intern_float_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C10 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C10 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stfsx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_intern_float_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C10(r2) # target-flags(ppc-tprel) @intern_float_zero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stfsx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_float_zero)
+  store float %i, ptr %addr, align 4
+  ret void
+}
+
+define void @store_intern_float_nonzero(float noundef %i) {
+; LARGE64-LABEL: store_intern_float_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C11 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C11 at l(r3)
+; LARGE64-NEXT:    stfsx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_intern_float_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C11(r2) # target-flags(ppc-tprel) @intern_float_nonzero
+; SMALL64-NEXT:    stfsx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_intern_float_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C11 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C11 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stfsx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_intern_float_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C11(r2) # target-flags(ppc-tprel) @intern_float_nonzero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stfsx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_float_nonzero)
+  store float %i, ptr %addr, align 4
+  ret void
+}
+
+define float @load_global_float_zero() {
+; LARGE64-LABEL: load_global_float_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C8 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C8 at l(r3)
+; LARGE64-NEXT:    lfsx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_global_float_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C8(r2) # target-flags(ppc-tprel) @global_float_zero
+; SMALL64-NEXT:    lfsx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_global_float_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C8 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C8 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lfsx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_global_float_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C8(r2) # target-flags(ppc-tprel) @global_float_zero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lfsx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_float_zero)
+  %val = load float, ptr %addr, align 4
+  ret float %val
+}
+
+define float @load_global_float_nonzero() {
+; LARGE64-LABEL: load_global_float_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C9 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C9 at l(r3)
+; LARGE64-NEXT:    lfsx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_global_float_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C9(r2) # target-flags(ppc-tprel) @global_float_nonzero
+; SMALL64-NEXT:    lfsx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_global_float_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C9 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C9 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lfsx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_global_float_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C9(r2) # target-flags(ppc-tprel) @global_float_nonzero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lfsx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_float_nonzero)
+  %val = load float, ptr %addr, align 4
+  ret float %val
+}
+
+define float @load_intern_float_zero() {
+; LARGE64-LABEL: load_intern_float_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C10 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C10 at l(r3)
+; LARGE64-NEXT:    lfsx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_intern_float_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C10(r2) # target-flags(ppc-tprel) @intern_float_zero
+; SMALL64-NEXT:    lfsx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_intern_float_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C10 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C10 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lfsx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_intern_float_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C10(r2) # target-flags(ppc-tprel) @intern_float_zero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lfsx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_float_zero)
+  %val = load float, ptr %addr, align 4
+  ret float %val
+}
+
+define float @load_intern_float_nonzero() {
+; LARGE64-LABEL: load_intern_float_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C11 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C11 at l(r3)
+; LARGE64-NEXT:    lfsx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_intern_float_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C11(r2) # target-flags(ppc-tprel) @intern_float_nonzero
+; SMALL64-NEXT:    lfsx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_intern_float_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C11 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C11 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lfsx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_intern_float_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C11(r2) # target-flags(ppc-tprel) @intern_float_nonzero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lfsx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_float_nonzero)
+  %val = load float, ptr %addr, align 4
+  ret float %val
+}
+
+define void @store_global_double_zero(double noundef %i) {
+; LARGE64-LABEL: store_global_double_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C12 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C12 at l(r3)
+; LARGE64-NEXT:    stfdx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_global_double_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C12(r2) # target-flags(ppc-tprel) @global_double_zero
+; SMALL64-NEXT:    stfdx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_global_double_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C12 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C12 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stfdx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_global_double_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C12(r2) # target-flags(ppc-tprel) @global_double_zero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stfdx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @global_double_zero)
+  store double %i, ptr %addr, align 8
+  ret void
+}
+
+define void @store_global_double_nonzero(double noundef %i) {
+; LARGE64-LABEL: store_global_double_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C13 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C13 at l(r3)
+; LARGE64-NEXT:    stfdx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_global_double_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C13(r2) # target-flags(ppc-tprel) @global_double_nonzero
+; SMALL64-NEXT:    stfdx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_global_double_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C13 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C13 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stfdx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_global_double_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C13(r2) # target-flags(ppc-tprel) @global_double_nonzero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stfdx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @global_double_nonzero)
+  store double %i, ptr %addr, align 8
+  ret void
+}
+
+define void @store_intern_double_zero(double noundef %i) {
+; LARGE64-LABEL: store_intern_double_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C14 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C14 at l(r3)
+; LARGE64-NEXT:    stfdx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_intern_double_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C14(r2) # target-flags(ppc-tprel) @intern_double_zero
+; SMALL64-NEXT:    stfdx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_intern_double_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C14 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C14 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stfdx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_intern_double_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C14(r2) # target-flags(ppc-tprel) @intern_double_zero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stfdx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @intern_double_zero)
+  store double %i, ptr %addr, align 8
+  ret void
+}
+
+define void @store_intern_double_nonzero(double noundef %i) {
+; LARGE64-LABEL: store_intern_double_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C15 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C15 at l(r3)
+; LARGE64-NEXT:    stfdx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: store_intern_double_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C15(r2) # target-flags(ppc-tprel) @intern_double_nonzero
+; SMALL64-NEXT:    stfdx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: store_intern_double_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C15 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C15 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    stfdx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: store_intern_double_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C15(r2) # target-flags(ppc-tprel) @intern_double_nonzero
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    stfdx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @intern_double_nonzero)
+  store double %i, ptr %addr, align 8
+  ret void
+}
+
+define double @load_global_double_zero() {
+; LARGE64-LABEL: load_global_double_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C12 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C12 at l(r3)
+; LARGE64-NEXT:    lfdx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_global_double_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C12(r2) # target-flags(ppc-tprel) @global_double_zero
+; SMALL64-NEXT:    lfdx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_global_double_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C12 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C12 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lfdx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_global_double_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C12(r2) # target-flags(ppc-tprel) @global_double_zero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lfdx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @global_double_zero)
+  %val = load double, ptr %addr, align 8
+  ret double %val
+}
+
+define double @load_global_double_nonzero() {
+; LARGE64-LABEL: load_global_double_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C13 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C13 at l(r3)
+; LARGE64-NEXT:    lfdx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_global_double_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C13(r2) # target-flags(ppc-tprel) @global_double_nonzero
+; SMALL64-NEXT:    lfdx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_global_double_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C13 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C13 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lfdx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_global_double_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C13(r2) # target-flags(ppc-tprel) @global_double_nonzero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lfdx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @global_double_nonzero)
+  %val = load double, ptr %addr, align 8
+  ret double %val
+}
+
+define double @load_intern_double_zero() {
+; LARGE64-LABEL: load_intern_double_zero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C14 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C14 at l(r3)
+; LARGE64-NEXT:    lfdx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_intern_double_zero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C14(r2) # target-flags(ppc-tprel) @intern_double_zero
+; SMALL64-NEXT:    lfdx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_intern_double_zero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C14 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C14 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lfdx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_intern_double_zero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C14(r2) # target-flags(ppc-tprel) @intern_double_zero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lfdx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @intern_double_zero)
+  %val = load double, ptr %addr, align 8
+  ret double %val
+}
+
+define double @load_intern_double_nonzero() {
+; LARGE64-LABEL: load_intern_double_nonzero:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    addis r3, L..C15 at u(r2)
+; LARGE64-NEXT:    ld r3, L..C15 at l(r3)
+; LARGE64-NEXT:    lfdx f1, r13, r3
+; LARGE64-NEXT:    blr
+;
+; SMALL64-LABEL: load_intern_double_nonzero:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    ld r3, L..C15(r2) # target-flags(ppc-tprel) @intern_double_nonzero
+; SMALL64-NEXT:    lfdx f1, r13, r3
+; SMALL64-NEXT:    blr
+;
+; LARGE32-LABEL: load_intern_double_nonzero:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr r0
+; LARGE32-NEXT:    stwu r1, -32(r1)
+; LARGE32-NEXT:    stw r0, 40(r1)
+; LARGE32-NEXT:    addis r3, L..C15 at u(r2)
+; LARGE32-NEXT:    lwz r4, L..C15 at l(r3)
+; LARGE32-NEXT:    bla .__get_tpointer[PR]
+; LARGE32-NEXT:    lfdx f1, r3, r4
+; LARGE32-NEXT:    addi r1, r1, 32
+; LARGE32-NEXT:    lwz r0, 8(r1)
+; LARGE32-NEXT:    mtlr r0
+; LARGE32-NEXT:    blr
+;
+; SMALL32-LABEL: load_intern_double_nonzero:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr r0
+; SMALL32-NEXT:    stwu r1, -32(r1)
+; SMALL32-NEXT:    lwz r4, L..C15(r2) # target-flags(ppc-tprel) @intern_double_nonzero
+; SMALL32-NEXT:    stw r0, 40(r1)
+; SMALL32-NEXT:    bla .__get_tpointer[PR]
+; SMALL32-NEXT:    lfdx f1, r3, r4
+; SMALL32-NEXT:    addi r1, r1, 32
+; SMALL32-NEXT:    lwz r0, 8(r1)
+; SMALL32-NEXT:    mtlr r0
+; SMALL32-NEXT:    blr
+entry:
+  %addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @intern_double_nonzero)
+  %val = load double, ptr %addr, align 8
+  ret double %val
+}
+
+declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
+
+; Lines below check if the symbols have correct suffix for TLS model, not
+; generated by test update script, but kept well after updates.
+
+; LARGE64: L..C0:
+; LARGE64-NEXT: .tc global_int_zero[TE],global_int_zero[TL]@ie
+; LARGE64-NEXT: L..C1:
+; LARGE64-NEXT: .tc global_int_nonzero[TE],global_int_nonzero[TL]@ie
+; LARGE64-NEXT: L..C2:
+; LARGE64-NEXT: .tc intern_int_zero[TE],intern_int_zero[UL]@ie
+; LARGE64-NEXT: L..C3:
+; LARGE64-NEXT: .tc intern_int_nonzero[TE],intern_int_nonzero[TL]@ie
+; LARGE64-NEXT: L..C4:
+; LARGE64-NEXT: .tc global_long_zero[TE],global_long_zero[TL]@ie
+; LARGE64-NEXT: L..C5:
+; LARGE64-NEXT: .tc global_long_nonzero[TE],global_long_nonzero[TL]@ie
+; LARGE64-NEXT: L..C6:
+; LARGE64-NEXT: .tc intern_long_zero[TE],intern_long_zero[UL]@ie
+; LARGE64-NEXT: L..C7:
+; LARGE64-NEXT: .tc intern_long_nonzero[TE],intern_long_nonzero[TL]@ie
+; LARGE64-NEXT: L..C8:
+; LARGE64-NEXT: .tc global_float_zero[TE],global_float_zero[TL]@ie
+; LARGE64-NEXT: L..C9:
+; LARGE64-NEXT: .tc global_float_nonzero[TE],global_float_nonzero[TL]@ie
+; LARGE64-NEXT: L..C10:
+; LARGE64-NEXT: .tc intern_float_zero[TE],intern_float_zero[UL]@ie
+; LARGE64-NEXT: L..C11:
+; LARGE64-NEXT: .tc intern_float_nonzero[TE],intern_float_nonzero[TL]@ie
+; LARGE64-NEXT: L..C12:
+; LARGE64-NEXT: .tc global_double_zero[TE],global_double_zero[TL]@ie
+; LARGE64-NEXT: L..C13:
+; LARGE64-NEXT: .tc global_double_nonzero[TE],global_double_nonzero[TL]@ie
+; LARGE64-NEXT: L..C14:
+; LARGE64-NEXT: .tc intern_double_zero[TE],intern_double_zero[UL]@ie
+; LARGE64-NEXT: L..C15:
+; LARGE64-NEXT: .tc intern_double_nonzero[TE],intern_double_nonzero[TL]@ie
+
+; SMALL64: L..C0:
+; SMALL64-NEXT: .tc global_int_zero[TC],global_int_zero[TL]@ie
+; SMALL64-NEXT: L..C1:
+; SMALL64-NEXT: .tc global_int_nonzero[TC],global_int_nonzero[TL]@ie
+; SMALL64-NEXT: L..C2:
+; SMALL64-NEXT: .tc intern_int_zero[TC],intern_int_zero[UL]@ie
+; SMALL64-NEXT: L..C3:
+; SMALL64-NEXT: .tc intern_int_nonzero[TC],intern_int_nonzero[TL]@ie
+; SMALL64-NEXT: L..C4:
+; SMALL64-NEXT: .tc global_long_zero[TC],global_long_zero[TL]@ie
+; SMALL64-NEXT: L..C5:
+; SMALL64-NEXT: .tc global_long_nonzero[TC],global_long_nonzero[TL]@ie
+; SMALL64-NEXT: L..C6:
+; SMALL64-NEXT: .tc intern_long_zero[TC],intern_long_zero[UL]@ie
+; SMALL64-NEXT: L..C7:
+; SMALL64-NEXT: .tc intern_long_nonzero[TC],intern_long_nonzero[TL]@ie
+; SMALL64-NEXT: L..C8:
+; SMALL64-NEXT: .tc global_float_zero[TC],global_float_zero[TL]@ie
+; SMALL64-NEXT: L..C9:
+; SMALL64-NEXT: .tc global_float_nonzero[TC],global_float_nonzero[TL]@ie
+; SMALL64-NEXT: L..C10:
+; SMALL64-NEXT: .tc intern_float_zero[TC],intern_float_zero[UL]@ie
+; SMALL64-NEXT: L..C11:
+; SMALL64-NEXT: .tc intern_float_nonzero[TC],intern_float_nonzero[TL]@ie
+; SMALL64-NEXT: L..C12:
+; SMALL64-NEXT: .tc global_double_zero[TC],global_double_zero[TL]@ie
+; SMALL64-NEXT: L..C13:
+; SMALL64-NEXT: .tc global_double_nonzero[TC],global_double_nonzero[TL]@ie
+; SMALL64-NEXT: L..C14:
+; SMALL64-NEXT: .tc intern_double_zero[TC],intern_double_zero[UL]@ie
+; SMALL64-NEXT: L..C15:
+; SMALL64-NEXT: .tc intern_double_nonzero[TC],intern_double_nonzero[TL]@ie
+
+; LARGE32: L..C0:
+; LARGE32-NEXT: .tc global_int_zero[TE],global_int_zero[TL]@ie
+; LARGE32-NEXT: L..C1:
+; LARGE32-NEXT: .tc global_int_nonzero[TE],global_int_nonzero[TL]@ie
+; LARGE32-NEXT: L..C2:
+; LARGE32-NEXT: .tc intern_int_zero[TE],intern_int_zero[UL]@ie
+; LARGE32-NEXT: L..C3:
+; LARGE32-NEXT: .tc intern_int_nonzero[TE],intern_int_nonzero[TL]@ie
+; LARGE32-NEXT: L..C4:
+; LARGE32-NEXT: .tc global_long_zero[TE],global_long_zero[TL]@ie
+; LARGE32-NEXT: L..C5:
+; LARGE32-NEXT: .tc global_long_nonzero[TE],global_long_nonzero[TL]@ie
+; LARGE32-NEXT: L..C6:
+; LARGE32-NEXT: .tc intern_long_zero[TE],intern_long_zero[UL]@ie
+; LARGE32-NEXT: L..C7:
+; LARGE32-NEXT: .tc intern_long_nonzero[TE],intern_long_nonzero[TL]@ie
+; LARGE32-NEXT: L..C8:
+; LARGE32-NEXT: .tc global_float_zero[TE],global_float_zero[TL]@ie
+; LARGE32-NEXT: L..C9:
+; LARGE32-NEXT: .tc global_float_nonzero[TE],global_float_nonzero[TL]@ie
+; LARGE32-NEXT: L..C10:
+; LARGE32-NEXT: .tc intern_float_zero[TE],intern_float_zero[UL]@ie
+; LARGE32-NEXT: L..C11:
+; LARGE32-NEXT: .tc intern_float_nonzero[TE],intern_float_nonzero[TL]@ie
+; LARGE32-NEXT: L..C12:
+; LARGE32-NEXT: .tc global_double_zero[TE],global_double_zero[TL]@ie
+; LARGE32-NEXT: L..C13:
+; LARGE32-NEXT: .tc global_double_nonzero[TE],global_double_nonzero[TL]@ie
+; LARGE32-NEXT: L..C14:
+; LARGE32-NEXT: .tc intern_double_zero[TE],intern_double_zero[UL]@ie
+; LARGE32-NEXT: L..C15:
+; LARGE32-NEXT: .tc intern_double_nonzero[TE],intern_double_nonzero[TL]@ie
+
+; SMALL32: L..C0:
+; SMALL32-NEXT: .tc global_int_zero[TC],global_int_zero[TL]@ie
+; SMALL32-NEXT: L..C1:
+; SMALL32-NEXT: .tc global_int_nonzero[TC],global_int_nonzero[TL]@ie
+; SMALL32-NEXT: L..C2:
+; SMALL32-NEXT: .tc intern_int_zero[TC],intern_int_zero[UL]@ie
+; SMALL32-NEXT: L..C3:
+; SMALL32-NEXT: .tc intern_int_nonzero[TC],intern_int_nonzero[TL]@ie
+; SMALL32-NEXT: L..C4:
+; SMALL32-NEXT: .tc global_long_zero[TC],global_long_zero[TL]@ie
+; SMALL32-NEXT: L..C5:
+; SMALL32-NEXT: .tc global_long_nonzero[TC],global_long_nonzero[TL]@ie
+; SMALL32-NEXT: L..C6:
+; SMALL32-NEXT: .tc intern_long_zero[TC],intern_long_zero[UL]@ie
+; SMALL32-NEXT: L..C7:
+; SMALL32-NEXT: .tc intern_long_nonzero[TC],intern_long_nonzero[TL]@ie
+; SMALL32-NEXT: L..C8:
+; SMALL32-NEXT: .tc global_float_zero[TC],global_float_zero[TL]@ie
+; SMALL32-NEXT: L..C9:
+; SMALL32-NEXT: .tc global_float_nonzero[TC],global_float_nonzero[TL]@ie
+; SMALL32-NEXT: L..C10:
+; SMALL32-NEXT: .tc intern_float_zero[TC],intern_float_zero[UL]@ie
+; SMALL32-NEXT: L..C11:
+; SMALL32-NEXT: .tc intern_float_nonzero[TC],intern_float_nonzero[TL]@ie
+; SMALL32-NEXT: L..C12:
+; SMALL32-NEXT: .tc global_double_zero[TC],global_double_zero[TL]@ie
+; SMALL32-NEXT: L..C13:
+; SMALL32-NEXT: .tc global_double_nonzero[TC],global_double_nonzero[TL]@ie
+; SMALL32-NEXT: L..C14:
+; SMALL32-NEXT: .tc intern_double_zero[TC],intern_double_zero[UL]@ie
+; SMALL32-NEXT: L..C15:
+; SMALL32-NEXT: .tc intern_double_nonzero[TC],intern_double_nonzero[TL]@ie

diff  --git a/llvm/test/CodeGen/PowerPC/aix-tls-ie-xcoff-reloc.ll b/llvm/test/CodeGen/PowerPC/aix-tls-ie-xcoff-reloc.ll
new file mode 100644
index 00000000000000..e34bb130d5ed21
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-ie-xcoff-reloc.ll
@@ -0,0 +1,387 @@
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -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=REL64 %s
+; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=SYM64 %s
+; RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck --check-prefix=DIS64 %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple=powerpc64-ibm-aix-xcoff -code-model=small \
+; 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=REL64 %s
+; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=SYM64 %s
+; RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck --check-prefix=DIS64 %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple=powerpc-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=REL32 %s
+; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=SYM32 %s
+; RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck --check-prefix=DIS32 %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple=powerpc-ibm-aix-xcoff -code-model=small \
+; 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=REL32 %s
+; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=SYM32 %s
+; RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck --check-prefix=DIS32 %s
+
+ at global_int_nonzero = thread_local(initialexec) global i32 1, align 4
+ at intern_int_zero = internal thread_local(initialexec) global i32 0, align 4
+
+define void @store_intern_int_zero(i32 noundef signext %i) {
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_int_zero)
+  store i32 %i, ptr %addr, align 4
+  ret void
+}
+
+define signext i32 @load_global_int_nonzero() {
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @global_int_nonzero)
+  %val = load i32, ptr %addr, align 4
+  ret i32 %val
+}
+
+define signext i32 @load_intern_int_zero() {
+entry:
+  %addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @intern_int_zero)
+  %val = load i32, ptr %addr, align 4
+  ret i32 %val
+}
+
+declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
+
+; REL64:      File: {{.*}}aix-tls-ie-xcoff-reloc.ll.tmp.o
+; REL64-NEXT: Format: aix5coff64-rs6000
+; REL64-NEXT: Arch: powerpc64
+; REL64-NEXT: AddressSize: 64bit
+; REL64-NEXT: Relocations [
+; REL64:       Virtual Address: 0x2
+; REL64-NEXT:       Symbol: intern_int_zero (17)
+; REL64-NEXT:       IsSigned: No
+; REL64-NEXT:       FixupBitValue: 0
+; REL64-NEXT:       Length: 16
+; REL64-NEXT:       Type: R_TOC (0x3)
+; REL64-NEXT:     }
+; REL64:       Virtual Address: 0x12
+; REL64-NEXT:       Symbol: global_int_nonzero (19)
+; REL64-NEXT:       IsSigned: No
+; REL64-NEXT:       FixupBitValue: 0
+; REL64-NEXT:       Length: 16
+; REL64-NEXT:       Type: R_TOC (0x3)
+; REL64-NEXT:     }
+; REL64:       Virtual Address: 0x22
+; REL64-NEXT:       Symbol: intern_int_zero (17)
+; REL64-NEXT:       IsSigned: No
+; REL64-NEXT:       FixupBitValue: 0
+; REL64-NEXT:       Length: 16
+; REL64-NEXT:       Type: R_TOC (0x3)
+; REL64-NEXT:     }
+; REL64:       Virtual Address: 0x78
+; REL64-NEXT:       Symbol: intern_int_zero (25)
+; REL64-NEXT:       IsSigned: No
+; REL64-NEXT:       FixupBitValue: 0
+; REL64-NEXT:       Length: 64
+; REL64-NEXT:       Type: R_TLS_IE (0x21)
+; REL64-NEXT:     }
+; REL64:       Virtual Address: 0x80
+; REL64-NEXT:       Symbol: global_int_nonzero (23)
+; REL64-NEXT:       IsSigned: No
+; REL64-NEXT:       FixupBitValue: 0
+; REL64-NEXT:       Length: 64
+; REL64-NEXT:       Type: R_TLS_IE (0x21)
+; REL64-NEXT:     }
+
+; SYM64:      File: {{.*}}aix-tls-ie-xcoff-reloc.ll.tmp.o
+; SYM64-NEXT: Format: aix5coff64-rs6000
+; SYM64-NEXT: Arch: powerpc64
+; SYM64-NEXT: AddressSize: 64bit
+; SYM64-NEXT: Symbols [
+; SYM64:     Index: 17
+; SYM64-NEXT:     Name: intern_int_zero
+; SYM64-NEXT:     Value (RelocatableAddress): 0x78
+; SYM64-NEXT:     Section: .data
+; SYM64-NEXT:     Type: 0x0
+; SYM64-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; SYM64-NEXT:     NumberOfAuxEntries: 1
+; SYM64-NEXT:     CSECT Auxiliary Entry {
+; SYM64-NEXT:       Index: 18
+; SYM64-NEXT:       SectionLen: 8
+; SYM64-NEXT:       ParameterHashIndex: 0x0
+; SYM64-NEXT:       TypeChkSectNum: 0x0
+; SYM64-NEXT:       SymbolAlignmentLog2: 3
+; SYM64-NEXT:       SymbolType: XTY_SD (0x1)
+; SYM64-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; SYM64-NEXT:       Auxiliary Type: AUX_CSECT (0xFB)
+; SYM64-NEXT:     }
+; SYM64-NEXT:   }
+; SYM64:     Index: 19
+; SYM64-NEXT:     Name: global_int_nonzero
+; SYM64-NEXT:     Value (RelocatableAddress): 0x80
+; SYM64-NEXT:     Section: .data
+; SYM64-NEXT:     Type: 0x0
+; SYM64-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; SYM64-NEXT:     NumberOfAuxEntries: 1
+; SYM64-NEXT:     CSECT Auxiliary Entry {
+; SYM64-NEXT:       Index: 20
+; SYM64-NEXT:       SectionLen: 8
+; SYM64-NEXT:       ParameterHashIndex: 0x0
+; SYM64-NEXT:       TypeChkSectNum: 0x0
+; SYM64-NEXT:       SymbolAlignmentLog2: 3
+; SYM64-NEXT:       SymbolType: XTY_SD (0x1)
+; SYM64-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; SYM64-NEXT:       Auxiliary Type: AUX_CSECT (0xFB)
+; SYM64-NEXT:     }
+; SYM64-NEXT:   }
+; SYM64:     Index: 23
+; SYM64-NEXT:     Name: global_int_nonzero
+; SYM64-NEXT:     Value (RelocatableAddress): 0x0
+; SYM64-NEXT:     Section: .tdata
+; SYM64-NEXT:     Type: 0x0
+; SYM64-NEXT:     StorageClass: C_EXT (0x2)
+; SYM64-NEXT:     NumberOfAuxEntries: 1
+; SYM64-NEXT:     CSECT Auxiliary Entry {
+; SYM64-NEXT:       Index: 24
+; SYM64-NEXT:       ContainingCsectSymbolIndex: 21
+; SYM64-NEXT:       ParameterHashIndex: 0x0
+; SYM64-NEXT:       TypeChkSectNum: 0x0
+; SYM64-NEXT:       SymbolAlignmentLog2: 0
+; SYM64-NEXT:       SymbolType: XTY_LD (0x2)
+; SYM64-NEXT:       StorageMappingClass: XMC_TL (0x14)
+; SYM64-NEXT:       Auxiliary Type: AUX_CSECT (0xFB)
+; SYM64-NEXT:     }
+; SYM64-NEXT:   }
+; SYM64:     Index: 25
+; SYM64-NEXT:     Name: intern_int_zero
+; SYM64-NEXT:     Value (RelocatableAddress): 0x4
+; SYM64-NEXT:     Section: .tbss
+; SYM64-NEXT:     Type: 0x0
+; SYM64-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; SYM64-NEXT:     NumberOfAuxEntries: 1
+; SYM64-NEXT:     CSECT Auxiliary Entry {
+; SYM64-NEXT:       Index: 26
+; SYM64-NEXT:       SectionLen: 4
+; SYM64-NEXT:       ParameterHashIndex: 0x0
+; SYM64-NEXT:       TypeChkSectNum: 0x0
+; SYM64-NEXT:       SymbolAlignmentLog2: 2
+; SYM64-NEXT:       SymbolType: XTY_CM (0x3)
+; SYM64-NEXT:       StorageMappingClass: XMC_UL (0x15)
+; SYM64-NEXT:       Auxiliary Type: AUX_CSECT (0xFB)
+; SYM64-NEXT:     }
+; SYM64-NEXT:   }
+
+; DIS64: {{.*}}aix-tls-ie-xcoff-reloc.ll.tmp.o:	file format aix5coff64-rs6000
+; DIS64: Disassembly of section .text:
+; DIS64: (idx: 3) .store_intern_int_zero:
+; DIS64-NEXT: ld 4, 0(2)
+; DIS64-NEXT: (idx: 17) intern_int_zero[TC]
+; DIS64-NEXT: stwx 3, 13, 4
+; DIS64-NEXT: blr
+; DIS64: (idx: 5) .load_global_int_nonzero:
+; DIS64-NEXT: ld 3, 8(2)
+; DIS64-NEXT: (idx: 19) global_int_nonzero[TC]
+; DIS64-NEXT: lwax 3, 13, 3
+; DIS64-NEXT: blr
+; DIS64: (idx: 7) .load_intern_int_zero:
+; DIS64-NEXT: ld 3, 0(2)
+; DIS64-NEXT: (idx: 17) intern_int_zero[TC]
+; DIS64-NEXT: lwax 3, 13, 3
+; DIS64-NEXT: blr
+
+; DIS64: Disassembly of section .data:
+; DIS64: (idx: 9) store_intern_int_zero[DS]:
+; DIS64: R_POS        (idx: 3) .store_intern_int_zero
+; DIS64: R_POS        (idx: 15) TOC[TC0]
+; DIS64: (idx: 11) load_global_int_nonzero[DS]:
+; DIS64: R_POS        (idx: 5) .load_global_int_nonzero
+; DIS64: R_POS        (idx: 15) TOC[TC0]
+; DIS64: (idx: 13) load_intern_int_zero[DS]:
+; DIS64: R_POS        (idx: 7) .load_intern_int_zero
+; DIS64: R_POS        (idx: 15) TOC[TC0]
+; DIS64: (idx: 17) intern_int_zero[TC]:
+; DIS64: R_TLS_IE     (idx: 25) intern_int_zero[UL]
+; DIS64: (idx: 19) global_int_nonzero[TC]:
+; DIS64: R_TLS_IE     (idx: 23) global_int_nonzero
+
+; DIS64: Disassembly of section .tdata:
+; DIS64: (idx: 23) global_int_nonzero:
+
+; DIS64: Disassembly of section .tbss:
+; DIS64: (idx: 25) intern_int_zero[UL]:
+
+; REL32:      File: {{.*}}aix-tls-ie-xcoff-reloc.ll.tmp.o
+; REL32-NEXT: Format: aixcoff-rs6000
+; REL32-NEXT: Arch: powerpc
+; REL32-NEXT: AddressSize: 32bit
+; REL32-NEXT: Relocations [
+; REL32:       Virtual Address: 0xA
+; REL32-NEXT:       Symbol: intern_int_zero (19)
+; REL32-NEXT:       IsSigned: No
+; REL32-NEXT:       FixupBitValue: 0
+; REL32-NEXT:       Length: 16
+; REL32-NEXT:       Type: R_TOC (0x3)
+; REL32-NEXT:     }
+; REL32:       Virtual Address: 0x10
+; REL32-NEXT:       Symbol: .__get_tpointer (1)
+; REL32-NEXT:       IsSigned: No
+; REL32-NEXT:       FixupBitValue: 0
+; REL32-NEXT:       Length: 26
+; REL32-NEXT:       Type: R_RBA (0x18)
+; REL32-NEXT:     }
+; REL32:       Virtual Address: 0x3A
+; REL32-NEXT:       Symbol: global_int_nonzero (21)
+; REL32-NEXT:       IsSigned: No
+; REL32-NEXT:       FixupBitValue: 0
+; REL32-NEXT:       Length: 16
+; REL32-NEXT:       Type: R_TOC (0x3)
+; REL32-NEXT:     }
+; REL32:       Virtual Address: 0x40
+; REL32-NEXT:       Symbol: .__get_tpointer (1)
+; REL32-NEXT:       IsSigned: No
+; REL32-NEXT:       FixupBitValue: 0
+; REL32-NEXT:       Length: 26
+; REL32-NEXT:       Type: R_RBA (0x18)
+; REL32-NEXT:     }
+; REL32:       Virtual Address: 0x6A
+; REL32-NEXT:       Symbol: intern_int_zero (19)
+; REL32-NEXT:       IsSigned: No
+; REL32-NEXT:       FixupBitValue: 0
+; REL32-NEXT:       Length: 16
+; REL32-NEXT:       Type: R_TOC (0x3)
+; REL32-NEXT:     }
+; REL32:       Virtual Address: 0x70
+; REL32-NEXT:       Symbol: .__get_tpointer (1)
+; REL32-NEXT:       IsSigned: No
+; REL32-NEXT:       FixupBitValue: 0
+; REL32-NEXT:       Length: 26
+; REL32-NEXT:       Type: R_RBA (0x18)
+; REL32-NEXT:     }
+; REL32:       Virtual Address: 0xAC
+; REL32-NEXT:       Symbol: intern_int_zero (27)
+; REL32-NEXT:       IsSigned: No
+; REL32-NEXT:       FixupBitValue: 0
+; REL32-NEXT:       Length: 32
+; REL32-NEXT:       Type: R_TLS_IE (0x21)
+; REL32-NEXT:     }
+; REL32:       Virtual Address: 0xB0
+; REL32-NEXT:       Symbol: global_int_nonzero (25)
+; REL32-NEXT:       IsSigned: No
+; REL32-NEXT:       FixupBitValue: 0
+; REL32-NEXT:       Length: 32
+; REL32-NEXT:       Type: R_TLS_IE (0x21)
+; REL32-NEXT:     }
+
+; SYM32:      File: {{.*}}aix-tls-ie-xcoff-reloc.ll.tmp.o
+; SYM32-NEXT: Format: aixcoff-rs6000
+; SYM32-NEXT: Arch: powerpc
+; SYM32-NEXT: AddressSize: 32bit
+; SYM32-NEXT: Symbols [
+; SYM32:     Index: 19
+; SYM32-NEXT:     Name: intern_int_zero
+; SYM32-NEXT:     Value (RelocatableAddress): 0xAC
+; SYM32-NEXT:     Section: .data
+; SYM32-NEXT:     Type: 0x0
+; SYM32-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; SYM32-NEXT:     NumberOfAuxEntries: 1
+; SYM32-NEXT:     CSECT Auxiliary Entry {
+; SYM32-NEXT:       Index: 20
+; SYM32-NEXT:       SectionLen: 4
+; SYM32-NEXT:       ParameterHashIndex: 0x0
+; SYM32-NEXT:       TypeChkSectNum: 0x0
+; SYM32-NEXT:       SymbolAlignmentLog2: 2
+; SYM32-NEXT:       SymbolType: XTY_SD (0x1)
+; SYM32-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; SYM32-NEXT:       StabInfoIndex: 0x0
+; SYM32-NEXT:       StabSectNum: 0x0
+; SYM32-NEXT:     }
+; SYM32-NEXT:   }
+; SYM32:     Index: 21
+; SYM32-NEXT:     Name: global_int_nonzero
+; SYM32-NEXT:     Value (RelocatableAddress): 0xB0
+; SYM32-NEXT:     Section: .data
+; SYM32-NEXT:     Type: 0x0
+; SYM32-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; SYM32-NEXT:     NumberOfAuxEntries: 1
+; SYM32-NEXT:     CSECT Auxiliary Entry {
+; SYM32-NEXT:       Index: 22
+; SYM32-NEXT:       SectionLen: 4
+; SYM32-NEXT:       ParameterHashIndex: 0x0
+; SYM32-NEXT:       TypeChkSectNum: 0x0
+; SYM32-NEXT:       SymbolAlignmentLog2: 2
+; SYM32-NEXT:       SymbolType: XTY_SD (0x1)
+; SYM32-NEXT:       StorageMappingClass: XMC_TC (0x3)
+; SYM32-NEXT:       StabInfoIndex: 0x0
+; SYM32-NEXT:       StabSectNum: 0x0
+; SYM32-NEXT:     }
+; SYM32-NEXT:   }
+; SYM32:     Index: 25
+; SYM32-NEXT:     Name: global_int_nonzero
+; SYM32-NEXT:     Value (RelocatableAddress): 0x0
+; SYM32-NEXT:     Section: .tdata
+; SYM32-NEXT:     Type: 0x0
+; SYM32-NEXT:     StorageClass: C_EXT (0x2)
+; SYM32-NEXT:     NumberOfAuxEntries: 1
+; SYM32-NEXT:     CSECT Auxiliary Entry {
+; SYM32-NEXT:       Index: 26
+; SYM32-NEXT:       ContainingCsectSymbolIndex: 23
+; SYM32-NEXT:       ParameterHashIndex: 0x0
+; SYM32-NEXT:       TypeChkSectNum: 0x0
+; SYM32-NEXT:       SymbolAlignmentLog2: 0
+; SYM32-NEXT:       SymbolType: XTY_LD (0x2)
+; SYM32-NEXT:       StorageMappingClass: XMC_TL (0x14)
+; SYM32-NEXT:       StabInfoIndex: 0x0
+; SYM32-NEXT:       StabSectNum: 0x0
+; SYM32-NEXT:     }
+; SYM32-NEXT:   }
+; SYM32:     Index: 27
+; SYM32-NEXT:     Name: intern_int_zero
+; SYM32-NEXT:     Value (RelocatableAddress): 0x4
+; SYM32-NEXT:     Section: .tbss
+; SYM32-NEXT:     Type: 0x0
+; SYM32-NEXT:     StorageClass: C_HIDEXT (0x6B)
+; SYM32-NEXT:     NumberOfAuxEntries: 1
+; SYM32-NEXT:     CSECT Auxiliary Entry {
+; SYM32-NEXT:       Index: 28
+; SYM32-NEXT:       SectionLen: 4
+; SYM32-NEXT:       ParameterHashIndex: 0x0
+; SYM32-NEXT:       TypeChkSectNum: 0x0
+; SYM32-NEXT:       SymbolAlignmentLog2: 2
+; SYM32-NEXT:       SymbolType: XTY_CM (0x3)
+; SYM32-NEXT:       StorageMappingClass: XMC_UL (0x15)
+; SYM32-NEXT:       StabInfoIndex: 0x0
+; SYM32-NEXT:       StabSectNum: 0x0
+; SYM32-NEXT:     }
+; SYM32-NEXT:   }
+
+; DIS32: {{.*}}aix-tls-ie-xcoff-reloc.ll.tmp.o:	file format aixcoff-rs6000
+; DIS32: Disassembly of section .text:
+; DIS32: (idx: 5) .store_intern_int_zero:
+; DIS32: R_TOC        (idx: 19) intern_int_zero[TC]
+; DIS32: R_RBA        (idx: 1) .__get_tpointer[PR]
+; DIS32: blr
+; DIS32: (idx: 7) .load_global_int_nonzero:
+; DIS32: R_TOC        (idx: 21) global_int_nonzero[TC]
+; DIS32: R_RBA        (idx: 1) .__get_tpointer[PR]
+; DIS32: blr
+; DIS32: (idx: 9) .load_intern_int_zero:
+; DIS32: R_TOC        (idx: 19) intern_int_zero[TC]
+; DIS32: R_RBA        (idx: 1) .__get_tpointer[PR]
+; DIS32: blr
+
+; DIS32: Disassembly of section .data:
+; DIS32: (idx: 11) store_intern_int_zero[DS]:
+; DIS32: R_POS        (idx: 5) .store_intern_int_zero
+; DIS32: R_POS        (idx: 17) TOC[TC0]
+; DIS32: (idx: 13) load_global_int_nonzero[DS]:
+; DIS32: R_POS        (idx: 7) .load_global_int_nonzero
+; DIS32: R_POS        (idx: 17) TOC[TC0]
+; DIS32: (idx: 15) load_intern_int_zero[DS]:
+; DIS32: R_POS        (idx: 9) .load_intern_int_zero
+; DIS32: R_POS        (idx: 17) TOC[TC0]
+; DIS32: (idx: 19) intern_int_zero[TC]:
+; DIS32: R_TLS_IE     (idx: 27) intern_int_zero[UL]
+; DIS32: (idx: 21) global_int_nonzero[TC]:
+; DIS32: R_TLS_IE     (idx: 25) global_int_nonzero
+
+; DIS32: Disassembly of section .tdata:
+; DIS32: (idx: 25) global_int_nonzero:
+
+; DIS32: Disassembly of section .tbss:
+; DIS32: (idx: 27) intern_int_zero[UL]:


        


More information about the llvm-commits mailing list