Add a triple to switch.ll test.
[oota-llvm.git] / test / CodeGen / X86 / musttail-varargs.ll
1 ; RUN: llc < %s -enable-tail-merge=0 -mtriple=x86_64-linux | FileCheck %s --check-prefix=LINUX
2 ; RUN: llc < %s -enable-tail-merge=0 -mtriple=x86_64-windows | FileCheck %s --check-prefix=WINDOWS
3 ; RUN: llc < %s -enable-tail-merge=0 -mtriple=i686-windows | FileCheck %s --check-prefix=X86
4
5 ; Test that we actually spill and reload all arguments in the variadic argument
6 ; pack. Doing a normal call will clobber all argument registers, and we will
7 ; spill around it. A simple adjustment should not require any XMM spills.
8
9 declare void @llvm.va_start(i8*) nounwind
10
11 declare void(i8*, ...)* @get_f(i8* %this)
12
13 define void @f_thunk(i8* %this, ...) {
14   ; Use va_start so that we exercise the combination.
15   %ap = alloca [4 x i8*], align 16
16   %ap_i8 = bitcast [4 x i8*]* %ap to i8*
17   call void @llvm.va_start(i8* %ap_i8)
18
19   %fptr = call void(i8*, ...)*(i8*)* @get_f(i8* %this)
20   musttail call void (i8*, ...)* %fptr(i8* %this, ...)
21   ret void
22 }
23
24 ; Save and restore 6 GPRs, 8 XMMs, and AL around the call.
25
26 ; LINUX-LABEL: f_thunk:
27 ; LINUX-DAG: movq %rdi, {{.*}}
28 ; LINUX-DAG: movq %rsi, {{.*}}
29 ; LINUX-DAG: movq %rdx, {{.*}}
30 ; LINUX-DAG: movq %rcx, {{.*}}
31 ; LINUX-DAG: movq %r8, {{.*}}
32 ; LINUX-DAG: movq %r9, {{.*}}
33 ; LINUX-DAG: movb %al, {{.*}}
34 ; LINUX-DAG: movaps %xmm0, {{[0-9]*}}(%rsp)
35 ; LINUX-DAG: movaps %xmm1, {{[0-9]*}}(%rsp)
36 ; LINUX-DAG: movaps %xmm2, {{[0-9]*}}(%rsp)
37 ; LINUX-DAG: movaps %xmm3, {{[0-9]*}}(%rsp)
38 ; LINUX-DAG: movaps %xmm4, {{[0-9]*}}(%rsp)
39 ; LINUX-DAG: movaps %xmm5, {{[0-9]*}}(%rsp)
40 ; LINUX-DAG: movaps %xmm6, {{[0-9]*}}(%rsp)
41 ; LINUX-DAG: movaps %xmm7, {{[0-9]*}}(%rsp)
42 ; LINUX: callq get_f
43 ; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm0
44 ; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm1
45 ; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm2
46 ; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm3
47 ; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm4
48 ; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm5
49 ; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm6
50 ; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm7
51 ; LINUX-DAG: movq {{.*}}, %rdi
52 ; LINUX-DAG: movq {{.*}}, %rsi
53 ; LINUX-DAG: movq {{.*}}, %rdx
54 ; LINUX-DAG: movq {{.*}}, %rcx
55 ; LINUX-DAG: movq {{.*}}, %r8
56 ; LINUX-DAG: movq {{.*}}, %r9
57 ; LINUX-DAG: movb {{.*}}, %al
58 ; LINUX: jmpq *{{.*}}  # TAILCALL
59
60 ; WINDOWS-LABEL: f_thunk:
61 ; WINDOWS-NOT: mov{{.}}ps
62 ; WINDOWS-DAG: movq %rdx, {{.*}}
63 ; WINDOWS-DAG: movq %rcx, {{.*}}
64 ; WINDOWS-DAG: movq %r8, {{.*}}
65 ; WINDOWS-DAG: movq %r9, {{.*}}
66 ; WINDOWS-NOT: mov{{.}}ps
67 ; WINDOWS: callq get_f
68 ; WINDOWS-NOT: mov{{.}}ps
69 ; WINDOWS-DAG: movq {{.*}}, %rdx
70 ; WINDOWS-DAG: movq {{.*}}, %rcx
71 ; WINDOWS-DAG: movq {{.*}}, %r8
72 ; WINDOWS-DAG: movq {{.*}}, %r9
73 ; WINDOWS-NOT: mov{{.}}ps
74 ; WINDOWS: jmpq *{{.*}} # TAILCALL
75
76 ; No regparms on normal x86 conventions.
77
78 ; X86-LABEL: _f_thunk:
79 ; X86: calll _get_f
80 ; X86: jmpl *{{.*}} # TAILCALL
81
82 ; This thunk shouldn't require any spills and reloads, assuming the register
83 ; allocator knows what it's doing.
84
85 define void @g_thunk(i8* %fptr_i8, ...) {
86   %fptr = bitcast i8* %fptr_i8 to void (i8*, ...)*
87   musttail call void (i8*, ...)* %fptr(i8* %fptr_i8, ...)
88   ret void
89 }
90
91 ; LINUX-LABEL: g_thunk:
92 ; LINUX-NOT: movq
93 ; LINUX: jmpq *%rdi  # TAILCALL
94
95 ; WINDOWS-LABEL: g_thunk:
96 ; WINDOWS-NOT: movq
97 ; WINDOWS: jmpq *%rcx # TAILCALL
98
99 ; X86-LABEL: _g_thunk:
100 ; X86: jmpl *%eax # TAILCALL
101
102 ; Do a simple multi-exit multi-bb test.
103
104 %struct.Foo = type { i1, i8*, i8* }
105
106 @g = external global i32
107
108 define void @h_thunk(%struct.Foo* %this, ...) {
109   %cond_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 0
110   %cond = load i1, i1* %cond_p
111   br i1 %cond, label %then, label %else
112
113 then:
114   %a_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 1
115   %a_i8 = load i8*, i8** %a_p
116   %a = bitcast i8* %a_i8 to void (%struct.Foo*, ...)*
117   musttail call void (%struct.Foo*, ...)* %a(%struct.Foo* %this, ...)
118   ret void
119
120 else:
121   %b_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 2
122   %b_i8 = load i8*, i8** %b_p
123   %b = bitcast i8* %b_i8 to void (%struct.Foo*, ...)*
124   store i32 42, i32* @g
125   musttail call void (%struct.Foo*, ...)* %b(%struct.Foo* %this, ...)
126   ret void
127 }
128
129 ; LINUX-LABEL: h_thunk:
130 ; LINUX: jne
131 ; LINUX: jmpq *{{.*}} # TAILCALL
132 ; LINUX: jmpq *{{.*}} # TAILCALL
133 ; WINDOWS-LABEL: h_thunk:
134 ; WINDOWS: jne
135 ; WINDOWS: jmpq *{{.*}} # TAILCALL
136 ; WINDOWS: jmpq *{{.*}} # TAILCALL
137 ; X86-LABEL: _h_thunk:
138 ; X86: jne
139 ; X86: jmpl *{{.*}} # TAILCALL
140 ; X86: jmpl *{{.*}} # TAILCALL