OSDN Git Service

Implement "general dynamic", "initial exec" and "local exec" TLS models for
authorLauro Ramos Venancio <lauro.venancio@gmail.com>
Fri, 20 Apr 2007 21:38:10 +0000 (21:38 +0000)
committerLauro Ramos Venancio <lauro.venancio@gmail.com>
Fri, 20 Apr 2007 21:38:10 +0000 (21:38 +0000)
X86 32 bits.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36283 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/llvm/CodeGen/SelectionDAG.h
include/llvm/CodeGen/SelectionDAGNodes.h
include/llvm/Target/TargetAsmInfo.h
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/Target/TargetAsmInfo.cpp
lib/Target/TargetSelectionDAG.td
lib/Target/X86/X86ATTAsmPrinter.cpp
lib/Target/X86/X86AsmPrinter.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
lib/Target/X86/X86InstrInfo.td
utils/TableGen/DAGISelEmitter.cpp

index 253d574..0f17e69 100644 (file)
@@ -398,6 +398,9 @@ public:
   SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1,
                         MVT::ValueType VT2, MVT::ValueType VT3,
                         SDOperand Op1, SDOperand Op2);
+  SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1,
+                        MVT::ValueType VT2, MVT::ValueType VT3,
+                        SDOperand Op1, SDOperand Op2, SDOperand Op3);
   SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1, 
                         MVT::ValueType VT2, MVT::ValueType VT3,
                         const SDOperand *Ops, unsigned NumOps);
index 74f405f..77d607a 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
 #define LLVM_CODEGEN_SELECTIONDAGNODES_H
 
+#include "llvm/GlobalVariable.h"
 #include "llvm/Value.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/GraphTraits.h"
@@ -95,7 +96,8 @@ namespace ISD {
     // Various leaf nodes.
     STRING, BasicBlock, VALUETYPE, CONDCODE, Register,
     Constant, ConstantFP,
-    GlobalAddress, FrameIndex, JumpTable, ConstantPool, ExternalSymbol,
+    GlobalAddress, GlobalTLSAddress, FrameIndex,
+    JumpTable, ConstantPool, ExternalSymbol,
 
     // The address of the GOT
     GLOBAL_OFFSET_TABLE,
@@ -124,6 +126,7 @@ namespace ISD {
     // anything else with this node, and this is valid in the target-specific
     // dag, turning into a GlobalAddress operand.
     TargetGlobalAddress,
+    TargetGlobalTLSAddress,
     TargetFrameIndex,
     TargetJumpTable,
     TargetConstantPool,
@@ -1164,7 +1167,12 @@ protected:
   friend class SelectionDAG;
   GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT::ValueType VT,
                       int o = 0)
-    : SDNode(isTarget ? ISD::TargetGlobalAddress : ISD::GlobalAddress,
+    : SDNode(dyn_cast<GlobalVariable>(GA) &&
+             dyn_cast<GlobalVariable>(GA)->isThreadLocal() ?
+             // Thread Local
+             (isTarget ? ISD::TargetGlobalTLSAddress : ISD::GlobalTLSAddress) :
+             // Non Thread Local
+             (isTarget ? ISD::TargetGlobalAddress : ISD::GlobalAddress),
              getSDVTList(VT)), Offset(o) {
     TheGlobal = const_cast<GlobalValue*>(GA);
   }
@@ -1176,11 +1184,12 @@ public:
   static bool classof(const GlobalAddressSDNode *) { return true; }
   static bool classof(const SDNode *N) {
     return N->getOpcode() == ISD::GlobalAddress ||
-           N->getOpcode() == ISD::TargetGlobalAddress;
+           N->getOpcode() == ISD::TargetGlobalAddress ||
+           N->getOpcode() == ISD::GlobalTLSAddress ||
+           N->getOpcode() == ISD::TargetGlobalTLSAddress;
   }
 };
 
-
 class FrameIndexSDNode : public SDNode {
   int FI;
   virtual void ANCHOR();  // Out-of-line virtual method to give class a home.
index 04f9118..60de430 100644 (file)
@@ -43,7 +43,15 @@ namespace llvm {
     /// target doesn't support a BSS section.
     ///
     const char *BSSSection;               // Default to ".bss".
-    
+
+    /// TLSDataSection - Section directive for Thread Local data.
+    ///
+    const char *TLSDataSection;// Defaults to ".section .tdata,"awT",@progbits".
+
+    /// TLSBSSSection - Section directive for Thread Local uninitialized data.
+    /// Null if this target doesn't support a BSS section.
+    ///
+    const char *TLSBSSSection;// Default to ".section .tbss,"awT",@nobits".
     /// ZeroFillDirective - Directive for emitting a global to the ZeroFill
     /// section on this target.  Null if this target doesn't support zerofill.
     const char *ZeroFillDirective;        // Default is null.
@@ -362,6 +370,12 @@ namespace llvm {
     const char *getBSSSection() const {
       return BSSSection;
     }
+    const char *getTLSDataSection() const {
+      return TLSDataSection;
+    }
+    const char *getTLSBSSSection() const {
+      return TLSBSSSection;
+    }
     const char *getZeroFillDirective() const {
       return ZeroFillDirective;
     }
index c5288c4..42e7e22 100644 (file)
@@ -622,6 +622,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
   case ISD::TargetConstantFP:
   case ISD::TargetConstantPool:
   case ISD::TargetGlobalAddress:
+  case ISD::TargetGlobalTLSAddress:
   case ISD::TargetExternalSymbol:
   case ISD::VALUETYPE:
   case ISD::SRCVALUE:
@@ -653,6 +654,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     assert(0 && "Do not know how to legalize this operator!");
     abort();
   case ISD::GlobalAddress:
+  case ISD::GlobalTLSAddress:
   case ISD::ExternalSymbol:
   case ISD::ConstantPool:
   case ISD::JumpTable: // Nothing to do.
index 7c8a94e..75fbf8a 100644 (file)
@@ -14,6 +14,7 @@
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/Constants.h"
 #include "llvm/GlobalValue.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -296,7 +297,9 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, SDNode *N) {
     ID.AddDouble(cast<ConstantFPSDNode>(N)->getValue());
     break;
   case ISD::TargetGlobalAddress:
-  case ISD::GlobalAddress: {
+  case ISD::GlobalAddress:
+  case ISD::TargetGlobalTLSAddress:
+  case ISD::GlobalTLSAddress: {
     GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
     ID.AddPointer(GA->getGlobal());
     ID.AddInteger(GA->getOffset());
@@ -692,7 +695,12 @@ SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT,
 SDOperand SelectionDAG::getGlobalAddress(const GlobalValue *GV,
                                          MVT::ValueType VT, int Offset,
                                          bool isTargetGA) {
-  unsigned Opc = isTargetGA ? ISD::TargetGlobalAddress : ISD::GlobalAddress;
+  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
+  unsigned Opc;
+  if (GVar && GVar->isThreadLocal())
+    Opc = isTargetGA ? ISD::TargetGlobalTLSAddress : ISD::GlobalTLSAddress;
+  else
+    Opc = isTargetGA ? ISD::TargetGlobalAddress : ISD::GlobalAddress;
   FoldingSetNodeID ID;
   AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0);
   ID.AddPointer(GV);
@@ -2282,6 +2290,14 @@ SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT::ValueType VT1,
   SDOperand Ops[] = { Op1, Op2 };
   return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 3, Ops, 2).Val;
 }
+SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT::ValueType VT1,
+                                    MVT::ValueType VT2, MVT::ValueType VT3,
+                                    SDOperand Op1, SDOperand Op2,
+                                    SDOperand Op3) {
+  const MVT::ValueType *VTs = getNodeValueTypes(VT1, VT2, VT3);
+  SDOperand Ops[] = { Op1, Op2, Op3 };
+  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 3, Ops, 3).Val;
+}
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT::ValueType VT1, 
                                     MVT::ValueType VT2, MVT::ValueType VT3,
                                     const SDOperand *Ops, unsigned NumOps) {
@@ -2702,6 +2718,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
   case ISD::Constant:      return "Constant";
   case ISD::ConstantFP:    return "ConstantFP";
   case ISD::GlobalAddress: return "GlobalAddress";
+  case ISD::GlobalTLSAddress: return "GlobalTLSAddress";
   case ISD::FrameIndex:    return "FrameIndex";
   case ISD::JumpTable:     return "JumpTable";
   case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE";
@@ -2725,6 +2742,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
   case ISD::TargetConstant: return "TargetConstant";
   case ISD::TargetConstantFP:return "TargetConstantFP";
   case ISD::TargetGlobalAddress: return "TargetGlobalAddress";
+  case ISD::TargetGlobalTLSAddress: return "TargetGlobalTLSAddress";
   case ISD::TargetFrameIndex: return "TargetFrameIndex";
   case ISD::TargetJumpTable:  return "TargetJumpTable";
   case ISD::TargetConstantPool:  return "TargetConstantPool";
index cf3f6ee..62c8b90 100644 (file)
@@ -20,6 +20,8 @@ TargetAsmInfo::TargetAsmInfo() :
   TextSection(".text"),
   DataSection(".data"),
   BSSSection(".bss"),
+  TLSDataSection("\t.section .tdata,\"awT\",@progbits"),
+  TLSBSSSection("\t.section .tbss,\"awT\",@nobits"),
   ZeroFillDirective(0),
   AddressSize(4),
   NeedsSet(false),
index 17c0ddd..3d728e9 100644 (file)
@@ -211,6 +211,10 @@ def globaladdr : SDNode<"ISD::GlobalAddress",         SDTPtrLeaf, [],
                         "GlobalAddressSDNode">;
 def tglobaladdr : SDNode<"ISD::TargetGlobalAddress",  SDTPtrLeaf, [],
                          "GlobalAddressSDNode">;
+def globaltlsaddr : SDNode<"ISD::GlobalTLSAddress",         SDTPtrLeaf, [],
+                          "GlobalAddressSDNode">;
+def tglobaltlsaddr : SDNode<"ISD::TargetGlobalTLSAddress",  SDTPtrLeaf, [],
+                           "GlobalAddressSDNode">;
 def constpool   : SDNode<"ISD::ConstantPool",         SDTPtrLeaf, [],
                          "ConstantPoolSDNode">;
 def tconstpool  : SDNode<"ISD::TargetConstantPool",   SDTPtrLeaf, [],
index f80e6e8..f36de92 100755 (executable)
@@ -272,9 +272,13 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
   case MachineOperand::MO_GlobalAddress: {
     bool isCallOp = Modifier && !strcmp(Modifier, "call");
     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
-    if (!isMemOp && !isCallOp) O << '$';
 
     GlobalValue *GV = MO.getGlobal();
+    GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
+    bool isThreadLocal = GVar && GVar->isThreadLocal();
+
+    if (!isMemOp && !isCallOp && !isThreadLocal) O << '$';
+
     std::string Name = Mang->getValueName(GV);
     X86SharedAsmPrinter::decorateName(Name, GV);
     
@@ -328,7 +332,15 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
     else if (Offset < 0)
       O << Offset;
 
-    if (isMemOp) {
+    if (isThreadLocal) {
+      if (TM.getRelocationModel() == Reloc::PIC_)
+        O << "@TLSGD"; // general dynamic TLS model
+      else
+        if (GV->isDeclaration())
+          O << "@INDNTPOFF"; // initial exec TLS model
+        else
+          O << "@NTPOFF"; // local exec TLS model
+    } else if (isMemOp) {
       if (printGOT(TM, Subtarget)) {
         if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
           O << "@GOT";
index bc103d7..76037f1 100644 (file)
@@ -171,7 +171,7 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
         }
       }
       
-      if (!I->hasSection() &&
+      if (!I->hasSection() && !I->isThreadLocal() &&
           (I->hasInternalLinkage() || I->hasWeakLinkage() ||
            I->hasLinkOnceLinkage())) {
         if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
@@ -256,9 +256,13 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
         SwitchToDataSection(SectionName.c_str());
       } else {
         if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
-          SwitchToDataSection(TAI->getBSSSection(), I);
+          SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSBSSSection() :
+                              TAI->getBSSSection(), I);
         else if (!I->isConstant())
-          SwitchToDataSection(TAI->getDataSection(), I);
+          SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSDataSection() :
+                              TAI->getDataSection(), I);
+        else if (I->isThreadLocal())
+          SwitchToDataSection(TAI->getTLSDataSection());
         else {
           // Read-only data.
           bool HasReloc = C->ContainsRelocations();
index 747a15b..b37e47c 100644 (file)
@@ -20,6 +20,7 @@
 #include "llvm/CallingConv.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Function.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/ADT/VectorExtras.h"
@@ -200,6 +201,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
   setOperationAction(ISD::ConstantPool    , MVT::i32  , Custom);
   setOperationAction(ISD::JumpTable       , MVT::i32  , Custom);
   setOperationAction(ISD::GlobalAddress   , MVT::i32  , Custom);
+  setOperationAction(ISD::GlobalTLSAddress, MVT::i32  , Custom);
   setOperationAction(ISD::ExternalSymbol  , MVT::i32  , Custom);
   if (Subtarget->is64Bit()) {
     setOperationAction(ISD::ConstantPool  , MVT::i64  , Custom);
@@ -2943,6 +2945,76 @@ X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
   return Result;
 }
 
+// Lower ISD::GlobalTLSAddress using the "general dynamic" model
+static SDOperand
+LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
+                              const MVT::ValueType PtrVT) {
+  SDOperand InFlag;
+  SDOperand Chain = DAG.getCopyToReg(DAG.getEntryNode(), X86::EBX,
+                                     DAG.getNode(X86ISD::GlobalBaseReg,
+                                                 PtrVT), InFlag);
+  InFlag = Chain.getValue(1);
+
+  // emit leal symbol@TLSGD(,%ebx,1), %eax
+  SDVTList NodeTys = DAG.getVTList(PtrVT, MVT::Other, MVT::Flag);
+  SDOperand TGA = DAG.getTargetGlobalAddress(GA->getGlobal(),
+                                             GA->getValueType(0),
+                                             GA->getOffset());
+  SDOperand Ops[] = { Chain,  TGA, InFlag };
+  SDOperand Result = DAG.getNode(X86ISD::TLSADDR, NodeTys, Ops, 3);
+  InFlag = Result.getValue(2);
+  Chain = Result.getValue(1);
+
+  // call ___tls_get_addr. This function receives its argument in
+  // the register EAX.
+  Chain = DAG.getCopyToReg(Chain, X86::EAX, Result, InFlag);
+  InFlag = Chain.getValue(1);
+
+  NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+  SDOperand Ops1[] = { Chain,
+                      DAG.getTargetExternalSymbol("___tls_get_addr",
+                                                  PtrVT),
+                      DAG.getRegister(X86::EAX, PtrVT),
+                      DAG.getRegister(X86::EBX, PtrVT),
+                      InFlag };
+  Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops1, 5);
+  InFlag = Chain.getValue(1);
+
+  return DAG.getCopyFromReg(Chain, X86::EAX, PtrVT, InFlag);
+}
+
+// Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or
+// "local exec" model.
+static SDOperand
+LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
+                         const MVT::ValueType PtrVT) {
+  // Get the Thread Pointer
+  SDOperand ThreadPointer = DAG.getNode(X86ISD::THREAD_POINTER, PtrVT);
+  // emit "addl x@ntpoff,%eax" (local exec) or "addl x@indntpoff,%eax" (initial
+  // exec)
+  SDOperand TGA = DAG.getTargetGlobalAddress(GA->getGlobal(),
+                                             GA->getValueType(0),
+                                             GA->getOffset());
+  SDOperand Offset = DAG.getNode(X86ISD::Wrapper, PtrVT, TGA);
+  // The address of the thread local variable is the add of the thread
+  // pointer with the offset of the variable.
+  return DAG.getNode(ISD::ADD, PtrVT, ThreadPointer, Offset);
+}
+
+SDOperand
+X86TargetLowering::LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) {
+  // TODO: implement the "local dynamic" model
+  // TODO: implement the "initial exec"model for pic executables 
+  assert(!Subtarget->is64Bit() && "TLS not implemented for X86_64");
+  GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
+  // If the relocation model is PIC, use the "General Dynamic" TLS Model,
+  // otherwise use the "Local Exec"TLS Model
+  if (getTargetMachine().getRelocationModel() == Reloc::PIC_)
+    return LowerToTLSGeneralDynamicModel(GA, DAG, getPointerTy());
+  else
+    return LowerToTLSExecModel(GA, DAG, getPointerTy());
+}
+
 SDOperand
 X86TargetLowering::LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
   const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
@@ -4022,6 +4094,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::SCALAR_TO_VECTOR:   return LowerSCALAR_TO_VECTOR(Op, DAG);
   case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
   case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);
+  case ISD::GlobalTLSAddress:   return LowerGlobalTLSAddress(Op, DAG);
   case ISD::ExternalSymbol:     return LowerExternalSymbol(Op, DAG);
   case ISD::SHL_PARTS:
   case ISD::SRA_PARTS:
@@ -4090,6 +4163,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case X86ISD::PINSRW:             return "X86ISD::PINSRW";
   case X86ISD::FMAX:               return "X86ISD::FMAX";
   case X86ISD::FMIN:               return "X86ISD::FMIN";
+  case X86ISD::TLSADDR:            return "X86ISD::TLSADDR";
+  case X86ISD::THREAD_POINTER:     return "X86ISD::THREAD_POINTER";
   }
 }
 
index 8b9c269..88064d3 100644 (file)
@@ -176,7 +176,9 @@ namespace llvm {
 
       /// FMAX, FMIN - Floating point max and min.
       ///
-      FMAX, FMIN
+      FMAX, FMIN,
+      // Thread Local Storage
+      TLSADDR, THREAD_POINTER
     };
   }
 
@@ -386,6 +388,7 @@ namespace llvm {
     SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerShift(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG);
index bfdaff6..fdc2bc9 100644 (file)
@@ -47,6 +47,10 @@ def SDTX86RdTsc   : SDTypeProfile<0, 0, []>;
 
 def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
 
+def SDT_X86TLSADDR : SDTypeProfile<1, 1, [SDTCisPtrTy<0>, SDTCisInt<1>]>;
+
+def SDT_X86TLSTP : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
+
 def X86shld    : SDNode<"X86ISD::SHLD",     SDTIntShiftDOp>;
 def X86shrd    : SDNode<"X86ISD::SHRD",     SDTIntShiftDOp>;
 
@@ -87,6 +91,11 @@ def X86rdtsc   : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc,
 def X86Wrapper    : SDNode<"X86ISD::Wrapper",     SDTX86Wrapper>;
 def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP",  SDTX86Wrapper>;
 
+def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR,
+                        [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
+def X86TLStp : SDNode<"X86ISD::THREAD_POINTER", SDT_X86TLSTP, []>;
+
+
 //===----------------------------------------------------------------------===//
 // X86 Operand Definitions.
 //
@@ -2449,6 +2458,19 @@ def MOV32_mr : I<0x89, MRMDestMem, (ops i32mem:$dst, GR32_:$src),
                 "mov{l} {$src, $dst|$dst, $src}", []>;
 
 //===----------------------------------------------------------------------===//
+// Thread Local Storage Instructions
+//
+
+def TLS_addr : I<0, Pseudo, (ops GR32:$dst, i32imm:$sym),
+               "leal $sym(,%ebx,1), $dst",
+               [(set GR32:$dst, (X86tlsaddr tglobaltlsaddr:$sym))]>,
+               Imp<[EBX],[]>;
+
+def TLS_tp : I<0, Pseudo, (ops GR32:$dst),
+               "movl %gs:0, $dst",
+               [(set GR32:$dst, X86TLStp)]>;
+
+//===----------------------------------------------------------------------===//
 // DWARF Pseudo Instructions
 //
 
index 6ad7999..11f7f77 100644 (file)
@@ -2654,10 +2654,12 @@ public:
         } else {
           NodeOps.push_back(Val);
         }
-      } else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
+      } else if (!N->isLeaf() && (N->getOperator()->getName() == "tglobaladdr"
+                 || N->getOperator()->getName() == "tglobaltlsaddr")) {
         Record *Op = OperatorMap[N->getName()];
         // Transform GlobalAddress to TargetGlobalAddress
-        if (Op && Op->getName() == "globaladdr") {
+        if (Op && (Op->getName() == "globaladdr" ||
+                   Op->getName() == "globaltlsaddr")) {
           emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
                    "GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
                    ")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
@@ -3716,6 +3718,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "  case ISD::TargetConstantPool:\n"
      << "  case ISD::TargetFrameIndex:\n"
      << "  case ISD::TargetJumpTable:\n"
+     << "  case ISD::TargetGlobalTLSAddress:\n"
      << "  case ISD::TargetGlobalAddress: {\n"
      << "    return NULL;\n"
      << "  }\n"