[TLS on Darwin] use a different mask for tls calls on x86-64.
authorManman Ren <manman.ren@gmail.com>
Thu, 12 Nov 2015 00:54:04 +0000 (00:54 +0000)
committerManman Ren <manman.ren@gmail.com>
Thu, 12 Nov 2015 00:54:04 +0000 (00:54 +0000)
Calls involved in thread-local variable lookup save more registers
than normal calls.

rdar://problem/23073171

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

lib/Target/X86/X86CallingConv.td
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86RegisterInfo.cpp
lib/Target/X86/X86RegisterInfo.h
test/CodeGen/X86/darwin-tls.ll [new file with mode: 0644]

index aaabf7a..76256f3 100644 (file)
@@ -796,6 +796,12 @@ def CSR_64EHRet : CalleeSavedRegs<(add RAX, RDX, CSR_64)>;
 def CSR_Win64 : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12, R13, R14, R15,
                                      (sequence "XMM%u", 6, 15))>;
 
+// The function used by Darwin to obtain the address of a thread-local variable
+// uses rdi to pass a single parameter and rax for the return value. All other
+// GPRs are preserved.
+def CSR_64_TLS_Darwin : CalleeSavedRegs<(add CSR_64, RCX, RDX, RSI,
+                                             R8, R9, R10, R11)>;
+
 // All GPRs - except r11
 def CSR_64_RT_MostRegs : CalleeSavedRegs<(add CSR_64, RAX, RCX, RDX, RSI, RDI,
                                               R8, R9, R10, RSP)>;
index a0ffa12..46b2b5e 100644 (file)
@@ -21461,6 +21461,8 @@ X86TargetLowering::EmitLoweredTLSCall(MachineInstr *MI,
   // FIXME: The 32-bit calls have non-standard calling conventions. Use a
   // proper register mask.
   const uint32_t *RegMask =
+      Subtarget->is64Bit() ?
+      Subtarget->getRegisterInfo()->getDarwinTLSCallPreservedMask() :
       Subtarget->getRegisterInfo()->getCallPreservedMask(*F, CallingConv::C);
   if (Subtarget->is64Bit()) {
     MachineInstrBuilder MIB = BuildMI(*BB, MI, DL,
index b114787..8b4bbac 100644 (file)
@@ -347,6 +347,10 @@ X86RegisterInfo::getNoPreservedMask() const {
   return CSR_NoRegs_RegMask;
 }
 
+const uint32_t *X86RegisterInfo::getDarwinTLSCallPreservedMask() const {
+  return CSR_64_TLS_Darwin_RegMask;
+}
+
 BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   BitVector Reserved(getNumRegs());
   const X86FrameLowering *TFI = getFrameLowering(MF);
index c20842b..1b1a1cc 100644 (file)
@@ -98,6 +98,10 @@ public:
                                        CallingConv::ID) const override;
   const uint32_t *getNoPreservedMask() const override;
 
+  // Calls involved in thread-local variable lookup save more registers than
+  // normal calls, so they need a different mask to represent this.
+  const uint32_t *getDarwinTLSCallPreservedMask() const;
+
   /// getReservedRegs - Returns a bitset indexed by physical register number
   /// indicating if a register is a special register that has particular uses and
   /// should be considered unavailable at all times, e.g. SP, RA. This is used by
diff --git a/test/CodeGen/X86/darwin-tls.ll b/test/CodeGen/X86/darwin-tls.ll
new file mode 100644 (file)
index 0000000..ca9a998
--- /dev/null
@@ -0,0 +1,28 @@
+; RUN: llc < %s -mtriple x86_64-apple-darwin | FileCheck %s
+
+@a = thread_local global i32 4, align 4
+
+define i32 @f2(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5) {
+entry:
+; Parameters are in %edi, %esi, %edx, %ecx, %r8d, there is no need to save
+; these parameters except the one in %edi, before making the TLS call.
+; %edi is used to pass parameter to the TLS call.
+; CHECK-NOT: movl %r8d
+; CHECK-NOT: movl %ecx
+; CHECK-NOT: movl %edx
+; CHECK-NOT: movl %esi
+; CHECK: movq {{.*}}TLVP{{.*}}, %rdi
+; CHECK-NEXT: callq
+; CHECK-NEXT: movl (%rax),
+; CHECK-NOT: movl {{.*}}, %esi
+; CHECK-NOT: movl {{.*}}, %edx
+; CHECK-NOT: movl {{.*}}, %ecx
+; CHECK-NOT: movl {{.*}}, %r8d
+; CHECK: callq
+  %0 = load i32, i32* @a, align 4
+  %call = tail call i32 @f3(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5)
+  %add = add nsw i32 %call, %0
+  ret i32 %add
+}
+
+declare i32 @f3(i32, i32, i32, i32, i32)