X86-64 TLS support for local exec and initial exec.
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 13 Apr 2009 13:02:49 +0000 (13:02 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 13 Apr 2009 13:02:49 +0000 (13:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68947 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
lib/Target/X86/X86ISelDAGToDAG.cpp
lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/tls1.ll
test/CodeGen/X86/tls10.ll
test/CodeGen/X86/tls11.ll
test/CodeGen/X86/tls12.ll
test/CodeGen/X86/tls13.ll
test/CodeGen/X86/tls14.ll
test/CodeGen/X86/tls15.ll
test/CodeGen/X86/tls2.ll
test/CodeGen/X86/tls3.ll
test/CodeGen/X86/tls4.ll
test/CodeGen/X86/tls5.ll
test/CodeGen/X86/tls6.ll
test/CodeGen/X86/tls7.ll
test/CodeGen/X86/tls8.ll
test/CodeGen/X86/tls9.ll

index e9b62a8c14b19ee044a96f74293f16332f3b033a..65ce5acb9dfe78c2e9a9200abf819ca470bccf3a 100644 (file)
@@ -454,14 +454,16 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
        O << "@TLSGD";
         break;
       case TLSModel::InitialExec:
-        if (Subtarget->is64Bit())
-          O << "@TLSGD"; // 64 bit intial exec not implemented
-        else
+        if (Subtarget->is64Bit()) {
+          assert (!NotRIPRel);
+          O << "@GOTTPOFF(%rip)";
+        } else {
           O << "@INDNTPOFF";
+        }
         break;
       case TLSModel::LocalExec:
         if (Subtarget->is64Bit())
-          O << "@TLSGD"; // 64 bit local exec not implemented
+          O << "@TPOFF";
         else
          O << "@NTPOFF";
         break;
index bb8061fed8d487c5e84388daabb2dafebe2b568f..339261f98385f3382a0c58fa47eb981a015a9f86 100644 (file)
@@ -808,9 +808,16 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) {
     uint64_t Offset = G->getOffset();
     if (!is64Bit || isInt32(AM.Disp + Offset)) {
       GlobalValue *GV = G->getGlobal();
+      bool isRIPRel = TM.symbolicAddressesAreRIPRel();
+      if (N0.getOpcode() == llvm::ISD::TargetGlobalTLSAddress) {
+        TLSModel::Model model =
+          getTLSModel (GV, TM.getRelocationModel());
+        if (is64Bit && model == TLSModel::InitialExec)
+          isRIPRel = true;
+      }
       AM.GV = GV;
       AM.Disp += Offset;
-      AM.isRIPRel = TM.symbolicAddressesAreRIPRel();
+      AM.isRIPRel = isRIPRel;
       return false;
     }
   } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
index ff8382a5abf3cf930ca49a2c36ba1532c0944a7b..825e31d503cabd422b33bbabdce442953b09c20e 100644 (file)
@@ -4831,12 +4831,14 @@ LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG,
 // Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or
 // "local exec" model.
 static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
-                                   const MVT PtrVT, TLSModel::Model model) {
+                                   const MVT PtrVT, TLSModel::Model model,
+                                   bool is64Bit) {
   DebugLoc dl = GA->getDebugLoc();
   // Get the Thread Pointer
   SDValue Base = DAG.getNode(X86ISD::SegmentBaseAddress,
                              DebugLoc::getUnknownLoc(), PtrVT,
-                             DAG.getRegister(X86::GS, MVT::i32));
+                             DAG.getRegister(is64Bit? X86::FS : X86::GS,
+                                             MVT::i32));
 
   SDValue ThreadPointer = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Base,
                                       NULL, 0);
@@ -4871,9 +4873,11 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) {
     switch (model) {
     case TLSModel::GeneralDynamic:
     case TLSModel::LocalDynamic: // not implemented
-    case TLSModel::InitialExec:  // not implemented
-    case TLSModel::LocalExec:    // not implemented
       return LowerToTLSGeneralDynamicModel64(GA, DAG, getPointerTy());
+
+    case TLSModel::InitialExec:
+    case TLSModel::LocalExec:
+      return LowerToTLSExecModel(GA, DAG, getPointerTy(), model, true);
     }
   } else {
     switch (model) {
@@ -4883,7 +4887,7 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) {
 
     case TLSModel::InitialExec:
     case TLSModel::LocalExec:
-      return LowerToTLSExecModel(GA, DAG, getPointerTy(), model);
+      return LowerToTLSExecModel(GA, DAG, getPointerTy(), model, false);
     }
   }
   assert(0 && "Unreachable");
index ccff7180eb00134d0a409a401c55f5d0a66be65c..5155dfd4a11896cd3bda1c583bf8bc325559527b 100644 (file)
@@ -1,5 +1,7 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:i@NTPOFF, %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movl      %fs:i@TPOFF, %eax} %t2
 
 @i = thread_local global i32 15
 
index a4f2fb1293b94d481a46e286404fbb7df1546247..2f5f02b9ac96b3db4782391f5313c74fb514c788 100644 (file)
@@ -1,6 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:0, %eax} %t
 ; RUN: grep {leal      i@NTPOFF(%eax), %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movq      %fs:0, %rax} %t2
+; RUN: grep {leaq      i@TPOFF(%rax), %rax} %t2
 
 @i = external hidden thread_local global i32
 
index f8543c089f2cd119a94c9429c4439817e92e2c56..b6aed9aaa04d1865298695cba992ceb3c8aa2db8 100644 (file)
@@ -1,5 +1,7 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movw      %gs:i@NTPOFF, %ax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movw      %fs:i@TPOFF, %ax} %t2
 
 @i = thread_local global i16 15
 
index 17ea996aa455996cfab09dad7644b7e805d3b909..b5288391f03f011d17514a3545f6824ee4bbf9ff 100644 (file)
@@ -1,5 +1,7 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movb      %gs:i@NTPOFF, %al} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movb      %fs:i@TPOFF, %al} %t2
 
 @i = thread_local global i8 15
 
index 308944398555bd5f3a464da16c5f6c1e07cb936f..ec23a41113eef8bd87f382c08768d9c6b12596fc 100644 (file)
@@ -1,6 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movswl    %gs:i@NTPOFF, %eax} %t
 ; RUN: grep {movzwl    %gs:j@NTPOFF, %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movswl    %fs:i@TPOFF, %edi} %t2
+; RUN: grep {movzwl    %fs:j@TPOFF, %edi} %t2
 
 @i = thread_local global i16 0
 @j = thread_local global i16 0
index d3401b655377329e2d1b6fdad7ff4d75fd6f1529..941601eb4f9b6b3cc46e2bde6f5cf7031ad38cbf 100644 (file)
@@ -1,6 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movsbl    %gs:i@NTPOFF, %eax} %t
 ; RUN: grep {movzbl    %gs:j@NTPOFF, %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movsbl    %fs:i@TPOFF, %edi} %t2
+; RUN: grep {movzbl    %fs:j@TPOFF, %edi} %t2
 
 @i = thread_local global i8 0
 @j = thread_local global i8 0
index 5d3ee16a476f14b538940c26bfc3a07799c5a97e..62f3677629be3574011b4a888817a101f0a7e4b9 100644 (file)
@@ -2,6 +2,10 @@
 ; RUN: grep {movl      %gs:0, %eax} %t | count 1
 ; RUN: grep {leal      i@NTPOFF(%eax), %ecx} %t
 ; RUN: grep {leal      j@NTPOFF(%eax), %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movq      %fs:0, %rax} %t2 | count 1
+; RUN: grep {leaq      i@TPOFF(%rax), %rcx} %t2
+; RUN: grep {leaq      j@TPOFF(%rax), %rax} %t2
 
 @i = thread_local global i32 0
 @j = thread_local global i32 0
index fb57ae1a3917073ac35ec4864e0a8b3b29600ae1..baa51bbb6ead9d58686250a23d3fd6474339817f 100644 (file)
@@ -1,6 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:0, %eax} %t
 ; RUN: grep {leal      i@NTPOFF(%eax), %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movq      %fs:0, %rax} %t2
+; RUN: grep {leaq      i@TPOFF(%rax), %rax} %t2
 
 @i = thread_local global i32 15
 
index 396e7901accf2ea296e78a91c45061c9f92932b9..e8d1a340baa65596de9c6a4c0e8c1719e7e31552 100644 (file)
@@ -1,6 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      i@INDNTPOFF, %eax} %t
 ; RUN: grep {movl      %gs:(%eax), %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movq      i@GOTTPOFF(%rip), %rax} %t2
+; RUN: grep {movl      %fs:(%rax), %eax} %t2
 
 @i = external thread_local global i32          ; <i32*> [#uses=2]
 
index 31466997d1945671151a02849b4eb47987fbf0b5..33f221b8ad3ab0d1e10b84c89e598322f4035e01 100644 (file)
@@ -1,6 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:0, %eax} %t
 ; RUN: grep {addl      i@INDNTPOFF, %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movq      %fs:0, %rax} %t2
+; RUN: grep {addq      i@GOTTPOFF(%rip), %rax} %t2
 
 @i = external thread_local global i32          ; <i32*> [#uses=2]
 
index b32f5fc334296def5e4beec1f9a3673e4faf0006..ff7b9e0a5ffe713b19679137af063f6366062eb1 100644 (file)
@@ -1,5 +1,7 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:i@NTPOFF, %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movl      %fs:i@TPOFF, %eax} %t2
 
 @i = internal thread_local global i32 15
 
index e0bcade8dd88512b55a0518f8a120c096237be43..ab53929206a180158c1e75652ae2f5f416552a0a 100644 (file)
@@ -1,6 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:0, %eax} %t
 ; RUN: grep {leal      i@NTPOFF(%eax), %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movq      %fs:0, %rax} %t2
+; RUN: grep {leaq      i@TPOFF(%rax), %rax} %t2
 
 @i = internal thread_local global i32 15
 
index eafa5c2c2465e07301aa5b8aee29aadfff300fe9..6a7739bc1a31d9dd8dab44fcc37ba337fdc827f3 100644 (file)
@@ -1,5 +1,7 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:i@NTPOFF, %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movl      %fs:i@TPOFF, %eax} %t2
 
 @i = hidden thread_local global i32 15
 
index 4971fd23ba6b238f0a964f421c566b2503249be1..fd9d472bb66c318e1a02e8963bf3f1f3b8bcf181 100644 (file)
@@ -1,6 +1,9 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:0, %eax} %t
 ; RUN: grep {leal      i@NTPOFF(%eax), %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movq      %fs:0, %rax} %t2
+; RUN: grep {leaq      i@TPOFF(%rax), %rax} %t2
 
 @i = hidden thread_local global i32 15
 
index 31dffcc18c8cea358dc16c33ada0c790359c9970..bc0a6f0bbe618dcde40f9c13d321f5f939021582 100644 (file)
@@ -1,5 +1,7 @@
 ; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu > %t
 ; RUN: grep {movl      %gs:i@NTPOFF, %eax} %t
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
+; RUN: grep {movl      %fs:i@TPOFF, %eax} %t2
 
 @i = external hidden thread_local global i32