From 6c3ce45003cded5afa2b972d09c5255f67327ea4 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Thu, 12 Nov 2015 00:54:04 +0000 Subject: [PATCH] [TLS on Darwin] use a different mask for tls calls on x86-64. 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 | 6 ++++++ lib/Target/X86/X86ISelLowering.cpp | 2 ++ lib/Target/X86/X86RegisterInfo.cpp | 4 ++++ lib/Target/X86/X86RegisterInfo.h | 4 ++++ test/CodeGen/X86/darwin-tls.ll | 28 ++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 test/CodeGen/X86/darwin-tls.ll diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td index aaabf7a59f5..76256f3c704 100644 --- a/lib/Target/X86/X86CallingConv.td +++ b/lib/Target/X86/X86CallingConv.td @@ -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)>; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index a0ffa12bb36..46b2b5e669f 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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, diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index b1147877753..8b4bbac7007 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -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); diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index c20842b25de..1b1a1ccfc1a 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -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 index 00000000000..ca9a998ccc7 --- /dev/null +++ b/test/CodeGen/X86/darwin-tls.ll @@ -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) -- 2.11.0