[clang] [llvm] [PowerPC] Tune AIX shared library TLS model at function level (PR #84132)

Felix via cfe-commits cfe-commits at lists.llvm.org
Wed May 8 17:27:16 PDT 2024


https://github.com/orcguru updated https://github.com/llvm/llvm-project/pull/84132

>From a61fcecc1186fd149b694bc8c4d185d05712e815 Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Wed, 6 Mar 2024 02:51:40 -0500
Subject: [PATCH 01/10] [PowerPC] Rename symbols references by
 tls-local-dynamic model

On AIX, rename those tls-local-dynamic referenced TOC symbols, so that in
following patches we can switch between different TLS models (local-dynamic
or initial-exec) for the same TLS GV in different functions within the same
module.
---
 .../CodeGen/TargetLoweringObjectFileImpl.h    |   5 +-
 llvm/include/llvm/MC/MCContext.h              |   3 +-
 .../llvm/Target/TargetLoweringObjectFile.h    |   6 +-
 llvm/lib/MC/MCContext.cpp                     |   5 +-
 .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp  |  15 +-
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     |   6 +-
 .../test/CodeGen/PowerPC/aix-tls-gd-double.ll |  12 +-
 llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll   |  12 +-
 .../CodeGen/PowerPC/aix-tls-gd-longlong.ll    |  24 +-
 .../PowerPC/aix-tls-ld-unqualified-symbols.ll | 362 ++++++++++++++++++
 .../CodeGen/PowerPC/aix-tls-local-dynamic.ll  |  39 +-
 11 files changed, 449 insertions(+), 40 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/aix-tls-ld-unqualified-symbols.ll

diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 8eef45ce565de..1aa25e98423af 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -279,8 +279,9 @@ class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile {
   MCSection *
   getSectionForFunctionDescriptor(const Function *F,
                                   const TargetMachine &TM) const override;
-  MCSection *getSectionForTOCEntry(const MCSymbol *Sym,
-                                   const TargetMachine &TM) const override;
+  MCSection *
+  getSectionForTOCEntry(const MCSymbol *Sym, const TargetMachine &TM,
+                        const MCSymbolRefExpr::VariantKind VK) const override;
 
   /// For external functions, this will always return a function descriptor
   /// csect.
diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index ef9833cdf2b07..3708b2dff727e 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -691,7 +691,8 @@ class MCContext {
       std::optional<XCOFF::CsectProperties> CsectProp = std::nullopt,
       bool MultiSymbolsAllowed = false, const char *BeginSymName = nullptr,
       std::optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSubtypeFlags =
-          std::nullopt);
+          std::nullopt,
+      StringRef RenamePrefix = StringRef());
 
   // Create and save a copy of STI and return a reference to the copy.
   MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index 0c09cfe684783..31a466a18d77a 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
 #define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
 
+#include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCRegister.h"
 #include <cstdint>
@@ -256,8 +257,9 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
   /// On targets that support TOC entries, return a section for the entry given
   /// the symbol it refers to.
   /// TODO: Implement this interface for existing ELF targets.
-  virtual MCSection *getSectionForTOCEntry(const MCSymbol *S,
-                                           const TargetMachine &TM) const {
+  virtual MCSection *
+  getSectionForTOCEntry(const MCSymbol *S, const TargetMachine &TM,
+                        const MCSymbolRefExpr::VariantKind VK) const {
     return nullptr;
   }
 
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 3aee96fdf57fc..b8e96c7b6995d 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -785,7 +785,8 @@ MCSectionXCOFF *MCContext::getXCOFFSection(
     StringRef Section, SectionKind Kind,
     std::optional<XCOFF::CsectProperties> CsectProp, bool MultiSymbolsAllowed,
     const char *BeginSymName,
-    std::optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSectionSubtypeFlags) {
+    std::optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSectionSubtypeFlags,
+    StringRef RenamePrefix) {
   bool IsDwarfSec = DwarfSectionSubtypeFlags.has_value();
   assert((IsDwarfSec != CsectProp.has_value()) && "Invalid XCOFF section!");
 
@@ -811,7 +812,7 @@ MCSectionXCOFF *MCContext::getXCOFFSection(
     QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(CachedName));
   else
     QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(
-        CachedName + "[" +
+        RenamePrefix + CachedName + "[" +
         XCOFF::getMappingClassString(CsectProp->MappingClass) + "]"));
 
   MCSymbol *Begin = nullptr;
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index 9106e6ab6397d..13cce8fb27129 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -232,6 +232,20 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
       MCSymbolXCOFF *TCSym =
           cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
               ->getQualNameSymbol();
+
+      // On AIX, symbol accessed using TLS local-dynamic model has been renamed
+      // by adding prefix "_$TLSLD.". Do assert that it has been renamed, and
+      // then emit the .rename with the original symbol name.
+      if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD) {
+        assert(TCSym->hasRename());
+        OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
+           << MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
+        StringRef Lhs, Rhs;
+        std::tie(Lhs, Rhs) = TCSym->getSymbolTableName().split("_$TLSLD.");
+        Streamer.emitXCOFFRenameDirective(TCSym, Rhs);
+        return;
+      }
+
       // On AIX, we have TLS variable offsets (symbol@({gd|ie|le|ld}) depending
       // on the TLS access method (or model). For the general-dynamic access
       // method, we also have region handle (symbol at m) for each variable. For
@@ -243,7 +257,6 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE ||
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE ||
-          Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD ||
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML)
         OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
            << MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index a63824735490f..6145481ae8fac 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2957,10 +2957,10 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
       Name += cast<MCSymbolXCOFF>(I.first.first)->getSymbolTableName();
       MCSymbol *S = OutContext.getOrCreateSymbol(Name);
       TCEntry = cast<MCSectionXCOFF>(
-          getObjFileLowering().getSectionForTOCEntry(S, TM));
+          getObjFileLowering().getSectionForTOCEntry(S, TM, I.first.second));
     } else {
-      TCEntry = cast<MCSectionXCOFF>(
-          getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
+      TCEntry = cast<MCSectionXCOFF>(getObjFileLowering().getSectionForTOCEntry(
+          I.first.first, TM, I.first.second));
     }
     OutStreamer->switchSection(TCEntry);
 
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-gd-double.ll b/llvm/test/CodeGen/PowerPC/aix-tls-gd-double.ll
index ae41b6b130106..d84f92b11c978 100644
--- a/llvm/test/CodeGen/PowerPC/aix-tls-gd-double.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-gd-double.ll
@@ -636,7 +636,8 @@ entry:
 ; SMALL32-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL32-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL32-LABEL:  L..C5:
-; SMALL32-NEXT:   .tc TIInit[TC],TIInit[TL]@ld
+; SMALL32-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
+; SMALL32-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
 ; SMALL32-LABEL:  L..C6:
 ; SMALL32-NEXT:   .tc .TWInit[TC],TWInit[TL]@m
 ; SMALL32-LABEL:  L..C7:
@@ -654,7 +655,8 @@ entry:
 ; LARGE32-LABEL:  L..C3:
 ; LARGE32-NEXT:   .tc TGInit[TE],TGInit[TL]@gd
 ; LARGE32-LABEL:  L..C4:
-; LARGE32-NEXT:   .tc TIInit[TE],TIInit[TL]@ld
+; LARGE32-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
+; LARGE32-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
 ; LARGE32-LABEL:  L..C5:
 ; LARGE32-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE32-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
@@ -678,7 +680,8 @@ entry:
 ; SMALL64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL64-LABEL:  L..C5:
-; SMALL64-NEXT:  .tc TIInit[TC],TIInit[TL]@ld
+; SMALL64-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
+; SMALL64-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
 ; SMALL64-LABEL:  L..C6:
 ; SMALL64-NEXT:  .tc .TWInit[TC],TWInit[TL]@m
 ; SMALL64-LABEL:  L..C7:
@@ -699,7 +702,8 @@ entry:
 ; LARGE64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE64-LABEL:  L..C5:
-; LARGE64-NEXT:  .tc TIInit[TE],TIInit[TL]@ld
+; LARGE64-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
+; LARGE64-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
 ; LARGE64-LABEL:  L..C6:
 ; LARGE64-NEXT:  .tc .TWInit[TE],TWInit[TL]@m
 ; LARGE64-LABEL:  L..C7:
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll b/llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll
index bbb8e04b67b95..f9567840a1965 100644
--- a/llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll
@@ -651,7 +651,8 @@ entry:
 ; SMALL32-NEXT:	 .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL32-NEXT:	 .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL32-LABEL: L..C5:
-; SMALL32-NEXT:	 .tc TIUninit[TC],TIUninit[UL]@ld
+; SMALL32-NEXT:	 .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
+; SMALL32-NEXT:	 .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
 ; SMALL32-LABEL: L..C6:
 ; SMALL32-NEXT:	 .tc .TWUninit[TC],TWUninit[TL]@m
 ; SMALL32-LABEL: L..C7:
@@ -669,7 +670,8 @@ entry:
 ; LARGE32-LABEL: L..C3:
 ; LARGE32-NEXT:  .tc TGInit[TE],TGInit[TL]@gd
 ; LARGE32-LABEL: L..C4:
-; LARGE32-NEXT:  .tc TIUninit[TE],TIUninit[UL]@ld
+; LARGE32-NEXT:	 .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
+; LARGE32-NEXT:	 .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
 ; LARGE32-LABEL: L..C5:
 ; LARGE32-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE32-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
@@ -693,7 +695,8 @@ entry:
 ; SMALL64-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL64-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL64-LABEL:  L..C5:
-; SMALL64-NEXT:   .tc TIUninit[TC],TIUninit[UL]@ld
+; SMALL64-NEXT:	 .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
+; SMALL64-NEXT:	 .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
 ; SMALL64-LABEL:  L..C6:
 ; SMALL64-NEXT:   .tc .TWUninit[TC],TWUninit[TL]@m
 ; SMALL64-LABEL:  L..C7:
@@ -714,7 +717,8 @@ entry:
 ; LARGE64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE64-LABEL:  L..C5:
-; LARGE64-NEXT:  .tc TIUninit[TE],TIUninit[UL]@ld
+; LARGE64-NEXT:	 .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
+; LARGE64-NEXT:	 .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
 ; LARGE64-LABEL:  L..C6:
 ; LARGE64-NEXT:  .tc .TWUninit[TE],TWUninit[TL]@m
 ; LARGE64-LABEL:  L..C7:
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-gd-longlong.ll b/llvm/test/CodeGen/PowerPC/aix-tls-gd-longlong.ll
index ff087a2144488..06937635bbd18 100644
--- a/llvm/test/CodeGen/PowerPC/aix-tls-gd-longlong.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-gd-longlong.ll
@@ -687,9 +687,11 @@ entry:
 ; SMALL32-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL32-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL32-LABEL:  L..C3:
-; SMALL32-NEXT:  .tc TIUninit[TC],TIUninit[UL]@ld
+; SMALL32-NEXT:  .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
+; SMALL32-NEXT:  .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
 ; SMALL32-LABEL:  L..C4:
-; SMALL32-NEXT:  .tc TIInit[TC],TIInit[TL]@ld
+; SMALL32-NEXT:  .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
+; SMALL32-NEXT:  .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
 ; SMALL32-LABEL:  L..C5:
 ; SMALL32-NEXT:  .tc .TWInit[TC],TWInit[TL]@m
 ; SMALL32-LABEL:  L..C6:
@@ -703,12 +705,14 @@ entry:
 ; LARGE32-LABEL:  L..C1:
 ; LARGE32-NEXT:  .tc TGInit[TE],TGInit[TL]@gd
 ; LARGE32-LABEL:  L..C2:
-; LARGE32-NEXT:  .tc TIUninit[TE],TIUninit[UL]@ld
+; LARGE32-NEXT:  .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
+; LARGE32-NEXT:  .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
 ; LARGE32-LABEL:  L..C3:
 ; LARGE32-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE32-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE32-LABEL:  L..C4:
-; LARGE32-NEXT:  .tc TIInit[TE],TIInit[TL]@ld
+; LARGE32-NEXT:  .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
+; LARGE32-NEXT:  .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
 ; LARGE32-LABEL:  L..C5:
 ; LARGE32-NEXT:  .tc .TWInit[TE],TWInit[TL]@m
 ; LARGE32-LABEL:  L..C6:
@@ -725,9 +729,11 @@ entry:
 ; SMALL64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL64-LABEL:  L..C3:
-; SMALL64-NEXT:  .tc TIUninit[TC],TIUninit[UL]@ld
+; SMALL64-NEXT:  .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
+; SMALL64-NEXT:  .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
 ; SMALL64-LABEL:  L..C4:
-; SMALL64-NEXT:  .tc TIInit[TC],TIInit[TL]@ld
+; SMALL64-NEXT:  .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
+; SMALL64-NEXT:  .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
 ; SMALL64-LABEL:  L..C5:
 ; SMALL64-NEXT:  .tc .TWInit[TC],TWInit[TL]@m
 ; SMALL64-LABEL:  L..C6:
@@ -744,9 +750,11 @@ entry:
 ; LARGE64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE64-LABEL:  L..C3:
-; LARGE64-NEXT:  .tc TIUninit[TE],TIUninit[UL]@ld
+; LARGE64-NEXT:  .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
+; LARGE64-NEXT:  .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
 ; LARGE64-LABEL:  L..C4:
-; LARGE64-NEXT:  .tc TIInit[TE],TIInit[TL]@ld
+; LARGE64-NEXT:  .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
+; LARGE64-NEXT:  .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
 ; LARGE64-LABEL:  L..C5:
 ; LARGE64-NEXT:  .tc .TWInit[TE],TWInit[TL]@m
 ; LARGE64-LABEL:  L..C6:
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-ld-unqualified-symbols.ll b/llvm/test/CodeGen/PowerPC/aix-tls-ld-unqualified-symbols.ll
new file mode 100644
index 0000000000000..d92375730a95a
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-ld-unqualified-symbols.ll
@@ -0,0 +1,362 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:     --code-model=small < %s | FileCheck %s --check-prefixes=SMALL64,COMMON
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:     --code-model=large < %s | FileCheck %s --check-prefixes=LARGE64,COMMON
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
+; RUN:     --code-model=small < %s | FileCheck %s --check-prefixes=SMALL32,COMMON
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
+; RUN:     --code-model=large < %s | FileCheck %s --check-prefixes=LARGE32,COMMON
+
+ at _$TLSLD. = thread_local(localdynamic) global i32 42, align 4
+ at _$TLSLD.a = thread_local(localdynamic) global i32 42, align 4
+ at __$TLSLD. = internal thread_local(localdynamic) global i32 42, align 4
+ at _$TLSLD._$TLSLD. = internal thread_local(localdynamic) global i32 42, align 4
+
+declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
+
+define i32 @loadSym1() {
+; SMALL64-LABEL: loadSym1:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    mflr 0
+; SMALL64-NEXT:    stdu 1, -48(1)
+; SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; SMALL64-NEXT:    std 0, 64(1)
+; SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; SMALL64-NEXT:    ld 4, L..C1(2) # target-flags(ppc-tlsld) @"_$TLSLD."
+; SMALL64-NEXT:    lwzx 3, 3, 4
+; SMALL64-NEXT:    addi 1, 1, 48
+; SMALL64-NEXT:    ld 0, 16(1)
+; SMALL64-NEXT:    mtlr 0
+; SMALL64-NEXT:    blr
+;
+; LARGE64-LABEL: loadSym1:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    mflr 0
+; LARGE64-NEXT:    stdu 1, -48(1)
+; LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; LARGE64-NEXT:    addis 6, L..C1 at u(2)
+; LARGE64-NEXT:    std 0, 64(1)
+; LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; LARGE64-NEXT:    ld 4, L..C1 at l(6)
+; LARGE64-NEXT:    lwzx 3, 3, 4
+; LARGE64-NEXT:    addi 1, 1, 48
+; LARGE64-NEXT:    ld 0, 16(1)
+; LARGE64-NEXT:    mtlr 0
+; LARGE64-NEXT:    blr
+;
+; SMALL32-LABEL: loadSym1:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr 0
+; SMALL32-NEXT:    stwu 1, -32(1)
+; SMALL32-NEXT:    lwz 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; SMALL32-NEXT:    stw 0, 40(1)
+; SMALL32-NEXT:    bla .__tls_get_mod[PR]
+; SMALL32-NEXT:    lwz 4, L..C1(2) # target-flags(ppc-tlsld) @"_$TLSLD."
+; SMALL32-NEXT:    lwzx 3, 3, 4
+; SMALL32-NEXT:    addi 1, 1, 32
+; SMALL32-NEXT:    lwz 0, 8(1)
+; SMALL32-NEXT:    mtlr 0
+; SMALL32-NEXT:    blr
+;
+; LARGE32-LABEL: loadSym1:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr 0
+; LARGE32-NEXT:    stwu 1, -32(1)
+; LARGE32-NEXT:    stw 0, 40(1)
+; LARGE32-NEXT:    addis 6, L..C0 at u(2)
+; LARGE32-NEXT:    addis 3, L..C1 at u(2)
+; LARGE32-NEXT:    lwz 3, L..C1 at l(3)
+; LARGE32-NEXT:    bla .__tls_get_mod[PR]
+; LARGE32-NEXT:    lwz 4, L..C0 at l(6)
+; LARGE32-NEXT:    lwzx 3, 3, 4
+; LARGE32-NEXT:    addi 1, 1, 32
+; LARGE32-NEXT:    lwz 0, 8(1)
+; LARGE32-NEXT:    mtlr 0
+; LARGE32-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_$TLSLD.)
+  %1 = load i32, ptr %0, align 4
+  ret i32 %1
+}
+
+define i32 @loadSym2() {
+; SMALL64-LABEL: loadSym2:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    mflr 0
+; SMALL64-NEXT:    stdu 1, -48(1)
+; SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; SMALL64-NEXT:    std 0, 64(1)
+; SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @"_$TLSLD.a"
+; SMALL64-NEXT:    lwzx 3, 3, 4
+; SMALL64-NEXT:    addi 1, 1, 48
+; SMALL64-NEXT:    ld 0, 16(1)
+; SMALL64-NEXT:    mtlr 0
+; SMALL64-NEXT:    blr
+;
+; LARGE64-LABEL: loadSym2:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    mflr 0
+; LARGE64-NEXT:    stdu 1, -48(1)
+; LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; LARGE64-NEXT:    addis 6, L..C2 at u(2)
+; LARGE64-NEXT:    std 0, 64(1)
+; LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; LARGE64-NEXT:    ld 4, L..C2 at l(6)
+; LARGE64-NEXT:    lwzx 3, 3, 4
+; LARGE64-NEXT:    addi 1, 1, 48
+; LARGE64-NEXT:    ld 0, 16(1)
+; LARGE64-NEXT:    mtlr 0
+; LARGE64-NEXT:    blr
+;
+; SMALL32-LABEL: loadSym2:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr 0
+; SMALL32-NEXT:    stwu 1, -32(1)
+; SMALL32-NEXT:    lwz 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; SMALL32-NEXT:    stw 0, 40(1)
+; SMALL32-NEXT:    bla .__tls_get_mod[PR]
+; SMALL32-NEXT:    lwz 4, L..C2(2) # target-flags(ppc-tlsld) @"_$TLSLD.a"
+; SMALL32-NEXT:    lwzx 3, 3, 4
+; SMALL32-NEXT:    addi 1, 1, 32
+; SMALL32-NEXT:    lwz 0, 8(1)
+; SMALL32-NEXT:    mtlr 0
+; SMALL32-NEXT:    blr
+;
+; LARGE32-LABEL: loadSym2:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr 0
+; LARGE32-NEXT:    stwu 1, -32(1)
+; LARGE32-NEXT:    stw 0, 40(1)
+; LARGE32-NEXT:    addis 6, L..C2 at u(2)
+; LARGE32-NEXT:    addis 3, L..C1 at u(2)
+; LARGE32-NEXT:    lwz 3, L..C1 at l(3)
+; LARGE32-NEXT:    bla .__tls_get_mod[PR]
+; LARGE32-NEXT:    lwz 4, L..C2 at l(6)
+; LARGE32-NEXT:    lwzx 3, 3, 4
+; LARGE32-NEXT:    addi 1, 1, 32
+; LARGE32-NEXT:    lwz 0, 8(1)
+; LARGE32-NEXT:    mtlr 0
+; LARGE32-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_$TLSLD.a)
+  %1 = load i32, ptr %0, align 4
+  ret i32 %1
+}
+
+define i32 @loadSym3() {
+; SMALL64-LABEL: loadSym3:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    mflr 0
+; SMALL64-NEXT:    stdu 1, -48(1)
+; SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; SMALL64-NEXT:    std 0, 64(1)
+; SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @"__$TLSLD."
+; SMALL64-NEXT:    lwzx 3, 3, 4
+; SMALL64-NEXT:    addi 1, 1, 48
+; SMALL64-NEXT:    ld 0, 16(1)
+; SMALL64-NEXT:    mtlr 0
+; SMALL64-NEXT:    blr
+;
+; LARGE64-LABEL: loadSym3:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    mflr 0
+; LARGE64-NEXT:    stdu 1, -48(1)
+; LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; LARGE64-NEXT:    addis 6, L..C3 at u(2)
+; LARGE64-NEXT:    std 0, 64(1)
+; LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; LARGE64-NEXT:    ld 4, L..C3 at l(6)
+; LARGE64-NEXT:    lwzx 3, 3, 4
+; LARGE64-NEXT:    addi 1, 1, 48
+; LARGE64-NEXT:    ld 0, 16(1)
+; LARGE64-NEXT:    mtlr 0
+; LARGE64-NEXT:    blr
+;
+; SMALL32-LABEL: loadSym3:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr 0
+; SMALL32-NEXT:    stwu 1, -32(1)
+; SMALL32-NEXT:    lwz 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; SMALL32-NEXT:    stw 0, 40(1)
+; SMALL32-NEXT:    bla .__tls_get_mod[PR]
+; SMALL32-NEXT:    lwz 4, L..C3(2) # target-flags(ppc-tlsld) @"__$TLSLD."
+; SMALL32-NEXT:    lwzx 3, 3, 4
+; SMALL32-NEXT:    addi 1, 1, 32
+; SMALL32-NEXT:    lwz 0, 8(1)
+; SMALL32-NEXT:    mtlr 0
+; SMALL32-NEXT:    blr
+;
+; LARGE32-LABEL: loadSym3:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr 0
+; LARGE32-NEXT:    stwu 1, -32(1)
+; LARGE32-NEXT:    stw 0, 40(1)
+; LARGE32-NEXT:    addis 6, L..C3 at u(2)
+; LARGE32-NEXT:    addis 3, L..C1 at u(2)
+; LARGE32-NEXT:    lwz 3, L..C1 at l(3)
+; LARGE32-NEXT:    bla .__tls_get_mod[PR]
+; LARGE32-NEXT:    lwz 4, L..C3 at l(6)
+; LARGE32-NEXT:    lwzx 3, 3, 4
+; LARGE32-NEXT:    addi 1, 1, 32
+; LARGE32-NEXT:    lwz 0, 8(1)
+; LARGE32-NEXT:    mtlr 0
+; LARGE32-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @__$TLSLD.)
+  %1 = load i32, ptr %0, align 4
+  ret i32 %1
+}
+
+define i32 @loadSym4() {
+; SMALL64-LABEL: loadSym4:
+; SMALL64:       # %bb.0: # %entry
+; SMALL64-NEXT:    mflr 0
+; SMALL64-NEXT:    stdu 1, -48(1)
+; SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; SMALL64-NEXT:    std 0, 64(1)
+; SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; SMALL64-NEXT:    ld 4, L..C4(2) # target-flags(ppc-tlsld) @"_$TLSLD._$TLSLD."
+; SMALL64-NEXT:    lwzx 3, 3, 4
+; SMALL64-NEXT:    addi 1, 1, 48
+; SMALL64-NEXT:    ld 0, 16(1)
+; SMALL64-NEXT:    mtlr 0
+; SMALL64-NEXT:    blr
+;
+; LARGE64-LABEL: loadSym4:
+; LARGE64:       # %bb.0: # %entry
+; LARGE64-NEXT:    mflr 0
+; LARGE64-NEXT:    stdu 1, -48(1)
+; LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; LARGE64-NEXT:    addis 6, L..C4 at u(2)
+; LARGE64-NEXT:    std 0, 64(1)
+; LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; LARGE64-NEXT:    ld 4, L..C4 at l(6)
+; LARGE64-NEXT:    lwzx 3, 3, 4
+; LARGE64-NEXT:    addi 1, 1, 48
+; LARGE64-NEXT:    ld 0, 16(1)
+; LARGE64-NEXT:    mtlr 0
+; LARGE64-NEXT:    blr
+;
+; SMALL32-LABEL: loadSym4:
+; SMALL32:       # %bb.0: # %entry
+; SMALL32-NEXT:    mflr 0
+; SMALL32-NEXT:    stwu 1, -32(1)
+; SMALL32-NEXT:    lwz 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; SMALL32-NEXT:    stw 0, 40(1)
+; SMALL32-NEXT:    bla .__tls_get_mod[PR]
+; SMALL32-NEXT:    lwz 4, L..C4(2) # target-flags(ppc-tlsld) @"_$TLSLD._$TLSLD."
+; SMALL32-NEXT:    lwzx 3, 3, 4
+; SMALL32-NEXT:    addi 1, 1, 32
+; SMALL32-NEXT:    lwz 0, 8(1)
+; SMALL32-NEXT:    mtlr 0
+; SMALL32-NEXT:    blr
+;
+; LARGE32-LABEL: loadSym4:
+; LARGE32:       # %bb.0: # %entry
+; LARGE32-NEXT:    mflr 0
+; LARGE32-NEXT:    stwu 1, -32(1)
+; LARGE32-NEXT:    stw 0, 40(1)
+; LARGE32-NEXT:    addis 6, L..C4 at u(2)
+; LARGE32-NEXT:    addis 3, L..C1 at u(2)
+; LARGE32-NEXT:    lwz 3, L..C1 at l(3)
+; LARGE32-NEXT:    bla .__tls_get_mod[PR]
+; LARGE32-NEXT:    lwz 4, L..C4 at l(6)
+; LARGE32-NEXT:    lwzx 3, 3, 4
+; LARGE32-NEXT:    addi 1, 1, 32
+; LARGE32-NEXT:    lwz 0, 8(1)
+; LARGE32-NEXT:    mtlr 0
+; LARGE32-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_$TLSLD._$TLSLD.)
+  %1 = load i32, ptr %0, align 4
+  ret i32 %1
+}
+
+; COMMON:      .csect _Renamed..5f24__TLSLD.[TL],2
+; COMMON-NEXT: .globl  _Renamed..5f24__TLSLD.[TL]      # @"_$TLSLD."
+; COMMON-NEXT: .rename _Renamed..5f24__TLSLD.[TL],"_$TLSLD."
+; COMMON:      .csect _Renamed..5f24__TLSLD.a[TL],2
+; COMMON-NEXT: .globl  _Renamed..5f24__TLSLD.a[TL]     # @"_$TLSLD.a"
+; COMMON-NEXT: .rename _Renamed..5f24__TLSLD.a[TL],"_$TLSLD.a"
+; COMMON:      .csect _Renamed..5f5f24___TLSLD.[TL],2
+; COMMON-NEXT: .lglobl _Renamed..5f5f24___TLSLD.[TL]   # @"__$TLSLD."
+; COMMON-NEXT: .rename _Renamed..5f5f24___TLSLD.[TL],"__$TLSLD."
+; COMMON:      .csect _Renamed..5f245f24__TLSLD.__TLSLD.[TL],2
+; COMMON-NEXT: .lglobl _Renamed..5f245f24__TLSLD.__TLSLD.[TL] # @"_$TLSLD._$TLSLD."
+; COMMON-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TL],"_$TLSLD._$TLSLD."
+
+; SMALL64-LABEL: .toc
+; SMALL64-LABEL: L..C0:
+; SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; SMALL64-LABEL: L..C1:
+; SMALL64-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.[TC],_Renamed..5f24__TLSLD.[TL]@ld
+; SMALL64-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TC],"_$TLSLD."
+; SMALL64-LABEL: L..C2:
+; SMALL64-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.a[TC],_Renamed..5f24__TLSLD.a[TL]@ld
+; SMALL64-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.a[TC],"_$TLSLD.a"
+; SMALL64-LABEL: L..C3:
+; SMALL64-NEXT: .tc _Renamed..5f245f5f24__TLSLD.___TLSLD.[TC],_Renamed..5f5f24___TLSLD.[TL]@ld
+; SMALL64-NEXT: .rename _Renamed..5f245f5f24__TLSLD.___TLSLD.[TC],"__$TLSLD."
+; SMALL64-LABEL: L..C4:
+; SMALL64-NEXT: .tc _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TC],_Renamed..5f245f24__TLSLD.__TLSLD.[TL]@ld
+; SMALL64-NEXT: .rename _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TC],"_$TLSLD._$TLSLD."
+
+; LARGE64-LABEL: .toc
+; LARGE64-LABEL: L..C0:
+; LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; LARGE64-LABEL: L..C1:
+; LARGE64-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.[TE],_Renamed..5f24__TLSLD.[TL]@ld
+; LARGE64-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TE],"_$TLSLD."
+; LARGE64-LABEL: L..C2:
+; LARGE64-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.a[TE],_Renamed..5f24__TLSLD.a[TL]@ld
+; LARGE64-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.a[TE],"_$TLSLD.a"
+; LARGE64-LABEL: L..C3:
+; LARGE64-NEXT: .tc _Renamed..5f245f5f24__TLSLD.___TLSLD.[TE],_Renamed..5f5f24___TLSLD.[TL]@ld
+; LARGE64-NEXT: .rename _Renamed..5f245f5f24__TLSLD.___TLSLD.[TE],"__$TLSLD."
+; LARGE64-LABEL: L..C4:
+; LARGE64-NEXT: .tc _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TE],_Renamed..5f245f24__TLSLD.__TLSLD.[TL]@ld
+; LARGE64-NEXT: .rename _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TE],"_$TLSLD._$TLSLD."
+
+; SMALL32-LABEL: .toc
+; SMALL32-LABEL: L..C0:
+; SMALL32-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; SMALL32-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; SMALL32-LABEL: L..C1:
+; SMALL32-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.[TC],_Renamed..5f24__TLSLD.[TL]@ld
+; SMALL32-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TC],"_$TLSLD."
+; SMALL32-LABEL: L..C2:
+; SMALL32-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.a[TC],_Renamed..5f24__TLSLD.a[TL]@ld
+; SMALL32-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.a[TC],"_$TLSLD.a"
+; SMALL32-LABEL: L..C3:
+; SMALL32-NEXT: .tc _Renamed..5f245f5f24__TLSLD.___TLSLD.[TC],_Renamed..5f5f24___TLSLD.[TL]@ld
+; SMALL32-NEXT: .rename _Renamed..5f245f5f24__TLSLD.___TLSLD.[TC],"__$TLSLD."
+; SMALL32-LABEL: L..C4:
+; SMALL32-NEXT: .tc _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TC],_Renamed..5f245f24__TLSLD.__TLSLD.[TL]@ld
+; SMALL32-NEXT: .rename _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TC],"_$TLSLD._$TLSLD."
+
+; LARGE32-LABEL: .toc
+; LARGE32-LABEL: L..C0:
+; LARGE32-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.[TE],_Renamed..5f24__TLSLD.[TL]@ld
+; LARGE32-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TE],"_$TLSLD."
+; LARGE32-LABEL: L..C1:
+; LARGE32-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; LARGE32-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; LARGE32-LABEL: L..C2:
+; LARGE32-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.a[TE],_Renamed..5f24__TLSLD.a[TL]@ld
+; LARGE32-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.a[TE],"_$TLSLD.a"
+; LARGE32-LABEL: L..C3:
+; LARGE32-NEXT: .tc _Renamed..5f245f5f24__TLSLD.___TLSLD.[TE],_Renamed..5f5f24___TLSLD.[TL]@ld
+; LARGE32-NEXT: .rename _Renamed..5f245f5f24__TLSLD.___TLSLD.[TE],"__$TLSLD."
+; LARGE32-LABEL: L..C4:
+; LARGE32-NEXT: .tc _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TE],_Renamed..5f245f24__TLSLD.__TLSLD.[TL]@ld
+; LARGE32-NEXT: .rename _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TE],"_$TLSLD._$TLSLD."
+
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-local-dynamic.ll b/llvm/test/CodeGen/PowerPC/aix-tls-local-dynamic.ll
index 22349337f1890..d5dc7e57d3632 100644
--- a/llvm/test/CodeGen/PowerPC/aix-tls-local-dynamic.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-local-dynamic.ll
@@ -358,39 +358,52 @@ entry:
 ; SMALL-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL:        [[TGInitL]]:
-; SMALL-NEXT:   .tc TGInit[TC],TGInit[TL]@ld
+; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TGInit[TC],TGInit[TL]@ld
+; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TGInit[TC],"TGInit"
 ; SMALL:        [[TGUninitL]]:
-; SMALL-NEXT:   .tc TGUninit[TC],TGUninit[TL]@ld
+; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TGUninit[TC],TGUninit[TL]@ld
+; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TGUninit[TC],"TGUninit"
 ; SMALL:        [[TIInitL]]:
-; SMALL-NEXT:   .tc TIInit[TC],TIInit[TL]@ld
+; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
+; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
 ; SMALL:        [[TIUninitL]]:
-; SMALL-NEXT:   .tc TIUninit[TC],TIUninit[UL]@ld
+; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
+; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
 ; SMALL:        [[TWInitL]]:
-; SMALL-NEXT:   .tc TWInit[TC],TWInit[TL]@ld
+; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TWInit[TC],TWInit[TL]@ld
+; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TWInit[TC],"TWInit"
 ; SMALL:        [[TWUninitL]]:
-; SMALL-NEXT:   .tc TWUninit[TC],TWUninit[TL]@ld
+; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TWUninit[TC],TWUninit[TL]@ld
+; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TWUninit[TC],"TWUninit"
 
 ; LARGE64:        [[ModuleHandleL]]:
 ; LARGE64-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE64-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE64:        [[TGInitL]]:
-; LARGE64-NEXT:   .tc TGInit[TE],TGInit[TL]@ld
+; LARGE64-NEXT:   .tc _Renamed..5f24__TLSLD.TGInit[TE],TGInit[TL]@ld
+; LARGE64-NEXT:   .rename _Renamed..5f24__TLSLD.TGInit[TE],"TGInit"
 ;
 ; LARGE32:        [[TGInitL]]:
-; LARGE32-NEXT:   .tc TGInit[TE],TGInit[TL]@ld
+; LARGE32-NEXT:   .tc _Renamed..5f24__TLSLD.TGInit[TE],TGInit[TL]@ld
+; LARGE32-NEXT:   .rename _Renamed..5f24__TLSLD.TGInit[TE],"TGInit"
 ; LARGE32:        [[ModuleHandleL]]:
 ; LARGE32-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE32-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ;
 ; LARGE:        [[TGUninitL]]:
-; LARGE-NEXT:   .tc TGUninit[TE],TGUninit[TL]@ld
+; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TGUninit[TE],TGUninit[TL]@ld
+; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TGUninit[TE],"TGUninit"
 ; LARGE:        [[TIInitL]]:
-; LARGE-NEXT:   .tc TIInit[TE],TIInit[TL]@ld
+; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
+; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
 ; LARGE:        [[TIUninitL]]:
-; LARGE-NEXT:   .tc TIUninit[TE],TIUninit[UL]@ld
+; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
+; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
 ; LARGE:        [[TWInitL]]:
-; LARGE-NEXT:   .tc TWInit[TE],TWInit[TL]@ld
+; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TWInit[TE],TWInit[TL]@ld
+; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TWInit[TE],"TWInit"
 ; LARGE:        [[TWUninitL]]:
-; LARGE-NEXT:   .tc TWUninit[TE],TWUninit[TL]@ld
+; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TWUninit[TE],TWUninit[TL]@ld
+; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TWUninit[TE],"TWUninit"
 
 declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)

>From 4525b9c7fce9df2840e3643c1797c0edafc4473a Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Thu, 7 Mar 2024 00:05:03 -0500
Subject: [PATCH 02/10] [NFC] Update comment.

---
 llvm/lib/MC/MCContext.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index b8e96c7b6995d..ad903657716c6 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -811,6 +811,7 @@ MCSectionXCOFF *MCContext::getXCOFFSection(
   if (IsDwarfSec)
     QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(CachedName));
   else
+    // For TLS local-dynamic model RenamePrefix is "_$TLSLD.", otherwise empty.
     QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(
         RenamePrefix + CachedName + "[" +
         XCOFF::getMappingClassString(CsectProp->MappingClass) + "]"));

>From 27ba4caa95dc41ffd42ca76cad9c27775c0f05d2 Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Thu, 14 Mar 2024 01:41:50 -0400
Subject: [PATCH 03/10] WIP: need check assert

---
 clang/lib/Basic/Targets/PPC.cpp               |  5 +++
 clang/lib/Basic/Targets/PPC.h                 |  1 +
 llvm/lib/Target/PowerPC/PPC.td                |  4 ++
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     |  7 ++++
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   | 40 +++++++++++++++++++
 .../Target/PowerPC/PPCMachineFunctionInfo.h   | 12 ++++++
 6 files changed, 69 insertions(+)

diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index bad5259958a88..eb98d012dd30e 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -91,6 +91,9 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
       IsISA3_1 = true;
     } else if (Feature == "+quadword-atomics") {
       HasQuadwordAtomics = true;
+    } else if (Feature == "+aix-use-tls-initial-exec-for-local-dynamic-in-"
+                          "shared-library") {
+      HasAIXUseTLSIEForLDInSharedLibrary = true;
     }
     // TODO: Finish this list and add an assert that we've handled them
     // all.
@@ -722,6 +725,8 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
       .Case("isa-v30-instructions", IsISA3_0)
       .Case("isa-v31-instructions", IsISA3_1)
       .Case("quadword-atomics", HasQuadwordAtomics)
+      .Case("aix-use-tls-initial-exec-for-local-dynamic-in-shared-library",
+            HasAIXUseTLSIEForLDInSharedLibrary)
       .Default(false);
 }
 
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index 30059e418e69b..55b357a18d937 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -81,6 +81,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
   bool IsISA3_0 = false;
   bool IsISA3_1 = false;
   bool HasQuadwordAtomics = false;
+  bool HasAIXUseTLSIEForLDInSharedLibrary = false;
 
 protected:
   std::string ABI;
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td
index b962ed28d7200..36260c73b3ebc 100644
--- a/llvm/lib/Target/PowerPC/PPC.td
+++ b/llvm/lib/Target/PowerPC/PPC.td
@@ -338,6 +338,10 @@ def FeatureAIXLocalDynamicTLS :
                    "true", "Produce a faster local-dynamic TLS sequence for this "
                    "function for 64-bit AIX">;
 
+def FeatureAIXUseTLSInitialExecForLocalDynamicInSharedLibraries :
+  SubtargetFeature<"aix-use-tls-initial-exec-for-local-dynamic-in-shared-library", "HasAIXUseTLSIEForLDInSharedLibrary", "true",
+                   "Use TLS initial-exec model for TLS local-dynamic accesses in shared libraries loaded with the main function">;
+
 def FeaturePredictableSelectIsExpensive :
   SubtargetFeature<"predictable-select-expensive",
                    "PredictableSelectIsExpensive",
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 6145481ae8fac..e16248bf59f7c 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -878,6 +878,13 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
       if (Model == TLSModel::InitialExec)
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
+      // On AIX, TLS-LD heuristic may have turned LD access into IE access.
+      PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
+      if (Model == TLSModel::LocalDynamic && FuncInfo->isAIXFuncUseTLSIE()) {
+        LLVM_DEBUG(
+            dbgs() << "Current function use IE access for default LD vars.\n");
+        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
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index d27932f2915fb..4fbb17d7d10c3 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3374,6 +3374,46 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   bool Is64Bit = Subtarget.isPPC64();
   TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
+  // Initialize heuristic setting lazily:
+  // (1) Use initial-exec for single TLS var reference within current function.
+  // (2) Use local-dynamic for multiple TLS var references within current func.
+  PPCFunctionInfo *FuncInfo =
+      DAG.getMachineFunction().getInfo<PPCFunctionInfo>();
+  if (Subtarget.hasAIXUseTLSIEForLDInSharedLibrary() &&
+      !FuncInfo->isAIXFuncUseInitDone()) {
+    std::set<const GlobalValue *> TLSGV;
+    for (SDNode &Node : DAG.allnodes()) {
+      SDNode *N = &Node;
+      if (N->getOpcode() == ISD::GlobalTLSAddress) {
+        if (GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N)) {
+          const GlobalValue *GV = GA->getGlobal();
+          TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
+          if (Model == TLSModel::InitialExec ||
+              Model == TLSModel::LocalDynamic) {
+            TLSGV.insert(GV);
+          }
+        }
+      }
+    }
+    LLVM_DEBUG(dbgs() << format("TLSGV count:%d\n", TLSGV.size()));
+    if (TLSGV.size() == 1) {
+      FuncInfo->setAIXFuncUseTLSIE();
+    } else if (TLSGV.size() > 1) {
+      FuncInfo->setAIXFuncUseTLSLD();
+    }
+    FuncInfo->setAIXFuncUseInitDone();
+  }
+
+  if (FuncInfo->isAIXFuncUseTLSLD()) {
+    LLVM_DEBUG(dbgs() << DAG.getMachineFunction().getName()
+                      << " function use TLS-LD model for TLS IE/LD vars.\n");
+    Model = TLSModel::LocalDynamic;
+  } else if (FuncInfo->isAIXFuncUseTLSIE()) {
+    LLVM_DEBUG(dbgs() << DAG.getMachineFunction().getName()
+                      << " function use TLS-IE model for TLS IE/LD vars.\n");
+    Model = TLSModel::InitialExec;
+  }
+
   bool IsTLSLocalExecModel = Model == TLSModel::LocalExec;
 
   if (IsTLSLocalExecModel || Model == TLSModel::InitialExec) {
diff --git a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
index df655a3be9512..03136743358ec 100644
--- a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
@@ -150,6 +150,11 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   /// to use SExt/ZExt flags in later optimization.
   std::vector<std::pair<Register, ISD::ArgFlagsTy>> LiveInAttrs;
 
+  /// FIXME: Flags for heuristic.
+  bool AIXFuncUseTLSLD = false;
+  bool AIXFuncUseTLSIE = false;
+  bool AIXFuncUseInitDone = false;
+
 public:
   explicit PPCFunctionInfo(const Function &F, const TargetSubtargetInfo *STI);
 
@@ -221,6 +226,13 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   void setHasFastCall() { HasFastCall = true; }
   bool hasFastCall() const { return HasFastCall;}
 
+  void setAIXFuncUseInitDone() { AIXFuncUseInitDone = true; }
+  bool isAIXFuncUseInitDone() const { return AIXFuncUseInitDone; }
+  void setAIXFuncUseTLSLD() { AIXFuncUseTLSLD = true; }
+  bool isAIXFuncUseTLSLD() const { return AIXFuncUseTLSLD; }
+  void setAIXFuncUseTLSIE() { AIXFuncUseTLSIE = true; }
+  bool isAIXFuncUseTLSIE() const { return AIXFuncUseTLSIE; }
+
   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
   void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
 

>From 7fb862a7d80b7f932ef81900772ad35ff6424df6 Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Fri, 15 Mar 2024 02:02:52 -0400
Subject: [PATCH 04/10] Reset to try another approach

---
 clang/lib/Basic/Targets/PPC.cpp               |   5 -
 clang/lib/Basic/Targets/PPC.h                 |   1 -
 .../CodeGen/TargetLoweringObjectFileImpl.h    |   5 +-
 llvm/include/llvm/MC/MCContext.h              |   3 +-
 .../llvm/Target/TargetLoweringObjectFile.h    |   6 +-
 llvm/lib/MC/MCContext.cpp                     |   6 +-
 .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp  |  15 +-
 llvm/lib/Target/PowerPC/PPC.td                |   4 -
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     |  13 +-
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  40 --
 .../Target/PowerPC/PPCMachineFunctionInfo.h   |  12 -
 .../test/CodeGen/PowerPC/aix-tls-gd-double.ll |  12 +-
 llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll   |  12 +-
 .../CodeGen/PowerPC/aix-tls-gd-longlong.ll    |  24 +-
 .../PowerPC/aix-tls-ld-unqualified-symbols.ll | 362 ------------------
 .../CodeGen/PowerPC/aix-tls-local-dynamic.ll  |  39 +-
 16 files changed, 40 insertions(+), 519 deletions(-)
 delete mode 100644 llvm/test/CodeGen/PowerPC/aix-tls-ld-unqualified-symbols.ll

diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index eb98d012dd30e..bad5259958a88 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -91,9 +91,6 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
       IsISA3_1 = true;
     } else if (Feature == "+quadword-atomics") {
       HasQuadwordAtomics = true;
-    } else if (Feature == "+aix-use-tls-initial-exec-for-local-dynamic-in-"
-                          "shared-library") {
-      HasAIXUseTLSIEForLDInSharedLibrary = true;
     }
     // TODO: Finish this list and add an assert that we've handled them
     // all.
@@ -725,8 +722,6 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
       .Case("isa-v30-instructions", IsISA3_0)
       .Case("isa-v31-instructions", IsISA3_1)
       .Case("quadword-atomics", HasQuadwordAtomics)
-      .Case("aix-use-tls-initial-exec-for-local-dynamic-in-shared-library",
-            HasAIXUseTLSIEForLDInSharedLibrary)
       .Default(false);
 }
 
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index 55b357a18d937..30059e418e69b 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -81,7 +81,6 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
   bool IsISA3_0 = false;
   bool IsISA3_1 = false;
   bool HasQuadwordAtomics = false;
-  bool HasAIXUseTLSIEForLDInSharedLibrary = false;
 
 protected:
   std::string ABI;
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 1aa25e98423af..8eef45ce565de 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -279,9 +279,8 @@ class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile {
   MCSection *
   getSectionForFunctionDescriptor(const Function *F,
                                   const TargetMachine &TM) const override;
-  MCSection *
-  getSectionForTOCEntry(const MCSymbol *Sym, const TargetMachine &TM,
-                        const MCSymbolRefExpr::VariantKind VK) const override;
+  MCSection *getSectionForTOCEntry(const MCSymbol *Sym,
+                                   const TargetMachine &TM) const override;
 
   /// For external functions, this will always return a function descriptor
   /// csect.
diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 3708b2dff727e..ef9833cdf2b07 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -691,8 +691,7 @@ class MCContext {
       std::optional<XCOFF::CsectProperties> CsectProp = std::nullopt,
       bool MultiSymbolsAllowed = false, const char *BeginSymName = nullptr,
       std::optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSubtypeFlags =
-          std::nullopt,
-      StringRef RenamePrefix = StringRef());
+          std::nullopt);
 
   // Create and save a copy of STI and return a reference to the copy.
   MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index 31a466a18d77a..0c09cfe684783 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -14,7 +14,6 @@
 #ifndef LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
 #define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
 
-#include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCRegister.h"
 #include <cstdint>
@@ -257,9 +256,8 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
   /// On targets that support TOC entries, return a section for the entry given
   /// the symbol it refers to.
   /// TODO: Implement this interface for existing ELF targets.
-  virtual MCSection *
-  getSectionForTOCEntry(const MCSymbol *S, const TargetMachine &TM,
-                        const MCSymbolRefExpr::VariantKind VK) const {
+  virtual MCSection *getSectionForTOCEntry(const MCSymbol *S,
+                                           const TargetMachine &TM) const {
     return nullptr;
   }
 
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index ad903657716c6..3aee96fdf57fc 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -785,8 +785,7 @@ MCSectionXCOFF *MCContext::getXCOFFSection(
     StringRef Section, SectionKind Kind,
     std::optional<XCOFF::CsectProperties> CsectProp, bool MultiSymbolsAllowed,
     const char *BeginSymName,
-    std::optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSectionSubtypeFlags,
-    StringRef RenamePrefix) {
+    std::optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSectionSubtypeFlags) {
   bool IsDwarfSec = DwarfSectionSubtypeFlags.has_value();
   assert((IsDwarfSec != CsectProp.has_value()) && "Invalid XCOFF section!");
 
@@ -811,9 +810,8 @@ MCSectionXCOFF *MCContext::getXCOFFSection(
   if (IsDwarfSec)
     QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(CachedName));
   else
-    // For TLS local-dynamic model RenamePrefix is "_$TLSLD.", otherwise empty.
     QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(
-        RenamePrefix + CachedName + "[" +
+        CachedName + "[" +
         XCOFF::getMappingClassString(CsectProp->MappingClass) + "]"));
 
   MCSymbol *Begin = nullptr;
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index 13cce8fb27129..9106e6ab6397d 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -232,20 +232,6 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
       MCSymbolXCOFF *TCSym =
           cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
               ->getQualNameSymbol();
-
-      // On AIX, symbol accessed using TLS local-dynamic model has been renamed
-      // by adding prefix "_$TLSLD.". Do assert that it has been renamed, and
-      // then emit the .rename with the original symbol name.
-      if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD) {
-        assert(TCSym->hasRename());
-        OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
-           << MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
-        StringRef Lhs, Rhs;
-        std::tie(Lhs, Rhs) = TCSym->getSymbolTableName().split("_$TLSLD.");
-        Streamer.emitXCOFFRenameDirective(TCSym, Rhs);
-        return;
-      }
-
       // On AIX, we have TLS variable offsets (symbol@({gd|ie|le|ld}) depending
       // on the TLS access method (or model). For the general-dynamic access
       // method, we also have region handle (symbol at m) for each variable. For
@@ -257,6 +243,7 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE ||
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE ||
+          Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD ||
           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML)
         OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
            << MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td
index 36260c73b3ebc..b962ed28d7200 100644
--- a/llvm/lib/Target/PowerPC/PPC.td
+++ b/llvm/lib/Target/PowerPC/PPC.td
@@ -338,10 +338,6 @@ def FeatureAIXLocalDynamicTLS :
                    "true", "Produce a faster local-dynamic TLS sequence for this "
                    "function for 64-bit AIX">;
 
-def FeatureAIXUseTLSInitialExecForLocalDynamicInSharedLibraries :
-  SubtargetFeature<"aix-use-tls-initial-exec-for-local-dynamic-in-shared-library", "HasAIXUseTLSIEForLDInSharedLibrary", "true",
-                   "Use TLS initial-exec model for TLS local-dynamic accesses in shared libraries loaded with the main function">;
-
 def FeaturePredictableSelectIsExpensive :
   SubtargetFeature<"predictable-select-expensive",
                    "PredictableSelectIsExpensive",
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index e16248bf59f7c..a63824735490f 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -878,13 +878,6 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
       if (Model == TLSModel::InitialExec)
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
-      // On AIX, TLS-LD heuristic may have turned LD access into IE access.
-      PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
-      if (Model == TLSModel::LocalDynamic && FuncInfo->isAIXFuncUseTLSIE()) {
-        LLVM_DEBUG(
-            dbgs() << "Current function use IE access for default LD vars.\n");
-        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
@@ -2964,10 +2957,10 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
       Name += cast<MCSymbolXCOFF>(I.first.first)->getSymbolTableName();
       MCSymbol *S = OutContext.getOrCreateSymbol(Name);
       TCEntry = cast<MCSectionXCOFF>(
-          getObjFileLowering().getSectionForTOCEntry(S, TM, I.first.second));
+          getObjFileLowering().getSectionForTOCEntry(S, TM));
     } else {
-      TCEntry = cast<MCSectionXCOFF>(getObjFileLowering().getSectionForTOCEntry(
-          I.first.first, TM, I.first.second));
+      TCEntry = cast<MCSectionXCOFF>(
+          getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
     }
     OutStreamer->switchSection(TCEntry);
 
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 4fbb17d7d10c3..d27932f2915fb 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3374,46 +3374,6 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   bool Is64Bit = Subtarget.isPPC64();
   TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
-  // Initialize heuristic setting lazily:
-  // (1) Use initial-exec for single TLS var reference within current function.
-  // (2) Use local-dynamic for multiple TLS var references within current func.
-  PPCFunctionInfo *FuncInfo =
-      DAG.getMachineFunction().getInfo<PPCFunctionInfo>();
-  if (Subtarget.hasAIXUseTLSIEForLDInSharedLibrary() &&
-      !FuncInfo->isAIXFuncUseInitDone()) {
-    std::set<const GlobalValue *> TLSGV;
-    for (SDNode &Node : DAG.allnodes()) {
-      SDNode *N = &Node;
-      if (N->getOpcode() == ISD::GlobalTLSAddress) {
-        if (GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N)) {
-          const GlobalValue *GV = GA->getGlobal();
-          TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
-          if (Model == TLSModel::InitialExec ||
-              Model == TLSModel::LocalDynamic) {
-            TLSGV.insert(GV);
-          }
-        }
-      }
-    }
-    LLVM_DEBUG(dbgs() << format("TLSGV count:%d\n", TLSGV.size()));
-    if (TLSGV.size() == 1) {
-      FuncInfo->setAIXFuncUseTLSIE();
-    } else if (TLSGV.size() > 1) {
-      FuncInfo->setAIXFuncUseTLSLD();
-    }
-    FuncInfo->setAIXFuncUseInitDone();
-  }
-
-  if (FuncInfo->isAIXFuncUseTLSLD()) {
-    LLVM_DEBUG(dbgs() << DAG.getMachineFunction().getName()
-                      << " function use TLS-LD model for TLS IE/LD vars.\n");
-    Model = TLSModel::LocalDynamic;
-  } else if (FuncInfo->isAIXFuncUseTLSIE()) {
-    LLVM_DEBUG(dbgs() << DAG.getMachineFunction().getName()
-                      << " function use TLS-IE model for TLS IE/LD vars.\n");
-    Model = TLSModel::InitialExec;
-  }
-
   bool IsTLSLocalExecModel = Model == TLSModel::LocalExec;
 
   if (IsTLSLocalExecModel || Model == TLSModel::InitialExec) {
diff --git a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
index 03136743358ec..df655a3be9512 100644
--- a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
@@ -150,11 +150,6 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   /// to use SExt/ZExt flags in later optimization.
   std::vector<std::pair<Register, ISD::ArgFlagsTy>> LiveInAttrs;
 
-  /// FIXME: Flags for heuristic.
-  bool AIXFuncUseTLSLD = false;
-  bool AIXFuncUseTLSIE = false;
-  bool AIXFuncUseInitDone = false;
-
 public:
   explicit PPCFunctionInfo(const Function &F, const TargetSubtargetInfo *STI);
 
@@ -226,13 +221,6 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   void setHasFastCall() { HasFastCall = true; }
   bool hasFastCall() const { return HasFastCall;}
 
-  void setAIXFuncUseInitDone() { AIXFuncUseInitDone = true; }
-  bool isAIXFuncUseInitDone() const { return AIXFuncUseInitDone; }
-  void setAIXFuncUseTLSLD() { AIXFuncUseTLSLD = true; }
-  bool isAIXFuncUseTLSLD() const { return AIXFuncUseTLSLD; }
-  void setAIXFuncUseTLSIE() { AIXFuncUseTLSIE = true; }
-  bool isAIXFuncUseTLSIE() const { return AIXFuncUseTLSIE; }
-
   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
   void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
 
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-gd-double.ll b/llvm/test/CodeGen/PowerPC/aix-tls-gd-double.ll
index d84f92b11c978..ae41b6b130106 100644
--- a/llvm/test/CodeGen/PowerPC/aix-tls-gd-double.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-gd-double.ll
@@ -636,8 +636,7 @@ entry:
 ; SMALL32-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL32-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL32-LABEL:  L..C5:
-; SMALL32-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
-; SMALL32-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
+; SMALL32-NEXT:   .tc TIInit[TC],TIInit[TL]@ld
 ; SMALL32-LABEL:  L..C6:
 ; SMALL32-NEXT:   .tc .TWInit[TC],TWInit[TL]@m
 ; SMALL32-LABEL:  L..C7:
@@ -655,8 +654,7 @@ entry:
 ; LARGE32-LABEL:  L..C3:
 ; LARGE32-NEXT:   .tc TGInit[TE],TGInit[TL]@gd
 ; LARGE32-LABEL:  L..C4:
-; LARGE32-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
-; LARGE32-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
+; LARGE32-NEXT:   .tc TIInit[TE],TIInit[TL]@ld
 ; LARGE32-LABEL:  L..C5:
 ; LARGE32-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE32-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
@@ -680,8 +678,7 @@ entry:
 ; SMALL64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL64-LABEL:  L..C5:
-; SMALL64-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
-; SMALL64-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
+; SMALL64-NEXT:  .tc TIInit[TC],TIInit[TL]@ld
 ; SMALL64-LABEL:  L..C6:
 ; SMALL64-NEXT:  .tc .TWInit[TC],TWInit[TL]@m
 ; SMALL64-LABEL:  L..C7:
@@ -702,8 +699,7 @@ entry:
 ; LARGE64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE64-LABEL:  L..C5:
-; LARGE64-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
-; LARGE64-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
+; LARGE64-NEXT:  .tc TIInit[TE],TIInit[TL]@ld
 ; LARGE64-LABEL:  L..C6:
 ; LARGE64-NEXT:  .tc .TWInit[TE],TWInit[TL]@m
 ; LARGE64-LABEL:  L..C7:
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll b/llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll
index f9567840a1965..bbb8e04b67b95 100644
--- a/llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-gd-int.ll
@@ -651,8 +651,7 @@ entry:
 ; SMALL32-NEXT:	 .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL32-NEXT:	 .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL32-LABEL: L..C5:
-; SMALL32-NEXT:	 .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
-; SMALL32-NEXT:	 .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
+; SMALL32-NEXT:	 .tc TIUninit[TC],TIUninit[UL]@ld
 ; SMALL32-LABEL: L..C6:
 ; SMALL32-NEXT:	 .tc .TWUninit[TC],TWUninit[TL]@m
 ; SMALL32-LABEL: L..C7:
@@ -670,8 +669,7 @@ entry:
 ; LARGE32-LABEL: L..C3:
 ; LARGE32-NEXT:  .tc TGInit[TE],TGInit[TL]@gd
 ; LARGE32-LABEL: L..C4:
-; LARGE32-NEXT:	 .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
-; LARGE32-NEXT:	 .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
+; LARGE32-NEXT:  .tc TIUninit[TE],TIUninit[UL]@ld
 ; LARGE32-LABEL: L..C5:
 ; LARGE32-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE32-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
@@ -695,8 +693,7 @@ entry:
 ; SMALL64-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL64-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL64-LABEL:  L..C5:
-; SMALL64-NEXT:	 .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
-; SMALL64-NEXT:	 .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
+; SMALL64-NEXT:   .tc TIUninit[TC],TIUninit[UL]@ld
 ; SMALL64-LABEL:  L..C6:
 ; SMALL64-NEXT:   .tc .TWUninit[TC],TWUninit[TL]@m
 ; SMALL64-LABEL:  L..C7:
@@ -717,8 +714,7 @@ entry:
 ; LARGE64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE64-LABEL:  L..C5:
-; LARGE64-NEXT:	 .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
-; LARGE64-NEXT:	 .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
+; LARGE64-NEXT:  .tc TIUninit[TE],TIUninit[UL]@ld
 ; LARGE64-LABEL:  L..C6:
 ; LARGE64-NEXT:  .tc .TWUninit[TE],TWUninit[TL]@m
 ; LARGE64-LABEL:  L..C7:
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-gd-longlong.ll b/llvm/test/CodeGen/PowerPC/aix-tls-gd-longlong.ll
index 06937635bbd18..ff087a2144488 100644
--- a/llvm/test/CodeGen/PowerPC/aix-tls-gd-longlong.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-gd-longlong.ll
@@ -687,11 +687,9 @@ entry:
 ; SMALL32-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL32-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL32-LABEL:  L..C3:
-; SMALL32-NEXT:  .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
-; SMALL32-NEXT:  .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
+; SMALL32-NEXT:  .tc TIUninit[TC],TIUninit[UL]@ld
 ; SMALL32-LABEL:  L..C4:
-; SMALL32-NEXT:  .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
-; SMALL32-NEXT:  .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
+; SMALL32-NEXT:  .tc TIInit[TC],TIInit[TL]@ld
 ; SMALL32-LABEL:  L..C5:
 ; SMALL32-NEXT:  .tc .TWInit[TC],TWInit[TL]@m
 ; SMALL32-LABEL:  L..C6:
@@ -705,14 +703,12 @@ entry:
 ; LARGE32-LABEL:  L..C1:
 ; LARGE32-NEXT:  .tc TGInit[TE],TGInit[TL]@gd
 ; LARGE32-LABEL:  L..C2:
-; LARGE32-NEXT:  .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
-; LARGE32-NEXT:  .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
+; LARGE32-NEXT:  .tc TIUninit[TE],TIUninit[UL]@ld
 ; LARGE32-LABEL:  L..C3:
 ; LARGE32-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE32-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE32-LABEL:  L..C4:
-; LARGE32-NEXT:  .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
-; LARGE32-NEXT:  .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
+; LARGE32-NEXT:  .tc TIInit[TE],TIInit[TL]@ld
 ; LARGE32-LABEL:  L..C5:
 ; LARGE32-NEXT:  .tc .TWInit[TE],TWInit[TL]@m
 ; LARGE32-LABEL:  L..C6:
@@ -729,11 +725,9 @@ entry:
 ; SMALL64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL64-LABEL:  L..C3:
-; SMALL64-NEXT:  .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
-; SMALL64-NEXT:  .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
+; SMALL64-NEXT:  .tc TIUninit[TC],TIUninit[UL]@ld
 ; SMALL64-LABEL:  L..C4:
-; SMALL64-NEXT:  .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
-; SMALL64-NEXT:  .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
+; SMALL64-NEXT:  .tc TIInit[TC],TIInit[TL]@ld
 ; SMALL64-LABEL:  L..C5:
 ; SMALL64-NEXT:  .tc .TWInit[TC],TWInit[TL]@m
 ; SMALL64-LABEL:  L..C6:
@@ -750,11 +744,9 @@ entry:
 ; LARGE64-NEXT:  .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE64-NEXT:  .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE64-LABEL:  L..C3:
-; LARGE64-NEXT:  .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
-; LARGE64-NEXT:  .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
+; LARGE64-NEXT:  .tc TIUninit[TE],TIUninit[UL]@ld
 ; LARGE64-LABEL:  L..C4:
-; LARGE64-NEXT:  .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
-; LARGE64-NEXT:  .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
+; LARGE64-NEXT:  .tc TIInit[TE],TIInit[TL]@ld
 ; LARGE64-LABEL:  L..C5:
 ; LARGE64-NEXT:  .tc .TWInit[TE],TWInit[TL]@m
 ; LARGE64-LABEL:  L..C6:
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-ld-unqualified-symbols.ll b/llvm/test/CodeGen/PowerPC/aix-tls-ld-unqualified-symbols.ll
deleted file mode 100644
index d92375730a95a..0000000000000
--- a/llvm/test/CodeGen/PowerPC/aix-tls-ld-unqualified-symbols.ll
+++ /dev/null
@@ -1,362 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
-; RUN:     --code-model=small < %s | FileCheck %s --check-prefixes=SMALL64,COMMON
-; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
-; RUN:     --code-model=large < %s | FileCheck %s --check-prefixes=LARGE64,COMMON
-; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
-; RUN:     --code-model=small < %s | FileCheck %s --check-prefixes=SMALL32,COMMON
-; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
-; RUN:     --code-model=large < %s | FileCheck %s --check-prefixes=LARGE32,COMMON
-
- at _$TLSLD. = thread_local(localdynamic) global i32 42, align 4
- at _$TLSLD.a = thread_local(localdynamic) global i32 42, align 4
- at __$TLSLD. = internal thread_local(localdynamic) global i32 42, align 4
- at _$TLSLD._$TLSLD. = internal thread_local(localdynamic) global i32 42, align 4
-
-declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
-
-define i32 @loadSym1() {
-; SMALL64-LABEL: loadSym1:
-; SMALL64:       # %bb.0: # %entry
-; SMALL64-NEXT:    mflr 0
-; SMALL64-NEXT:    stdu 1, -48(1)
-; SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; SMALL64-NEXT:    std 0, 64(1)
-; SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; SMALL64-NEXT:    ld 4, L..C1(2) # target-flags(ppc-tlsld) @"_$TLSLD."
-; SMALL64-NEXT:    lwzx 3, 3, 4
-; SMALL64-NEXT:    addi 1, 1, 48
-; SMALL64-NEXT:    ld 0, 16(1)
-; SMALL64-NEXT:    mtlr 0
-; SMALL64-NEXT:    blr
-;
-; LARGE64-LABEL: loadSym1:
-; LARGE64:       # %bb.0: # %entry
-; LARGE64-NEXT:    mflr 0
-; LARGE64-NEXT:    stdu 1, -48(1)
-; LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; LARGE64-NEXT:    addis 6, L..C1 at u(2)
-; LARGE64-NEXT:    std 0, 64(1)
-; LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; LARGE64-NEXT:    ld 4, L..C1 at l(6)
-; LARGE64-NEXT:    lwzx 3, 3, 4
-; LARGE64-NEXT:    addi 1, 1, 48
-; LARGE64-NEXT:    ld 0, 16(1)
-; LARGE64-NEXT:    mtlr 0
-; LARGE64-NEXT:    blr
-;
-; SMALL32-LABEL: loadSym1:
-; SMALL32:       # %bb.0: # %entry
-; SMALL32-NEXT:    mflr 0
-; SMALL32-NEXT:    stwu 1, -32(1)
-; SMALL32-NEXT:    lwz 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; SMALL32-NEXT:    stw 0, 40(1)
-; SMALL32-NEXT:    bla .__tls_get_mod[PR]
-; SMALL32-NEXT:    lwz 4, L..C1(2) # target-flags(ppc-tlsld) @"_$TLSLD."
-; SMALL32-NEXT:    lwzx 3, 3, 4
-; SMALL32-NEXT:    addi 1, 1, 32
-; SMALL32-NEXT:    lwz 0, 8(1)
-; SMALL32-NEXT:    mtlr 0
-; SMALL32-NEXT:    blr
-;
-; LARGE32-LABEL: loadSym1:
-; LARGE32:       # %bb.0: # %entry
-; LARGE32-NEXT:    mflr 0
-; LARGE32-NEXT:    stwu 1, -32(1)
-; LARGE32-NEXT:    stw 0, 40(1)
-; LARGE32-NEXT:    addis 6, L..C0 at u(2)
-; LARGE32-NEXT:    addis 3, L..C1 at u(2)
-; LARGE32-NEXT:    lwz 3, L..C1 at l(3)
-; LARGE32-NEXT:    bla .__tls_get_mod[PR]
-; LARGE32-NEXT:    lwz 4, L..C0 at l(6)
-; LARGE32-NEXT:    lwzx 3, 3, 4
-; LARGE32-NEXT:    addi 1, 1, 32
-; LARGE32-NEXT:    lwz 0, 8(1)
-; LARGE32-NEXT:    mtlr 0
-; LARGE32-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_$TLSLD.)
-  %1 = load i32, ptr %0, align 4
-  ret i32 %1
-}
-
-define i32 @loadSym2() {
-; SMALL64-LABEL: loadSym2:
-; SMALL64:       # %bb.0: # %entry
-; SMALL64-NEXT:    mflr 0
-; SMALL64-NEXT:    stdu 1, -48(1)
-; SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; SMALL64-NEXT:    std 0, 64(1)
-; SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @"_$TLSLD.a"
-; SMALL64-NEXT:    lwzx 3, 3, 4
-; SMALL64-NEXT:    addi 1, 1, 48
-; SMALL64-NEXT:    ld 0, 16(1)
-; SMALL64-NEXT:    mtlr 0
-; SMALL64-NEXT:    blr
-;
-; LARGE64-LABEL: loadSym2:
-; LARGE64:       # %bb.0: # %entry
-; LARGE64-NEXT:    mflr 0
-; LARGE64-NEXT:    stdu 1, -48(1)
-; LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; LARGE64-NEXT:    addis 6, L..C2 at u(2)
-; LARGE64-NEXT:    std 0, 64(1)
-; LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; LARGE64-NEXT:    ld 4, L..C2 at l(6)
-; LARGE64-NEXT:    lwzx 3, 3, 4
-; LARGE64-NEXT:    addi 1, 1, 48
-; LARGE64-NEXT:    ld 0, 16(1)
-; LARGE64-NEXT:    mtlr 0
-; LARGE64-NEXT:    blr
-;
-; SMALL32-LABEL: loadSym2:
-; SMALL32:       # %bb.0: # %entry
-; SMALL32-NEXT:    mflr 0
-; SMALL32-NEXT:    stwu 1, -32(1)
-; SMALL32-NEXT:    lwz 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; SMALL32-NEXT:    stw 0, 40(1)
-; SMALL32-NEXT:    bla .__tls_get_mod[PR]
-; SMALL32-NEXT:    lwz 4, L..C2(2) # target-flags(ppc-tlsld) @"_$TLSLD.a"
-; SMALL32-NEXT:    lwzx 3, 3, 4
-; SMALL32-NEXT:    addi 1, 1, 32
-; SMALL32-NEXT:    lwz 0, 8(1)
-; SMALL32-NEXT:    mtlr 0
-; SMALL32-NEXT:    blr
-;
-; LARGE32-LABEL: loadSym2:
-; LARGE32:       # %bb.0: # %entry
-; LARGE32-NEXT:    mflr 0
-; LARGE32-NEXT:    stwu 1, -32(1)
-; LARGE32-NEXT:    stw 0, 40(1)
-; LARGE32-NEXT:    addis 6, L..C2 at u(2)
-; LARGE32-NEXT:    addis 3, L..C1 at u(2)
-; LARGE32-NEXT:    lwz 3, L..C1 at l(3)
-; LARGE32-NEXT:    bla .__tls_get_mod[PR]
-; LARGE32-NEXT:    lwz 4, L..C2 at l(6)
-; LARGE32-NEXT:    lwzx 3, 3, 4
-; LARGE32-NEXT:    addi 1, 1, 32
-; LARGE32-NEXT:    lwz 0, 8(1)
-; LARGE32-NEXT:    mtlr 0
-; LARGE32-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_$TLSLD.a)
-  %1 = load i32, ptr %0, align 4
-  ret i32 %1
-}
-
-define i32 @loadSym3() {
-; SMALL64-LABEL: loadSym3:
-; SMALL64:       # %bb.0: # %entry
-; SMALL64-NEXT:    mflr 0
-; SMALL64-NEXT:    stdu 1, -48(1)
-; SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; SMALL64-NEXT:    std 0, 64(1)
-; SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @"__$TLSLD."
-; SMALL64-NEXT:    lwzx 3, 3, 4
-; SMALL64-NEXT:    addi 1, 1, 48
-; SMALL64-NEXT:    ld 0, 16(1)
-; SMALL64-NEXT:    mtlr 0
-; SMALL64-NEXT:    blr
-;
-; LARGE64-LABEL: loadSym3:
-; LARGE64:       # %bb.0: # %entry
-; LARGE64-NEXT:    mflr 0
-; LARGE64-NEXT:    stdu 1, -48(1)
-; LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; LARGE64-NEXT:    addis 6, L..C3 at u(2)
-; LARGE64-NEXT:    std 0, 64(1)
-; LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; LARGE64-NEXT:    ld 4, L..C3 at l(6)
-; LARGE64-NEXT:    lwzx 3, 3, 4
-; LARGE64-NEXT:    addi 1, 1, 48
-; LARGE64-NEXT:    ld 0, 16(1)
-; LARGE64-NEXT:    mtlr 0
-; LARGE64-NEXT:    blr
-;
-; SMALL32-LABEL: loadSym3:
-; SMALL32:       # %bb.0: # %entry
-; SMALL32-NEXT:    mflr 0
-; SMALL32-NEXT:    stwu 1, -32(1)
-; SMALL32-NEXT:    lwz 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; SMALL32-NEXT:    stw 0, 40(1)
-; SMALL32-NEXT:    bla .__tls_get_mod[PR]
-; SMALL32-NEXT:    lwz 4, L..C3(2) # target-flags(ppc-tlsld) @"__$TLSLD."
-; SMALL32-NEXT:    lwzx 3, 3, 4
-; SMALL32-NEXT:    addi 1, 1, 32
-; SMALL32-NEXT:    lwz 0, 8(1)
-; SMALL32-NEXT:    mtlr 0
-; SMALL32-NEXT:    blr
-;
-; LARGE32-LABEL: loadSym3:
-; LARGE32:       # %bb.0: # %entry
-; LARGE32-NEXT:    mflr 0
-; LARGE32-NEXT:    stwu 1, -32(1)
-; LARGE32-NEXT:    stw 0, 40(1)
-; LARGE32-NEXT:    addis 6, L..C3 at u(2)
-; LARGE32-NEXT:    addis 3, L..C1 at u(2)
-; LARGE32-NEXT:    lwz 3, L..C1 at l(3)
-; LARGE32-NEXT:    bla .__tls_get_mod[PR]
-; LARGE32-NEXT:    lwz 4, L..C3 at l(6)
-; LARGE32-NEXT:    lwzx 3, 3, 4
-; LARGE32-NEXT:    addi 1, 1, 32
-; LARGE32-NEXT:    lwz 0, 8(1)
-; LARGE32-NEXT:    mtlr 0
-; LARGE32-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @__$TLSLD.)
-  %1 = load i32, ptr %0, align 4
-  ret i32 %1
-}
-
-define i32 @loadSym4() {
-; SMALL64-LABEL: loadSym4:
-; SMALL64:       # %bb.0: # %entry
-; SMALL64-NEXT:    mflr 0
-; SMALL64-NEXT:    stdu 1, -48(1)
-; SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; SMALL64-NEXT:    std 0, 64(1)
-; SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; SMALL64-NEXT:    ld 4, L..C4(2) # target-flags(ppc-tlsld) @"_$TLSLD._$TLSLD."
-; SMALL64-NEXT:    lwzx 3, 3, 4
-; SMALL64-NEXT:    addi 1, 1, 48
-; SMALL64-NEXT:    ld 0, 16(1)
-; SMALL64-NEXT:    mtlr 0
-; SMALL64-NEXT:    blr
-;
-; LARGE64-LABEL: loadSym4:
-; LARGE64:       # %bb.0: # %entry
-; LARGE64-NEXT:    mflr 0
-; LARGE64-NEXT:    stdu 1, -48(1)
-; LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; LARGE64-NEXT:    addis 6, L..C4 at u(2)
-; LARGE64-NEXT:    std 0, 64(1)
-; LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; LARGE64-NEXT:    ld 4, L..C4 at l(6)
-; LARGE64-NEXT:    lwzx 3, 3, 4
-; LARGE64-NEXT:    addi 1, 1, 48
-; LARGE64-NEXT:    ld 0, 16(1)
-; LARGE64-NEXT:    mtlr 0
-; LARGE64-NEXT:    blr
-;
-; SMALL32-LABEL: loadSym4:
-; SMALL32:       # %bb.0: # %entry
-; SMALL32-NEXT:    mflr 0
-; SMALL32-NEXT:    stwu 1, -32(1)
-; SMALL32-NEXT:    lwz 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; SMALL32-NEXT:    stw 0, 40(1)
-; SMALL32-NEXT:    bla .__tls_get_mod[PR]
-; SMALL32-NEXT:    lwz 4, L..C4(2) # target-flags(ppc-tlsld) @"_$TLSLD._$TLSLD."
-; SMALL32-NEXT:    lwzx 3, 3, 4
-; SMALL32-NEXT:    addi 1, 1, 32
-; SMALL32-NEXT:    lwz 0, 8(1)
-; SMALL32-NEXT:    mtlr 0
-; SMALL32-NEXT:    blr
-;
-; LARGE32-LABEL: loadSym4:
-; LARGE32:       # %bb.0: # %entry
-; LARGE32-NEXT:    mflr 0
-; LARGE32-NEXT:    stwu 1, -32(1)
-; LARGE32-NEXT:    stw 0, 40(1)
-; LARGE32-NEXT:    addis 6, L..C4 at u(2)
-; LARGE32-NEXT:    addis 3, L..C1 at u(2)
-; LARGE32-NEXT:    lwz 3, L..C1 at l(3)
-; LARGE32-NEXT:    bla .__tls_get_mod[PR]
-; LARGE32-NEXT:    lwz 4, L..C4 at l(6)
-; LARGE32-NEXT:    lwzx 3, 3, 4
-; LARGE32-NEXT:    addi 1, 1, 32
-; LARGE32-NEXT:    lwz 0, 8(1)
-; LARGE32-NEXT:    mtlr 0
-; LARGE32-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_$TLSLD._$TLSLD.)
-  %1 = load i32, ptr %0, align 4
-  ret i32 %1
-}
-
-; COMMON:      .csect _Renamed..5f24__TLSLD.[TL],2
-; COMMON-NEXT: .globl  _Renamed..5f24__TLSLD.[TL]      # @"_$TLSLD."
-; COMMON-NEXT: .rename _Renamed..5f24__TLSLD.[TL],"_$TLSLD."
-; COMMON:      .csect _Renamed..5f24__TLSLD.a[TL],2
-; COMMON-NEXT: .globl  _Renamed..5f24__TLSLD.a[TL]     # @"_$TLSLD.a"
-; COMMON-NEXT: .rename _Renamed..5f24__TLSLD.a[TL],"_$TLSLD.a"
-; COMMON:      .csect _Renamed..5f5f24___TLSLD.[TL],2
-; COMMON-NEXT: .lglobl _Renamed..5f5f24___TLSLD.[TL]   # @"__$TLSLD."
-; COMMON-NEXT: .rename _Renamed..5f5f24___TLSLD.[TL],"__$TLSLD."
-; COMMON:      .csect _Renamed..5f245f24__TLSLD.__TLSLD.[TL],2
-; COMMON-NEXT: .lglobl _Renamed..5f245f24__TLSLD.__TLSLD.[TL] # @"_$TLSLD._$TLSLD."
-; COMMON-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TL],"_$TLSLD._$TLSLD."
-
-; SMALL64-LABEL: .toc
-; SMALL64-LABEL: L..C0:
-; SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
-; SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; SMALL64-LABEL: L..C1:
-; SMALL64-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.[TC],_Renamed..5f24__TLSLD.[TL]@ld
-; SMALL64-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TC],"_$TLSLD."
-; SMALL64-LABEL: L..C2:
-; SMALL64-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.a[TC],_Renamed..5f24__TLSLD.a[TL]@ld
-; SMALL64-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.a[TC],"_$TLSLD.a"
-; SMALL64-LABEL: L..C3:
-; SMALL64-NEXT: .tc _Renamed..5f245f5f24__TLSLD.___TLSLD.[TC],_Renamed..5f5f24___TLSLD.[TL]@ld
-; SMALL64-NEXT: .rename _Renamed..5f245f5f24__TLSLD.___TLSLD.[TC],"__$TLSLD."
-; SMALL64-LABEL: L..C4:
-; SMALL64-NEXT: .tc _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TC],_Renamed..5f245f24__TLSLD.__TLSLD.[TL]@ld
-; SMALL64-NEXT: .rename _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TC],"_$TLSLD._$TLSLD."
-
-; LARGE64-LABEL: .toc
-; LARGE64-LABEL: L..C0:
-; LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
-; LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; LARGE64-LABEL: L..C1:
-; LARGE64-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.[TE],_Renamed..5f24__TLSLD.[TL]@ld
-; LARGE64-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TE],"_$TLSLD."
-; LARGE64-LABEL: L..C2:
-; LARGE64-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.a[TE],_Renamed..5f24__TLSLD.a[TL]@ld
-; LARGE64-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.a[TE],"_$TLSLD.a"
-; LARGE64-LABEL: L..C3:
-; LARGE64-NEXT: .tc _Renamed..5f245f5f24__TLSLD.___TLSLD.[TE],_Renamed..5f5f24___TLSLD.[TL]@ld
-; LARGE64-NEXT: .rename _Renamed..5f245f5f24__TLSLD.___TLSLD.[TE],"__$TLSLD."
-; LARGE64-LABEL: L..C4:
-; LARGE64-NEXT: .tc _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TE],_Renamed..5f245f24__TLSLD.__TLSLD.[TL]@ld
-; LARGE64-NEXT: .rename _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TE],"_$TLSLD._$TLSLD."
-
-; SMALL32-LABEL: .toc
-; SMALL32-LABEL: L..C0:
-; SMALL32-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
-; SMALL32-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; SMALL32-LABEL: L..C1:
-; SMALL32-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.[TC],_Renamed..5f24__TLSLD.[TL]@ld
-; SMALL32-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TC],"_$TLSLD."
-; SMALL32-LABEL: L..C2:
-; SMALL32-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.a[TC],_Renamed..5f24__TLSLD.a[TL]@ld
-; SMALL32-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.a[TC],"_$TLSLD.a"
-; SMALL32-LABEL: L..C3:
-; SMALL32-NEXT: .tc _Renamed..5f245f5f24__TLSLD.___TLSLD.[TC],_Renamed..5f5f24___TLSLD.[TL]@ld
-; SMALL32-NEXT: .rename _Renamed..5f245f5f24__TLSLD.___TLSLD.[TC],"__$TLSLD."
-; SMALL32-LABEL: L..C4:
-; SMALL32-NEXT: .tc _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TC],_Renamed..5f245f24__TLSLD.__TLSLD.[TL]@ld
-; SMALL32-NEXT: .rename _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TC],"_$TLSLD._$TLSLD."
-
-; LARGE32-LABEL: .toc
-; LARGE32-LABEL: L..C0:
-; LARGE32-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.[TE],_Renamed..5f24__TLSLD.[TL]@ld
-; LARGE32-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.[TE],"_$TLSLD."
-; LARGE32-LABEL: L..C1:
-; LARGE32-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
-; LARGE32-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; LARGE32-LABEL: L..C2:
-; LARGE32-NEXT: .tc _Renamed..5f245f24__TLSLD.__TLSLD.a[TE],_Renamed..5f24__TLSLD.a[TL]@ld
-; LARGE32-NEXT: .rename _Renamed..5f245f24__TLSLD.__TLSLD.a[TE],"_$TLSLD.a"
-; LARGE32-LABEL: L..C3:
-; LARGE32-NEXT: .tc _Renamed..5f245f5f24__TLSLD.___TLSLD.[TE],_Renamed..5f5f24___TLSLD.[TL]@ld
-; LARGE32-NEXT: .rename _Renamed..5f245f5f24__TLSLD.___TLSLD.[TE],"__$TLSLD."
-; LARGE32-LABEL: L..C4:
-; LARGE32-NEXT: .tc _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TE],_Renamed..5f245f24__TLSLD.__TLSLD.[TL]@ld
-; LARGE32-NEXT: .rename _Renamed..5f245f245f24__TLSLD.__TLSLD.__TLSLD.[TE],"_$TLSLD._$TLSLD."
-
diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-local-dynamic.ll b/llvm/test/CodeGen/PowerPC/aix-tls-local-dynamic.ll
index d5dc7e57d3632..22349337f1890 100644
--- a/llvm/test/CodeGen/PowerPC/aix-tls-local-dynamic.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-local-dynamic.ll
@@ -358,52 +358,39 @@ entry:
 ; SMALL-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; SMALL-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; SMALL:        [[TGInitL]]:
-; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TGInit[TC],TGInit[TL]@ld
-; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TGInit[TC],"TGInit"
+; SMALL-NEXT:   .tc TGInit[TC],TGInit[TL]@ld
 ; SMALL:        [[TGUninitL]]:
-; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TGUninit[TC],TGUninit[TL]@ld
-; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TGUninit[TC],"TGUninit"
+; SMALL-NEXT:   .tc TGUninit[TC],TGUninit[TL]@ld
 ; SMALL:        [[TIInitL]]:
-; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TC],TIInit[TL]@ld
-; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TC],"TIInit"
+; SMALL-NEXT:   .tc TIInit[TC],TIInit[TL]@ld
 ; SMALL:        [[TIUninitL]]:
-; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TIUninit[TC],TIUninit[UL]@ld
-; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TIUninit[TC],"TIUninit"
+; SMALL-NEXT:   .tc TIUninit[TC],TIUninit[UL]@ld
 ; SMALL:        [[TWInitL]]:
-; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TWInit[TC],TWInit[TL]@ld
-; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TWInit[TC],"TWInit"
+; SMALL-NEXT:   .tc TWInit[TC],TWInit[TL]@ld
 ; SMALL:        [[TWUninitL]]:
-; SMALL-NEXT:   .tc _Renamed..5f24__TLSLD.TWUninit[TC],TWUninit[TL]@ld
-; SMALL-NEXT:   .rename _Renamed..5f24__TLSLD.TWUninit[TC],"TWUninit"
+; SMALL-NEXT:   .tc TWUninit[TC],TWUninit[TL]@ld
 
 ; LARGE64:        [[ModuleHandleL]]:
 ; LARGE64-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE64-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ; LARGE64:        [[TGInitL]]:
-; LARGE64-NEXT:   .tc _Renamed..5f24__TLSLD.TGInit[TE],TGInit[TL]@ld
-; LARGE64-NEXT:   .rename _Renamed..5f24__TLSLD.TGInit[TE],"TGInit"
+; LARGE64-NEXT:   .tc TGInit[TE],TGInit[TL]@ld
 ;
 ; LARGE32:        [[TGInitL]]:
-; LARGE32-NEXT:   .tc _Renamed..5f24__TLSLD.TGInit[TE],TGInit[TL]@ld
-; LARGE32-NEXT:   .rename _Renamed..5f24__TLSLD.TGInit[TE],"TGInit"
+; LARGE32-NEXT:   .tc TGInit[TE],TGInit[TL]@ld
 ; LARGE32:        [[ModuleHandleL]]:
 ; LARGE32-NEXT:   .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; LARGE32-NEXT:   .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
 ;
 ; LARGE:        [[TGUninitL]]:
-; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TGUninit[TE],TGUninit[TL]@ld
-; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TGUninit[TE],"TGUninit"
+; LARGE-NEXT:   .tc TGUninit[TE],TGUninit[TL]@ld
 ; LARGE:        [[TIInitL]]:
-; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TIInit[TE],TIInit[TL]@ld
-; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TIInit[TE],"TIInit"
+; LARGE-NEXT:   .tc TIInit[TE],TIInit[TL]@ld
 ; LARGE:        [[TIUninitL]]:
-; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TIUninit[TE],TIUninit[UL]@ld
-; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TIUninit[TE],"TIUninit"
+; LARGE-NEXT:   .tc TIUninit[TE],TIUninit[UL]@ld
 ; LARGE:        [[TWInitL]]:
-; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TWInit[TE],TWInit[TL]@ld
-; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TWInit[TE],"TWInit"
+; LARGE-NEXT:   .tc TWInit[TE],TWInit[TL]@ld
 ; LARGE:        [[TWUninitL]]:
-; LARGE-NEXT:   .tc _Renamed..5f24__TLSLD.TWUninit[TE],TWUninit[TL]@ld
-; LARGE-NEXT:   .rename _Renamed..5f24__TLSLD.TWUninit[TE],"TWUninit"
+; LARGE-NEXT:   .tc TWUninit[TE],TWUninit[TL]@ld
 
 declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)

>From ad0db6cd32e90a41dc2c728965d59dfd408ad76b Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Fri, 15 Mar 2024 04:41:09 -0400
Subject: [PATCH 05/10] Initial commit for
 aix-shared-library-tls-model-heuristic

---
 clang/include/clang/Driver/Options.td         |   4 +
 clang/lib/Basic/Targets/PPC.cpp               |   7 +
 clang/lib/Basic/Targets/PPC.h                 |   1 +
 llvm/lib/Target/PowerPC/PPC.td                |   6 +
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     |  14 +-
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  42 ++
 .../Target/PowerPC/PPCMachineFunctionInfo.h   |  13 +
 llvm/lib/Target/PowerPC/PPCSubtarget.cpp      |   5 +
 .../aix-shared-library-tls-model-heuristic.ll | 405 ++++++++++++++++++
 ...ary-tls-model-heuristic-opt-IRattribute.ll |  21 +
 ...-shared-library-tls-model-heuristic-opt.ll |  22 +
 11 files changed, 539 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/aix-shared-library-tls-model-heuristic.ll
 create mode 100644 llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt-IRattribute.ll
 create mode 100644 llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt.ll

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 322cc12af34ac..17d7a4612c203 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5077,6 +5077,10 @@ def maix_small_local_dynamic_tls : Flag<["-"], "maix-small-local-dynamic-tls">,
            "where the offset from the TLS base is encoded as an "
            "immediate operand (AIX 64-bit only). "
            "This access sequence is not used for variables larger than 32KB.">;
+def maix_shared_library_tls_model_heuristic : Flag<["-"], "maix-shared-library-tls-model-heuristic">,
+  Group<m_ppc_Features_Group>,
+  HelpText<"For shared library loaded with the main program, use heuristic to "
+           "tune TLS model at function level (AIX 64-bit only).">;
 def maix_struct_return : Flag<["-"], "maix-struct-return">,
   Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Return all structs in memory (PPC32 only)">,
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index bad5259958a88..61971898fee95 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -91,6 +91,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
       IsISA3_1 = true;
     } else if (Feature == "+quadword-atomics") {
       HasQuadwordAtomics = true;
+    } else if (Feature == "+aix-shared-library-tls-model-heuristic") {
+      HasAIXShLibTLSModelHeuristic = true;
     }
     // TODO: Finish this list and add an assert that we've handled them
     // all.
@@ -580,6 +582,9 @@ bool PPCTargetInfo::initFeatureMap(
   Features["aix-small-local-exec-tls"] = false;
   Features["aix-small-local-dynamic-tls"] = false;
 
+  // Turn off TLS model heuristic by default.
+  Features["aix-shared-library-tls-model-heuristic"] = false;
+
   Features["spe"] = llvm::StringSwitch<bool>(CPU)
                         .Case("8548", true)
                         .Case("e500", true)
@@ -722,6 +727,8 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
       .Case("isa-v30-instructions", IsISA3_0)
       .Case("isa-v31-instructions", IsISA3_1)
       .Case("quadword-atomics", HasQuadwordAtomics)
+      .Case("aix-shared-library-tls-model-heuristic",
+            HasAIXShLibTLSModelHeuristic)
       .Default(false);
 }
 
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index 30059e418e69b..fa299f086fb9b 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -81,6 +81,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
   bool IsISA3_0 = false;
   bool IsISA3_1 = false;
   bool HasQuadwordAtomics = false;
+  bool HasAIXShLibTLSModelHeuristic = false;
 
 protected:
   std::string ABI;
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td
index b962ed28d7200..15f43f9f34a75 100644
--- a/llvm/lib/Target/PowerPC/PPC.td
+++ b/llvm/lib/Target/PowerPC/PPC.td
@@ -338,6 +338,12 @@ def FeatureAIXLocalDynamicTLS :
                    "true", "Produce a faster local-dynamic TLS sequence for this "
                    "function for 64-bit AIX">;
 
+def FeatureAIXSharedLibraryTLSModelHeuristic :
+  SubtargetFeature<"aix-shared-library-tls-model-heuristic",
+                   "HasAIXShLibTLSModelHeuristic", "true",
+                   "Tune TLS model at function level in shared library loaded "
+                   "with the main program (for 64-bit AIX only)">;
+
 def FeaturePredictableSelectIsExpensive :
   SubtargetFeature<"predictable-select-expensive",
                    "PredictableSelectIsExpensive",
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index a63824735490f..8e8fb84ac9774 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -878,6 +878,14 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
       if (Model == TLSModel::InitialExec)
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
+      // On AIX, TLS model heuristic may have turned local-dynamic access into
+      // initial-exec access.
+      PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
+      if (Model == TLSModel::LocalDynamic && FuncInfo->isAIXFuncUseTLSIE()) {
+        LLVM_DEBUG(
+            dbgs() << "Current function use IE access for default LD vars.\n");
+        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
@@ -2950,7 +2958,11 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
     // Setup the csect for the current TC entry. If the variant kind is
     // VK_PPC_AIX_TLSGDM the entry represents the region handle, we create a
     // new symbol to prefix the name with a dot.
-    if (I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM) {
+    // If TLS model heuristic is turned on, create a new symbol to prefix the
+    // name with a dot.
+    if (I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
+        (Subtarget->hasAIXShLibTLSModelHeuristic() &&
+         I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD)) {
       SmallString<128> Name;
       StringRef Prefix = ".";
       Name += Prefix;
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index d27932f2915fb..4e31651e3e762 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3374,6 +3374,48 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   bool Is64Bit = Subtarget.isPPC64();
   TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
+  // Initialize heuristic setting lazily:
+  // (1) Use initial-exec for single TLS var reference within current function.
+  // (2) Use local-dynamic for multiple TLS var references within current func.
+  PPCFunctionInfo *FuncInfo =
+      DAG.getMachineFunction().getInfo<PPCFunctionInfo>();
+  if (Subtarget.hasAIXShLibTLSModelHeuristic() &&
+      !FuncInfo->isAIXFuncUseInitDone()) {
+    std::set<const GlobalValue *> TLSGV;
+    for (SDNode &Node : DAG.allnodes()) {
+      SDNode *N = &Node;
+      if (N->getOpcode() == ISD::GlobalTLSAddress) {
+        if (GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N)) {
+          const GlobalValue *GV = GA->getGlobal();
+          TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
+          if (Model == TLSModel::InitialExec ||
+              Model == TLSModel::LocalDynamic) {
+            TLSGV.insert(GV);
+          }
+        }
+      }
+    }
+    LLVM_DEBUG(dbgs() << format("TLSGV count:%d\n", TLSGV.size()));
+    if (TLSGV.size() == 1) {
+      FuncInfo->setAIXFuncUseTLSIE();
+    } else if (TLSGV.size() > 1) {
+      FuncInfo->setAIXFuncUseTLSLD();
+    }
+    FuncInfo->setAIXFuncUseInitDone();
+  }
+
+  if (FuncInfo->isAIXFuncUseTLSLD()) {
+    LLVM_DEBUG(
+        dbgs() << DAG.getMachineFunction().getName()
+               << " function use TLS-LD model for TLS IE/LD accesses.\n");
+    Model = TLSModel::LocalDynamic;
+  } else if (FuncInfo->isAIXFuncUseTLSIE()) {
+    LLVM_DEBUG(
+        dbgs() << DAG.getMachineFunction().getName()
+               << " function use TLS-IE model for TLS IE/LD accesses.\n");
+    Model = TLSModel::InitialExec;
+  }
+
   bool IsTLSLocalExecModel = Model == TLSModel::LocalExec;
 
   if (IsTLSLocalExecModel || Model == TLSModel::InitialExec) {
diff --git a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
index df655a3be9512..aa640e8ef65e0 100644
--- a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
@@ -150,6 +150,12 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   /// to use SExt/ZExt flags in later optimization.
   std::vector<std::pair<Register, ISD::ArgFlagsTy>> LiveInAttrs;
 
+  /// Flags for aix-shared-library-tls-model-heuristic, will be lazily
+  /// initialized for each function.
+  bool AIXFuncUseTLSLD = false;
+  bool AIXFuncUseTLSIE = false;
+  bool AIXFuncUseInitDone = false;
+
 public:
   explicit PPCFunctionInfo(const Function &F, const TargetSubtargetInfo *STI);
 
@@ -221,6 +227,13 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   void setHasFastCall() { HasFastCall = true; }
   bool hasFastCall() const { return HasFastCall;}
 
+  void setAIXFuncUseInitDone() { AIXFuncUseInitDone = true; }
+  bool isAIXFuncUseInitDone() const { return AIXFuncUseInitDone; }
+  void setAIXFuncUseTLSLD() { AIXFuncUseTLSLD = true; }
+  bool isAIXFuncUseTLSLD() const { return AIXFuncUseTLSLD; }
+  void setAIXFuncUseTLSIE() { AIXFuncUseTLSIE = true; }
+  bool isAIXFuncUseTLSIE() const { return AIXFuncUseTLSIE; }
+
   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
   void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
 
diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
index d1722555f1fcb..cb3fafa303c0d 100644
--- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
+++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
@@ -141,6 +141,11 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU,
                          "-data-sections.\n",
                          false);
   }
+
+  if (HasAIXShLibTLSModelHeuristic && (!TargetTriple.isOSAIX() || !IsPPC64))
+    report_fatal_error("The aix-shared-library-tls-model-heuristic attribute "
+                       "is only supported on AIX in 64-bit mode.\n",
+                       false);
 }
 
 bool PPCSubtarget::enableMachineScheduler() const { return true; }
diff --git a/llvm/test/CodeGen/PowerPC/aix-shared-library-tls-model-heuristic.ll b/llvm/test/CodeGen/PowerPC/aix-shared-library-tls-model-heuristic.ll
new file mode 100644
index 0000000000000..b78822dc65f1d
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-shared-library-tls-model-heuristic.ll
@@ -0,0 +1,405 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      --code-model=small < %s | FileCheck %s --check-prefixes=DEFAULT_SMALL64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      --code-model=large < %s | FileCheck %s --check-prefixes=DEFAULT_LARGE64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-library-tls-model-heuristic --code-model=small < %s | FileCheck %s --check-prefixes=HEURISTIC_SMALL64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-library-tls-model-heuristic --code-model=large < %s | FileCheck %s --check-prefixes=HEURISTIC_LARGE64
+
+ at VarTLSIE1 = internal thread_local(initialexec) global i32 42, align 4
+ at VarTLSIE2 = internal thread_local(initialexec) global i32 0, align 4
+ at VarTLSLD1 = internal thread_local(localdynamic) global i32 42, align 4
+ at VarTLSLD2 = internal thread_local(localdynamic) global i32 0, align 4
+
+; Heuristic to tune function level TLS model settings:
+; Use initial-exec when we have a function accessing only one TLS variable.
+; Use local-dynamic when we have a function accessing a handful or more different TLS variables.
+
+define i32 @Single_IE_USE_IE() {
+; DEFAULT_SMALL64-LABEL: Single_IE_USE_IE:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Single_IE_USE_IE:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; HEURISTIC_SMALL64-LABEL: Single_IE_USE_IE:
+; HEURISTIC_SMALL64:       # %bb.0: # %entry
+; HEURISTIC_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
+; HEURISTIC_SMALL64-NEXT:    lwzx 3, 13, 3
+; HEURISTIC_SMALL64-NEXT:    blr
+;
+; HEURISTIC_LARGE64-LABEL: Single_IE_USE_IE:
+; HEURISTIC_LARGE64:       # %bb.0: # %entry
+; HEURISTIC_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; HEURISTIC_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; HEURISTIC_LARGE64-NEXT:    lwzx 3, 13, 3
+; HEURISTIC_LARGE64-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %1 = load i32, ptr %0, align 4
+  ret i32 %1
+}
+
+define i32 @Single_LD_USE_IE() {
+; DEFAULT_SMALL64-LABEL: Single_LD_USE_IE:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    mflr 0
+; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
+; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_SMALL64-NEXT:    ld 5, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    lwzx 4, 3, 5
+; DEFAULT_SMALL64-NEXT:    addi 6, 4, 42
+; DEFAULT_SMALL64-NEXT:    stwx 6, 3, 5
+; DEFAULT_SMALL64-NEXT:    mr 3, 4
+; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
+; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
+; DEFAULT_SMALL64-NEXT:    mtlr 0
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Single_LD_USE_IE:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    mflr 0
+; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    addis 6, L..C2 at u(2)
+; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_LARGE64-NEXT:    ld 5, L..C2 at l(6)
+; DEFAULT_LARGE64-NEXT:    lwzx 4, 3, 5
+; DEFAULT_LARGE64-NEXT:    addi 6, 4, 42
+; DEFAULT_LARGE64-NEXT:    stwx 6, 3, 5
+; DEFAULT_LARGE64-NEXT:    mr 3, 4
+; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
+; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
+; DEFAULT_LARGE64-NEXT:    mtlr 0
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; HEURISTIC_SMALL64-LABEL: Single_LD_USE_IE:
+; HEURISTIC_SMALL64:       # %bb.0: # %entry
+; HEURISTIC_SMALL64-NEXT:    ld 4, L..C1(2) # target-flags(ppc-tprel) @VarTLSLD1
+; HEURISTIC_SMALL64-NEXT:    lwzx 3, 13, 4
+; HEURISTIC_SMALL64-NEXT:    addi 5, 3, 42
+; HEURISTIC_SMALL64-NEXT:    stwx 5, 13, 4
+; HEURISTIC_SMALL64-NEXT:    blr
+;
+; HEURISTIC_LARGE64-LABEL: Single_LD_USE_IE:
+; HEURISTIC_LARGE64:       # %bb.0: # %entry
+; HEURISTIC_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; HEURISTIC_LARGE64-NEXT:    ld 4, L..C1 at l(3)
+; HEURISTIC_LARGE64-NEXT:    lwzx 3, 13, 4
+; HEURISTIC_LARGE64-NEXT:    addi 5, 3, 42
+; HEURISTIC_LARGE64-NEXT:    stwx 5, 13, 4
+; HEURISTIC_LARGE64-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %1 = load i32, ptr %0, align 4
+  %2 = add nsw i32 42, %1
+  store i32 %2, ptr %0, align 4
+  ret i32 %1
+}
+
+define i32 @Multiple_IE_USE_LD() {
+; DEFAULT_SMALL64-LABEL: Multiple_IE_USE_LD:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tprel) @VarTLSIE2
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_SMALL64-NEXT:    lwzx 4, 13, 4
+; DEFAULT_SMALL64-NEXT:    add 3, 3, 4
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Multiple_IE_USE_LD:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; DEFAULT_LARGE64-NEXT:    addis 4, L..C3 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C3 at l(4)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_LARGE64-NEXT:    lwzx 4, 13, 4
+; DEFAULT_LARGE64-NEXT:    add 3, 3, 4
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; HEURISTIC_SMALL64-LABEL: Multiple_IE_USE_LD:
+; HEURISTIC_SMALL64:       # %bb.0: # %entry
+; HEURISTIC_SMALL64-NEXT:    mflr 0
+; HEURISTIC_SMALL64-NEXT:    stdu 1, -48(1)
+; HEURISTIC_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; HEURISTIC_SMALL64-NEXT:    std 0, 64(1)
+; HEURISTIC_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; HEURISTIC_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSIE1
+; HEURISTIC_SMALL64-NEXT:    ld 5, L..C4(2) # target-flags(ppc-tlsld) @VarTLSIE2
+; HEURISTIC_SMALL64-NEXT:    lwzx 4, 3, 4
+; HEURISTIC_SMALL64-NEXT:    lwzx 3, 3, 5
+; HEURISTIC_SMALL64-NEXT:    add 3, 4, 3
+; HEURISTIC_SMALL64-NEXT:    addi 1, 1, 48
+; HEURISTIC_SMALL64-NEXT:    ld 0, 16(1)
+; HEURISTIC_SMALL64-NEXT:    mtlr 0
+; HEURISTIC_SMALL64-NEXT:    blr
+;
+; HEURISTIC_LARGE64-LABEL: Multiple_IE_USE_LD:
+; HEURISTIC_LARGE64:       # %bb.0: # %entry
+; HEURISTIC_LARGE64-NEXT:    mflr 0
+; HEURISTIC_LARGE64-NEXT:    stdu 1, -48(1)
+; HEURISTIC_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; HEURISTIC_LARGE64-NEXT:    std 0, 64(1)
+; HEURISTIC_LARGE64-NEXT:    addis 6, L..C3 at u(2)
+; HEURISTIC_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; HEURISTIC_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; HEURISTIC_LARGE64-NEXT:    addis 5, L..C4 at u(2)
+; HEURISTIC_LARGE64-NEXT:    ld 4, L..C3 at l(6)
+; HEURISTIC_LARGE64-NEXT:    ld 5, L..C4 at l(5)
+; HEURISTIC_LARGE64-NEXT:    lwzx 4, 3, 4
+; HEURISTIC_LARGE64-NEXT:    lwzx 3, 3, 5
+; HEURISTIC_LARGE64-NEXT:    add 3, 4, 3
+; HEURISTIC_LARGE64-NEXT:    addi 1, 1, 48
+; HEURISTIC_LARGE64-NEXT:    ld 0, 16(1)
+; HEURISTIC_LARGE64-NEXT:    mtlr 0
+; HEURISTIC_LARGE64-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %1 = load i32, ptr %0, align 4
+  %2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE2)
+  %3 = load i32, ptr %2, align 4
+  %add = add nsw i32 %1, %3
+  ret i32 %add
+}
+
+define i32 @Multiple_LD_USE_LD() {
+; DEFAULT_SMALL64-LABEL: Multiple_LD_USE_LD:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    mflr 0
+; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
+; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    ld 5, L..C4(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; DEFAULT_SMALL64-NEXT:    lwzx 4, 3, 4
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 5
+; DEFAULT_SMALL64-NEXT:    add 3, 4, 3
+; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
+; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
+; DEFAULT_SMALL64-NEXT:    mtlr 0
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Multiple_LD_USE_LD:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    mflr 0
+; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
+; DEFAULT_LARGE64-NEXT:    addis 6, L..C2 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_LARGE64-NEXT:    addis 5, L..C4 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(6)
+; DEFAULT_LARGE64-NEXT:    ld 5, L..C4 at l(5)
+; DEFAULT_LARGE64-NEXT:    lwzx 4, 3, 4
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 5
+; DEFAULT_LARGE64-NEXT:    add 3, 4, 3
+; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
+; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
+; DEFAULT_LARGE64-NEXT:    mtlr 0
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; HEURISTIC_SMALL64-LABEL: Multiple_LD_USE_LD:
+; HEURISTIC_SMALL64:       # %bb.0: # %entry
+; HEURISTIC_SMALL64-NEXT:    mflr 0
+; HEURISTIC_SMALL64-NEXT:    stdu 1, -48(1)
+; HEURISTIC_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; HEURISTIC_SMALL64-NEXT:    std 0, 64(1)
+; HEURISTIC_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; HEURISTIC_SMALL64-NEXT:    ld 4, L..C5(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; HEURISTIC_SMALL64-NEXT:    ld 5, L..C6(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; HEURISTIC_SMALL64-NEXT:    lwzx 4, 3, 4
+; HEURISTIC_SMALL64-NEXT:    lwzx 3, 3, 5
+; HEURISTIC_SMALL64-NEXT:    add 3, 4, 3
+; HEURISTIC_SMALL64-NEXT:    addi 1, 1, 48
+; HEURISTIC_SMALL64-NEXT:    ld 0, 16(1)
+; HEURISTIC_SMALL64-NEXT:    mtlr 0
+; HEURISTIC_SMALL64-NEXT:    blr
+;
+; HEURISTIC_LARGE64-LABEL: Multiple_LD_USE_LD:
+; HEURISTIC_LARGE64:       # %bb.0: # %entry
+; HEURISTIC_LARGE64-NEXT:    mflr 0
+; HEURISTIC_LARGE64-NEXT:    stdu 1, -48(1)
+; HEURISTIC_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; HEURISTIC_LARGE64-NEXT:    std 0, 64(1)
+; HEURISTIC_LARGE64-NEXT:    addis 6, L..C5 at u(2)
+; HEURISTIC_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; HEURISTIC_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; HEURISTIC_LARGE64-NEXT:    addis 5, L..C6 at u(2)
+; HEURISTIC_LARGE64-NEXT:    ld 4, L..C5 at l(6)
+; HEURISTIC_LARGE64-NEXT:    ld 5, L..C6 at l(5)
+; HEURISTIC_LARGE64-NEXT:    lwzx 4, 3, 4
+; HEURISTIC_LARGE64-NEXT:    lwzx 3, 3, 5
+; HEURISTIC_LARGE64-NEXT:    add 3, 4, 3
+; HEURISTIC_LARGE64-NEXT:    addi 1, 1, 48
+; HEURISTIC_LARGE64-NEXT:    ld 0, 16(1)
+; HEURISTIC_LARGE64-NEXT:    mtlr 0
+; HEURISTIC_LARGE64-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %1 = load i32, ptr %0, align 4
+  %2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD2)
+  %3 = load i32, ptr %2, align 4
+  %add = add nsw i32 %1, %3
+  ret i32 %add
+}
+
+define i32 @Multiple_MIX_USE_LD() {
+; DEFAULT_SMALL64-LABEL: Multiple_MIX_USE_LD:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    mflr 0
+; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
+; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
+; DEFAULT_SMALL64-NEXT:    lwzx 6, 13, 3
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_SMALL64-NEXT:    add 3, 6, 3
+; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
+; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
+; DEFAULT_SMALL64-NEXT:    mtlr 0
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Multiple_MIX_USE_LD:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    mflr 0
+; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
+; DEFAULT_LARGE64-NEXT:    addis 7, L..C2 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; DEFAULT_LARGE64-NEXT:    lwzx 6, 13, 3
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(7)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_LARGE64-NEXT:    add 3, 6, 3
+; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
+; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
+; DEFAULT_LARGE64-NEXT:    mtlr 0
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; HEURISTIC_SMALL64-LABEL: Multiple_MIX_USE_LD:
+; HEURISTIC_SMALL64:       # %bb.0: # %entry
+; HEURISTIC_SMALL64-NEXT:    mflr 0
+; HEURISTIC_SMALL64-NEXT:    stdu 1, -48(1)
+; HEURISTIC_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; HEURISTIC_SMALL64-NEXT:    std 0, 64(1)
+; HEURISTIC_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; HEURISTIC_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSIE1
+; HEURISTIC_SMALL64-NEXT:    ld 5, L..C5(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; HEURISTIC_SMALL64-NEXT:    lwzx 4, 3, 4
+; HEURISTIC_SMALL64-NEXT:    lwzx 3, 3, 5
+; HEURISTIC_SMALL64-NEXT:    add 3, 4, 3
+; HEURISTIC_SMALL64-NEXT:    addi 1, 1, 48
+; HEURISTIC_SMALL64-NEXT:    ld 0, 16(1)
+; HEURISTIC_SMALL64-NEXT:    mtlr 0
+; HEURISTIC_SMALL64-NEXT:    blr
+;
+; HEURISTIC_LARGE64-LABEL: Multiple_MIX_USE_LD:
+; HEURISTIC_LARGE64:       # %bb.0: # %entry
+; HEURISTIC_LARGE64-NEXT:    mflr 0
+; HEURISTIC_LARGE64-NEXT:    stdu 1, -48(1)
+; HEURISTIC_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; HEURISTIC_LARGE64-NEXT:    std 0, 64(1)
+; HEURISTIC_LARGE64-NEXT:    addis 6, L..C3 at u(2)
+; HEURISTIC_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; HEURISTIC_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; HEURISTIC_LARGE64-NEXT:    addis 5, L..C5 at u(2)
+; HEURISTIC_LARGE64-NEXT:    ld 4, L..C3 at l(6)
+; HEURISTIC_LARGE64-NEXT:    ld 5, L..C5 at l(5)
+; HEURISTIC_LARGE64-NEXT:    lwzx 4, 3, 4
+; HEURISTIC_LARGE64-NEXT:    lwzx 3, 3, 5
+; HEURISTIC_LARGE64-NEXT:    add 3, 4, 3
+; HEURISTIC_LARGE64-NEXT:    addi 1, 1, 48
+; HEURISTIC_LARGE64-NEXT:    ld 0, 16(1)
+; HEURISTIC_LARGE64-NEXT:    mtlr 0
+; HEURISTIC_LARGE64-NEXT:    blr
+entry:
+  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %1 = load i32, ptr %0, align 4
+  %2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %3 = load i32, ptr %2, align 4
+  %add = add nsw i32 %1, %3
+  ret i32 %add
+}
+
+declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
+
+; DEFAULT_SMALL64-LABEL: .toc
+; DEFAULT_SMALL64-LABEL: L..C0:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSIE1[TC],VarTLSIE1[TL]@ie
+; DEFAULT_SMALL64-LABEL: L..C1:
+; DEFAULT_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; DEFAULT_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; DEFAULT_SMALL64-LABEL: L..C2:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ld
+; DEFAULT_SMALL64-LABEL: L..C3:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSIE2[TC],VarTLSIE2[UL]@ie
+; DEFAULT_SMALL64-LABEL: L..C4:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSLD2[TC],VarTLSLD2[UL]@ld
+
+; DEFAULT_LARGE64-LABEL: .toc
+; DEFAULT_LARGE64-LABEL: L..C0:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSIE1[TE],VarTLSIE1[TL]@ie
+; DEFAULT_LARGE64-LABEL: L..C1:
+; DEFAULT_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; DEFAULT_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; DEFAULT_LARGE64-LABEL: L..C2:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ld
+; DEFAULT_LARGE64-LABEL: L..C3:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSIE2[TE],VarTLSIE2[UL]@ie
+; DEFAULT_LARGE64-LABEL: L..C4:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSLD2[TE],VarTLSLD2[UL]@ld
+
+; HEURISTIC_SMALL64-LABEL: .toc
+; HEURISTIC_SMALL64-LABEL: L..C0:
+; HEURISTIC_SMALL64-NEXT: .tc VarTLSIE1[TC],VarTLSIE1[TL]@ie
+; HEURISTIC_SMALL64-LABEL: L..C1:
+; HEURISTIC_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ie
+; HEURISTIC_SMALL64-LABEL: L..C2:
+; HEURISTIC_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; HEURISTIC_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; HEURISTIC_SMALL64-LABEL: L..C3:
+; HEURISTIC_SMALL64-NEXT: .tc .VarTLSIE1[TC],VarTLSIE1[TL]@ld
+; HEURISTIC_SMALL64-LABEL: L..C4:
+; HEURISTIC_SMALL64-NEXT: .tc .VarTLSIE2[TC],VarTLSIE2[UL]@ld
+; HEURISTIC_SMALL64-LABEL: L..C5:
+; HEURISTIC_SMALL64-NEXT: .tc .VarTLSLD1[TC],VarTLSLD1[TL]@ld
+; HEURISTIC_SMALL64-LABEL: L..C6:
+; HEURISTIC_SMALL64-NEXT: .tc .VarTLSLD2[TC],VarTLSLD2[UL]@ld
+
+; HEURISTIC_LARGE64-LABEL: .toc
+; HEURISTIC_LARGE64-LABEL: L..C0:
+; HEURISTIC_LARGE64-NEXT: .tc VarTLSIE1[TE],VarTLSIE1[TL]@ie
+; HEURISTIC_LARGE64-LABEL: L..C1:
+; HEURISTIC_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ie
+; HEURISTIC_LARGE64-LABEL: L..C2:
+; HEURISTIC_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; HEURISTIC_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; HEURISTIC_LARGE64-LABEL: L..C3:
+; HEURISTIC_LARGE64-NEXT: .tc .VarTLSIE1[TE],VarTLSIE1[TL]@ld
+; HEURISTIC_LARGE64-LABEL: L..C4:
+; HEURISTIC_LARGE64-NEXT: .tc .VarTLSIE2[TE],VarTLSIE2[UL]@ld
+; HEURISTIC_LARGE64-LABEL: L..C5:
+; HEURISTIC_LARGE64-NEXT: .tc .VarTLSLD1[TE],VarTLSLD1[TL]@ld
+; HEURISTIC_LARGE64-LABEL: L..C6:
+; HEURISTIC_LARGE64-NEXT: .tc .VarTLSLD2[TE],VarTLSLD2[UL]@ld
diff --git a/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt-IRattribute.ll b/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt-IRattribute.ll
new file mode 100644
index 0000000000000..154d573671bf5
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt-IRattribute.ll
@@ -0,0 +1,21 @@
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -ppc-asm-full-reg-names \
+; RUN:   < %s | FileCheck %s
+; RUN: not llc -mtriple powerpc-ibm-aix-xcoff -ppc-asm-full-reg-names \
+; RUN:   < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED
+; RUN: not llc -mtriple powerpc64le-unknown-linux-gnu -ppc-asm-full-reg-names \
+; RUN:   < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED
+
+define dso_local signext i32 @testWithIRAttr() #0 {
+entry:
+  ret i32 0
+}
+; Check that the aix-shared-library-tls-model-heuristic attribute is not supported on Linux and AIX (32-bit).
+; CHECK-NOT-SUPPORTED: The aix-shared-library-tls-model-heuristic attribute is only supported on AIX in 64-bit mode.
+
+; Make sure that the test was actually compiled successfully after using the
+; aix-shared-library-tls-model-heuristic attribute.
+; CHECK-LABEL: testWithIRAttr:
+; CHECK:        li r3, 0
+; CHECK-NEXT:   blr
+
+attributes #0 = { "target-features"="+aix-shared-library-tls-model-heuristic" }
diff --git a/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt.ll b/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt.ll
new file mode 100644
index 0000000000000..de85655c998f8
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt.ll
@@ -0,0 +1,22 @@
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -mattr=+aix-shared-library-tls-model-heuristic \
+; RUN:   -ppc-asm-full-reg-names < %s | FileCheck %s
+; RUN: not llc -mtriple powerpc-ibm-aix-xcoff -mattr=+aix-shared-library-tls-model-heuristic \
+; RUN:   -ppc-asm-full-reg-names < %s 2>&1 | \
+; RUN:   FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED
+; RUN: not llc -mtriple powerpc64le-unknown-linux-gnu -mattr=+aix-shared-library-tls-model-heuristic \
+; RUN:   -ppc-asm-full-reg-names < %s 2>&1 | \
+; RUN:   FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED
+
+define dso_local signext i32 @testNoIRAttr() {
+entry:
+  ret i32 0
+}
+
+; Check that the aix-shared-library-tls-model-heuristic attribute is not supported on Linux and AIX (32-bit).
+; CHECK-NOT-SUPPORTED: The aix-shared-library-tls-model-heuristic attribute is only supported on AIX in 64-bit mode.
+
+; Make sure that the test was actually compiled successfully after using the
+; aix-shared-library-tls-model-heuristic attribute.
+; CHECK-LABEL: testNoIRAttr:
+; CHECK:        li r3, 0
+; CHECK-NEXT:   blr

>From f89db67498ec61c7731ab931751883c18c4cd03b Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Mon, 25 Mar 2024 04:18:17 -0400
Subject: [PATCH 06/10] Fix issue/update according to comments (1) Address
 issue that only the first BB get checked inside `LowerGlobalTLSAddressAIX`,
 also added test case to expose the issue. (2) Change feature name from
 `aix-shared-library-tls-model-heuristic` to `aix-shared-lib-tls-model-opt`.
 (3) Update naming convention in test cases to avoid numbered identifiers. (4)
 Update comments and code simplifications.

---
 clang/include/clang/Driver/Options.td         |   6 +-
 clang/lib/Basic/Targets/PPC.cpp               |  11 +-
 clang/lib/Basic/Targets/PPC.h                 |   2 +-
 llvm/lib/Target/PowerPC/PPC.td                |   6 +-
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     |   8 +-
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  63 ++-
 llvm/lib/Target/PowerPC/PPCSubtarget.cpp      |   4 +-
 .../PowerPC/aix-shared-lib-tls-model-opt.ll   | 523 ++++++++++++++++++
 .../aix-shared-library-tls-model-heuristic.ll | 405 --------------
 ...x-shared-lib-tls-model-opt-IRattribute.ll} |   8 +-
 ...ck-aix-shared-lib-tls-model-opt-Option.ll} |  12 +-
 11 files changed, 588 insertions(+), 460 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt.ll
 delete mode 100644 llvm/test/CodeGen/PowerPC/aix-shared-library-tls-model-heuristic.ll
 rename llvm/test/CodeGen/PowerPC/{check-aix-shared-library-tls-model-heuristic-opt-IRattribute.ll => check-aix-shared-lib-tls-model-opt-IRattribute.ll} (63%)
 rename llvm/test/CodeGen/PowerPC/{check-aix-shared-library-tls-model-heuristic-opt.ll => check-aix-shared-lib-tls-model-opt-Option.ll} (64%)

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 17d7a4612c203..68931a9c949c1 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5077,10 +5077,10 @@ def maix_small_local_dynamic_tls : Flag<["-"], "maix-small-local-dynamic-tls">,
            "where the offset from the TLS base is encoded as an "
            "immediate operand (AIX 64-bit only). "
            "This access sequence is not used for variables larger than 32KB.">;
-def maix_shared_library_tls_model_heuristic : Flag<["-"], "maix-shared-library-tls-model-heuristic">,
+def maix_shared_lib_tls_model_opt : Flag<["-"], "maix-shared-lib-tls-model-opt">,
   Group<m_ppc_Features_Group>,
-  HelpText<"For shared library loaded with the main program, use heuristic to "
-           "tune TLS model at function level (AIX 64-bit only).">;
+  HelpText<"For shared library loaded with the main program, use heuristics to "
+           "tune the TLS model at the function level (AIX 64-bit only).">;
 def maix_struct_return : Flag<["-"], "maix-struct-return">,
   Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Return all structs in memory (PPC32 only)">,
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index 61971898fee95..a1e5f20f7dbe2 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -91,8 +91,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
       IsISA3_1 = true;
     } else if (Feature == "+quadword-atomics") {
       HasQuadwordAtomics = true;
-    } else if (Feature == "+aix-shared-library-tls-model-heuristic") {
-      HasAIXShLibTLSModelHeuristic = true;
+    } else if (Feature == "+aix-shared-lib-tls-model-opt") {
+      HasAIXShLibTLSModelOpt = true;
     }
     // TODO: Finish this list and add an assert that we've handled them
     // all.
@@ -582,8 +582,8 @@ bool PPCTargetInfo::initFeatureMap(
   Features["aix-small-local-exec-tls"] = false;
   Features["aix-small-local-dynamic-tls"] = false;
 
-  // Turn off TLS model heuristic by default.
-  Features["aix-shared-library-tls-model-heuristic"] = false;
+  // Turn off TLS model opt by default.
+  Features["aix-shared-lib-tls-model-opt"] = false;
 
   Features["spe"] = llvm::StringSwitch<bool>(CPU)
                         .Case("8548", true)
@@ -727,8 +727,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
       .Case("isa-v30-instructions", IsISA3_0)
       .Case("isa-v31-instructions", IsISA3_1)
       .Case("quadword-atomics", HasQuadwordAtomics)
-      .Case("aix-shared-library-tls-model-heuristic",
-            HasAIXShLibTLSModelHeuristic)
+      .Case("aix-shared-lib-tls-model-opt", HasAIXShLibTLSModelOpt)
       .Default(false);
 }
 
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index fa299f086fb9b..496b6131d09bb 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -81,7 +81,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
   bool IsISA3_0 = false;
   bool IsISA3_1 = false;
   bool HasQuadwordAtomics = false;
-  bool HasAIXShLibTLSModelHeuristic = false;
+  bool HasAIXShLibTLSModelOpt = false;
 
 protected:
   std::string ABI;
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td
index 15f43f9f34a75..639771ab9eabb 100644
--- a/llvm/lib/Target/PowerPC/PPC.td
+++ b/llvm/lib/Target/PowerPC/PPC.td
@@ -338,9 +338,9 @@ def FeatureAIXLocalDynamicTLS :
                    "true", "Produce a faster local-dynamic TLS sequence for this "
                    "function for 64-bit AIX">;
 
-def FeatureAIXSharedLibraryTLSModelHeuristic :
-  SubtargetFeature<"aix-shared-library-tls-model-heuristic",
-                   "HasAIXShLibTLSModelHeuristic", "true",
+def FeatureAIXSharedLibTLSModelOpt :
+  SubtargetFeature<"aix-shared-lib-tls-model-opt",
+                   "HasAIXShLibTLSModelOpt", "true",
                    "Tune TLS model at function level in shared library loaded "
                    "with the main program (for 64-bit AIX only)">;
 
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 8e8fb84ac9774..9d828fca08d5f 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -878,12 +878,12 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
       if (Model == TLSModel::InitialExec)
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
-      // On AIX, TLS model heuristic may have turned local-dynamic access into
-      // initial-exec access.
+      // On AIX, TLS model heuristics may have turned local-dynamic accesses
+      // into initial-exec accesses.
       PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
       if (Model == TLSModel::LocalDynamic && FuncInfo->isAIXFuncUseTLSIE()) {
         LLVM_DEBUG(
-            dbgs() << "Current function use IE access for default LD vars.\n");
+            dbgs() << "Current function uses IE access for default LD vars.\n");
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
       }
       llvm_unreachable("Only expecting local-exec or initial-exec accesses!");
@@ -2961,7 +2961,7 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
     // If TLS model heuristic is turned on, create a new symbol to prefix the
     // name with a dot.
     if (I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
-        (Subtarget->hasAIXShLibTLSModelHeuristic() &&
+        (Subtarget->hasAIXShLibTLSModelOpt() &&
          I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD)) {
       SmallString<128> Name;
       StringRef Prefix = ".";
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 4e31651e3e762..fb4f6d129afe2 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3374,31 +3374,40 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   bool Is64Bit = Subtarget.isPPC64();
   TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
-  // Initialize heuristic setting lazily:
-  // (1) Use initial-exec for single TLS var reference within current function.
-  // (2) Use local-dynamic for multiple TLS var references within current func.
+  // Initialize TLS model opt setting lazily:
+  // (1) Use initial-exec for single TLS var references within current function.
+  // (2) Use local-dynamic for multiple TLS var references within current
+  // function.
   PPCFunctionInfo *FuncInfo =
       DAG.getMachineFunction().getInfo<PPCFunctionInfo>();
-  if (Subtarget.hasAIXShLibTLSModelHeuristic() &&
-      !FuncInfo->isAIXFuncUseInitDone()) {
-    std::set<const GlobalValue *> TLSGV;
-    for (SDNode &Node : DAG.allnodes()) {
-      SDNode *N = &Node;
-      if (N->getOpcode() == ISD::GlobalTLSAddress) {
-        if (GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N)) {
-          const GlobalValue *GV = GA->getGlobal();
-          TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
-          if (Model == TLSModel::InitialExec ||
-              Model == TLSModel::LocalDynamic) {
-            TLSGV.insert(GV);
-          }
-        }
-      }
-    }
-    LLVM_DEBUG(dbgs() << format("TLSGV count:%d\n", TLSGV.size()));
-    if (TLSGV.size() == 1) {
+  if (Subtarget.hasAIXShLibTLSModelOpt() && !FuncInfo->isAIXFuncUseInitDone()) {
+    SmallPtrSet<const GlobalValue *, 8> TLSGV;
+    // Iterate over all instructions within current function, collect all TLS
+    // global variables (global variables taken as the first parameter to
+    // Intrinsic::threadlocal_address).
+    const Function &Func = DAG.getMachineFunction().getFunction();
+    for (Function::const_iterator BI = Func.begin(), BE = Func.end(); BI != BE;
+         ++BI)
+      for (BasicBlock::const_iterator II = BI->begin(), IE = BI->end();
+           II != IE; ++II)
+        if (II->getOpcode() == Instruction::Call)
+          if (const CallInst *CI = dyn_cast<const CallInst>(&*II))
+            if (Function *CF = CI->getCalledFunction())
+              if (CF->isDeclaration() &&
+                  CF->getIntrinsicID() == Intrinsic::threadlocal_address)
+                if (const GlobalValue *GV =
+                        dyn_cast<GlobalValue>(II->getOperand(0))) {
+                  TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
+                  if (Model == TLSModel::InitialExec ||
+                      Model == TLSModel::LocalDynamic)
+                    TLSGV.insert(GV);
+                }
+
+    unsigned TLSGVCnt = TLSGV.size();
+    LLVM_DEBUG(dbgs() << format("TLSGV count:%d\n", TLSGVCnt));
+    if (TLSGVCnt == 1) {
       FuncInfo->setAIXFuncUseTLSIE();
-    } else if (TLSGV.size() > 1) {
+    } else if (TLSGVCnt > 1) {
       FuncInfo->setAIXFuncUseTLSLD();
     }
     FuncInfo->setAIXFuncUseInitDone();
@@ -3406,13 +3415,15 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
 
   if (FuncInfo->isAIXFuncUseTLSLD()) {
     LLVM_DEBUG(
-        dbgs() << DAG.getMachineFunction().getName()
-               << " function use TLS-LD model for TLS IE/LD accesses.\n");
+        dbgs()
+        << DAG.getMachineFunction().getName()
+        << " function is using the TLS-LD model for TLS IE/LD accesses.\n");
     Model = TLSModel::LocalDynamic;
   } else if (FuncInfo->isAIXFuncUseTLSIE()) {
     LLVM_DEBUG(
-        dbgs() << DAG.getMachineFunction().getName()
-               << " function use TLS-IE model for TLS IE/LD accesses.\n");
+        dbgs()
+        << DAG.getMachineFunction().getName()
+        << " function is using the TLS-IE model for TLS IE/LD accesses.\n");
     Model = TLSModel::InitialExec;
   }
 
diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
index cb3fafa303c0d..0628fbb26245c 100644
--- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
+++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
@@ -142,8 +142,8 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU,
                          false);
   }
 
-  if (HasAIXShLibTLSModelHeuristic && (!TargetTriple.isOSAIX() || !IsPPC64))
-    report_fatal_error("The aix-shared-library-tls-model-heuristic attribute "
+  if (HasAIXShLibTLSModelOpt && (!TargetTriple.isOSAIX() || !IsPPC64))
+    report_fatal_error("The aix-shared-lib-tls-model-opt attribute "
                        "is only supported on AIX in 64-bit mode.\n",
                        false);
 }
diff --git a/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt.ll b/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt.ll
new file mode 100644
index 0000000000000..9db3c2b825684
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt.ll
@@ -0,0 +1,523 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      --code-model=small < %s | FileCheck %s --check-prefixes=DEFAULT_SMALL64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      --code-model=large < %s | FileCheck %s --check-prefixes=DEFAULT_LARGE64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-lib-tls-model-opt --code-model=small < %s | FileCheck %s --check-prefixes=TLS_MODEL_OPT_SMALL64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-lib-tls-model-opt --code-model=large < %s | FileCheck %s --check-prefixes=TLS_MODEL_OPT_LARGE64
+
+ at VarTLSIE1 = internal thread_local(initialexec) global i32 42, align 4
+ at VarTLSIE2 = internal thread_local(initialexec) global i32 0, align 4
+ at VarTLSLD1 = internal thread_local(localdynamic) global i32 42, align 4
+ at VarTLSLD2 = internal thread_local(localdynamic) global i32 0, align 4
+
+; Tune function level TLS model settings:
+; Use initial-exec when we have a function accessing only one TLS variable.
+; Use local-dynamic when we have a function accessing a handful or more different TLS variables.
+
+define i32 @Single_IE_USE_IE(i32 %P, i32 %Q) {
+; DEFAULT_SMALL64-LABEL: Single_IE_USE_IE:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    and 4, 3, 4
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
+; DEFAULT_SMALL64-NEXT:    cmpwi 4, -1
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Single_IE_USE_IE:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    and 4, 3, 4
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; DEFAULT_LARGE64-NEXT:    cmpwi 4, -1
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_SMALL64-LABEL: Single_IE_USE_IE:
+; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_SMALL64-NEXT:    and 4, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
+; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 4, -1
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LARGE64-LABEL: Single_IE_USE_IE:
+; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LARGE64-NEXT:    and 4, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 4, -1
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LARGE64-NEXT:    blr
+entry:
+  %a = icmp slt i32 %P, 0
+  %b = icmp slt i32 %Q, 0
+  %c = and i1 %a, %b
+  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %load1 = load i32, ptr %tls1, align 4
+  br i1 %c, label %bb1, label %return
+
+bb1:
+  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %load2 = load i32, ptr %tls2, align 4
+  ret i32 %load2
+
+return:
+  ret i32 %load1
+}
+
+define i32 @Single_LD_USE_IE(i32 %P, i32 %Q) {
+; DEFAULT_SMALL64-LABEL: Single_LD_USE_IE:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    mflr 0
+; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
+; DEFAULT_SMALL64-NEXT:    and 6, 3, 4
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
+; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    cmpwi 6, -1
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
+; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
+; DEFAULT_SMALL64-NEXT:    mtlr 0
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Single_LD_USE_IE:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    mflr 0
+; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
+; DEFAULT_LARGE64-NEXT:    and 6, 3, 4
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    addis 7, L..C2 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
+; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(7)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_LARGE64-NEXT:    cmpwi 6, -1
+; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
+; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
+; DEFAULT_LARGE64-NEXT:    mtlr 0
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_SMALL64-LABEL: Single_LD_USE_IE:
+; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_SMALL64-NEXT:    and 4, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tprel) @VarTLSLD1
+; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 4, -1
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LARGE64-LABEL: Single_LD_USE_IE:
+; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LARGE64-NEXT:    and 4, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 4, -1
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LARGE64-NEXT:    blr
+entry:
+  %a = icmp slt i32 %P, 0
+  %b = icmp slt i32 %Q, 0
+  %c = and i1 %a, %b
+  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %load1 = load i32, ptr %tls1, align 4
+  br i1 %c, label %bb1, label %return
+
+bb1:
+  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %load2 = load i32, ptr %tls2, align 4
+  ret i32 %load2
+
+return:
+  ret i32 %load1
+}
+
+define i32 @Multiple_IE_USE_LD(i32 %P, i32 %Q) {
+; DEFAULT_SMALL64-LABEL: Multiple_IE_USE_LD:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    and 3, 3, 4
+; DEFAULT_SMALL64-NEXT:    cmpwi 3, -1
+; DEFAULT_SMALL64-NEXT:    bgt 0, L..BB2_2
+; DEFAULT_SMALL64-NEXT:  # %bb.1: # %bb1
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C3(2) # target-flags(ppc-tprel) @VarTLSIE2
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_SMALL64-NEXT:    blr
+; DEFAULT_SMALL64-NEXT:  L..BB2_2: # %return
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Multiple_IE_USE_LD:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    and 3, 3, 4
+; DEFAULT_LARGE64-NEXT:    cmpwi 3, -1
+; DEFAULT_LARGE64-NEXT:    bgt 0, L..BB2_2
+; DEFAULT_LARGE64-NEXT:  # %bb.1: # %bb1
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C3 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C3 at l(3)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_LARGE64-NEXT:    blr
+; DEFAULT_LARGE64-NEXT:  L..BB2_2: # %return
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_SMALL64-LABEL: Multiple_IE_USE_LD:
+; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_SMALL64-NEXT:    mflr 0
+; TLS_MODEL_OPT_SMALL64-NEXT:    stdu 1, -48(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    and 6, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; TLS_MODEL_OPT_SMALL64-NEXT:    std 0, 64(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 6, -1
+; TLS_MODEL_OPT_SMALL64-NEXT:    bgt 0, L..BB2_2
+; TLS_MODEL_OPT_SMALL64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSIE2
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    b L..BB2_3
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB2_2: # %return
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C4(2) # target-flags(ppc-tlsld) @VarTLSIE1
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB2_3: # %bb1
+; TLS_MODEL_OPT_SMALL64-NEXT:    addi 1, 1, 48
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 0, 16(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    mtlr 0
+; TLS_MODEL_OPT_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LARGE64-LABEL: Multiple_IE_USE_LD:
+; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LARGE64-NEXT:    mflr 0
+; TLS_MODEL_OPT_LARGE64-NEXT:    stdu 1, -48(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    and 6, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    std 0, 64(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; TLS_MODEL_OPT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 6, -1
+; TLS_MODEL_OPT_LARGE64-NEXT:    bgt 0, L..BB2_2
+; TLS_MODEL_OPT_LARGE64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C3 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C3 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    b L..BB2_3
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB2_2: # %return
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C4 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C4 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB2_3: # %bb1
+; TLS_MODEL_OPT_LARGE64-NEXT:    addi 1, 1, 48
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 0, 16(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    mtlr 0
+; TLS_MODEL_OPT_LARGE64-NEXT:    blr
+entry:
+  %a = icmp slt i32 %P, 0
+  %b = icmp slt i32 %Q, 0
+  %c = and i1 %a, %b
+  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %load1 = load i32, ptr %tls1, align 4
+  br i1 %c, label %bb1, label %return
+
+bb1:
+  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE2)
+  %load2 = load i32, ptr %tls2, align 4
+  ret i32 %load2
+
+return:
+  ret i32 %load1
+}
+
+define i32 @Multiple_LD_USE_LD(i32 %P, i32 %Q) {
+; DEFAULT_SMALL64-LABEL: Multiple_LD_USE_LD:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    mflr 0
+; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
+; DEFAULT_SMALL64-NEXT:    and 6, 3, 4
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
+; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_SMALL64-NEXT:    cmpwi 6, -1
+; DEFAULT_SMALL64-NEXT:    bgt 0, L..BB3_2
+; DEFAULT_SMALL64-NEXT:  # %bb.1: # %bb1
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C4(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_SMALL64-NEXT:    b L..BB3_3
+; DEFAULT_SMALL64-NEXT:  L..BB3_2: # %return
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_SMALL64-NEXT:  L..BB3_3: # %bb1
+; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
+; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
+; DEFAULT_SMALL64-NEXT:    mtlr 0
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Multiple_LD_USE_LD:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    mflr 0
+; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
+; DEFAULT_LARGE64-NEXT:    and 6, 3, 4
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_LARGE64-NEXT:    cmpwi 6, -1
+; DEFAULT_LARGE64-NEXT:    bgt 0, L..BB3_2
+; DEFAULT_LARGE64-NEXT:  # %bb.1: # %bb1
+; DEFAULT_LARGE64-NEXT:    addis 4, L..C4 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C4 at l(4)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_LARGE64-NEXT:    b L..BB3_3
+; DEFAULT_LARGE64-NEXT:  L..BB3_2: # %return
+; DEFAULT_LARGE64-NEXT:    addis 4, L..C2 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(4)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_LARGE64-NEXT:  L..BB3_3: # %bb1
+; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
+; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
+; DEFAULT_LARGE64-NEXT:    mtlr 0
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_SMALL64-LABEL: Multiple_LD_USE_LD:
+; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_SMALL64-NEXT:    mflr 0
+; TLS_MODEL_OPT_SMALL64-NEXT:    stdu 1, -48(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    and 6, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; TLS_MODEL_OPT_SMALL64-NEXT:    std 0, 64(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 6, -1
+; TLS_MODEL_OPT_SMALL64-NEXT:    bgt 0, L..BB3_2
+; TLS_MODEL_OPT_SMALL64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C5(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    b L..BB3_3
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB3_2: # %return
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C6(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB3_3: # %bb1
+; TLS_MODEL_OPT_SMALL64-NEXT:    addi 1, 1, 48
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 0, 16(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    mtlr 0
+; TLS_MODEL_OPT_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LARGE64-LABEL: Multiple_LD_USE_LD:
+; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LARGE64-NEXT:    mflr 0
+; TLS_MODEL_OPT_LARGE64-NEXT:    stdu 1, -48(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    and 6, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    std 0, 64(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; TLS_MODEL_OPT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 6, -1
+; TLS_MODEL_OPT_LARGE64-NEXT:    bgt 0, L..BB3_2
+; TLS_MODEL_OPT_LARGE64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C5 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C5 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    b L..BB3_3
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB3_2: # %return
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C6 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C6 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB3_3: # %bb1
+; TLS_MODEL_OPT_LARGE64-NEXT:    addi 1, 1, 48
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 0, 16(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    mtlr 0
+; TLS_MODEL_OPT_LARGE64-NEXT:    blr
+entry:
+  %a = icmp slt i32 %P, 0
+  %b = icmp slt i32 %Q, 0
+  %c = and i1 %a, %b
+  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %load1 = load i32, ptr %tls1, align 4
+  br i1 %c, label %bb1, label %return
+
+bb1:
+  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD2)
+  %load2 = load i32, ptr %tls2, align 4
+  ret i32 %load2
+
+return:
+  ret i32 %load1
+}
+
+define i32 @Multiple_MIX_USE_LD(i32 %P, i32 %Q) {
+; DEFAULT_SMALL64-LABEL: Multiple_MIX_USE_LD:
+; DEFAULT_SMALL64:       # %bb.0: # %entry
+; DEFAULT_SMALL64-NEXT:    and 3, 3, 4
+; DEFAULT_SMALL64-NEXT:    cmpwi 3, -1
+; DEFAULT_SMALL64-NEXT:    bgt 0, L..BB4_2
+; DEFAULT_SMALL64-NEXT:  # %bb.1: # %bb1
+; DEFAULT_SMALL64-NEXT:    mflr 0
+; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
+; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
+; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
+; DEFAULT_SMALL64-NEXT:    mtlr 0
+; DEFAULT_SMALL64-NEXT:    blr
+; DEFAULT_SMALL64-NEXT:  L..BB4_2: # %return
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_SMALL64-NEXT:    blr
+;
+; DEFAULT_LARGE64-LABEL: Multiple_MIX_USE_LD:
+; DEFAULT_LARGE64:       # %bb.0: # %entry
+; DEFAULT_LARGE64-NEXT:    and 3, 3, 4
+; DEFAULT_LARGE64-NEXT:    cmpwi 3, -1
+; DEFAULT_LARGE64-NEXT:    bgt 0, L..BB4_2
+; DEFAULT_LARGE64-NEXT:  # %bb.1: # %bb1
+; DEFAULT_LARGE64-NEXT:    mflr 0
+; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    addis 6, L..C2 at u(2)
+; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(6)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
+; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
+; DEFAULT_LARGE64-NEXT:    mtlr 0
+; DEFAULT_LARGE64-NEXT:    blr
+; DEFAULT_LARGE64-NEXT:  L..BB4_2: # %return
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
+; DEFAULT_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_SMALL64-LABEL: Multiple_MIX_USE_LD:
+; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_SMALL64-NEXT:    mflr 0
+; TLS_MODEL_OPT_SMALL64-NEXT:    stdu 1, -48(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    and 6, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; TLS_MODEL_OPT_SMALL64-NEXT:    std 0, 64(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 6, -1
+; TLS_MODEL_OPT_SMALL64-NEXT:    bgt 0, L..BB4_2
+; TLS_MODEL_OPT_SMALL64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C6(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    b L..BB4_3
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB4_2: # %return
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C4(2) # target-flags(ppc-tlsld) @VarTLSIE1
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB4_3: # %bb1
+; TLS_MODEL_OPT_SMALL64-NEXT:    addi 1, 1, 48
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 0, 16(1)
+; TLS_MODEL_OPT_SMALL64-NEXT:    mtlr 0
+; TLS_MODEL_OPT_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LARGE64-LABEL: Multiple_MIX_USE_LD:
+; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LARGE64-NEXT:    mflr 0
+; TLS_MODEL_OPT_LARGE64-NEXT:    stdu 1, -48(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    and 6, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    std 0, 64(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; TLS_MODEL_OPT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 6, -1
+; TLS_MODEL_OPT_LARGE64-NEXT:    bgt 0, L..BB4_2
+; TLS_MODEL_OPT_LARGE64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C6 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C6 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    b L..BB4_3
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB4_2: # %return
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C4 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C4 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB4_3: # %bb1
+; TLS_MODEL_OPT_LARGE64-NEXT:    addi 1, 1, 48
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 0, 16(1)
+; TLS_MODEL_OPT_LARGE64-NEXT:    mtlr 0
+; TLS_MODEL_OPT_LARGE64-NEXT:    blr
+entry:
+  %a = icmp slt i32 %P, 0
+  %b = icmp slt i32 %Q, 0
+  %c = and i1 %a, %b
+  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %load1 = load i32, ptr %tls1, align 4
+  br i1 %c, label %bb1, label %return
+
+bb1:
+  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %load2 = load i32, ptr %tls2, align 4
+  ret i32 %load2
+
+return:
+  ret i32 %load1
+}
+
+declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
+
+; DEFAULT_SMALL64-LABEL: .toc
+; DEFAULT_SMALL64-LABEL: L..C0:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSIE1[TC],VarTLSIE1[TL]@ie
+; DEFAULT_SMALL64-LABEL: L..C1:
+; DEFAULT_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; DEFAULT_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; DEFAULT_SMALL64-LABEL: L..C2:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ld
+; DEFAULT_SMALL64-LABEL: L..C3:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSIE2[TC],VarTLSIE2[UL]@ie
+; DEFAULT_SMALL64-LABEL: L..C4:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSLD2[TC],VarTLSLD2[UL]@ld
+
+; DEFAULT_LARGE64-LABEL: .toc
+; DEFAULT_LARGE64-LABEL: L..C0:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSIE1[TE],VarTLSIE1[TL]@ie
+; DEFAULT_LARGE64-LABEL: L..C1:
+; DEFAULT_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; DEFAULT_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; DEFAULT_LARGE64-LABEL: L..C2:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ld
+; DEFAULT_LARGE64-LABEL: L..C3:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSIE2[TE],VarTLSIE2[UL]@ie
+; DEFAULT_LARGE64-LABEL: L..C4:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSLD2[TE],VarTLSLD2[UL]@ld
+
+; TLS_MODEL_OPT_SMALL64-LABEL: .toc
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C0:
+; TLS_MODEL_OPT_SMALL64-NEXT: .tc VarTLSIE1[TC],VarTLSIE1[TL]@ie
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C1:
+; TLS_MODEL_OPT_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ie
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C2:
+; TLS_MODEL_OPT_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; TLS_MODEL_OPT_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C3:
+; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSIE2[TC],VarTLSIE2[UL]@ld
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C4:
+; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSIE1[TC],VarTLSIE1[TL]@ld
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C5:
+; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSLD2[TC],VarTLSLD2[UL]@ld
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C6:
+; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSLD1[TC],VarTLSLD1[TL]@ld
+
+; TLS_MODEL_OPT_LARGE64-LABEL: .toc
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C0:
+; TLS_MODEL_OPT_LARGE64-NEXT: .tc VarTLSIE1[TE],VarTLSIE1[TL]@ie
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C1:
+; TLS_MODEL_OPT_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ie
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C2:
+; TLS_MODEL_OPT_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; TLS_MODEL_OPT_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C3:
+; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSIE2[TE],VarTLSIE2[UL]@ld
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C4:
+; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSIE1[TE],VarTLSIE1[TL]@ld
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C5:
+; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSLD2[TE],VarTLSLD2[UL]@ld
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C6:
+; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSLD1[TE],VarTLSLD1[TL]@ld
diff --git a/llvm/test/CodeGen/PowerPC/aix-shared-library-tls-model-heuristic.ll b/llvm/test/CodeGen/PowerPC/aix-shared-library-tls-model-heuristic.ll
deleted file mode 100644
index b78822dc65f1d..0000000000000
--- a/llvm/test/CodeGen/PowerPC/aix-shared-library-tls-model-heuristic.ll
+++ /dev/null
@@ -1,405 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
-; RUN:      --code-model=small < %s | FileCheck %s --check-prefixes=DEFAULT_SMALL64
-; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
-; RUN:      --code-model=large < %s | FileCheck %s --check-prefixes=DEFAULT_LARGE64
-; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
-; RUN:      -mattr=+aix-shared-library-tls-model-heuristic --code-model=small < %s | FileCheck %s --check-prefixes=HEURISTIC_SMALL64
-; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
-; RUN:      -mattr=+aix-shared-library-tls-model-heuristic --code-model=large < %s | FileCheck %s --check-prefixes=HEURISTIC_LARGE64
-
- at VarTLSIE1 = internal thread_local(initialexec) global i32 42, align 4
- at VarTLSIE2 = internal thread_local(initialexec) global i32 0, align 4
- at VarTLSLD1 = internal thread_local(localdynamic) global i32 42, align 4
- at VarTLSLD2 = internal thread_local(localdynamic) global i32 0, align 4
-
-; Heuristic to tune function level TLS model settings:
-; Use initial-exec when we have a function accessing only one TLS variable.
-; Use local-dynamic when we have a function accessing a handful or more different TLS variables.
-
-define i32 @Single_IE_USE_IE() {
-; DEFAULT_SMALL64-LABEL: Single_IE_USE_IE:
-; DEFAULT_SMALL64:       # %bb.0: # %entry
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
-; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_SMALL64-NEXT:    blr
-;
-; DEFAULT_LARGE64-LABEL: Single_IE_USE_IE:
-; DEFAULT_LARGE64:       # %bb.0: # %entry
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_LARGE64-NEXT:    blr
-;
-; HEURISTIC_SMALL64-LABEL: Single_IE_USE_IE:
-; HEURISTIC_SMALL64:       # %bb.0: # %entry
-; HEURISTIC_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
-; HEURISTIC_SMALL64-NEXT:    lwzx 3, 13, 3
-; HEURISTIC_SMALL64-NEXT:    blr
-;
-; HEURISTIC_LARGE64-LABEL: Single_IE_USE_IE:
-; HEURISTIC_LARGE64:       # %bb.0: # %entry
-; HEURISTIC_LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; HEURISTIC_LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; HEURISTIC_LARGE64-NEXT:    lwzx 3, 13, 3
-; HEURISTIC_LARGE64-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
-  %1 = load i32, ptr %0, align 4
-  ret i32 %1
-}
-
-define i32 @Single_LD_USE_IE() {
-; DEFAULT_SMALL64-LABEL: Single_LD_USE_IE:
-; DEFAULT_SMALL64:       # %bb.0: # %entry
-; DEFAULT_SMALL64-NEXT:    mflr 0
-; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
-; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_SMALL64-NEXT:    ld 5, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
-; DEFAULT_SMALL64-NEXT:    lwzx 4, 3, 5
-; DEFAULT_SMALL64-NEXT:    addi 6, 4, 42
-; DEFAULT_SMALL64-NEXT:    stwx 6, 3, 5
-; DEFAULT_SMALL64-NEXT:    mr 3, 4
-; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
-; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
-; DEFAULT_SMALL64-NEXT:    mtlr 0
-; DEFAULT_SMALL64-NEXT:    blr
-;
-; DEFAULT_LARGE64-LABEL: Single_LD_USE_IE:
-; DEFAULT_LARGE64:       # %bb.0: # %entry
-; DEFAULT_LARGE64-NEXT:    mflr 0
-; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
-; DEFAULT_LARGE64-NEXT:    addis 6, L..C2 at u(2)
-; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
-; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_LARGE64-NEXT:    ld 5, L..C2 at l(6)
-; DEFAULT_LARGE64-NEXT:    lwzx 4, 3, 5
-; DEFAULT_LARGE64-NEXT:    addi 6, 4, 42
-; DEFAULT_LARGE64-NEXT:    stwx 6, 3, 5
-; DEFAULT_LARGE64-NEXT:    mr 3, 4
-; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
-; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
-; DEFAULT_LARGE64-NEXT:    mtlr 0
-; DEFAULT_LARGE64-NEXT:    blr
-;
-; HEURISTIC_SMALL64-LABEL: Single_LD_USE_IE:
-; HEURISTIC_SMALL64:       # %bb.0: # %entry
-; HEURISTIC_SMALL64-NEXT:    ld 4, L..C1(2) # target-flags(ppc-tprel) @VarTLSLD1
-; HEURISTIC_SMALL64-NEXT:    lwzx 3, 13, 4
-; HEURISTIC_SMALL64-NEXT:    addi 5, 3, 42
-; HEURISTIC_SMALL64-NEXT:    stwx 5, 13, 4
-; HEURISTIC_SMALL64-NEXT:    blr
-;
-; HEURISTIC_LARGE64-LABEL: Single_LD_USE_IE:
-; HEURISTIC_LARGE64:       # %bb.0: # %entry
-; HEURISTIC_LARGE64-NEXT:    addis 3, L..C1 at u(2)
-; HEURISTIC_LARGE64-NEXT:    ld 4, L..C1 at l(3)
-; HEURISTIC_LARGE64-NEXT:    lwzx 3, 13, 4
-; HEURISTIC_LARGE64-NEXT:    addi 5, 3, 42
-; HEURISTIC_LARGE64-NEXT:    stwx 5, 13, 4
-; HEURISTIC_LARGE64-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
-  %1 = load i32, ptr %0, align 4
-  %2 = add nsw i32 42, %1
-  store i32 %2, ptr %0, align 4
-  ret i32 %1
-}
-
-define i32 @Multiple_IE_USE_LD() {
-; DEFAULT_SMALL64-LABEL: Multiple_IE_USE_LD:
-; DEFAULT_SMALL64:       # %bb.0: # %entry
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
-; DEFAULT_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tprel) @VarTLSIE2
-; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_SMALL64-NEXT:    lwzx 4, 13, 4
-; DEFAULT_SMALL64-NEXT:    add 3, 3, 4
-; DEFAULT_SMALL64-NEXT:    blr
-;
-; DEFAULT_LARGE64-LABEL: Multiple_IE_USE_LD:
-; DEFAULT_LARGE64:       # %bb.0: # %entry
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; DEFAULT_LARGE64-NEXT:    addis 4, L..C3 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; DEFAULT_LARGE64-NEXT:    ld 4, L..C3 at l(4)
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_LARGE64-NEXT:    lwzx 4, 13, 4
-; DEFAULT_LARGE64-NEXT:    add 3, 3, 4
-; DEFAULT_LARGE64-NEXT:    blr
-;
-; HEURISTIC_SMALL64-LABEL: Multiple_IE_USE_LD:
-; HEURISTIC_SMALL64:       # %bb.0: # %entry
-; HEURISTIC_SMALL64-NEXT:    mflr 0
-; HEURISTIC_SMALL64-NEXT:    stdu 1, -48(1)
-; HEURISTIC_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; HEURISTIC_SMALL64-NEXT:    std 0, 64(1)
-; HEURISTIC_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; HEURISTIC_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSIE1
-; HEURISTIC_SMALL64-NEXT:    ld 5, L..C4(2) # target-flags(ppc-tlsld) @VarTLSIE2
-; HEURISTIC_SMALL64-NEXT:    lwzx 4, 3, 4
-; HEURISTIC_SMALL64-NEXT:    lwzx 3, 3, 5
-; HEURISTIC_SMALL64-NEXT:    add 3, 4, 3
-; HEURISTIC_SMALL64-NEXT:    addi 1, 1, 48
-; HEURISTIC_SMALL64-NEXT:    ld 0, 16(1)
-; HEURISTIC_SMALL64-NEXT:    mtlr 0
-; HEURISTIC_SMALL64-NEXT:    blr
-;
-; HEURISTIC_LARGE64-LABEL: Multiple_IE_USE_LD:
-; HEURISTIC_LARGE64:       # %bb.0: # %entry
-; HEURISTIC_LARGE64-NEXT:    mflr 0
-; HEURISTIC_LARGE64-NEXT:    stdu 1, -48(1)
-; HEURISTIC_LARGE64-NEXT:    addis 3, L..C2 at u(2)
-; HEURISTIC_LARGE64-NEXT:    std 0, 64(1)
-; HEURISTIC_LARGE64-NEXT:    addis 6, L..C3 at u(2)
-; HEURISTIC_LARGE64-NEXT:    ld 3, L..C2 at l(3)
-; HEURISTIC_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; HEURISTIC_LARGE64-NEXT:    addis 5, L..C4 at u(2)
-; HEURISTIC_LARGE64-NEXT:    ld 4, L..C3 at l(6)
-; HEURISTIC_LARGE64-NEXT:    ld 5, L..C4 at l(5)
-; HEURISTIC_LARGE64-NEXT:    lwzx 4, 3, 4
-; HEURISTIC_LARGE64-NEXT:    lwzx 3, 3, 5
-; HEURISTIC_LARGE64-NEXT:    add 3, 4, 3
-; HEURISTIC_LARGE64-NEXT:    addi 1, 1, 48
-; HEURISTIC_LARGE64-NEXT:    ld 0, 16(1)
-; HEURISTIC_LARGE64-NEXT:    mtlr 0
-; HEURISTIC_LARGE64-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
-  %1 = load i32, ptr %0, align 4
-  %2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE2)
-  %3 = load i32, ptr %2, align 4
-  %add = add nsw i32 %1, %3
-  ret i32 %add
-}
-
-define i32 @Multiple_LD_USE_LD() {
-; DEFAULT_SMALL64-LABEL: Multiple_LD_USE_LD:
-; DEFAULT_SMALL64:       # %bb.0: # %entry
-; DEFAULT_SMALL64-NEXT:    mflr 0
-; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
-; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
-; DEFAULT_SMALL64-NEXT:    ld 5, L..C4(2) # target-flags(ppc-tlsld) @VarTLSLD2
-; DEFAULT_SMALL64-NEXT:    lwzx 4, 3, 4
-; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 5
-; DEFAULT_SMALL64-NEXT:    add 3, 4, 3
-; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
-; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
-; DEFAULT_SMALL64-NEXT:    mtlr 0
-; DEFAULT_SMALL64-NEXT:    blr
-;
-; DEFAULT_LARGE64-LABEL: Multiple_LD_USE_LD:
-; DEFAULT_LARGE64:       # %bb.0: # %entry
-; DEFAULT_LARGE64-NEXT:    mflr 0
-; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
-; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
-; DEFAULT_LARGE64-NEXT:    addis 6, L..C2 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
-; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_LARGE64-NEXT:    addis 5, L..C4 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(6)
-; DEFAULT_LARGE64-NEXT:    ld 5, L..C4 at l(5)
-; DEFAULT_LARGE64-NEXT:    lwzx 4, 3, 4
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 5
-; DEFAULT_LARGE64-NEXT:    add 3, 4, 3
-; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
-; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
-; DEFAULT_LARGE64-NEXT:    mtlr 0
-; DEFAULT_LARGE64-NEXT:    blr
-;
-; HEURISTIC_SMALL64-LABEL: Multiple_LD_USE_LD:
-; HEURISTIC_SMALL64:       # %bb.0: # %entry
-; HEURISTIC_SMALL64-NEXT:    mflr 0
-; HEURISTIC_SMALL64-NEXT:    stdu 1, -48(1)
-; HEURISTIC_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; HEURISTIC_SMALL64-NEXT:    std 0, 64(1)
-; HEURISTIC_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; HEURISTIC_SMALL64-NEXT:    ld 4, L..C5(2) # target-flags(ppc-tlsld) @VarTLSLD1
-; HEURISTIC_SMALL64-NEXT:    ld 5, L..C6(2) # target-flags(ppc-tlsld) @VarTLSLD2
-; HEURISTIC_SMALL64-NEXT:    lwzx 4, 3, 4
-; HEURISTIC_SMALL64-NEXT:    lwzx 3, 3, 5
-; HEURISTIC_SMALL64-NEXT:    add 3, 4, 3
-; HEURISTIC_SMALL64-NEXT:    addi 1, 1, 48
-; HEURISTIC_SMALL64-NEXT:    ld 0, 16(1)
-; HEURISTIC_SMALL64-NEXT:    mtlr 0
-; HEURISTIC_SMALL64-NEXT:    blr
-;
-; HEURISTIC_LARGE64-LABEL: Multiple_LD_USE_LD:
-; HEURISTIC_LARGE64:       # %bb.0: # %entry
-; HEURISTIC_LARGE64-NEXT:    mflr 0
-; HEURISTIC_LARGE64-NEXT:    stdu 1, -48(1)
-; HEURISTIC_LARGE64-NEXT:    addis 3, L..C2 at u(2)
-; HEURISTIC_LARGE64-NEXT:    std 0, 64(1)
-; HEURISTIC_LARGE64-NEXT:    addis 6, L..C5 at u(2)
-; HEURISTIC_LARGE64-NEXT:    ld 3, L..C2 at l(3)
-; HEURISTIC_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; HEURISTIC_LARGE64-NEXT:    addis 5, L..C6 at u(2)
-; HEURISTIC_LARGE64-NEXT:    ld 4, L..C5 at l(6)
-; HEURISTIC_LARGE64-NEXT:    ld 5, L..C6 at l(5)
-; HEURISTIC_LARGE64-NEXT:    lwzx 4, 3, 4
-; HEURISTIC_LARGE64-NEXT:    lwzx 3, 3, 5
-; HEURISTIC_LARGE64-NEXT:    add 3, 4, 3
-; HEURISTIC_LARGE64-NEXT:    addi 1, 1, 48
-; HEURISTIC_LARGE64-NEXT:    ld 0, 16(1)
-; HEURISTIC_LARGE64-NEXT:    mtlr 0
-; HEURISTIC_LARGE64-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
-  %1 = load i32, ptr %0, align 4
-  %2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD2)
-  %3 = load i32, ptr %2, align 4
-  %add = add nsw i32 %1, %3
-  ret i32 %add
-}
-
-define i32 @Multiple_MIX_USE_LD() {
-; DEFAULT_SMALL64-LABEL: Multiple_MIX_USE_LD:
-; DEFAULT_SMALL64:       # %bb.0: # %entry
-; DEFAULT_SMALL64-NEXT:    mflr 0
-; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
-; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
-; DEFAULT_SMALL64-NEXT:    lwzx 6, 13, 3
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
-; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
-; DEFAULT_SMALL64-NEXT:    add 3, 6, 3
-; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
-; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
-; DEFAULT_SMALL64-NEXT:    mtlr 0
-; DEFAULT_SMALL64-NEXT:    blr
-;
-; DEFAULT_LARGE64-LABEL: Multiple_MIX_USE_LD:
-; DEFAULT_LARGE64:       # %bb.0: # %entry
-; DEFAULT_LARGE64-NEXT:    mflr 0
-; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
-; DEFAULT_LARGE64-NEXT:    addis 7, L..C2 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; DEFAULT_LARGE64-NEXT:    lwzx 6, 13, 3
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
-; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(7)
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
-; DEFAULT_LARGE64-NEXT:    add 3, 6, 3
-; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
-; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
-; DEFAULT_LARGE64-NEXT:    mtlr 0
-; DEFAULT_LARGE64-NEXT:    blr
-;
-; HEURISTIC_SMALL64-LABEL: Multiple_MIX_USE_LD:
-; HEURISTIC_SMALL64:       # %bb.0: # %entry
-; HEURISTIC_SMALL64-NEXT:    mflr 0
-; HEURISTIC_SMALL64-NEXT:    stdu 1, -48(1)
-; HEURISTIC_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; HEURISTIC_SMALL64-NEXT:    std 0, 64(1)
-; HEURISTIC_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; HEURISTIC_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSIE1
-; HEURISTIC_SMALL64-NEXT:    ld 5, L..C5(2) # target-flags(ppc-tlsld) @VarTLSLD1
-; HEURISTIC_SMALL64-NEXT:    lwzx 4, 3, 4
-; HEURISTIC_SMALL64-NEXT:    lwzx 3, 3, 5
-; HEURISTIC_SMALL64-NEXT:    add 3, 4, 3
-; HEURISTIC_SMALL64-NEXT:    addi 1, 1, 48
-; HEURISTIC_SMALL64-NEXT:    ld 0, 16(1)
-; HEURISTIC_SMALL64-NEXT:    mtlr 0
-; HEURISTIC_SMALL64-NEXT:    blr
-;
-; HEURISTIC_LARGE64-LABEL: Multiple_MIX_USE_LD:
-; HEURISTIC_LARGE64:       # %bb.0: # %entry
-; HEURISTIC_LARGE64-NEXT:    mflr 0
-; HEURISTIC_LARGE64-NEXT:    stdu 1, -48(1)
-; HEURISTIC_LARGE64-NEXT:    addis 3, L..C2 at u(2)
-; HEURISTIC_LARGE64-NEXT:    std 0, 64(1)
-; HEURISTIC_LARGE64-NEXT:    addis 6, L..C3 at u(2)
-; HEURISTIC_LARGE64-NEXT:    ld 3, L..C2 at l(3)
-; HEURISTIC_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; HEURISTIC_LARGE64-NEXT:    addis 5, L..C5 at u(2)
-; HEURISTIC_LARGE64-NEXT:    ld 4, L..C3 at l(6)
-; HEURISTIC_LARGE64-NEXT:    ld 5, L..C5 at l(5)
-; HEURISTIC_LARGE64-NEXT:    lwzx 4, 3, 4
-; HEURISTIC_LARGE64-NEXT:    lwzx 3, 3, 5
-; HEURISTIC_LARGE64-NEXT:    add 3, 4, 3
-; HEURISTIC_LARGE64-NEXT:    addi 1, 1, 48
-; HEURISTIC_LARGE64-NEXT:    ld 0, 16(1)
-; HEURISTIC_LARGE64-NEXT:    mtlr 0
-; HEURISTIC_LARGE64-NEXT:    blr
-entry:
-  %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
-  %1 = load i32, ptr %0, align 4
-  %2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
-  %3 = load i32, ptr %2, align 4
-  %add = add nsw i32 %1, %3
-  ret i32 %add
-}
-
-declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
-
-; DEFAULT_SMALL64-LABEL: .toc
-; DEFAULT_SMALL64-LABEL: L..C0:
-; DEFAULT_SMALL64-NEXT: .tc VarTLSIE1[TC],VarTLSIE1[TL]@ie
-; DEFAULT_SMALL64-LABEL: L..C1:
-; DEFAULT_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
-; DEFAULT_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; DEFAULT_SMALL64-LABEL: L..C2:
-; DEFAULT_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ld
-; DEFAULT_SMALL64-LABEL: L..C3:
-; DEFAULT_SMALL64-NEXT: .tc VarTLSIE2[TC],VarTLSIE2[UL]@ie
-; DEFAULT_SMALL64-LABEL: L..C4:
-; DEFAULT_SMALL64-NEXT: .tc VarTLSLD2[TC],VarTLSLD2[UL]@ld
-
-; DEFAULT_LARGE64-LABEL: .toc
-; DEFAULT_LARGE64-LABEL: L..C0:
-; DEFAULT_LARGE64-NEXT: .tc VarTLSIE1[TE],VarTLSIE1[TL]@ie
-; DEFAULT_LARGE64-LABEL: L..C1:
-; DEFAULT_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
-; DEFAULT_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; DEFAULT_LARGE64-LABEL: L..C2:
-; DEFAULT_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ld
-; DEFAULT_LARGE64-LABEL: L..C3:
-; DEFAULT_LARGE64-NEXT: .tc VarTLSIE2[TE],VarTLSIE2[UL]@ie
-; DEFAULT_LARGE64-LABEL: L..C4:
-; DEFAULT_LARGE64-NEXT: .tc VarTLSLD2[TE],VarTLSLD2[UL]@ld
-
-; HEURISTIC_SMALL64-LABEL: .toc
-; HEURISTIC_SMALL64-LABEL: L..C0:
-; HEURISTIC_SMALL64-NEXT: .tc VarTLSIE1[TC],VarTLSIE1[TL]@ie
-; HEURISTIC_SMALL64-LABEL: L..C1:
-; HEURISTIC_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ie
-; HEURISTIC_SMALL64-LABEL: L..C2:
-; HEURISTIC_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
-; HEURISTIC_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; HEURISTIC_SMALL64-LABEL: L..C3:
-; HEURISTIC_SMALL64-NEXT: .tc .VarTLSIE1[TC],VarTLSIE1[TL]@ld
-; HEURISTIC_SMALL64-LABEL: L..C4:
-; HEURISTIC_SMALL64-NEXT: .tc .VarTLSIE2[TC],VarTLSIE2[UL]@ld
-; HEURISTIC_SMALL64-LABEL: L..C5:
-; HEURISTIC_SMALL64-NEXT: .tc .VarTLSLD1[TC],VarTLSLD1[TL]@ld
-; HEURISTIC_SMALL64-LABEL: L..C6:
-; HEURISTIC_SMALL64-NEXT: .tc .VarTLSLD2[TC],VarTLSLD2[UL]@ld
-
-; HEURISTIC_LARGE64-LABEL: .toc
-; HEURISTIC_LARGE64-LABEL: L..C0:
-; HEURISTIC_LARGE64-NEXT: .tc VarTLSIE1[TE],VarTLSIE1[TL]@ie
-; HEURISTIC_LARGE64-LABEL: L..C1:
-; HEURISTIC_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ie
-; HEURISTIC_LARGE64-LABEL: L..C2:
-; HEURISTIC_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
-; HEURISTIC_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; HEURISTIC_LARGE64-LABEL: L..C3:
-; HEURISTIC_LARGE64-NEXT: .tc .VarTLSIE1[TE],VarTLSIE1[TL]@ld
-; HEURISTIC_LARGE64-LABEL: L..C4:
-; HEURISTIC_LARGE64-NEXT: .tc .VarTLSIE2[TE],VarTLSIE2[UL]@ld
-; HEURISTIC_LARGE64-LABEL: L..C5:
-; HEURISTIC_LARGE64-NEXT: .tc .VarTLSLD1[TE],VarTLSLD1[TL]@ld
-; HEURISTIC_LARGE64-LABEL: L..C6:
-; HEURISTIC_LARGE64-NEXT: .tc .VarTLSLD2[TE],VarTLSLD2[UL]@ld
diff --git a/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt-IRattribute.ll b/llvm/test/CodeGen/PowerPC/check-aix-shared-lib-tls-model-opt-IRattribute.ll
similarity index 63%
rename from llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt-IRattribute.ll
rename to llvm/test/CodeGen/PowerPC/check-aix-shared-lib-tls-model-opt-IRattribute.ll
index 154d573671bf5..15fac2d0c0ad9 100644
--- a/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt-IRattribute.ll
+++ b/llvm/test/CodeGen/PowerPC/check-aix-shared-lib-tls-model-opt-IRattribute.ll
@@ -9,13 +9,13 @@ define dso_local signext i32 @testWithIRAttr() #0 {
 entry:
   ret i32 0
 }
-; Check that the aix-shared-library-tls-model-heuristic attribute is not supported on Linux and AIX (32-bit).
-; CHECK-NOT-SUPPORTED: The aix-shared-library-tls-model-heuristic attribute is only supported on AIX in 64-bit mode.
+; Check that the aix-shared-lib-tls-model-opt attribute is not supported on Linux and AIX (32-bit).
+; CHECK-NOT-SUPPORTED: The aix-shared-lib-tls-model-opt attribute is only supported on AIX in 64-bit mode.
 
 ; Make sure that the test was actually compiled successfully after using the
-; aix-shared-library-tls-model-heuristic attribute.
+; aix-shared-lib-tls-model-opt attribute.
 ; CHECK-LABEL: testWithIRAttr:
 ; CHECK:        li r3, 0
 ; CHECK-NEXT:   blr
 
-attributes #0 = { "target-features"="+aix-shared-library-tls-model-heuristic" }
+attributes #0 = { "target-features"="+aix-shared-lib-tls-model-opt" }
diff --git a/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt.ll b/llvm/test/CodeGen/PowerPC/check-aix-shared-lib-tls-model-opt-Option.ll
similarity index 64%
rename from llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt.ll
rename to llvm/test/CodeGen/PowerPC/check-aix-shared-lib-tls-model-opt-Option.ll
index de85655c998f8..36f8bc78c77a5 100644
--- a/llvm/test/CodeGen/PowerPC/check-aix-shared-library-tls-model-heuristic-opt.ll
+++ b/llvm/test/CodeGen/PowerPC/check-aix-shared-lib-tls-model-opt-Option.ll
@@ -1,9 +1,9 @@
-; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -mattr=+aix-shared-library-tls-model-heuristic \
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -mattr=+aix-shared-lib-tls-model-opt \
 ; RUN:   -ppc-asm-full-reg-names < %s | FileCheck %s
-; RUN: not llc -mtriple powerpc-ibm-aix-xcoff -mattr=+aix-shared-library-tls-model-heuristic \
+; RUN: not llc -mtriple powerpc-ibm-aix-xcoff -mattr=+aix-shared-lib-tls-model-opt \
 ; RUN:   -ppc-asm-full-reg-names < %s 2>&1 | \
 ; RUN:   FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED
-; RUN: not llc -mtriple powerpc64le-unknown-linux-gnu -mattr=+aix-shared-library-tls-model-heuristic \
+; RUN: not llc -mtriple powerpc64le-unknown-linux-gnu -mattr=+aix-shared-lib-tls-model-opt \
 ; RUN:   -ppc-asm-full-reg-names < %s 2>&1 | \
 ; RUN:   FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED
 
@@ -12,11 +12,11 @@ entry:
   ret i32 0
 }
 
-; Check that the aix-shared-library-tls-model-heuristic attribute is not supported on Linux and AIX (32-bit).
-; CHECK-NOT-SUPPORTED: The aix-shared-library-tls-model-heuristic attribute is only supported on AIX in 64-bit mode.
+; Check that the aix-shared-lib-tls-model-opt attribute is not supported on Linux and AIX (32-bit).
+; CHECK-NOT-SUPPORTED: The aix-shared-lib-tls-model-opt attribute is only supported on AIX in 64-bit mode.
 
 ; Make sure that the test was actually compiled successfully after using the
-; aix-shared-library-tls-model-heuristic attribute.
+; aix-shared-lib-tls-model-opt attribute.
 ; CHECK-LABEL: testNoIRAttr:
 ; CHECK:        li r3, 0
 ; CHECK-NEXT:   blr

>From 3d2630ef331a8ddd8605b6305e4f6e2ba192ef14 Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Tue, 9 Apr 2024 01:21:02 -0400
Subject: [PATCH 07/10] Pull out logic as static function guarded by
 `Subtarget.hasAIXShLibTLSModelOpt()`.

---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 43 +++++++++++++--------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index fb4f6d129afe2..076d4d4683ca7 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3362,25 +3362,18 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
   return LowerGlobalTLSAddressLinux(Op, DAG);
 }
 
-SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
-                                                    SelectionDAG &DAG) const {
-  GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
-
-  if (DAG.getTarget().useEmulatedTLS())
-    report_fatal_error("Emulated TLS is not yet supported on AIX");
-
-  SDLoc dl(GA);
-  const GlobalValue *GV = GA->getGlobal();
-  EVT PtrVT = getPointerTy(DAG.getDataLayout());
-  bool Is64Bit = Subtarget.isPPC64();
-  TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
+/// updateForAIXShLibTLSModelOpt - Helper to initialize TLS model opt settings,
+/// and then apply the update.
+static void updateForAIXShLibTLSModelOpt(TLSModel::Model &Model,
+                                         SelectionDAG &DAG,
+                                         const TargetMachine &TM) {
   // Initialize TLS model opt setting lazily:
   // (1) Use initial-exec for single TLS var references within current function.
   // (2) Use local-dynamic for multiple TLS var references within current
   // function.
   PPCFunctionInfo *FuncInfo =
       DAG.getMachineFunction().getInfo<PPCFunctionInfo>();
-  if (Subtarget.hasAIXShLibTLSModelOpt() && !FuncInfo->isAIXFuncUseInitDone()) {
+  if (!FuncInfo->isAIXFuncUseInitDone()) {
     SmallPtrSet<const GlobalValue *, 8> TLSGV;
     // Iterate over all instructions within current function, collect all TLS
     // global variables (global variables taken as the first parameter to
@@ -3397,9 +3390,9 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
                   CF->getIntrinsicID() == Intrinsic::threadlocal_address)
                 if (const GlobalValue *GV =
                         dyn_cast<GlobalValue>(II->getOperand(0))) {
-                  TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
-                  if (Model == TLSModel::InitialExec ||
-                      Model == TLSModel::LocalDynamic)
+                  TLSModel::Model GVModel = TM.getTLSModel(GV);
+                  if (GVModel == TLSModel::InitialExec ||
+                      GVModel == TLSModel::LocalDynamic)
                     TLSGV.insert(GV);
                 }
 
@@ -3426,6 +3419,24 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
         << " function is using the TLS-IE model for TLS IE/LD accesses.\n");
     Model = TLSModel::InitialExec;
   }
+}
+
+SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
+                                                    SelectionDAG &DAG) const {
+  GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
+
+  if (DAG.getTarget().useEmulatedTLS())
+    report_fatal_error("Emulated TLS is not yet supported on AIX");
+
+  SDLoc dl(GA);
+  const GlobalValue *GV = GA->getGlobal();
+  EVT PtrVT = getPointerTy(DAG.getDataLayout());
+  bool Is64Bit = Subtarget.isPPC64();
+  TLSModel::Model Model = getTargetMachine().getTLSModel(GV);
+
+  // Apply update to the TLS model.
+  if (Subtarget.hasAIXShLibTLSModelOpt())
+    updateForAIXShLibTLSModelOpt(Model, DAG, getTargetMachine());
 
   bool IsTLSLocalExecModel = Model == TLSModel::LocalExec;
 

>From cc5cd2e4ef5c4b0b872bf7093839960cc50bf5b0 Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Wed, 10 Apr 2024 20:47:29 -0400
Subject: [PATCH 08/10] [NFC] address comment

---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 076d4d4683ca7..4460e3484df25 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3398,11 +3398,10 @@ static void updateForAIXShLibTLSModelOpt(TLSModel::Model &Model,
 
     unsigned TLSGVCnt = TLSGV.size();
     LLVM_DEBUG(dbgs() << format("TLSGV count:%d\n", TLSGVCnt));
-    if (TLSGVCnt == 1) {
+    if (TLSGVCnt == 1)
       FuncInfo->setAIXFuncUseTLSIE();
-    } else if (TLSGVCnt > 1) {
+    else if (TLSGVCnt > 1)
       FuncInfo->setAIXFuncUseTLSLD();
-    }
     FuncInfo->setAIXFuncUseInitDone();
   }
 

>From 4050abcfff5b6650afd693468aed07f5a30704c1 Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Thu, 18 Apr 2024 20:59:00 -0400
Subject: [PATCH 09/10] Update according to comments: (1) Update Options.td to
 make it clear this is about the transform from LD to IE. (2) Limit transfrom
 from LD to IE only. (3) Add target hidden flag to control Limit count of the
 transformation. (4) Update test case.

---
 clang/include/clang/Driver/Options.td         |   3 +-
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     |   3 +-
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  33 +-
 .../Target/PowerPC/PPCMachineFunctionInfo.h   |  21 +-
 .../PowerPC/aix-shared-lib-tls-model-opt.ll   | 664 ++++++++++--------
 5 files changed, 412 insertions(+), 312 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 68931a9c949c1..92a2f18a33e8d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5080,7 +5080,8 @@ def maix_small_local_dynamic_tls : Flag<["-"], "maix-small-local-dynamic-tls">,
 def maix_shared_lib_tls_model_opt : Flag<["-"], "maix-shared-lib-tls-model-opt">,
   Group<m_ppc_Features_Group>,
   HelpText<"For shared library loaded with the main program, use heuristics to "
-           "tune the TLS model at the function level (AIX 64-bit only).">;
+           "change local-dynamic access(es) to initial-exec access(es) at the "
+           "function level (AIX 64-bit only).">;
 def maix_struct_return : Flag<["-"], "maix-struct-return">,
   Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Return all structs in memory (PPC32 only)">,
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 9d828fca08d5f..eaf2e8685de8c 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -881,7 +881,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
       // On AIX, TLS model heuristics may have turned local-dynamic accesses
       // into initial-exec accesses.
       PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
-      if (Model == TLSModel::LocalDynamic && FuncInfo->isAIXFuncUseTLSIE()) {
+      if (Model == TLSModel::LocalDynamic &&
+          FuncInfo->isAIXFuncUseTLSIEForLD()) {
         LLVM_DEBUG(
             dbgs() << "Current function uses IE access for default LD vars.\n");
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 4460e3484df25..0a7483fc45b20 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -141,6 +141,11 @@ static cl::opt<unsigned> PPCGatherAllAliasesMaxDepth(
     "ppc-gather-alias-max-depth", cl::init(18), cl::Hidden,
     cl::desc("max depth when checking alias info in GatherAllAliases()"));
 
+static cl::opt<unsigned> PPCAIXTLSModelOptUseIEForLDLimit(
+    "ppc-aix-shared-lib-tls-model-opt-limit", cl::init(1), cl::Hidden,
+    cl::desc("Set inclusive limit count of TLS local-dynamic access(es) in a "
+             "function to use initial-exec"));
+
 STATISTIC(NumTailCalls, "Number of tail calls");
 STATISTIC(NumSiblingCalls, "Number of sibling calls");
 STATISTIC(ShufflesHandledWithVPERM,
@@ -3373,7 +3378,7 @@ static void updateForAIXShLibTLSModelOpt(TLSModel::Model &Model,
   // function.
   PPCFunctionInfo *FuncInfo =
       DAG.getMachineFunction().getInfo<PPCFunctionInfo>();
-  if (!FuncInfo->isAIXFuncUseInitDone()) {
+  if (!FuncInfo->isAIXFuncTLSModelOptInitDone()) {
     SmallPtrSet<const GlobalValue *, 8> TLSGV;
     // Iterate over all instructions within current function, collect all TLS
     // global variables (global variables taken as the first parameter to
@@ -3391,31 +3396,21 @@ static void updateForAIXShLibTLSModelOpt(TLSModel::Model &Model,
                 if (const GlobalValue *GV =
                         dyn_cast<GlobalValue>(II->getOperand(0))) {
                   TLSModel::Model GVModel = TM.getTLSModel(GV);
-                  if (GVModel == TLSModel::InitialExec ||
-                      GVModel == TLSModel::LocalDynamic)
+                  if (GVModel == TLSModel::LocalDynamic)
                     TLSGV.insert(GV);
                 }
 
     unsigned TLSGVCnt = TLSGV.size();
-    LLVM_DEBUG(dbgs() << format("TLSGV count:%d\n", TLSGVCnt));
-    if (TLSGVCnt == 1)
-      FuncInfo->setAIXFuncUseTLSIE();
-    else if (TLSGVCnt > 1)
-      FuncInfo->setAIXFuncUseTLSLD();
-    FuncInfo->setAIXFuncUseInitDone();
+    LLVM_DEBUG(dbgs() << format("LocalDynamic TLSGV count:%d\n", TLSGVCnt));
+    if (TLSGVCnt <= PPCAIXTLSModelOptUseIEForLDLimit)
+      FuncInfo->setAIXFuncUseTLSIEForLD();
+    FuncInfo->setAIXFuncTLSModelOptInitDone();
   }
 
-  if (FuncInfo->isAIXFuncUseTLSLD()) {
-    LLVM_DEBUG(
-        dbgs()
-        << DAG.getMachineFunction().getName()
-        << " function is using the TLS-LD model for TLS IE/LD accesses.\n");
-    Model = TLSModel::LocalDynamic;
-  } else if (FuncInfo->isAIXFuncUseTLSIE()) {
+  if (FuncInfo->isAIXFuncUseTLSIEForLD()) {
     LLVM_DEBUG(
-        dbgs()
-        << DAG.getMachineFunction().getName()
-        << " function is using the TLS-IE model for TLS IE/LD accesses.\n");
+        dbgs() << DAG.getMachineFunction().getName()
+               << " function is using the TLS-IE model for TLS-LD access.\n");
     Model = TLSModel::InitialExec;
   }
 }
diff --git a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
index aa640e8ef65e0..b7d14da05ee24 100644
--- a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
@@ -150,11 +150,10 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   /// to use SExt/ZExt flags in later optimization.
   std::vector<std::pair<Register, ISD::ArgFlagsTy>> LiveInAttrs;
 
-  /// Flags for aix-shared-library-tls-model-heuristic, will be lazily
-  /// initialized for each function.
-  bool AIXFuncUseTLSLD = false;
-  bool AIXFuncUseTLSIE = false;
-  bool AIXFuncUseInitDone = false;
+  /// Flags for aix-shared-lib-tls-model-opt, will be lazily initialized for
+  /// each function.
+  bool AIXFuncUseTLSIEForLD = false;
+  bool AIXFuncTLSModelOptInitDone = false;
 
 public:
   explicit PPCFunctionInfo(const Function &F, const TargetSubtargetInfo *STI);
@@ -227,12 +226,12 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   void setHasFastCall() { HasFastCall = true; }
   bool hasFastCall() const { return HasFastCall;}
 
-  void setAIXFuncUseInitDone() { AIXFuncUseInitDone = true; }
-  bool isAIXFuncUseInitDone() const { return AIXFuncUseInitDone; }
-  void setAIXFuncUseTLSLD() { AIXFuncUseTLSLD = true; }
-  bool isAIXFuncUseTLSLD() const { return AIXFuncUseTLSLD; }
-  void setAIXFuncUseTLSIE() { AIXFuncUseTLSIE = true; }
-  bool isAIXFuncUseTLSIE() const { return AIXFuncUseTLSIE; }
+  void setAIXFuncTLSModelOptInitDone() { AIXFuncTLSModelOptInitDone = true; }
+  bool isAIXFuncTLSModelOptInitDone() const {
+    return AIXFuncTLSModelOptInitDone;
+  }
+  void setAIXFuncUseTLSIEForLD() { AIXFuncUseTLSIEForLD = true; }
+  bool isAIXFuncUseTLSIEForLD() const { return AIXFuncUseTLSIEForLD; }
 
   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
   void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
diff --git a/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt.ll b/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt.ll
index 9db3c2b825684..140377270d6d9 100644
--- a/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt.ll
@@ -7,77 +7,37 @@
 ; RUN:      -mattr=+aix-shared-lib-tls-model-opt --code-model=small < %s | FileCheck %s --check-prefixes=TLS_MODEL_OPT_SMALL64
 ; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
 ; RUN:      -mattr=+aix-shared-lib-tls-model-opt --code-model=large < %s | FileCheck %s --check-prefixes=TLS_MODEL_OPT_LARGE64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-lib-tls-model-opt -ppc-aix-shared-lib-tls-model-opt-limit=2 \
+; RUN:      --code-model=small < %s | FileCheck %s --check-prefixes=TLS_MODEL_OPT_LIMIT2_SMALL64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-lib-tls-model-opt -ppc-aix-shared-lib-tls-model-opt-limit=2 \
+; RUN:      --code-model=large < %s | FileCheck %s --check-prefixes=TLS_MODEL_OPT_LIMIT2_LARGE64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-lib-tls-model-opt -ppc-aix-shared-lib-tls-model-opt-limit=3 \
+; RUN:      --code-model=small < %s | FileCheck %s --check-prefixes=TLS_MODEL_OPT_LIMIT3_SMALL64
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-lib-tls-model-opt -ppc-aix-shared-lib-tls-model-opt-limit=3 \
+; RUN:      --code-model=large < %s | FileCheck %s --check-prefixes=TLS_MODEL_OPT_LIMIT3_LARGE64
 
- at VarTLSIE1 = internal thread_local(initialexec) global i32 42, align 4
- at VarTLSIE2 = internal thread_local(initialexec) global i32 0, align 4
 @VarTLSLD1 = internal thread_local(localdynamic) global i32 42, align 4
 @VarTLSLD2 = internal thread_local(localdynamic) global i32 0, align 4
+ at VarTLSLD3 = internal thread_local(localdynamic) global i32 0, align 4
 
 ; Tune function level TLS model settings:
 ; Use initial-exec when we have a function accessing only one TLS variable.
 ; Use local-dynamic when we have a function accessing a handful or more different TLS variables.
 
-define i32 @Single_IE_USE_IE(i32 %P, i32 %Q) {
-; DEFAULT_SMALL64-LABEL: Single_IE_USE_IE:
-; DEFAULT_SMALL64:       # %bb.0: # %entry
-; DEFAULT_SMALL64-NEXT:    and 4, 3, 4
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
-; DEFAULT_SMALL64-NEXT:    cmpwi 4, -1
-; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_SMALL64-NEXT:    blr
-;
-; DEFAULT_LARGE64-LABEL: Single_IE_USE_IE:
-; DEFAULT_LARGE64:       # %bb.0: # %entry
-; DEFAULT_LARGE64-NEXT:    and 4, 3, 4
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; DEFAULT_LARGE64-NEXT:    cmpwi 4, -1
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_LARGE64-NEXT:    blr
-;
-; TLS_MODEL_OPT_SMALL64-LABEL: Single_IE_USE_IE:
-; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
-; TLS_MODEL_OPT_SMALL64-NEXT:    and 4, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
-; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 4, -1
-; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 13, 3
-; TLS_MODEL_OPT_SMALL64-NEXT:    blr
-;
-; TLS_MODEL_OPT_LARGE64-LABEL: Single_IE_USE_IE:
-; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
-; TLS_MODEL_OPT_LARGE64-NEXT:    and 4, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 4, -1
-; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 13, 3
-; TLS_MODEL_OPT_LARGE64-NEXT:    blr
-entry:
-  %a = icmp slt i32 %P, 0
-  %b = icmp slt i32 %Q, 0
-  %c = and i1 %a, %b
-  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
-  %load1 = load i32, ptr %tls1, align 4
-  br i1 %c, label %bb1, label %return
-
-bb1:
-  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
-  %load2 = load i32, ptr %tls2, align 4
-  ret i32 %load2
-
-return:
-  ret i32 %load1
-}
-
-define i32 @Single_LD_USE_IE(i32 %P, i32 %Q) {
-; DEFAULT_SMALL64-LABEL: Single_LD_USE_IE:
+define i32 @Single_LD(i32 %P, i32 %Q) {
+; DEFAULT_SMALL64-LABEL: Single_LD:
 ; DEFAULT_SMALL64:       # %bb.0: # %entry
 ; DEFAULT_SMALL64-NEXT:    mflr 0
 ; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
 ; DEFAULT_SMALL64-NEXT:    and 6, 3, 4
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
 ; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
 ; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C1(2) # target-flags(ppc-tlsld) @VarTLSLD1
 ; DEFAULT_SMALL64-NEXT:    cmpwi 6, -1
 ; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
 ; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
@@ -85,17 +45,17 @@ define i32 @Single_LD_USE_IE(i32 %P, i32 %Q) {
 ; DEFAULT_SMALL64-NEXT:    mtlr 0
 ; DEFAULT_SMALL64-NEXT:    blr
 ;
-; DEFAULT_LARGE64-LABEL: Single_LD_USE_IE:
+; DEFAULT_LARGE64-LABEL: Single_LD:
 ; DEFAULT_LARGE64:       # %bb.0: # %entry
 ; DEFAULT_LARGE64-NEXT:    mflr 0
 ; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
 ; DEFAULT_LARGE64-NEXT:    and 6, 3, 4
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
-; DEFAULT_LARGE64-NEXT:    addis 7, L..C2 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; DEFAULT_LARGE64-NEXT:    addis 7, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
 ; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
 ; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(7)
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C1 at l(7)
 ; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
 ; DEFAULT_LARGE64-NEXT:    cmpwi 6, -1
 ; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
@@ -103,128 +63,66 @@ define i32 @Single_LD_USE_IE(i32 %P, i32 %Q) {
 ; DEFAULT_LARGE64-NEXT:    mtlr 0
 ; DEFAULT_LARGE64-NEXT:    blr
 ;
-; TLS_MODEL_OPT_SMALL64-LABEL: Single_LD_USE_IE:
+; TLS_MODEL_OPT_SMALL64-LABEL: Single_LD:
 ; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
 ; TLS_MODEL_OPT_SMALL64-NEXT:    and 4, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tprel) @VarTLSLD1
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSLD1
 ; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 4, -1
 ; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 13, 3
 ; TLS_MODEL_OPT_SMALL64-NEXT:    blr
 ;
-; TLS_MODEL_OPT_LARGE64-LABEL: Single_LD_USE_IE:
+; TLS_MODEL_OPT_LARGE64-LABEL: Single_LD:
 ; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
 ; TLS_MODEL_OPT_LARGE64-NEXT:    and 4, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 4, -1
 ; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 13, 3
 ; TLS_MODEL_OPT_LARGE64-NEXT:    blr
-entry:
-  %a = icmp slt i32 %P, 0
-  %b = icmp slt i32 %Q, 0
-  %c = and i1 %a, %b
-  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
-  %load1 = load i32, ptr %tls1, align 4
-  br i1 %c, label %bb1, label %return
-
-bb1:
-  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
-  %load2 = load i32, ptr %tls2, align 4
-  ret i32 %load2
-
-return:
-  ret i32 %load1
-}
-
-define i32 @Multiple_IE_USE_LD(i32 %P, i32 %Q) {
-; DEFAULT_SMALL64-LABEL: Multiple_IE_USE_LD:
-; DEFAULT_SMALL64:       # %bb.0: # %entry
-; DEFAULT_SMALL64-NEXT:    and 3, 3, 4
-; DEFAULT_SMALL64-NEXT:    cmpwi 3, -1
-; DEFAULT_SMALL64-NEXT:    bgt 0, L..BB2_2
-; DEFAULT_SMALL64-NEXT:  # %bb.1: # %bb1
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C3(2) # target-flags(ppc-tprel) @VarTLSIE2
-; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_SMALL64-NEXT:    blr
-; DEFAULT_SMALL64-NEXT:  L..BB2_2: # %return
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
-; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_SMALL64-NEXT:    blr
 ;
-; DEFAULT_LARGE64-LABEL: Multiple_IE_USE_LD:
-; DEFAULT_LARGE64:       # %bb.0: # %entry
-; DEFAULT_LARGE64-NEXT:    and 3, 3, 4
-; DEFAULT_LARGE64-NEXT:    cmpwi 3, -1
-; DEFAULT_LARGE64-NEXT:    bgt 0, L..BB2_2
-; DEFAULT_LARGE64-NEXT:  # %bb.1: # %bb1
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C3 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C3 at l(3)
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_LARGE64-NEXT:    blr
-; DEFAULT_LARGE64-NEXT:  L..BB2_2: # %return
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_LARGE64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: Single_LD:
+; TLS_MODEL_OPT_LIMIT2_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    and 4, 3, 4
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSLD1
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    cmpwi 4, -1
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    blr
 ;
-; TLS_MODEL_OPT_SMALL64-LABEL: Multiple_IE_USE_LD:
-; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
-; TLS_MODEL_OPT_SMALL64-NEXT:    mflr 0
-; TLS_MODEL_OPT_SMALL64-NEXT:    stdu 1, -48(1)
-; TLS_MODEL_OPT_SMALL64-NEXT:    and 6, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
-; TLS_MODEL_OPT_SMALL64-NEXT:    std 0, 64(1)
-; TLS_MODEL_OPT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 6, -1
-; TLS_MODEL_OPT_SMALL64-NEXT:    bgt 0, L..BB2_2
-; TLS_MODEL_OPT_SMALL64-NEXT:  # %bb.1: # %bb1
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSIE2
-; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:    b L..BB2_3
-; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB2_2: # %return
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C4(2) # target-flags(ppc-tlsld) @VarTLSIE1
-; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB2_3: # %bb1
-; TLS_MODEL_OPT_SMALL64-NEXT:    addi 1, 1, 48
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 0, 16(1)
-; TLS_MODEL_OPT_SMALL64-NEXT:    mtlr 0
-; TLS_MODEL_OPT_SMALL64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: Single_LD:
+; TLS_MODEL_OPT_LIMIT2_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    and 4, 3, 4
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    cmpwi 4, -1
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    blr
 ;
-; TLS_MODEL_OPT_LARGE64-LABEL: Multiple_IE_USE_LD:
-; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
-; TLS_MODEL_OPT_LARGE64-NEXT:    mflr 0
-; TLS_MODEL_OPT_LARGE64-NEXT:    stdu 1, -48(1)
-; TLS_MODEL_OPT_LARGE64-NEXT:    and 6, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C2 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    std 0, 64(1)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C2 at l(3)
-; TLS_MODEL_OPT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 6, -1
-; TLS_MODEL_OPT_LARGE64-NEXT:    bgt 0, L..BB2_2
-; TLS_MODEL_OPT_LARGE64-NEXT:  # %bb.1: # %bb1
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C3 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C3 at l(4)
-; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:    b L..BB2_3
-; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB2_2: # %return
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C4 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C4 at l(4)
-; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB2_3: # %bb1
-; TLS_MODEL_OPT_LARGE64-NEXT:    addi 1, 1, 48
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 0, 16(1)
-; TLS_MODEL_OPT_LARGE64-NEXT:    mtlr 0
-; TLS_MODEL_OPT_LARGE64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT3_SMALL64-LABEL: Single_LD:
+; TLS_MODEL_OPT_LIMIT3_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    and 4, 3, 4
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSLD1
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    cmpwi 4, -1
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT3_LARGE64-LABEL: Single_LD:
+; TLS_MODEL_OPT_LIMIT3_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    and 4, 3, 4
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    cmpwi 4, -1
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    blr
 entry:
   %a = icmp slt i32 %P, 0
   %b = icmp slt i32 %Q, 0
   %c = and i1 %a, %b
-  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
   %load1 = load i32, ptr %tls1, align 4
   br i1 %c, label %bb1, label %return
 
 bb1:
-  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE2)
+  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
   %load2 = load i32, ptr %tls2, align 4
   ret i32 %load2
 
@@ -232,104 +130,164 @@ return:
   ret i32 %load1
 }
 
-define i32 @Multiple_LD_USE_LD(i32 %P, i32 %Q) {
-; DEFAULT_SMALL64-LABEL: Multiple_LD_USE_LD:
+define i32 @Two_LDs(i32 %P, i32 %Q) {
+; DEFAULT_SMALL64-LABEL: Two_LDs:
 ; DEFAULT_SMALL64:       # %bb.0: # %entry
 ; DEFAULT_SMALL64-NEXT:    mflr 0
 ; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
 ; DEFAULT_SMALL64-NEXT:    and 6, 3, 4
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
 ; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
 ; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
 ; DEFAULT_SMALL64-NEXT:    cmpwi 6, -1
-; DEFAULT_SMALL64-NEXT:    bgt 0, L..BB3_2
+; DEFAULT_SMALL64-NEXT:    bgt 0, L..BB1_2
 ; DEFAULT_SMALL64-NEXT:  # %bb.1: # %bb1
-; DEFAULT_SMALL64-NEXT:    ld 4, L..C4(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD2
 ; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
-; DEFAULT_SMALL64-NEXT:    b L..BB3_3
-; DEFAULT_SMALL64-NEXT:  L..BB3_2: # %return
-; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    b L..BB1_3
+; DEFAULT_SMALL64-NEXT:  L..BB1_2: # %return
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C1(2) # target-flags(ppc-tlsld) @VarTLSLD1
 ; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
-; DEFAULT_SMALL64-NEXT:  L..BB3_3: # %bb1
+; DEFAULT_SMALL64-NEXT:  L..BB1_3: # %bb1
 ; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
 ; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
 ; DEFAULT_SMALL64-NEXT:    mtlr 0
 ; DEFAULT_SMALL64-NEXT:    blr
 ;
-; DEFAULT_LARGE64-LABEL: Multiple_LD_USE_LD:
+; DEFAULT_LARGE64-LABEL: Two_LDs:
 ; DEFAULT_LARGE64:       # %bb.0: # %entry
 ; DEFAULT_LARGE64-NEXT:    mflr 0
 ; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
 ; DEFAULT_LARGE64-NEXT:    and 6, 3, 4
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
 ; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
 ; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
 ; DEFAULT_LARGE64-NEXT:    cmpwi 6, -1
-; DEFAULT_LARGE64-NEXT:    bgt 0, L..BB3_2
+; DEFAULT_LARGE64-NEXT:    bgt 0, L..BB1_2
 ; DEFAULT_LARGE64-NEXT:  # %bb.1: # %bb1
-; DEFAULT_LARGE64-NEXT:    addis 4, L..C4 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 4, L..C4 at l(4)
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
-; DEFAULT_LARGE64-NEXT:    b L..BB3_3
-; DEFAULT_LARGE64-NEXT:  L..BB3_2: # %return
 ; DEFAULT_LARGE64-NEXT:    addis 4, L..C2 at u(2)
 ; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(4)
 ; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
-; DEFAULT_LARGE64-NEXT:  L..BB3_3: # %bb1
+; DEFAULT_LARGE64-NEXT:    b L..BB1_3
+; DEFAULT_LARGE64-NEXT:  L..BB1_2: # %return
+; DEFAULT_LARGE64-NEXT:    addis 4, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C1 at l(4)
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_LARGE64-NEXT:  L..BB1_3: # %bb1
 ; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
 ; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
 ; DEFAULT_LARGE64-NEXT:    mtlr 0
 ; DEFAULT_LARGE64-NEXT:    blr
 ;
-; TLS_MODEL_OPT_SMALL64-LABEL: Multiple_LD_USE_LD:
+; TLS_MODEL_OPT_SMALL64-LABEL: Two_LDs:
 ; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
 ; TLS_MODEL_OPT_SMALL64-NEXT:    mflr 0
 ; TLS_MODEL_OPT_SMALL64-NEXT:    stdu 1, -48(1)
 ; TLS_MODEL_OPT_SMALL64-NEXT:    and 6, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
 ; TLS_MODEL_OPT_SMALL64-NEXT:    std 0, 64(1)
 ; TLS_MODEL_OPT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
 ; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 6, -1
-; TLS_MODEL_OPT_SMALL64-NEXT:    bgt 0, L..BB3_2
+; TLS_MODEL_OPT_SMALL64-NEXT:    bgt 0, L..BB1_2
 ; TLS_MODEL_OPT_SMALL64-NEXT:  # %bb.1: # %bb1
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C5(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD2
 ; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:    b L..BB3_3
-; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB3_2: # %return
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C6(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; TLS_MODEL_OPT_SMALL64-NEXT:    b L..BB1_3
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB1_2: # %return
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSLD1
 ; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB3_3: # %bb1
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB1_3: # %bb1
 ; TLS_MODEL_OPT_SMALL64-NEXT:    addi 1, 1, 48
 ; TLS_MODEL_OPT_SMALL64-NEXT:    ld 0, 16(1)
 ; TLS_MODEL_OPT_SMALL64-NEXT:    mtlr 0
 ; TLS_MODEL_OPT_SMALL64-NEXT:    blr
 ;
-; TLS_MODEL_OPT_LARGE64-LABEL: Multiple_LD_USE_LD:
+; TLS_MODEL_OPT_LARGE64-LABEL: Two_LDs:
 ; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
 ; TLS_MODEL_OPT_LARGE64-NEXT:    mflr 0
 ; TLS_MODEL_OPT_LARGE64-NEXT:    stdu 1, -48(1)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    and 6, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    std 0, 64(1)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
 ; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 6, -1
-; TLS_MODEL_OPT_LARGE64-NEXT:    bgt 0, L..BB3_2
+; TLS_MODEL_OPT_LARGE64-NEXT:    bgt 0, L..BB1_2
 ; TLS_MODEL_OPT_LARGE64-NEXT:  # %bb.1: # %bb1
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C5 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C5 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C2 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C2 at l(4)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:    b L..BB3_3
-; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB3_2: # %return
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C6 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C6 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    b L..BB1_3
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB1_2: # %return
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C3 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C3 at l(4)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB3_3: # %bb1
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB1_3: # %bb1
 ; TLS_MODEL_OPT_LARGE64-NEXT:    addi 1, 1, 48
 ; TLS_MODEL_OPT_LARGE64-NEXT:    ld 0, 16(1)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    mtlr 0
 ; TLS_MODEL_OPT_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: Two_LDs:
+; TLS_MODEL_OPT_LIMIT2_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    and 3, 3, 4
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    cmpwi 3, -1
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    bgt 0, L..BB1_2
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tprel) @VarTLSLD2
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:  L..BB1_2: # %return
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSLD1
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: Two_LDs:
+; TLS_MODEL_OPT_LIMIT2_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    and 3, 3, 4
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    cmpwi 3, -1
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    bgt 0, L..BB1_2
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:  L..BB1_2: # %return
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT3_SMALL64-LABEL: Two_LDs:
+; TLS_MODEL_OPT_LIMIT3_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    and 3, 3, 4
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    cmpwi 3, -1
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    bgt 0, L..BB1_2
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tprel) @VarTLSLD2
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:  L..BB1_2: # %return
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSLD1
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT3_LARGE64-LABEL: Two_LDs:
+; TLS_MODEL_OPT_LIMIT3_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    and 3, 3, 4
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    cmpwi 3, -1
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    bgt 0, L..BB1_2
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:  L..BB1_2: # %return
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    blr
 entry:
   %a = icmp slt i32 %P, 0
   %b = icmp slt i32 %Q, 0
@@ -347,114 +305,226 @@ return:
   ret i32 %load1
 }
 
-define i32 @Multiple_MIX_USE_LD(i32 %P, i32 %Q) {
-; DEFAULT_SMALL64-LABEL: Multiple_MIX_USE_LD:
+define i32 @Three_LDs(i32 %P, i32 %Q) {
+; DEFAULT_SMALL64-LABEL: Three_LDs:
 ; DEFAULT_SMALL64:       # %bb.0: # %entry
-; DEFAULT_SMALL64-NEXT:    and 3, 3, 4
-; DEFAULT_SMALL64-NEXT:    cmpwi 3, -1
-; DEFAULT_SMALL64-NEXT:    bgt 0, L..BB4_2
-; DEFAULT_SMALL64-NEXT:  # %bb.1: # %bb1
 ; DEFAULT_SMALL64-NEXT:    mflr 0
 ; DEFAULT_SMALL64-NEXT:    stdu 1, -48(1)
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; DEFAULT_SMALL64-NEXT:    and 6, 3, 4
+; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tlsldm) @"_$TLSML"
 ; DEFAULT_SMALL64-NEXT:    std 0, 64(1)
 ; DEFAULT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; DEFAULT_SMALL64-NEXT:    cmpwi 6, -1
+; DEFAULT_SMALL64-NEXT:    bgt 0, L..BB2_2
+; DEFAULT_SMALL64-NEXT:  # %bb.1: # %bb1
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; DEFAULT_SMALL64-NEXT:    ld 5, L..C3(2) # target-flags(ppc-tlsld) @VarTLSLD3
+; DEFAULT_SMALL64-NEXT:    lwzx 4, 3, 4
+; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 5
+; DEFAULT_SMALL64-NEXT:    add 3, 4, 3
+; DEFAULT_SMALL64-NEXT:    b L..BB2_3
+; DEFAULT_SMALL64-NEXT:  L..BB2_2: # %return
+; DEFAULT_SMALL64-NEXT:    ld 4, L..C1(2) # target-flags(ppc-tlsld) @VarTLSLD1
 ; DEFAULT_SMALL64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_SMALL64-NEXT:  L..BB2_3: # %return
 ; DEFAULT_SMALL64-NEXT:    addi 1, 1, 48
 ; DEFAULT_SMALL64-NEXT:    ld 0, 16(1)
 ; DEFAULT_SMALL64-NEXT:    mtlr 0
 ; DEFAULT_SMALL64-NEXT:    blr
-; DEFAULT_SMALL64-NEXT:  L..BB4_2: # %return
-; DEFAULT_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
-; DEFAULT_SMALL64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_SMALL64-NEXT:    blr
 ;
-; DEFAULT_LARGE64-LABEL: Multiple_MIX_USE_LD:
+; DEFAULT_LARGE64-LABEL: Three_LDs:
 ; DEFAULT_LARGE64:       # %bb.0: # %entry
-; DEFAULT_LARGE64-NEXT:    and 3, 3, 4
-; DEFAULT_LARGE64-NEXT:    cmpwi 3, -1
-; DEFAULT_LARGE64-NEXT:    bgt 0, L..BB4_2
-; DEFAULT_LARGE64-NEXT:  # %bb.1: # %bb1
 ; DEFAULT_LARGE64-NEXT:    mflr 0
 ; DEFAULT_LARGE64-NEXT:    stdu 1, -48(1)
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
-; DEFAULT_LARGE64-NEXT:    addis 6, L..C2 at u(2)
+; DEFAULT_LARGE64-NEXT:    and 6, 3, 4
+; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
 ; DEFAULT_LARGE64-NEXT:    std 0, 64(1)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
 ; DEFAULT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
-; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(6)
+; DEFAULT_LARGE64-NEXT:    cmpwi 6, -1
+; DEFAULT_LARGE64-NEXT:    bgt 0, L..BB2_2
+; DEFAULT_LARGE64-NEXT:  # %bb.1: # %bb1
+; DEFAULT_LARGE64-NEXT:    addis 4, L..C2 at u(2)
+; DEFAULT_LARGE64-NEXT:    addis 5, L..C3 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C2 at l(4)
+; DEFAULT_LARGE64-NEXT:    ld 5, L..C3 at l(5)
+; DEFAULT_LARGE64-NEXT:    lwzx 4, 3, 4
+; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 5
+; DEFAULT_LARGE64-NEXT:    add 3, 4, 3
+; DEFAULT_LARGE64-NEXT:    b L..BB2_3
+; DEFAULT_LARGE64-NEXT:  L..BB2_2: # %return
+; DEFAULT_LARGE64-NEXT:    addis 4, L..C1 at u(2)
+; DEFAULT_LARGE64-NEXT:    ld 4, L..C1 at l(4)
 ; DEFAULT_LARGE64-NEXT:    lwzx 3, 3, 4
+; DEFAULT_LARGE64-NEXT:  L..BB2_3: # %return
 ; DEFAULT_LARGE64-NEXT:    addi 1, 1, 48
 ; DEFAULT_LARGE64-NEXT:    ld 0, 16(1)
 ; DEFAULT_LARGE64-NEXT:    mtlr 0
 ; DEFAULT_LARGE64-NEXT:    blr
-; DEFAULT_LARGE64-NEXT:  L..BB4_2: # %return
-; DEFAULT_LARGE64-NEXT:    addis 3, L..C0 at u(2)
-; DEFAULT_LARGE64-NEXT:    ld 3, L..C0 at l(3)
-; DEFAULT_LARGE64-NEXT:    lwzx 3, 13, 3
-; DEFAULT_LARGE64-NEXT:    blr
 ;
-; TLS_MODEL_OPT_SMALL64-LABEL: Multiple_MIX_USE_LD:
+; TLS_MODEL_OPT_SMALL64-LABEL: Three_LDs:
 ; TLS_MODEL_OPT_SMALL64:       # %bb.0: # %entry
 ; TLS_MODEL_OPT_SMALL64-NEXT:    mflr 0
 ; TLS_MODEL_OPT_SMALL64-NEXT:    stdu 1, -48(1)
 ; TLS_MODEL_OPT_SMALL64-NEXT:    and 6, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tlsldm) @"_$TLSML"
 ; TLS_MODEL_OPT_SMALL64-NEXT:    std 0, 64(1)
 ; TLS_MODEL_OPT_SMALL64-NEXT:    bla .__tls_get_mod[PR]
 ; TLS_MODEL_OPT_SMALL64-NEXT:    cmpwi 6, -1
-; TLS_MODEL_OPT_SMALL64-NEXT:    bgt 0, L..BB4_2
+; TLS_MODEL_OPT_SMALL64-NEXT:    bgt 0, L..BB2_2
 ; TLS_MODEL_OPT_SMALL64-NEXT:  # %bb.1: # %bb1
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C6(2) # target-flags(ppc-tlsld) @VarTLSLD1
-; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:    b L..BB4_3
-; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB4_2: # %return
-; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C4(2) # target-flags(ppc-tlsld) @VarTLSIE1
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 5, L..C4(2) # target-flags(ppc-tlsld) @VarTLSLD3
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 4, 3, 4
+; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 5
+; TLS_MODEL_OPT_SMALL64-NEXT:    add 3, 4, 3
+; TLS_MODEL_OPT_SMALL64-NEXT:    b L..BB2_3
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB2_2: # %return
+; TLS_MODEL_OPT_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSLD1
 ; TLS_MODEL_OPT_SMALL64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB4_3: # %bb1
+; TLS_MODEL_OPT_SMALL64-NEXT:  L..BB2_3: # %return
 ; TLS_MODEL_OPT_SMALL64-NEXT:    addi 1, 1, 48
 ; TLS_MODEL_OPT_SMALL64-NEXT:    ld 0, 16(1)
 ; TLS_MODEL_OPT_SMALL64-NEXT:    mtlr 0
 ; TLS_MODEL_OPT_SMALL64-NEXT:    blr
 ;
-; TLS_MODEL_OPT_LARGE64-LABEL: Multiple_MIX_USE_LD:
+; TLS_MODEL_OPT_LARGE64-LABEL: Three_LDs:
 ; TLS_MODEL_OPT_LARGE64:       # %bb.0: # %entry
 ; TLS_MODEL_OPT_LARGE64-NEXT:    mflr 0
 ; TLS_MODEL_OPT_LARGE64-NEXT:    stdu 1, -48(1)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    and 6, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 3, L..C1 at u(2)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    std 0, 64(1)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 3, L..C1 at l(3)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    bla .__tls_get_mod[PR]
 ; TLS_MODEL_OPT_LARGE64-NEXT:    cmpwi 6, -1
-; TLS_MODEL_OPT_LARGE64-NEXT:    bgt 0, L..BB4_2
+; TLS_MODEL_OPT_LARGE64-NEXT:    bgt 0, L..BB2_2
 ; TLS_MODEL_OPT_LARGE64-NEXT:  # %bb.1: # %bb1
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C6 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C6 at l(4)
-; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:    b L..BB4_3
-; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB4_2: # %return
-; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C4 at u(2)
-; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C4 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C2 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 5, L..C4 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C2 at l(4)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 5, L..C4 at l(5)
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 4, 3, 4
+; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 5
+; TLS_MODEL_OPT_LARGE64-NEXT:    add 3, 4, 3
+; TLS_MODEL_OPT_LARGE64-NEXT:    b L..BB2_3
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB2_2: # %return
+; TLS_MODEL_OPT_LARGE64-NEXT:    addis 4, L..C3 at u(2)
+; TLS_MODEL_OPT_LARGE64-NEXT:    ld 4, L..C3 at l(4)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    lwzx 3, 3, 4
-; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB4_3: # %bb1
+; TLS_MODEL_OPT_LARGE64-NEXT:  L..BB2_3: # %return
 ; TLS_MODEL_OPT_LARGE64-NEXT:    addi 1, 1, 48
 ; TLS_MODEL_OPT_LARGE64-NEXT:    ld 0, 16(1)
 ; TLS_MODEL_OPT_LARGE64-NEXT:    mtlr 0
 ; TLS_MODEL_OPT_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: Three_LDs:
+; TLS_MODEL_OPT_LIMIT2_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    mflr 0
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    stdu 1, -48(1)
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    and 6, 3, 4
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    std 0, 64(1)
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    bla .__tls_get_mod[PR]
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    cmpwi 6, -1
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    bgt 0, L..BB2_2
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    ld 4, L..C3(2) # target-flags(ppc-tlsld) @VarTLSLD2
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    ld 5, L..C4(2) # target-flags(ppc-tlsld) @VarTLSLD3
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    lwzx 4, 3, 4
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    lwzx 3, 3, 5
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    add 3, 4, 3
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    b L..BB2_3
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:  L..BB2_2: # %return
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    ld 4, L..C5(2) # target-flags(ppc-tlsld) @VarTLSLD1
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:  L..BB2_3: # %return
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    addi 1, 1, 48
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    ld 0, 16(1)
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    mtlr 0
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: Three_LDs:
+; TLS_MODEL_OPT_LIMIT2_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    mflr 0
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    stdu 1, -48(1)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    and 6, 3, 4
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    addis 3, L..C2 at u(2)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    std 0, 64(1)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    ld 3, L..C2 at l(3)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    bla .__tls_get_mod[PR]
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    cmpwi 6, -1
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    bgt 0, L..BB2_2
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    addis 4, L..C3 at u(2)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    addis 5, L..C4 at u(2)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    ld 4, L..C3 at l(4)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    ld 5, L..C4 at l(5)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    lwzx 4, 3, 4
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    lwzx 3, 3, 5
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    add 3, 4, 3
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    b L..BB2_3
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:  L..BB2_2: # %return
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    addis 4, L..C5 at u(2)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    ld 4, L..C5 at l(4)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    lwzx 3, 3, 4
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:  L..BB2_3: # %return
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    addi 1, 1, 48
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    ld 0, 16(1)
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    mtlr 0
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT3_SMALL64-LABEL: Three_LDs:
+; TLS_MODEL_OPT_LIMIT3_SMALL64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    and 3, 3, 4
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    cmpwi 3, -1
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    bgt 0, L..BB2_2
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    ld 3, L..C1(2) # target-flags(ppc-tprel) @VarTLSLD2
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    ld 4, L..C2(2) # target-flags(ppc-tprel) @VarTLSLD3
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    lwzx 4, 13, 4
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    add 3, 3, 4
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:  L..BB2_2: # %return
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSLD1
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT:    blr
+;
+; TLS_MODEL_OPT_LIMIT3_LARGE64-LABEL: Three_LDs:
+; TLS_MODEL_OPT_LIMIT3_LARGE64:       # %bb.0: # %entry
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    and 3, 3, 4
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    cmpwi 3, -1
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    bgt 0, L..BB2_2
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:  # %bb.1: # %bb1
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    addis 3, L..C1 at u(2)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    addis 4, L..C2 at u(2)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    ld 3, L..C1 at l(3)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    ld 4, L..C2 at l(4)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    lwzx 4, 13, 4
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    add 3, 3, 4
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    blr
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:  L..BB2_2: # %return
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    addis 3, L..C0 at u(2)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    ld 3, L..C0 at l(3)
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    lwzx 3, 13, 3
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT:    blr
 entry:
   %a = icmp slt i32 %P, 0
   %b = icmp slt i32 %Q, 0
   %c = and i1 %a, %b
-  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
+  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
   %load1 = load i32, ptr %tls1, align 4
   br i1 %c, label %bb1, label %return
 
 bb1:
-  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD2)
   %load2 = load i32, ptr %tls2, align 4
-  ret i32 %load2
+  %tls3 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD3)
+  %load3 = load i32, ptr %tls3, align 4
+  %sum = add i32 %load2, %load3
+  ret i32 %sum
 
 return:
   ret i32 %load1
@@ -464,60 +534,94 @@ declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
 
 ; DEFAULT_SMALL64-LABEL: .toc
 ; DEFAULT_SMALL64-LABEL: L..C0:
-; DEFAULT_SMALL64-NEXT: .tc VarTLSIE1[TC],VarTLSIE1[TL]@ie
-; DEFAULT_SMALL64-LABEL: L..C1:
 ; DEFAULT_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; DEFAULT_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; DEFAULT_SMALL64-LABEL: L..C2:
+; DEFAULT_SMALL64-LABEL: L..C1:
 ; DEFAULT_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ld
-; DEFAULT_SMALL64-LABEL: L..C3:
-; DEFAULT_SMALL64-NEXT: .tc VarTLSIE2[TC],VarTLSIE2[UL]@ie
-; DEFAULT_SMALL64-LABEL: L..C4:
+; DEFAULT_SMALL64-LABEL: L..C2:
 ; DEFAULT_SMALL64-NEXT: .tc VarTLSLD2[TC],VarTLSLD2[UL]@ld
+; DEFAULT_SMALL64-LABEL: L..C3:
+; DEFAULT_SMALL64-NEXT: .tc VarTLSLD3[TC],VarTLSLD3[UL]@ld
 
 ; DEFAULT_LARGE64-LABEL: .toc
 ; DEFAULT_LARGE64-LABEL: L..C0:
-; DEFAULT_LARGE64-NEXT: .tc VarTLSIE1[TE],VarTLSIE1[TL]@ie
-; DEFAULT_LARGE64-LABEL: L..C1:
 ; DEFAULT_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; DEFAULT_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; DEFAULT_LARGE64-LABEL: L..C2:
+; DEFAULT_LARGE64-LABEL: L..C1:
 ; DEFAULT_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ld
-; DEFAULT_LARGE64-LABEL: L..C3:
-; DEFAULT_LARGE64-NEXT: .tc VarTLSIE2[TE],VarTLSIE2[UL]@ie
-; DEFAULT_LARGE64-LABEL: L..C4:
+; DEFAULT_LARGE64-LABEL: L..C2:
 ; DEFAULT_LARGE64-NEXT: .tc VarTLSLD2[TE],VarTLSLD2[UL]@ld
+; DEFAULT_LARGE64-LABEL: L..C3:
+; DEFAULT_LARGE64-NEXT: .tc VarTLSLD3[TE],VarTLSLD3[UL]@ld
 
 ; TLS_MODEL_OPT_SMALL64-LABEL: .toc
 ; TLS_MODEL_OPT_SMALL64-LABEL: L..C0:
-; TLS_MODEL_OPT_SMALL64-NEXT: .tc VarTLSIE1[TC],VarTLSIE1[TL]@ie
-; TLS_MODEL_OPT_SMALL64-LABEL: L..C1:
 ; TLS_MODEL_OPT_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ie
-; TLS_MODEL_OPT_SMALL64-LABEL: L..C2:
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C1:
 ; TLS_MODEL_OPT_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; TLS_MODEL_OPT_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; TLS_MODEL_OPT_SMALL64-LABEL: L..C3:
-; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSIE2[TC],VarTLSIE2[UL]@ld
-; TLS_MODEL_OPT_SMALL64-LABEL: L..C4:
-; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSIE1[TC],VarTLSIE1[TL]@ld
-; TLS_MODEL_OPT_SMALL64-LABEL: L..C5:
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C2:
 ; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSLD2[TC],VarTLSLD2[UL]@ld
-; TLS_MODEL_OPT_SMALL64-LABEL: L..C6:
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C3:
 ; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSLD1[TC],VarTLSLD1[TL]@ld
+; TLS_MODEL_OPT_SMALL64-LABEL: L..C4:
+; TLS_MODEL_OPT_SMALL64-NEXT: .tc .VarTLSLD3[TC],VarTLSLD3[UL]@ld
 
 ; TLS_MODEL_OPT_LARGE64-LABEL: .toc
 ; TLS_MODEL_OPT_LARGE64-LABEL: L..C0:
-; TLS_MODEL_OPT_LARGE64-NEXT: .tc VarTLSIE1[TE],VarTLSIE1[TL]@ie
-; TLS_MODEL_OPT_LARGE64-LABEL: L..C1:
 ; TLS_MODEL_OPT_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ie
-; TLS_MODEL_OPT_LARGE64-LABEL: L..C2:
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C1:
 ; TLS_MODEL_OPT_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
 ; TLS_MODEL_OPT_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
-; TLS_MODEL_OPT_LARGE64-LABEL: L..C3:
-; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSIE2[TE],VarTLSIE2[UL]@ld
-; TLS_MODEL_OPT_LARGE64-LABEL: L..C4:
-; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSIE1[TE],VarTLSIE1[TL]@ld
-; TLS_MODEL_OPT_LARGE64-LABEL: L..C5:
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C2:
 ; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSLD2[TE],VarTLSLD2[UL]@ld
-; TLS_MODEL_OPT_LARGE64-LABEL: L..C6:
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C3:
 ; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSLD1[TE],VarTLSLD1[TL]@ld
+; TLS_MODEL_OPT_LARGE64-LABEL: L..C4:
+; TLS_MODEL_OPT_LARGE64-NEXT: .tc .VarTLSLD3[TE],VarTLSLD3[UL]@ld
+
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: .toc
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: L..C0:
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ie
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: L..C1:
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT: .tc VarTLSLD2[TC],VarTLSLD2[UL]@ie
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: L..C2:
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: L..C3:
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT: .tc .VarTLSLD2[TC],VarTLSLD2[UL]@ld
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: L..C4:
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT: .tc .VarTLSLD3[TC],VarTLSLD3[UL]@ld
+; TLS_MODEL_OPT_LIMIT2_SMALL64-LABEL: L..C5:
+; TLS_MODEL_OPT_LIMIT2_SMALL64-NEXT: .tc .VarTLSLD1[TC],VarTLSLD1[TL]@ld
+
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: .toc
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: L..C0:
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ie
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: L..C1:
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT: .tc VarTLSLD2[TE],VarTLSLD2[UL]@ie
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: L..C2:
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: L..C3:
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT: .tc .VarTLSLD2[TE],VarTLSLD2[UL]@ld
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: L..C4:
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT: .tc .VarTLSLD3[TE],VarTLSLD3[UL]@ld
+; TLS_MODEL_OPT_LIMIT2_LARGE64-LABEL: L..C5:
+; TLS_MODEL_OPT_LIMIT2_LARGE64-NEXT: .tc .VarTLSLD1[TE],VarTLSLD1[TL]@ld
+
+; TLS_MODEL_OPT_LIMIT3_SMALL64-LABEL: .toc
+; TLS_MODEL_OPT_LIMIT3_SMALL64-LABEL: L..C0:
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT: .tc VarTLSLD1[TC],VarTLSLD1[TL]@ie
+; TLS_MODEL_OPT_LIMIT3_SMALL64-LABEL: L..C1:
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT: .tc VarTLSLD2[TC],VarTLSLD2[UL]@ie
+; TLS_MODEL_OPT_LIMIT3_SMALL64-LABEL: L..C2:
+; TLS_MODEL_OPT_LIMIT3_SMALL64-NEXT: .tc VarTLSLD3[TC],VarTLSLD3[UL]@ie
+
+; TLS_MODEL_OPT_LIMIT3_LARGE64-LABEL: .toc
+; TLS_MODEL_OPT_LIMIT3_LARGE64-LABEL: L..C0:
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ie
+; TLS_MODEL_OPT_LIMIT3_LARGE64-LABEL: L..C1:
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT: .tc VarTLSLD2[TE],VarTLSLD2[UL]@ie
+; TLS_MODEL_OPT_LIMIT3_LARGE64-LABEL: L..C2:
+; TLS_MODEL_OPT_LIMIT3_LARGE64-NEXT: .tc VarTLSLD3[TE],VarTLSLD3[UL]@ie

>From 305d36f69c674dae0deda6e1fe748184aa4a1556 Mon Sep 17 00:00:00 2001
From: Ting Wang <Ting.Wang.SH at ibm.com>
Date: Tue, 23 Apr 2024 01:37:49 -0400
Subject: [PATCH 10/10] (1) Add test case to check aix-shared-lib-tls-model-opt
 and aix-small-local-dynamic-tls interactions. (2) Since TM.getTLSModel()
 result may need further check once this is enabled, update GetSymbolRef()
 logic. (3) Removed "heuristic" from comments.

---
 clang/include/clang/Driver/Options.td         |  5 +-
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     |  8 +-
 llvm/lib/Target/PowerPC/PPCMCInstLower.cpp    | 11 ++-
 ...b-tls-model-opt-small-local-dynamic-tls.ll | 74 +++++++++++++++++++
 4 files changed, 89 insertions(+), 9 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt-small-local-dynamic-tls.ll

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 92a2f18a33e8d..1429528975853 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5079,9 +5079,8 @@ def maix_small_local_dynamic_tls : Flag<["-"], "maix-small-local-dynamic-tls">,
            "This access sequence is not used for variables larger than 32KB.">;
 def maix_shared_lib_tls_model_opt : Flag<["-"], "maix-shared-lib-tls-model-opt">,
   Group<m_ppc_Features_Group>,
-  HelpText<"For shared library loaded with the main program, use heuristics to "
-           "change local-dynamic access(es) to initial-exec access(es) at the "
-           "function level (AIX 64-bit only).">;
+  HelpText<"For shared library loaded with the main program, change local-dynamic access(es) "
+           "to initial-exec access(es) at the function level (AIX 64-bit only).">;
 def maix_struct_return : Flag<["-"], "maix-struct-return">,
   Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Return all structs in memory (PPC32 only)">,
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index eaf2e8685de8c..ac48dc5af9d5b 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -878,8 +878,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
       if (Model == TLSModel::InitialExec)
         return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
-      // On AIX, TLS model heuristics may have turned local-dynamic accesses
-      // into initial-exec accesses.
+      // On AIX, TLS model opt may have turned local-dynamic accesses into
+      // initial-exec accesses.
       PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
       if (Model == TLSModel::LocalDynamic &&
           FuncInfo->isAIXFuncUseTLSIEForLD()) {
@@ -2959,8 +2959,8 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
     // Setup the csect for the current TC entry. If the variant kind is
     // VK_PPC_AIX_TLSGDM the entry represents the region handle, we create a
     // new symbol to prefix the name with a dot.
-    // If TLS model heuristic is turned on, create a new symbol to prefix the
-    // name with a dot.
+    // If TLS model opt is turned on, create a new symbol to prefix the name
+    // with a dot.
     if (I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
         (Subtarget->hasAIXShLibTLSModelOpt() &&
          I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD)) {
diff --git a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
index c05bb37e58bf6..31a2614823587 100644
--- a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
@@ -13,6 +13,7 @@
 
 #include "MCTargetDesc/PPCMCExpr.h"
 #include "PPC.h"
+#include "PPCMachineFunctionInfo.h"
 #include "PPCSubtarget.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
@@ -81,6 +82,8 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
   }
 
   const TargetMachine &TM = Printer.TM;
+  const MachineInstr *MI = MO.getParent();
+  const MachineFunction *MF = MI->getMF();
 
   if (MO.getTargetFlags() == PPCII::MO_PLT)
     RefKind = MCSymbolRefExpr::VK_PLT;
@@ -100,18 +103,22 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
            MO.getTargetFlags() == PPCII::MO_TLSLD_FLAG) {
     assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");
     TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());
+    const PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
     // For the local-[exec|dynamic] TLS model, we may generate the offset from
     // the TLS base as an immediate operand (instead of using a TOC entry). Set
     // the relocation type in case the result is used for purposes other than a
     // TOC reference. In TOC reference cases, this result is discarded.
     if (Model == TLSModel::LocalExec)
       RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE;
+    else if (Model == TLSModel::LocalDynamic &&
+             FuncInfo->isAIXFuncUseTLSIEForLD())
+      // On AIX, TLS model opt may have turned local-dynamic accesses into
+      // initial-exec accesses.
+      RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSIE;
     else if (Model == TLSModel::LocalDynamic)
       RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLD;
   }
 
-  const MachineInstr *MI = MO.getParent();
-  const MachineFunction *MF = MI->getMF();
   const Module *M = MF->getFunction().getParent();
   const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>());
 
diff --git a/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt-small-local-dynamic-tls.ll b/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt-small-local-dynamic-tls.ll
new file mode 100644
index 0000000000000..cfb652ceeb8a6
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-shared-lib-tls-model-opt-small-local-dynamic-tls.ll
@@ -0,0 +1,74 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-lib-tls-model-opt --code-model=large < %s | FileCheck %s --check-prefixes=OPT
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-small-local-dynamic-tls --code-model=large < %s | FileCheck %s --check-prefixes=SMALL
+; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:      -mattr=+aix-shared-lib-tls-model-opt -mattr=+aix-small-local-dynamic-tls \
+; RUN:      --code-model=large < %s | FileCheck %s --check-prefixes=BOTH
+
+ at VarTLSLD1 = internal thread_local(localdynamic) global i32 42, align 4
+
+define i32 @Single_LD(i32 %P, i32 %Q) {
+; OPT-LABEL: Single_LD:
+; OPT:       # %bb.0: # %entry
+; OPT-NEXT:    and 4, 3, 4
+; OPT-NEXT:    addis 3, L..C0 at u(2)
+; OPT-NEXT:    ld 3, L..C0 at l(3)
+; OPT-NEXT:    cmpwi 4, -1
+; OPT-NEXT:    lwzx 3, 13, 3
+; OPT-NEXT:    blr
+;
+; SMALL-LABEL: Single_LD:
+; SMALL:       # %bb.0: # %entry
+; SMALL-NEXT:    mflr 0
+; SMALL-NEXT:    stdu 1, -48(1)
+; SMALL-NEXT:    and 6, 3, 4
+; SMALL-NEXT:    addis 3, L..C0 at u(2)
+; SMALL-NEXT:    std 0, 64(1)
+; SMALL-NEXT:    ld 3, L..C0 at l(3)
+; SMALL-NEXT:    bla .__tls_get_mod[PR]
+; SMALL-NEXT:    cmpwi 6, -1
+; SMALL-NEXT:    lwz 3, VarTLSLD1[TL]@ld(3)
+; SMALL-NEXT:    addi 1, 1, 48
+; SMALL-NEXT:    ld 0, 16(1)
+; SMALL-NEXT:    mtlr 0
+; SMALL-NEXT:    blr
+;
+; BOTH-LABEL: Single_LD:
+; BOTH:       # %bb.0: # %entry
+; BOTH-NEXT:    and 4, 3, 4
+; BOTH-NEXT:    addis 3, L..C0 at u(2)
+; BOTH-NEXT:    ld 3, L..C0 at l(3)
+; BOTH-NEXT:    cmpwi 4, -1
+; BOTH-NEXT:    lwzx 3, 13, 3
+; BOTH-NEXT:    blr
+entry:
+  %a = icmp slt i32 %P, 0
+  %b = icmp slt i32 %Q, 0
+  %c = and i1 %a, %b
+  %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %load1 = load i32, ptr %tls1, align 4
+  br i1 %c, label %bb1, label %return
+
+bb1:
+  %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
+  %load2 = load i32, ptr %tls2, align 4
+  ret i32 %load2
+
+return:
+  ret i32 %load1
+}
+
+; OPT-LABEL: .toc
+; OPT-LABEL: L..C0:
+; OPT-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ie
+
+; SMALL-LABEL: .toc
+; SMALL-LABEL: L..C0:
+; SMALL-NEXT: .tc _Renamed..5f24__TLSML[TC],_Renamed..5f24__TLSML[TC]@ml
+; SMALL-NEXT: .rename _Renamed..5f24__TLSML[TC],"_$TLSML"
+
+; BOTH-LABEL: .toc
+; BOTH-LABEL: L..C0:
+; BOTH-NEXT: .tc VarTLSLD1[TE],VarTLSLD1[TL]@ie



More information about the cfe-commits mailing list