diff options
author | Manman Ren <manman.ren@gmail.com> | 2015-12-04 17:40:13 +0000 |
---|---|---|
committer | Manman Ren <manman.ren@gmail.com> | 2015-12-04 17:40:13 +0000 |
commit | 19c7bbe3b727a4db8778f0b4ae42ede04195969a (patch) | |
tree | 9c69ddc2049fb4d5bffdac0782d7dda2c8356c2c /llvm/test | |
parent | a75f8261174f2c28caa4e809935d1d3dba831d55 (diff) | |
download | bcm5719-llvm-19c7bbe3b727a4db8778f0b4ae42ede04195969a.tar.gz bcm5719-llvm-19c7bbe3b727a4db8778f0b4ae42ede04195969a.zip |
[CXX TLS calling convention] Add CXX TLS calling convention.
This commit adds a new target-independent calling convention for C++ TLS
access functions. It aims to minimize overhead in the caller by perserving as
many registers as possible.
The target-specific implementation for X86-64 is defined as following:
Arguments are passed as for the default C calling convention
The same applies for the return value(s)
The callee preserves all GPRs - except RAX and RDI
The access function makes C-style TLS function calls in the entry and exit
block, C-style TLS functions save a lot more registers than normal calls.
The added calling convention ties into the existing implementation of the
C-style TLS functions, so we can't simply use existing calling conventions
such as preserve_mostcc.
rdar://9001553
llvm-svn: 254737
Diffstat (limited to 'llvm/test')
-rw-r--r-- | llvm/test/CodeGen/X86/cxx_tlscc64.ll | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/llvm/test/CodeGen/X86/cxx_tlscc64.ll b/llvm/test/CodeGen/X86/cxx_tlscc64.ll new file mode 100644 index 00000000000..c229521cc9a --- /dev/null +++ b/llvm/test/CodeGen/X86/cxx_tlscc64.ll @@ -0,0 +1,71 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-apple-darwin -enable-shrink-wrap=true | FileCheck --check-prefix=SHRINK %s +%struct.S = type { i8 } + +@sg = internal thread_local global %struct.S zeroinitializer, align 1 +@__dso_handle = external global i8 +@__tls_guard = internal thread_local unnamed_addr global i1 false + +declare void @_ZN1SC1Ev(%struct.S*) +declare void @_ZN1SD1Ev(%struct.S*) +declare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) + +; Every GPR should be saved - except rdi, rax, and rsp +; CHECK-LABEL: _ZTW2sg +; CHECK: pushq %r11 +; CHECK: pushq %r10 +; CHECK: pushq %r9 +; CHECK: pushq %r8 +; CHECK: pushq %rsi +; CHECK: pushq %rdx +; CHECK: pushq %rcx +; CHECK: pushq %rbx +; CHECK: callq +; CHECK: jne +; CHECK: callq +; CHECK: tlv_atexit +; CHECK: callq +; CHECK: popq %rbx +; CHECK: popq %rcx +; CHECK: popq %rdx +; CHECK: popq %rsi +; CHECK: popq %r8 +; CHECK: popq %r9 +; CHECK: popq %r10 +; CHECK: popq %r11 +; SHRINK-LABEL: _ZTW2sg +; SHRINK: callq +; SHRINK: jne +; SHRINK: pushq %r11 +; SHRINK: pushq %r10 +; SHRINK: pushq %r9 +; SHRINK: pushq %r8 +; SHRINK: pushq %rsi +; SHRINK: pushq %rdx +; SHRINK: pushq %rcx +; SHRINK: pushq %rbx +; SHRINK: callq +; SHRINK: tlv_atexit +; SHRINK: popq %rbx +; SHRINK: popq %rcx +; SHRINK: popq %rdx +; SHRINK: popq %rsi +; SHRINK: popq %r8 +; SHRINK: popq %r9 +; SHRINK: popq %r10 +; SHRINK: popq %r11 +; SHRINK: LBB{{.*}}: +; SHRINK: callq +define cxx_fast_tlscc nonnull %struct.S* @_ZTW2sg() { + %.b.i = load i1, i1* @__tls_guard, align 1 + br i1 %.b.i, label %__tls_init.exit, label %init.i + +init.i: + store i1 true, i1* @__tls_guard, align 1 + tail call void @_ZN1SC1Ev(%struct.S* nonnull @sg) #2 + %1 = tail call i32 @_tlv_atexit(void (i8*)* nonnull bitcast (void (%struct.S*)* @_ZN1SD1Ev to void (i8*)*), i8* nonnull getelementptr inbounds (%struct.S, %struct.S* @sg, i64 0, i32 0), i8* nonnull @__dso_handle) #2 + br label %__tls_init.exit + +__tls_init.exit: + ret %struct.S* @sg +} |