diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp index e9b62a8c14b..65ce5acb9df 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp @@ -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; diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index bb8061fed8d..339261f9838 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -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(N0)) { diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index ff8382a5abf..825e31d503c 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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"); diff --git a/test/CodeGen/X86/tls1.ll b/test/CodeGen/X86/tls1.ll index ccff7180eb0..5155dfd4a11 100644 --- a/test/CodeGen/X86/tls1.ll +++ b/test/CodeGen/X86/tls1.ll @@ -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 diff --git a/test/CodeGen/X86/tls10.ll b/test/CodeGen/X86/tls10.ll index a4f2fb1293b..2f5f02b9ac9 100644 --- a/test/CodeGen/X86/tls10.ll +++ b/test/CodeGen/X86/tls10.ll @@ -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 diff --git a/test/CodeGen/X86/tls11.ll b/test/CodeGen/X86/tls11.ll index f8543c089f2..b6aed9aaa04 100644 --- a/test/CodeGen/X86/tls11.ll +++ b/test/CodeGen/X86/tls11.ll @@ -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 diff --git a/test/CodeGen/X86/tls12.ll b/test/CodeGen/X86/tls12.ll index 17ea996aa45..b5288391f03 100644 --- a/test/CodeGen/X86/tls12.ll +++ b/test/CodeGen/X86/tls12.ll @@ -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 diff --git a/test/CodeGen/X86/tls13.ll b/test/CodeGen/X86/tls13.ll index 30894439855..ec23a41113e 100644 --- a/test/CodeGen/X86/tls13.ll +++ b/test/CodeGen/X86/tls13.ll @@ -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 diff --git a/test/CodeGen/X86/tls14.ll b/test/CodeGen/X86/tls14.ll index d3401b65537..941601eb4f9 100644 --- a/test/CodeGen/X86/tls14.ll +++ b/test/CodeGen/X86/tls14.ll @@ -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 diff --git a/test/CodeGen/X86/tls15.ll b/test/CodeGen/X86/tls15.ll index 5d3ee16a476..62f3677629b 100644 --- a/test/CodeGen/X86/tls15.ll +++ b/test/CodeGen/X86/tls15.ll @@ -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 diff --git a/test/CodeGen/X86/tls2.ll b/test/CodeGen/X86/tls2.ll index fb57ae1a391..baa51bbb6ea 100644 --- a/test/CodeGen/X86/tls2.ll +++ b/test/CodeGen/X86/tls2.ll @@ -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 diff --git a/test/CodeGen/X86/tls3.ll b/test/CodeGen/X86/tls3.ll index 396e7901acc..e8d1a340baa 100644 --- a/test/CodeGen/X86/tls3.ll +++ b/test/CodeGen/X86/tls3.ll @@ -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 ; [#uses=2] diff --git a/test/CodeGen/X86/tls4.ll b/test/CodeGen/X86/tls4.ll index 31466997d19..33f221b8ad3 100644 --- a/test/CodeGen/X86/tls4.ll +++ b/test/CodeGen/X86/tls4.ll @@ -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 ; [#uses=2] diff --git a/test/CodeGen/X86/tls5.ll b/test/CodeGen/X86/tls5.ll index b32f5fc3342..ff7b9e0a5ff 100644 --- a/test/CodeGen/X86/tls5.ll +++ b/test/CodeGen/X86/tls5.ll @@ -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 diff --git a/test/CodeGen/X86/tls6.ll b/test/CodeGen/X86/tls6.ll index e0bcade8dd8..ab53929206a 100644 --- a/test/CodeGen/X86/tls6.ll +++ b/test/CodeGen/X86/tls6.ll @@ -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 diff --git a/test/CodeGen/X86/tls7.ll b/test/CodeGen/X86/tls7.ll index eafa5c2c246..6a7739bc1a3 100644 --- a/test/CodeGen/X86/tls7.ll +++ b/test/CodeGen/X86/tls7.ll @@ -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 diff --git a/test/CodeGen/X86/tls8.ll b/test/CodeGen/X86/tls8.ll index 4971fd23ba6..fd9d472bb66 100644 --- a/test/CodeGen/X86/tls8.ll +++ b/test/CodeGen/X86/tls8.ll @@ -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 diff --git a/test/CodeGen/X86/tls9.ll b/test/CodeGen/X86/tls9.ll index 31dffcc18c8..bc0a6f0bbe6 100644 --- a/test/CodeGen/X86/tls9.ll +++ b/test/CodeGen/X86/tls9.ll @@ -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