<div dir="ltr">FYI this might have caused <a href="http://lab.llvm.org:8011/builders/sanitizer-ppc64-linux1/builds/4667/steps/run%20asan%20tests/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-ppc64-linux1/builds/4667/steps/run%20asan%20tests/logs/stdio</a></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Feb 3, 2015 at 8:16 AM, Bill Schmidt <span dir="ltr"><<a href="mailto:wschmidt@linux.vnet.ibm.com" target="_blank">wschmidt@linux.vnet.ibm.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: wschmidt<br>
Date: Tue Feb  3 10:16:01 2015<br>
New Revision: 227976<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=227976&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=227976&view=rev</a><br>
Log:<br>
[PowerPC] Yet another approach to __tls_get_addr<br>
<br>
This patch is a third attempt to properly handle the local-dynamic and<br>
global-dynamic TLS models.<br>
<br>
In my original implementation, calls to __tls_get_addr were hidden<br>
from view until the asm-printer phase, at which point the underlying<br>
branch-and-link instruction was created with proper relocations.  This<br>
mostly worked well, but I used some repellent techniques to ensure<br>
that the TLS_GET_ADDR nodes at the SD and MI levels correctly received<br>
input from GPR3 and produced output into GPR3.  This proved to work<br>
badly in the presence of multiple TLS variable accesses, with the<br>
copies to and from GPR3 being scheduled incorrectly and generally<br>
creating havoc.<br>
<br>
In r221703, I addressed that problem by representing the calls to<br>
__tls_get_addr as true calls during instruction lowering.  This had<br>
the advantage of removing all of the bad hacks and relying on the<br>
existing call machinery to properly glue the copies in place. It<br>
looked like this was going to be the right way to go.<br>
<br>
However, as a side effect of the recent discovery of problems with<br>
linker optimizations for TLS, we discovered cases of suboptimal code<br>
generation with this strategy.  The problem comes when tls_get_addr is<br>
called for the same address, and there is a resulting CSE<br>
opportunity.  It turns out that in such cases MachineCSE will common<br>
the addis/addi instructions that set up the input value to<br>
tls_get_addr, but will not common the calls themselves.  MachineCSE<br>
does not have any machinery to common idempotent calls.  This is<br>
perfectly sensible, since presumably this would be done at the IR<br>
level, and introducing calls in the back end isn't commonplace.  In<br>
any case, we end up with two calls to __tls_get_addr when one would<br>
suffice, and that isn't good.<br>
<br>
I presumed that the original design would have allowed commoning of<br>
the machine-specific nodes that hid the __tls_get_addr calls, so as<br>
suggested by Ulrich Weigand, I went back to that design and cleaned it<br>
up so that the copies were properly held together by glue<br>
nodes.  However, it turned out that this didn't work either...the<br>
presence of copies to physical registers kept the machine-specific<br>
nodes from being commoned also.<br>
<br>
All of which leads to the design presented here.  This is a return to<br>
the original design, except that no attempt is made to introduce<br>
copies to and from GPR3 during instruction lowering.  Virtual registers<br>
are used until prior to register allocation.  At that point, a special<br>
pass is run that identifies the machine-specific nodes that hide the<br>
tls_get_addr calls and introduces the copies to and from GPR3 around<br>
them.  The register allocator then coalesces these copies away.  With<br>
this design, MachineCSE succeeds in commoning tls_get_addr calls where<br>
possible, and we get nice optimal code generation (better than GCC at<br>
the moment, which does not common these calls).<br>
<br>
One additional problem must be dealt with:  After introducing the<br>
mentions of the physical register GPR3, the aggressive anti-dependence<br>
breaker sees opportunities to improve scheduling by selecting a<br>
different register instead.  Flags must be used on the instruction<br>
descriptions to tell the anti-dependence breaker to keep its hands in<br>
its pockets.<br>
<br>
One thing missing from the original design was recording a definition<br>
of the link register on the GET_TLS_ADDR nodes.  Doing this was found<br>
to be insufficient to force a stack frame to be created, which led to<br>
looping behavior because two different LR values were stored at the<br>
same address.  This appears to have been an oversight in<br>
PPCFrameLowering::determineFrameLayout(), which is repaired here.<br>
<br>
Because MustSaveLR() returns true for calls to builtin_return_address,<br>
this changed the expected behavior of<br>
test/CodeGen/PowerPC/retaddr2.ll, which now stacks a frame but<br>
formerly did not.  I've fixed the test case to reflect this.<br>
<br>
There are existing TLS tests to catch regressions; the checks in<br>
test/CodeGen/PowerPC/tls-store2.ll proved to be too restrictive in the<br>
face of instruction scheduling with these changes, so I fixed that<br>
up.<br>
<br>
I've added a new test case based on the PrettyStackTrace module that<br>
demonstrated the original problem. This checks that we get correct<br>
code generation and that CSE of the calls to __get_tls_addr has taken<br>
place.<br>
<br>
Added:<br>
    llvm/trunk/lib/Target/PowerPC/PPCTLSDynamicCall.cpp<br>
    llvm/trunk/test/CodeGen/PowerPC/tls-cse.ll<br>
Modified:<br>
    llvm/trunk/lib/Target/PowerPC/CMakeLists.txt<br>
    llvm/trunk/lib/Target/PowerPC/PPC.h<br>
    llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp<br>
    llvm/trunk/lib/Target/PowerPC/PPCFrameLowering.cpp<br>
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp<br>
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h<br>
    llvm/trunk/lib/Target/PowerPC/PPCInstr64Bit.td<br>
    llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.td<br>
    llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp<br>
    llvm/trunk/lib/Target/PowerPC/PPCTargetMachine.cpp<br>
    llvm/trunk/test/CodeGen/PowerPC/retaddr2.ll<br>
    llvm/trunk/test/CodeGen/PowerPC/tls-store2.ll<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/CMakeLists.txt?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/CMakeLists.txt?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/CMakeLists.txt Tue Feb  3 10:16:01 2015<br>
@@ -31,6 +31,7 @@ add_llvm_target(PowerPCCodeGen<br>
   PPCTargetObjectFile.cpp<br>
   PPCTargetTransformInfo.cpp<br>
   PPCSelectionDAGInfo.cpp<br>
+  PPCTLSDynamicCall.cpp<br>
   PPCVSXCopy.cpp<br>
   PPCVSXFMAMutate.cpp<br>
   )<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPC.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPC.h?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPC.h?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPC.h (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPC.h Tue Feb  3 10:16:01 2015<br>
@@ -39,6 +39,7 @@ namespace llvm {<br>
   FunctionPass *createPPCVSXFMAMutatePass();<br>
   FunctionPass *createPPCBranchSelectionPass();<br>
   FunctionPass *createPPCISelDag(PPCTargetMachine &TM);<br>
+  FunctionPass *createPPCTLSDynamicCallPass();<br>
   void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,<br>
                                     AsmPrinter &AP, bool isDarwin);<br>
<br>
@@ -89,12 +90,7 @@ namespace llvm {<br>
     MO_TOC_LO    = 7 << 4,<br>
<br>
     // Symbol for VK_PPC_TLS fixup attached to an ADD instruction<br>
-    MO_TLS       = 8 << 4,<br>
-<br>
-    // Symbols for VK_PPC_TLSGD and VK_PPC_TLSLD in __tls_get_addr<br>
-    // call sequences.<br>
-    MO_TLSLD     = 9 << 4,<br>
-    MO_TLSGD     = 10 << 4<br>
+    MO_TLS       = 8 << 4<br>
   };<br>
   } // end namespace PPCII<br>
<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp Tue Feb  3 10:16:01 2015<br>
@@ -101,6 +101,7 @@ namespace {<br>
                        const MachineInstr &MI);<br>
     void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,<br>
                          const MachineInstr &MI);<br>
+    void EmitTlsCall(const MachineInstr *MI, MCSymbolRefExpr::VariantKind VK);<br>
   };<br>
<br>
   /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux<br>
@@ -404,6 +405,39 @@ void PPCAsmPrinter::LowerPATCHPOINT(MCSt<br>
     EmitToStreamer(OutStreamer, MCInstBuilder(PPC::NOP));<br>
 }<br>
<br>
+/// EmitTlsCall -- Given a GETtls[ld]ADDR[32] instruction, print a<br>
+/// call to __tls_get_addr to the current output stream.<br>
+void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,<br>
+                                MCSymbolRefExpr::VariantKind VK) {<br>
+  StringRef Name = "__tls_get_addr";<br>
+  MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);<br>
+  MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;<br>
+<br>
+  assert(MI->getOperand(0).isReg() &&<br>
+         ((Subtarget.isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||<br>
+          (!Subtarget.isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&<br>
+         "GETtls[ld]ADDR[32] must define GPR3");<br>
+  assert(MI->getOperand(1).isReg() &&<br>
+         ((Subtarget.isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||<br>
+          (!Subtarget.isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&<br>
+         "GETtls[ld]ADDR[32] must read GPR3");<br>
+<br>
+  if (!Subtarget.isPPC64() && !Subtarget.isDarwin() &&<br>
+      TM.getRelocationModel() == Reloc::PIC_)<br>
+    Kind = MCSymbolRefExpr::VK_PLT;<br>
+  const MCSymbolRefExpr *TlsRef =<br>
+    MCSymbolRefExpr::Create(TlsGetAddr, Kind, OutContext);<br>
+  const MachineOperand &MO = MI->getOperand(2);<br>
+  const GlobalValue *GValue = MO.getGlobal();<br>
+  MCSymbol *MOSymbol = getSymbol(GValue);<br>
+  const MCExpr *SymVar = MCSymbolRefExpr::Create(MOSymbol, VK, OutContext);<br>
+  EmitToStreamer(OutStreamer,<br>
+                 MCInstBuilder(Subtarget.isPPC64() ?<br>
+                               PPC::BL8_NOP_TLS : PPC::BL_TLS)<br>
+                 .addExpr(TlsRef)<br>
+                 .addExpr(SymVar));<br>
+}<br>
+<br>
 /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to<br>
 /// the current output stream.<br>
 ///<br>
@@ -807,6 +841,15 @@ void PPCAsmPrinter::EmitInstruction(cons<br>
                    .addExpr(SymGotTlsGD));<br>
     return;<br>
   }<br>
+  case PPC::GETtlsADDR:<br>
+    // Transform: %X3 = GETtlsADDR %X3, <ga:@sym><br>
+    // Into: BL8_NOP_TLS __tls_get_addr(sym@tlsgd)<br>
+  case PPC::GETtlsADDR32: {<br>
+    // Transform: %R3 = GETtlsADDR32 %R3, <ga:@sym><br>
+    // Into: BL_TLS __tls_get_addr(sym@tlsgd)@PLT<br>
+    EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSGD);<br>
+    return;<br>
+  }<br>
   case PPC::ADDIStlsldHA: {<br>
     // Transform: %Xd = ADDIStlsldHA %X2, <ga:@sym><br>
     // Into:      %Xd = ADDIS8 %X2, sym@got@tlsld@ha<br>
@@ -844,6 +887,15 @@ void PPCAsmPrinter::EmitInstruction(cons<br>
                    .addExpr(SymGotTlsLD));<br>
     return;<br>
   }<br>
+  case PPC::GETtlsldADDR:<br>
+    // Transform: %X3 = GETtlsldADDR %X3, <ga:@sym><br>
+    // Into: BL8_NOP_TLS __tls_get_addr(sym@tlsld)<br>
+  case PPC::GETtlsldADDR32: {<br>
+    // Transform: %R3 = GETtlsldADDR32 %R3, <ga:@sym><br>
+    // Into: BL_TLS __tls_get_addr(sym@tlsld)@PLT<br>
+    EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSLD);<br>
+    return;<br>
+  }<br>
   case PPC::ADDISdtprelHA:<br>
     // Transform: %Xd = ADDISdtprelHA %X3, <ga:@sym><br>
     // Into:      %Xd = ADDIS8 %X3, sym@dtprel@ha<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPCFrameLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCFrameLowering.cpp?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCFrameLowering.cpp?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCFrameLowering.cpp (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCFrameLowering.cpp Tue Feb  3 10:16:01 2015<br>
@@ -355,6 +355,20 @@ static bool hasNonRISpills(const Machine<br>
   return FuncInfo->hasNonRISpills();<br>
 }<br>
<br>
+/// MustSaveLR - Return true if this function requires that we save the LR<br>
+/// register onto the stack in the prolog and restore it in the epilog of the<br>
+/// function.<br>
+static bool MustSaveLR(const MachineFunction &MF, unsigned LR) {<br>
+  const PPCFunctionInfo *MFI = MF.getInfo<PPCFunctionInfo>();<br>
+<br>
+  // We need a save/restore of LR if there is any def of LR (which is<br>
+  // defined by calls, including the PIC setup sequence), or if there is<br>
+  // some use of the LR stack slot (e.g. for builtin_return_address).<br>
+  // (LR comes in 32 and 64 bit versions.)<br>
+  MachineRegisterInfo::def_iterator RI = MF.getRegInfo().def_begin(LR);<br>
+  return RI !=MF.getRegInfo().def_end() || MFI->isLRStoreRequired();<br>
+}<br>
+<br>
 /// determineFrameLayout - Determine the size of the frame and maximum call<br>
 /// frame size.<br>
 unsigned PPCFrameLowering::determineFrameLayout(MachineFunction &MF,<br>
@@ -381,6 +395,7 @@ unsigned PPCFrameLowering::determineFram<br>
   // stackless code if all local vars are reg-allocated.<br>
   bool DisableRedZone = MF.getFunction()->getAttributes().<br>
     hasAttribute(AttributeSet::FunctionIndex, Attribute::NoRedZone);<br>
+  unsigned LR = RegInfo->getRARegister();<br>
   if (!DisableRedZone &&<br>
       (Subtarget.isPPC64() ||                      // 32-bit SVR4, no stack-<br>
        !Subtarget.isSVR4ABI() ||                   //   allocated locals.<br>
@@ -388,6 +403,7 @@ unsigned PPCFrameLowering::determineFram<br>
       FrameSize <= 224 &&                          // Fits in red zone.<br>
       !MFI->hasVarSizedObjects() &&                // No dynamic alloca.<br>
       !MFI->adjustsStack() &&                      // No calls.<br>
+      !MustSaveLR(MF, LR) &&<br>
       !RegInfo->hasBasePointer(MF)) { // No special alignment.<br>
     // No need for frame<br>
     if (UpdateMF)<br>
@@ -1108,20 +1124,6 @@ void PPCFrameLowering::emitEpilogue(Mach<br>
   }<br>
 }<br>
<br>
-/// MustSaveLR - Return true if this function requires that we save the LR<br>
-/// register onto the stack in the prolog and restore it in the epilog of the<br>
-/// function.<br>
-static bool MustSaveLR(const MachineFunction &MF, unsigned LR) {<br>
-  const PPCFunctionInfo *MFI = MF.getInfo<PPCFunctionInfo>();<br>
-<br>
-  // We need a save/restore of LR if there is any def of LR (which is<br>
-  // defined by calls, including the PIC setup sequence), or if there is<br>
-  // some use of the LR stack slot (e.g. for builtin_return_address).<br>
-  // (LR comes in 32 and 64 bit versions.)<br>
-  MachineRegisterInfo::def_iterator RI = MF.getRegInfo().def_begin(LR);<br>
-  return RI !=MF.getRegInfo().def_end() || MFI->isLRStoreRequired();<br>
-}<br>
-<br>
 void<br>
 PPCFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,<br>
                                                    RegScavenger *) const {<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Tue Feb  3 10:16:01 2015<br>
@@ -791,8 +791,6 @@ const char *PPCTargetLowering::getTarget<br>
   case PPCISD::SHL:             return "PPCISD::SHL";<br>
   case PPCISD::CALL:            return "PPCISD::CALL";<br>
   case PPCISD::CALL_NOP:        return "PPCISD::CALL_NOP";<br>
-  case PPCISD::CALL_TLS:        return "PPCISD::CALL_TLS";<br>
-  case PPCISD::CALL_NOP_TLS:    return "PPCISD::CALL_NOP_TLS";<br>
   case PPCISD::MTCTR:           return "PPCISD::MTCTR";<br>
   case PPCISD::BCTRL:           return "PPCISD::BCTRL";<br>
   case PPCISD::BCTRL_LOAD_TOC:  return "PPCISD::BCTRL_LOAD_TOC";<br>
@@ -826,8 +824,10 @@ const char *PPCTargetLowering::getTarget<br>
   case PPCISD::ADD_TLS:         return "PPCISD::ADD_TLS";<br>
   case PPCISD::ADDIS_TLSGD_HA:  return "PPCISD::ADDIS_TLSGD_HA";<br>
   case PPCISD::ADDI_TLSGD_L:    return "PPCISD::ADDI_TLSGD_L";<br>
+  case PPCISD::GET_TLS_ADDR:    return "PPCISD::GET_TLS_ADDR";<br>
   case PPCISD::ADDIS_TLSLD_HA:  return "PPCISD::ADDIS_TLSLD_HA";<br>
   case PPCISD::ADDI_TLSLD_L:    return "PPCISD::ADDI_TLSLD_L";<br>
+  case PPCISD::GET_TLSLD_ADDR:  return "PPCISD::GET_TLSLD_ADDR";<br>
   case PPCISD::ADDIS_DTPREL_HA: return "PPCISD::ADDIS_DTPREL_HA";<br>
   case PPCISD::ADDI_DTPREL_L:   return "PPCISD::ADDI_DTPREL_L";<br>
   case PPCISD::VADD_SPLAT:      return "PPCISD::VADD_SPLAT";<br>
@@ -1686,27 +1686,6 @@ SDValue PPCTargetLowering::LowerBlockAdd<br>
   return LowerLabelRef(TgtBAHi, TgtBALo, isPIC, DAG);<br>
 }<br>
<br>
-// Generate a call to __tls_get_addr for the given GOT entry Op.<br>
-std::pair<SDValue,SDValue><br>
-PPCTargetLowering::lowerTLSCall(SDValue Op, SDLoc dl,<br>
-                                SelectionDAG &DAG) const {<br>
-<br>
-  Type *IntPtrTy = getDataLayout()->getIntPtrType(*DAG.getContext());<br>
-  TargetLowering::ArgListTy Args;<br>
-  TargetLowering::ArgListEntry Entry;<br>
-  Entry.Node = Op;<br>
-  Entry.Ty = IntPtrTy;<br>
-  Args.push_back(Entry);<br>
-<br>
-  TargetLowering::CallLoweringInfo CLI(DAG);<br>
-  CLI.setDebugLoc(dl).setChain(DAG.getEntryNode())<br>
-    .setCallee(CallingConv::C, IntPtrTy,<br>
-               DAG.getTargetExternalSymbol("__tls_get_addr", getPointerTy()),<br>
-               std::move(Args), 0);<br>
-<br>
-  return LowerCallTo(CLI);<br>
-}<br>
-<br>
 SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,<br>
                                               SelectionDAG &DAG) const {<br>
<br>
@@ -1753,8 +1732,7 @@ SDValue PPCTargetLowering::LowerGlobalTL<br>
   }<br>
<br>
   if (Model == TLSModel::GeneralDynamic) {<br>
-    SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,<br>
-                                             PPCII::MO_TLSGD);<br>
+    SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0);<br>
     SDValue GOTPtr;<br>
     if (is64bit) {<br>
       setUsesTOCBasePtr(DAG);<br>
@@ -1767,15 +1745,13 @@ SDValue PPCTargetLowering::LowerGlobalTL<br>
       else<br>
         GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT);<br>
     }<br>
-    SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSGD_L, dl, PtrVT,<br>
-                                   GOTPtr, TGA);<br>
-    std::pair<SDValue, SDValue> CallResult = lowerTLSCall(GOTEntry, dl, DAG);<br>
-    return CallResult.first;<br>
+    SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSGD_L, dl,<br>
+                                   PtrVT, GOTPtr, TGA);<br>
+    return DAG.getNode(PPCISD::GET_TLS_ADDR, dl, PtrVT, GOTEntry, TGA);<br>
   }<br>
<br>
   if (Model == TLSModel::LocalDynamic) {<br>
-    SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,<br>
-                                             PPCII::MO_TLSLD);<br>
+    SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0);<br>
     SDValue GOTPtr;<br>
     if (is64bit) {<br>
       setUsesTOCBasePtr(DAG);<br>
@@ -1790,11 +1766,10 @@ SDValue PPCTargetLowering::LowerGlobalTL<br>
     }<br>
     SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSLD_L, dl, PtrVT,<br>
                                    GOTPtr, TGA);<br>
-    std::pair<SDValue, SDValue> CallResult = lowerTLSCall(GOTEntry, dl, DAG);<br>
-    SDValue TLSAddr = CallResult.first;<br>
-    SDValue Chain = CallResult.second;<br>
-    SDValue DtvOffsetHi = DAG.getNode(PPCISD::ADDIS_DTPREL_HA, dl, PtrVT,<br>
-                                      Chain, TLSAddr, TGA);<br>
+    SDValue TLSAddr = DAG.getNode(PPCISD::GET_TLSLD_ADDR, dl,<br>
+                                  PtrVT, GOTEntry, TGA);<br>
+    SDValue DtvOffsetHi = DAG.getNode(PPCISD::ADDIS_DTPREL_HA, dl,<br>
+                                      PtrVT, TLSAddr, TGA);<br>
     return DAG.getNode(PPCISD::ADDI_DTPREL_L, dl, PtrVT, DtvOffsetHi, TGA);<br>
   }<br>
<br>
@@ -3818,23 +3793,6 @@ unsigned PrepareCall(SelectionDAG &DAG,<br>
   if (Callee.getNode()) {<br>
     Ops.push_back(Chain);<br>
     Ops.push_back(Callee);<br>
-<br>
-    // If this is a call to __tls_get_addr, find the symbol whose address<br>
-    // is to be taken and add it to the list.  This will be used to<br>
-    // generate __tls_get_addr(<sym>@tlsgd) or __tls_get_addr(<sym>@tlsld).<br>
-    // We find the symbol by walking the chain to the CopyFromReg, walking<br>
-    // back from the CopyFromReg to the ADDI_TLSGD_L or ADDI_TLSLD_L, and<br>
-    // pulling the symbol from that node.<br>
-    if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))<br>
-      if (!strcmp(S->getSymbol(), "__tls_get_addr")) {<br>
-        assert(!needIndirectCall && "Indirect call to __tls_get_addr???");<br>
-        SDNode *AddI = Chain.getNode()->getOperand(2).getNode();<br>
-        SDValue TGTAddr = AddI->getOperand(1);<br>
-        assert(TGTAddr.getNode()->getOpcode() == ISD::TargetGlobalTLSAddress &&<br>
-               "Didn't find target global TLS address where we expected one");<br>
-        Ops.push_back(TGTAddr);<br>
-        CallOpc = PPCISD::CALL_TLS;<br>
-      }<br>
   }<br>
   // If this is a tail call add stack pointer delta.<br>
   if (isTailCall)<br>
@@ -3997,12 +3955,9 @@ PPCTargetLowering::FinishCall(CallingCon<br>
       Ops.insert(std::next(Ops.begin()), AddTOC);<br>
     } else if ((CallOpc == PPCISD::CALL) &&<br>
                (!isLocalCall(Callee) ||<br>
-                DAG.getTarget().getRelocationModel() == Reloc::PIC_)) {<br>
+                DAG.getTarget().getRelocationModel() == Reloc::PIC_))<br>
       // Otherwise insert NOP for non-local calls.<br>
       CallOpc = PPCISD::CALL_NOP;<br>
-    } else if (CallOpc == PPCISD::CALL_TLS)<br>
-      // For 64-bit SVR4, TLS calls are always non-local.<br>
-      CallOpc = PPCISD::CALL_NOP_TLS;<br>
   }<br>
<br>
   Chain = DAG.getNode(CallOpc, dl, NodeTys, Ops);<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h Tue Feb  3 10:16:01 2015<br>
@@ -101,10 +101,6 @@ namespace llvm {<br>
       /// SVR4 calls.<br>
       CALL, CALL_NOP,<br>
<br>
-      /// CALL_TLS and CALL_NOP_TLS - Versions of CALL and CALL_NOP used<br>
-      /// to access TLS variables.<br>
-      CALL_TLS, CALL_NOP_TLS,<br>
-<br>
       /// CHAIN,FLAG = MTCTR(VAL, CHAIN[, INFLAG]) - Directly corresponds to a<br>
       /// MTCTR instruction.<br>
       MTCTR,<br>
@@ -228,6 +224,10 @@ namespace llvm {<br>
       /// sym\@got\@tlsgd\@l.<br>
       ADDI_TLSGD_L,<br>
<br>
+      /// G8RC = GET_TLS_ADDR %X3, Symbol - For the general-dynamic TLS<br>
+      /// model, produces a call to __tls_get_addr(sym\@tlsgd).<br>
+      GET_TLS_ADDR,<br>
+<br>
       /// G8RC = ADDIS_TLSLD_HA %X2, Symbol - For the local-dynamic TLS<br>
       /// model, produces an ADDIS8 instruction that adds the GOT base<br>
       /// register to sym\@got\@tlsld\@ha.<br>
@@ -238,11 +238,13 @@ namespace llvm {<br>
       /// sym\@got\@tlsld\@l.<br>
       ADDI_TLSLD_L,<br>
<br>
-      /// G8RC = ADDIS_DTPREL_HA %X3, Symbol, Chain - For the<br>
-      /// local-dynamic TLS model, produces an ADDIS8 instruction<br>
-      /// that adds X3 to sym\@dtprel\@ha. The Chain operand is needed<br>
-      /// to tie this in place following a copy to %X3 from the result<br>
-      /// of a GET_TLSLD_ADDR.<br>
+      /// G8RC = GET_TLSLD_ADDR %X3, Symbol - For the local-dynamic TLS<br>
+      /// model, produces a call to __tls_get_addr(sym\@tlsld).<br>
+      GET_TLSLD_ADDR,<br>
+<br>
+      /// G8RC = ADDIS_DTPREL_HA %X3, Symbol - For the local-dynamic TLS<br>
+      /// model, produces an ADDIS8 instruction that adds X3 to<br>
+      /// sym\@dtprel\@ha.<br>
       ADDIS_DTPREL_HA,<br>
<br>
       /// G8RC = ADDI_DTPREL_L G8RReg, Symbol - For the local-dynamic TLS<br>
@@ -635,8 +637,6 @@ namespace llvm {<br>
     SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;<br>
     SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;<br>
     SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;<br>
-    std::pair<SDValue,SDValue> lowerTLSCall(SDValue Op, SDLoc dl,<br>
-                                            SelectionDAG &DAG) const;<br>
     SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;<br>
     SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;<br>
     SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPCInstr64Bit.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstr64Bit.td?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstr64Bit.td?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCInstr64Bit.td (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCInstr64Bit.td Tue Feb  3 10:16:01 2015<br>
@@ -202,9 +202,6 @@ def : Pat<(PPCcall (i64 texternalsym:$ds<br>
 def : Pat<(PPCcall_nop (i64 texternalsym:$dst)),<br>
           (BL8_NOP texternalsym:$dst)>;<br>
<br>
-def : Pat<(PPCcall_nop_tls texternalsym:$func, tglobaltlsaddr:$sym),<br>
-          (BL8_NOP_TLS texternalsym:$func, tglobaltlsaddr:$sym)>;<br>
-<br>
 // Atomic operations<br>
 let usesCustomInserter = 1 in {<br>
   let Defs = [CR0] in {<br>
@@ -904,6 +901,12 @@ def ADDItlsgdL : Pseudo<(outs g8rc:$rD),<br>
                        [(set i64:$rD,<br>
                          (PPCaddiTlsgdL i64:$reg, tglobaltlsaddr:$disp))]>,<br>
                  isPPC64;<br>
+let hasExtraSrcRegAllocReq = 1, hasExtraDefRegAllocReq = 1, Defs = [LR8] in<br>
+def GETtlsADDR : Pseudo<(outs g8rc:$rD), (ins g8rc:$reg, tlsgd:$sym),<br>
+                        "#GETtlsADDR",<br>
+                        [(set i64:$rD,<br>
+                          (PPCgetTlsAddr i64:$reg, tglobaltlsaddr:$sym))]>,<br>
+                 isPPC64;<br>
 def ADDIStlsldHA: Pseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, s16imm64:$disp),<br>
                          "#ADDIStlsldHA",<br>
                          [(set i64:$rD,<br>
@@ -914,6 +917,12 @@ def ADDItlsldL : Pseudo<(outs g8rc:$rD),<br>
                        [(set i64:$rD,<br>
                          (PPCaddiTlsldL i64:$reg, tglobaltlsaddr:$disp))]>,<br>
                  isPPC64;<br>
+let hasExtraSrcRegAllocReq = 1, hasExtraDefRegAllocReq = 1, Defs = [LR8] in<br>
+def GETtlsldADDR : Pseudo<(outs g8rc:$rD), (ins g8rc:$reg, tlsgd:$sym),<br>
+                          "#GETtlsldADDR",<br>
+                          [(set i64:$rD,<br>
+                            (PPCgetTlsldAddr i64:$reg, tglobaltlsaddr:$sym))]>,<br>
+                   isPPC64;<br>
 def ADDISdtprelHA: Pseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, s16imm64:$disp),<br>
                           "#ADDISdtprelHA",<br>
                           [(set i64:$rD,<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.td?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.td?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.td (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.td Tue Feb  3 10:16:01 2015<br>
@@ -110,10 +110,11 @@ def PPCldGotTprelL : SDNode<"PPCISD::LD_<br>
 def PPCaddTls     : SDNode<"PPCISD::ADD_TLS", SDTIntBinOp, []>;<br>
 def PPCaddisTlsgdHA : SDNode<"PPCISD::ADDIS_TLSGD_HA", SDTIntBinOp>;<br>
 def PPCaddiTlsgdL   : SDNode<"PPCISD::ADDI_TLSGD_L", SDTIntBinOp>;<br>
+def PPCgetTlsAddr   : SDNode<"PPCISD::GET_TLS_ADDR", SDTIntBinOp>;<br>
 def PPCaddisTlsldHA : SDNode<"PPCISD::ADDIS_TLSLD_HA", SDTIntBinOp>;<br>
 def PPCaddiTlsldL   : SDNode<"PPCISD::ADDI_TLSLD_L", SDTIntBinOp>;<br>
-def PPCaddisDtprelHA : SDNode<"PPCISD::ADDIS_DTPREL_HA", SDTIntBinOp,<br>
-                              [SDNPHasChain]>;<br>
+def PPCgetTlsldAddr : SDNode<"PPCISD::GET_TLSLD_ADDR", SDTIntBinOp>;<br>
+def PPCaddisDtprelHA : SDNode<"PPCISD::ADDIS_DTPREL_HA", SDTIntBinOp>;<br>
 def PPCaddiDtprelL   : SDNode<"PPCISD::ADDI_DTPREL_L", SDTIntBinOp>;<br>
<br>
 def PPCvperm    : SDNode<"PPCISD::VPERM", SDT_PPCvperm, []>;<br>
@@ -136,15 +137,9 @@ def SDT_PPCCall   : SDTypeProfile<0, -1,<br>
 def PPCcall  : SDNode<"PPCISD::CALL", SDT_PPCCall,<br>
                       [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,<br>
                        SDNPVariadic]>;<br>
-def PPCcall_tls : SDNode<"PPCISD::CALL_TLS", SDT_PPCCall,<br>
-                         [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,<br>
-                          SDNPVariadic]>;<br>
 def PPCcall_nop  : SDNode<"PPCISD::CALL_NOP", SDT_PPCCall,<br>
                           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,<br>
                            SDNPVariadic]>;<br>
-def PPCcall_nop_tls : SDNode<"PPCISD::CALL_NOP_TLS", SDT_PPCCall,<br>
-                             [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,<br>
-                              SDNPVariadic]>;<br>
 def PPCmtctr      : SDNode<"PPCISD::MTCTR", SDT_PPCCall,<br>
                            [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;<br>
 def PPCbctrl : SDNode<"PPCISD::BCTRL", SDTNone,<br>
@@ -2459,9 +2454,6 @@ def : Pat<(PPCcall (i32 tglobaladdr:$dst<br>
 def : Pat<(PPCcall (i32 texternalsym:$dst)),<br>
           (BL texternalsym:$dst)>;<br>
<br>
-def : Pat<(PPCcall_tls texternalsym:$func, tglobaltlsaddr:$sym),<br>
-          (BL_TLS texternalsym:$func, tglobaltlsaddr:$sym)>;<br>
-<br>
 def : Pat<(PPCtc_return (i32 tglobaladdr:$dst),  imm:$imm),<br>
           (TCRETURNdi tglobaladdr:$dst, imm:$imm)>;<br>
<br>
@@ -2516,10 +2508,21 @@ def ADDItlsgdL32 : Pseudo<(outs gprc:$rD<br>
                          "#ADDItlsgdL32",<br>
                          [(set i32:$rD,<br>
                            (PPCaddiTlsgdL i32:$reg, tglobaltlsaddr:$disp))]>;<br>
+let hasExtraSrcRegAllocReq = 1, hasExtraDefRegAllocReq = 1, Defs = [LR] in<br>
+def GETtlsADDR32 : Pseudo<(outs gprc:$rD), (ins gprc:$reg, tlsgd32:$sym),<br>
+                          "GETtlsADDR32",<br>
+                          [(set i32:$rD,<br>
+                            (PPCgetTlsAddr i32:$reg, tglobaltlsaddr:$sym))]>;<br>
 def ADDItlsldL32 : Pseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, s16imm:$disp),<br>
                           "#ADDItlsldL32",<br>
                           [(set i32:$rD,<br>
                             (PPCaddiTlsldL i32:$reg, tglobaltlsaddr:$disp))]>;<br>
+let hasExtraSrcRegAllocReq = 1, hasExtraDefRegAllocReq = 1, Defs = [LR] in<br>
+def GETtlsldADDR32 : Pseudo<(outs gprc:$rD), (ins gprc:$reg, tlsgd32:$sym),<br>
+                            "GETtlsldADDR32",<br>
+                            [(set i32:$rD,<br>
+                              (PPCgetTlsldAddr i32:$reg,<br>
+                                               tglobaltlsaddr:$sym))]>;<br>
 def ADDIdtprelL32 : Pseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, s16imm:$disp),<br>
                            "#ADDIdtprelL32",<br>
                            [(set i32:$rD,<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCMCInstLower.cpp Tue Feb  3 10:16:01 2015<br>
@@ -137,12 +137,6 @@ static MCOperand GetSymbolRef(const Mach<br>
     case PPCII::MO_TLS:<br>
       RefKind = MCSymbolRefExpr::VK_PPC_TLS;<br>
       break;<br>
-    case PPCII::MO_TLSGD:<br>
-      RefKind = MCSymbolRefExpr::VK_PPC_TLSGD;<br>
-      break;<br>
-    case PPCII::MO_TLSLD:<br>
-      RefKind = MCSymbolRefExpr::VK_PPC_TLSLD;<br>
-      break;<br>
   }<br>
<br>
   if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && !isDarwin)<br>
<br>
Added: llvm/trunk/lib/Target/PowerPC/PPCTLSDynamicCall.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCTLSDynamicCall.cpp?rev=227976&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCTLSDynamicCall.cpp?rev=227976&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCTLSDynamicCall.cpp (added)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCTLSDynamicCall.cpp Tue Feb  3 10:16:01 2015<br>
@@ -0,0 +1,111 @@<br>
+//===---------- PPCTLSDynamicCall.cpp - TLS Dynamic Call Fixup ------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This pass fixes up GETtls[ld]ADDR[32] machine instructions so that<br>
+// they read and write GPR3.  These are really call instructions, so<br>
+// must use the calling convention registers.  This is done in a late<br>
+// pass so that TLS variable accesses can be fully commoned.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "PPCInstrInfo.h"<br>
+#include "PPC.h"<br>
+#include "PPCInstrBuilder.h"<br>
+#include "PPCTargetMachine.h"<br>
+#include "llvm/CodeGen/MachineFunctionPass.h"<br>
+#include "llvm/CodeGen/MachineInstrBuilder.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+#define DEBUG_TYPE "ppc-tls-dynamic-call"<br>
+<br>
+namespace llvm {<br>
+  void initializePPCTLSDynamicCallPass(PassRegistry&);<br>
+}<br>
+<br>
+namespace {<br>
+  // PPCTLSDynamicCall pass - Add copies to and from GPR3 around<br>
+  // GETtls[ld]ADDR[32] machine instructions.  These instructions<br>
+  // are actually call instructions, so the register choice is<br>
+  // constrained.  We delay introducing these copies as late as<br>
+  // possible so that TLS variable accesses can be fully commoned.<br>
+  struct PPCTLSDynamicCall : public MachineFunctionPass {<br>
+    static char ID;<br>
+    PPCTLSDynamicCall() : MachineFunctionPass(ID) {<br>
+      initializePPCTLSDynamicCallPass(*PassRegistry::getPassRegistry());<br>
+    }<br>
+<br>
+    const PPCTargetMachine *TM;<br>
+    const PPCInstrInfo *TII;<br>
+<br>
+protected:<br>
+    bool processBlock(MachineBasicBlock &MBB) {<br>
+      bool Changed = false;<br>
+      bool Is64Bit = TM->getSubtargetImpl()->isPPC64();<br>
+<br>
+      for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();<br>
+           I != IE; ++I) {<br>
+        MachineInstr *MI = I;<br>
+<br>
+        if (MI->getOpcode() != PPC::GETtlsADDR &&<br>
+            MI->getOpcode() != PPC::GETtlsldADDR)<br>
+          continue;<br>
+<br>
+        DEBUG(dbgs() << "TLS Dynamic Call Fixup:\n    " << *MI;);<br>
+<br>
+        unsigned OutReg = MI->getOperand(0).getReg();<br>
+        unsigned InReg  = MI->getOperand(1).getReg();<br>
+        DebugLoc DL = MI->getDebugLoc();<br>
+        unsigned GPR3 = Is64Bit ? PPC::X3 : PPC::R3;<br>
+<br>
+        BuildMI(MBB, I, DL, TII->get(TargetOpcode::COPY), GPR3)<br>
+          .addReg(InReg);<br>
+        MI->getOperand(0).setReg(GPR3);<br>
+        MI->getOperand(1).setReg(GPR3);<br>
+        BuildMI(MBB, ++I, DL, TII->get(TargetOpcode::COPY), OutReg)<br>
+          .addReg(GPR3);<br>
+<br>
+        Changed = true;<br>
+      }<br>
+<br>
+      return Changed;<br>
+    }<br>
+<br>
+public:<br>
+    bool runOnMachineFunction(MachineFunction &MF) override {<br>
+      TM = static_cast<const PPCTargetMachine *>(&MF.getTarget());<br>
+      TII = TM->getSubtargetImpl()->getInstrInfo();<br>
+<br>
+      bool Changed = false;<br>
+<br>
+      for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {<br>
+        MachineBasicBlock &B = *I++;<br>
+        if (processBlock(B))<br>
+          Changed = true;<br>
+      }<br>
+<br>
+      return Changed;<br>
+    }<br>
+<br>
+    void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
+      MachineFunctionPass::getAnalysisUsage(AU);<br>
+    }<br>
+  };<br>
+}<br>
+<br>
+INITIALIZE_PASS_BEGIN(PPCTLSDynamicCall, DEBUG_TYPE,<br>
+                      "PowerPC TLS Dynamic Call Fixup", false, false)<br>
+INITIALIZE_PASS_END(PPCTLSDynamicCall, DEBUG_TYPE,<br>
+                    "PowerPC TLS Dynamic Call Fixup", false, false)<br>
+<br>
+char PPCTLSDynamicCall::ID = 0;<br>
+FunctionPass*<br>
+llvm::createPPCTLSDynamicCallPass() { return new PPCTLSDynamicCall(); }<br>
<br>
Modified: llvm/trunk/lib/Target/PowerPC/PPCTargetMachine.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCTargetMachine.cpp?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCTargetMachine.cpp?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/PowerPC/PPCTargetMachine.cpp (original)<br>
+++ llvm/trunk/lib/Target/PowerPC/PPCTargetMachine.cpp Tue Feb  3 10:16:01 2015<br>
@@ -259,6 +259,7 @@ void PPCPassConfig::addPreRegAlloc() {<br>
   initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry());<br>
   insertPass(VSXFMAMutateEarly ? &RegisterCoalescerID : &MachineSchedulerID,<br>
              &PPCVSXFMAMutateID);<br>
+  addPass(createPPCTLSDynamicCallPass());<br>
 }<br>
<br>
 void PPCPassConfig::addPreSched2() {<br>
<br>
Modified: llvm/trunk/test/CodeGen/PowerPC/retaddr2.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/retaddr2.ll?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/retaddr2.ll?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/PowerPC/retaddr2.ll (original)<br>
+++ llvm/trunk/test/CodeGen/PowerPC/retaddr2.ll Tue Feb  3 10:16:01 2015<br>
@@ -12,8 +12,7 @@ entry:<br>
 ; CHECK-LABEL: @test1<br>
 ; CHECK: mflr 0<br>
 ; CHECK: std 0, 16(1)<br>
-; FIXME: These next two lines don't both need to load the same value.<br>
-; CHECK-DAG: ld 3, 16(1)<br>
+; CHECK-DAG: ld 3, 64(1)<br>
 ; CHECK-DAG: ld 0, 16(1)<br>
 ; CHECK: mtlr 0<br>
 ; CHECK: blr<br>
<br>
Added: llvm/trunk/test/CodeGen/PowerPC/tls-cse.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/tls-cse.ll?rev=227976&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/tls-cse.ll?rev=227976&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/PowerPC/tls-cse.ll (added)<br>
+++ llvm/trunk/test/CodeGen/PowerPC/tls-cse.ll Tue Feb  3 10:16:01 2015<br>
@@ -0,0 +1,52 @@<br>
+; RUN: llc -march=ppc64 -mcpu=pwr7 -O2 -relocation-model=pic < %s | FileCheck %s<br>
+; RUN: llc -march=ppc64 -mcpu=pwr7 -O2 -relocation-model=pic < %s | grep "__tls_get_addr" | count 1<br>
+<br>
+; This test was derived from LLVM's own<br>
+; PrettyStackTraceEntry::~PrettyStackTraceEntry().  It demonstrates an<br>
+; opportunity for CSE of calls to __tls_get_addr().<br>
+<br>
+target datalayout = "e-m:e-i64:64-n32:64"<br>
+target triple = "powerpc64le-unknown-linux-gnu"<br>
+<br>
+%"class.llvm::PrettyStackTraceEntry" = type { i32 (...)**, %"class.llvm::PrettyStackTraceEntry"* }<br>
+<br>
+@_ZTVN4llvm21PrettyStackTraceEntryE = unnamed_addr constant [5 x i8*] [i8* null, i8* null, i8* bitcast (void (%"class.llvm::PrettyStackTraceEntry"*)* @_ZN4llvm21PrettyStackTraceEntryD2Ev to i8*), i8* bitcast (void (%"class.llvm::PrettyStackTraceEntry"*)* @_ZN4llvm21PrettyStackTraceEntryD0Ev to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*)], align 8<br>
+@_ZL20PrettyStackTraceHead = internal thread_local unnamed_addr global %"class.llvm::PrettyStackTraceEntry"* null, align 8<br>
+@.str = private unnamed_addr constant [87 x i8] c"PrettyStackTraceHead == this && \22Pretty stack trace entry destruction is out of order\22\00", align 1<br>
+@.str1 = private unnamed_addr constant [64 x i8] c"/home/wschmidt/llvm/llvm-test2/lib/Support/PrettyStackTrace.cpp\00", align 1<br>
+@__PRETTY_FUNCTION__._ZN4llvm21PrettyStackTraceEntryD2Ev = private unnamed_addr constant [62 x i8] c"virtual llvm::PrettyStackTraceEntry::~PrettyStackTraceEntry()\00", align 1<br>
+<br>
+declare void @_ZN4llvm21PrettyStackTraceEntryD2Ev(%"class.llvm::PrettyStackTraceEntry"* %this) unnamed_addr<br>
+declare void @__cxa_pure_virtual()<br>
+declare void @__assert_fail(i8*, i8*, i32 zeroext, i8*)<br>
+declare void @_ZdlPv(i8*)<br>
+<br>
+define void @_ZN4llvm21PrettyStackTraceEntryD0Ev(%"class.llvm::PrettyStackTraceEntry"* %this) unnamed_addr align 2 {<br>
+entry:<br>
+  %0 = getelementptr inbounds %"class.llvm::PrettyStackTraceEntry"* %this, i64 0, i32 0<br>
+  store i32 (...)** bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN4llvm21PrettyStackTraceEntryE, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 8<br>
+  %1 = load %"class.llvm::PrettyStackTraceEntry"** @_ZL20PrettyStackTraceHead, align 8<br>
+  %cmp.i = icmp eq %"class.llvm::PrettyStackTraceEntry"* %1, %this<br>
+  br i1 %cmp.i, label %_ZN4llvm21PrettyStackTraceEntryD2Ev.exit, label %cond.false.i<br>
+<br>
+cond.false.i:                                     ; preds = %entry<br>
+  tail call void @__assert_fail(i8* getelementptr inbounds ([87 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([64 x i8]* @.str1, i64 0, i64 0), i32 zeroext 119, i8* getelementptr inbounds ([62 x i8]* @__PRETTY_FUNCTION__._ZN4llvm21PrettyStackTraceEntryD2Ev, i64 0, i64 0))<br>
+  unreachable<br>
+<br>
+_ZN4llvm21PrettyStackTraceEntryD2Ev.exit:         ; preds = %entry<br>
+  %NextEntry.i.i = getelementptr inbounds %"class.llvm::PrettyStackTraceEntry"* %this, i64 0, i32 1<br>
+  %2 = bitcast %"class.llvm::PrettyStackTraceEntry"** %NextEntry.i.i to i64*<br>
+  %3 = load i64* %2, align 8<br>
+  store i64 %3, i64* bitcast (%"class.llvm::PrettyStackTraceEntry"** @_ZL20PrettyStackTraceHead to i64*), align 8<br>
+  %4 = bitcast %"class.llvm::PrettyStackTraceEntry"* %this to i8*<br>
+  tail call void @_ZdlPv(i8* %4)<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: _ZN4llvm21PrettyStackTraceEntryD0Ev:<br>
+; CHECK: addis [[REG1:[0-9]+]], 2, _ZL20PrettyStackTraceHead@got@tlsld@ha<br>
+; CHECK: addi 3, [[REG1]], _ZL20PrettyStackTraceHead@got@tlsld@l<br>
+; CHECK: bl __tls_get_addr(_ZL20PrettyStackTraceHead@tlsld)<br>
+; CHECK: addis 3, 3, _ZL20PrettyStackTraceHead@dtprel@ha<br>
+; CHECK: ld {{[0-9]+}}, _ZL20PrettyStackTraceHead@dtprel@l(3)<br>
+; CHECK: std {{[0-9]+}}, _ZL20PrettyStackTraceHead@dtprel@l(3)<br>
<br>
Modified: llvm/trunk/test/CodeGen/PowerPC/tls-store2.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/tls-store2.ll?rev=227976&r1=227975&r2=227976&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/tls-store2.ll?rev=227976&r1=227975&r2=227976&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/PowerPC/tls-store2.ll (original)<br>
+++ llvm/trunk/test/CodeGen/PowerPC/tls-store2.ll Tue Feb  3 10:16:01 2015<br>
@@ -19,13 +19,11 @@ entry:<br>
 }<br>
<br>
 ; CHECK-LABEL: call_once:<br>
-; CHECK: addis 3, 2, __once_callable@got@tlsgd@ha<br>
-; CHECK: addi 3, 3, __once_callable@got@tlsgd@l<br>
+; CHECK: addi 3, {{[0-9]+}}, __once_callable@got@tlsgd@l<br>
 ; CHECK: bl __tls_get_addr(__once_callable@tlsgd)<br>
 ; CHECK-NEXT: nop<br>
 ; CHECK: std {{[0-9]+}}, 0(3)<br>
-; CHECK: addis 3, 2, __once_call@got@tlsgd@ha<br>
-; CHECK: addi 3, 3, __once_call@got@tlsgd@l<br>
+; CHECK: addi 3, {{[0-9]+}}, __once_call@got@tlsgd@l<br>
 ; CHECK: bl __tls_get_addr(__once_call@tlsgd)<br>
 ; CHECK-NEXT: nop<br>
 ; CHECK: std {{[0-9]+}}, 0(3)<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr">Alexey Samsonov<br><a href="mailto:vonosmas@gmail.com" target="_blank">vonosmas@gmail.com</a></div></div>
</div>