For general dynamic TLS access we must use
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 17 Apr 2009 14:35:58 +0000 (14:35 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 17 Apr 2009 14:35:58 +0000 (14:35 +0000)
leaq foo@TLSGD(%rip), %rdi

as part of the instruction sequence. Using a register other than %rdi and then
copying it to %rdi is not valid.

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

lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86Instr64bit.td
lib/Target/X86/X86InstrInfo.td
test/CodeGen/X86/2009-04-17-tls-fast.ll [new file with mode: 0644]

index 825e31d503cabd422b33bbabdce442953b09c20e..cf3a6ce3b50301eb0cf4ca68f9da31c01343ea94 100644 (file)
@@ -4754,6 +4754,23 @@ X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) {
   return LowerGlobalAddress(GV, Op.getDebugLoc(), Offset, DAG);
 }
 
+static SDValue
+GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA,
+           SDValue *InFlag) {
+  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+  DebugLoc dl = GA->getDebugLoc();
+  SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(),
+                                           GA->getValueType(0),
+                                           GA->getOffset());
+  if (InFlag) {
+    SDValue Ops[] = { Chain,  TGA, *InFlag };
+    return DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3);
+  } else {
+    SDValue Ops[]  = { Chain, TGA };
+    return DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2);
+  }
+}
+
 // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit
 static SDValue
 LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG,
@@ -4766,22 +4783,10 @@ LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG,
                                                  PtrVT), InFlag);
   InFlag = Chain.getValue(1);
 
-  // emit leal symbol@TLSGD(,%ebx,1), %eax
-  SDVTList NodeTys = DAG.getVTList(PtrVT, MVT::Other, MVT::Flag);
-  SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(),
-                                             GA->getValueType(0),
-                                             GA->getOffset());
-  SDValue Ops[] = { Chain,  TGA, InFlag };
-  SDValue Result = DAG.getNode(X86ISD::TLSADDR, dl, 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, dl, X86::EAX, Result, InFlag);
+  Chain = GetTLSADDR(DAG, Chain, GA, &InFlag);
   InFlag = Chain.getValue(1);
 
-  NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
   SDValue Ops1[] = { Chain,
                       DAG.getTargetExternalSymbol("___tls_get_addr",
                                                   PtrVT),
@@ -4801,22 +4806,10 @@ LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG,
   SDValue InFlag, Chain;
   DebugLoc dl = GA->getDebugLoc();  // ? function entry point might be better
 
-  // emit leaq symbol@TLSGD(%rip), %rdi
-  SDVTList NodeTys = DAG.getVTList(PtrVT, MVT::Other, MVT::Flag);
-  SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(),
-                                             GA->getValueType(0),
-                                             GA->getOffset());
-  SDValue Ops[]  = { DAG.getEntryNode(), TGA};
-  SDValue Result = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2);
-  Chain  = Result.getValue(1);
-  InFlag = Result.getValue(2);
-
-  // call __tls_get_addr. This function receives its argument in
-  // the register RDI.
-  Chain = DAG.getCopyToReg(Chain, dl, X86::RDI, Result, InFlag);
+  Chain = GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL);
   InFlag = Chain.getValue(1);
 
-  NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
   SDValue Ops1[] = { Chain,
                       DAG.getTargetExternalSymbol("__tls_get_addr",
                                                   PtrVT),
index 1785bd13316638bb6d1868acdb1c8ec3c72a6de6..69c74b2c985355355d01e794f4f318331e57204f 100644 (file)
@@ -1303,9 +1303,11 @@ def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src),
 // Thread Local Storage Instructions
 //===----------------------------------------------------------------------===//
 
-def TLS_addr64 : I<0, Pseudo, (outs GR64:$dst), (ins i64imm:$sym),
-              ".byte\t0x66; leaq\t${sym:mem}(%rip), $dst; .word\t0x6666; rex64",
-                  [(set GR64:$dst, (X86tlsaddr tglobaltlsaddr:$sym))]>;
+let hasSideEffects = 1, Uses = [RDI] in
+def TLS_addr64 : I<0, Pseudo, (outs), (ins i64imm:$sym),
+              ".byte\t0x66; leaq\t${sym:mem}(%rip), %rdi; .word\t0x6666; rex64",
+                  [(X86tlsaddr tglobaltlsaddr:$sym)]>,
+                  Requires<[In64BitMode]>;
 
 let AddedComplexity = 5 in
 def MOV64GSrm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
index 343691188b1d61c507b110101f0080dd1240855a..7cf1ad31fcbb8257738576804fc52b94adb39792 100644 (file)
@@ -63,7 +63,7 @@ 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_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
 
 def SDT_X86SegmentBaseAddress : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>;
 
@@ -2977,10 +2977,11 @@ def MOV32r0  : I<0x31, MRMInitReg,  (outs GR32:$dst), (ins),
 // Thread Local Storage Instructions
 //
 
-let Uses = [EBX] in
-def TLS_addr32 : I<0, Pseudo, (outs GR32:$dst), (ins i32imm:$sym),
-                  "leal\t${sym:mem}(,%ebx,1), $dst",
-                  [(set GR32:$dst, (X86tlsaddr tglobaltlsaddr:$sym))]>;
+let hasSideEffects = 1, Uses = [EAX, EBX] in
+def TLS_addr32 : I<0, Pseudo, (outs), (ins i32imm:$sym),
+                  "leal\t${sym:mem}(,%ebx,1), %eax",
+                  [(X86tlsaddr tglobaltlsaddr:$sym)]>,
+                  Requires<[In32BitMode]>;
 
 let AddedComplexity = 5 in
 def GS_MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
diff --git a/test/CodeGen/X86/2009-04-17-tls-fast.ll b/test/CodeGen/X86/2009-04-17-tls-fast.ll
new file mode 100644 (file)
index 0000000..6a8054e
--- /dev/null
@@ -0,0 +1,17 @@
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -relocation-model=pic -regalloc=local > %t
+; RUN: grep {leaq      foo@TLSGD(%rip), %rdi} %t
+
+@foo = internal thread_local global i32 100
+
+define void @f(i32 %n) nounwind {
+entry:
+       %n_addr = alloca i32
+       %p = alloca i32*
+       %"alloca point" = bitcast i32 0 to i32
+       store i32 %n, i32* %n_addr
+       store i32* @foo, i32** %p, align 8
+       br label %return
+
+return:
+       ret void
+}