[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / X86 / musttail-varargs.ll
blob1144ce8eba74256ce29460309eeda4310e33be30
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-linux | FileCheck %s --check-prefix=LINUX
3 ; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-linux-gnux32 | FileCheck %s --check-prefix=LINUX-X32
4 ; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-windows | FileCheck %s --check-prefix=WINDOWS
5 ; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=i686-windows | FileCheck %s --check-prefix=X86 --check-prefix=X86-NOSSE
6 ; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=i686-windows -mattr=+sse2 | FileCheck %s --check-prefix=X86 --check-prefix=X86-SSE
8 ; Test that we actually spill and reload all arguments in the variadic argument
9 ; pack. Doing a normal call will clobber all argument registers, and we will
10 ; spill around it. A simple adjustment should not require any XMM spills.
12 declare void @llvm.va_start(i8*) nounwind
14 declare void(i8*, ...)* @get_f(i8* %this)
16 define void @f_thunk(i8* %this, ...) {
17   ; Use va_start so that we exercise the combination.
18 ; LINUX-LABEL: f_thunk:
19 ; LINUX:       # %bb.0:
20 ; LINUX-NEXT:    pushq %rbp
21 ; LINUX-NEXT:    .cfi_def_cfa_offset 16
22 ; LINUX-NEXT:    pushq %r15
23 ; LINUX-NEXT:    .cfi_def_cfa_offset 24
24 ; LINUX-NEXT:    pushq %r14
25 ; LINUX-NEXT:    .cfi_def_cfa_offset 32
26 ; LINUX-NEXT:    pushq %r13
27 ; LINUX-NEXT:    .cfi_def_cfa_offset 40
28 ; LINUX-NEXT:    pushq %r12
29 ; LINUX-NEXT:    .cfi_def_cfa_offset 48
30 ; LINUX-NEXT:    pushq %rbx
31 ; LINUX-NEXT:    .cfi_def_cfa_offset 56
32 ; LINUX-NEXT:    subq $360, %rsp # imm = 0x168
33 ; LINUX-NEXT:    .cfi_def_cfa_offset 416
34 ; LINUX-NEXT:    .cfi_offset %rbx, -56
35 ; LINUX-NEXT:    .cfi_offset %r12, -48
36 ; LINUX-NEXT:    .cfi_offset %r13, -40
37 ; LINUX-NEXT:    .cfi_offset %r14, -32
38 ; LINUX-NEXT:    .cfi_offset %r15, -24
39 ; LINUX-NEXT:    .cfi_offset %rbp, -16
40 ; LINUX-NEXT:    movq %r9, %r15
41 ; LINUX-NEXT:    movq %r8, %r12
42 ; LINUX-NEXT:    movq %rcx, %r13
43 ; LINUX-NEXT:    movq %rdx, %rbp
44 ; LINUX-NEXT:    movq %rsi, %rbx
45 ; LINUX-NEXT:    movq %rdi, %r14
46 ; LINUX-NEXT:    movb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
47 ; LINUX-NEXT:    testb %al, %al
48 ; LINUX-NEXT:    je .LBB0_2
49 ; LINUX-NEXT:  # %bb.1:
50 ; LINUX-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
51 ; LINUX-NEXT:    movaps %xmm1, {{[0-9]+}}(%rsp)
52 ; LINUX-NEXT:    movaps %xmm2, {{[0-9]+}}(%rsp)
53 ; LINUX-NEXT:    movaps %xmm3, {{[0-9]+}}(%rsp)
54 ; LINUX-NEXT:    movaps %xmm4, {{[0-9]+}}(%rsp)
55 ; LINUX-NEXT:    movaps %xmm5, {{[0-9]+}}(%rsp)
56 ; LINUX-NEXT:    movaps %xmm6, {{[0-9]+}}(%rsp)
57 ; LINUX-NEXT:    movaps %xmm7, {{[0-9]+}}(%rsp)
58 ; LINUX-NEXT:  .LBB0_2:
59 ; LINUX-NEXT:    movq %rbx, {{[0-9]+}}(%rsp)
60 ; LINUX-NEXT:    movq %rbp, {{[0-9]+}}(%rsp)
61 ; LINUX-NEXT:    movq %r13, {{[0-9]+}}(%rsp)
62 ; LINUX-NEXT:    movq %r12, {{[0-9]+}}(%rsp)
63 ; LINUX-NEXT:    movq %r15, {{[0-9]+}}(%rsp)
64 ; LINUX-NEXT:    leaq {{[0-9]+}}(%rsp), %rax
65 ; LINUX-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
66 ; LINUX-NEXT:    leaq {{[0-9]+}}(%rsp), %rax
67 ; LINUX-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
68 ; LINUX-NEXT:    movabsq $206158430216, %rax # imm = 0x3000000008
69 ; LINUX-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
70 ; LINUX-NEXT:    movq %r14, %rdi
71 ; LINUX-NEXT:    movaps %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
72 ; LINUX-NEXT:    movaps %xmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
73 ; LINUX-NEXT:    movaps %xmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
74 ; LINUX-NEXT:    movaps %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
75 ; LINUX-NEXT:    movaps %xmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
76 ; LINUX-NEXT:    movaps %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
77 ; LINUX-NEXT:    movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
78 ; LINUX-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
79 ; LINUX-NEXT:    callq get_f
80 ; LINUX-NEXT:    movq %rax, %r11
81 ; LINUX-NEXT:    movq %r14, %rdi
82 ; LINUX-NEXT:    movq %rbx, %rsi
83 ; LINUX-NEXT:    movq %rbp, %rdx
84 ; LINUX-NEXT:    movq %r13, %rcx
85 ; LINUX-NEXT:    movq %r12, %r8
86 ; LINUX-NEXT:    movq %r15, %r9
87 ; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
88 ; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
89 ; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
90 ; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload
91 ; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload
92 ; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm5 # 16-byte Reload
93 ; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm6 # 16-byte Reload
94 ; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm7 # 16-byte Reload
95 ; LINUX-NEXT:    movb {{[-0-9]+}}(%r{{[sb]}}p), %al # 1-byte Reload
96 ; LINUX-NEXT:    addq $360, %rsp # imm = 0x168
97 ; LINUX-NEXT:    .cfi_def_cfa_offset 56
98 ; LINUX-NEXT:    popq %rbx
99 ; LINUX-NEXT:    .cfi_def_cfa_offset 48
100 ; LINUX-NEXT:    popq %r12
101 ; LINUX-NEXT:    .cfi_def_cfa_offset 40
102 ; LINUX-NEXT:    popq %r13
103 ; LINUX-NEXT:    .cfi_def_cfa_offset 32
104 ; LINUX-NEXT:    popq %r14
105 ; LINUX-NEXT:    .cfi_def_cfa_offset 24
106 ; LINUX-NEXT:    popq %r15
107 ; LINUX-NEXT:    .cfi_def_cfa_offset 16
108 ; LINUX-NEXT:    popq %rbp
109 ; LINUX-NEXT:    .cfi_def_cfa_offset 8
110 ; LINUX-NEXT:    jmpq *%r11 # TAILCALL
112 ; LINUX-X32-LABEL: f_thunk:
113 ; LINUX-X32:       # %bb.0:
114 ; LINUX-X32-NEXT:    pushq %rbp
115 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 16
116 ; LINUX-X32-NEXT:    pushq %r15
117 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 24
118 ; LINUX-X32-NEXT:    pushq %r14
119 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 32
120 ; LINUX-X32-NEXT:    pushq %r13
121 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 40
122 ; LINUX-X32-NEXT:    pushq %r12
123 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 48
124 ; LINUX-X32-NEXT:    pushq %rbx
125 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 56
126 ; LINUX-X32-NEXT:    subl $344, %esp # imm = 0x158
127 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 400
128 ; LINUX-X32-NEXT:    .cfi_offset %rbx, -56
129 ; LINUX-X32-NEXT:    .cfi_offset %r12, -48
130 ; LINUX-X32-NEXT:    .cfi_offset %r13, -40
131 ; LINUX-X32-NEXT:    .cfi_offset %r14, -32
132 ; LINUX-X32-NEXT:    .cfi_offset %r15, -24
133 ; LINUX-X32-NEXT:    .cfi_offset %rbp, -16
134 ; LINUX-X32-NEXT:    movq %r9, %r15
135 ; LINUX-X32-NEXT:    movq %r8, %r12
136 ; LINUX-X32-NEXT:    movq %rcx, %r13
137 ; LINUX-X32-NEXT:    movq %rdx, %rbp
138 ; LINUX-X32-NEXT:    movq %rsi, %rbx
139 ; LINUX-X32-NEXT:    movl %edi, %r14d
140 ; LINUX-X32-NEXT:    movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill
141 ; LINUX-X32-NEXT:    testb %al, %al
142 ; LINUX-X32-NEXT:    je .LBB0_2
143 ; LINUX-X32-NEXT:  # %bb.1:
144 ; LINUX-X32-NEXT:    movaps %xmm0, {{[0-9]+}}(%esp)
145 ; LINUX-X32-NEXT:    movaps %xmm1, {{[0-9]+}}(%esp)
146 ; LINUX-X32-NEXT:    movaps %xmm2, {{[0-9]+}}(%esp)
147 ; LINUX-X32-NEXT:    movaps %xmm3, {{[0-9]+}}(%esp)
148 ; LINUX-X32-NEXT:    movaps %xmm4, {{[0-9]+}}(%esp)
149 ; LINUX-X32-NEXT:    movaps %xmm5, {{[0-9]+}}(%esp)
150 ; LINUX-X32-NEXT:    movaps %xmm6, {{[0-9]+}}(%esp)
151 ; LINUX-X32-NEXT:    movaps %xmm7, {{[0-9]+}}(%esp)
152 ; LINUX-X32-NEXT:  .LBB0_2:
153 ; LINUX-X32-NEXT:    movq %rbx, {{[0-9]+}}(%esp)
154 ; LINUX-X32-NEXT:    movq %rbp, {{[0-9]+}}(%esp)
155 ; LINUX-X32-NEXT:    movq %r13, {{[0-9]+}}(%esp)
156 ; LINUX-X32-NEXT:    movq %r12, {{[0-9]+}}(%esp)
157 ; LINUX-X32-NEXT:    movq %r15, {{[0-9]+}}(%esp)
158 ; LINUX-X32-NEXT:    leal {{[0-9]+}}(%rsp), %eax
159 ; LINUX-X32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
160 ; LINUX-X32-NEXT:    leal {{[0-9]+}}(%rsp), %eax
161 ; LINUX-X32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
162 ; LINUX-X32-NEXT:    movabsq $206158430216, %rax # imm = 0x3000000008
163 ; LINUX-X32-NEXT:    movq %rax, {{[0-9]+}}(%esp)
164 ; LINUX-X32-NEXT:    movl %r14d, %edi
165 ; LINUX-X32-NEXT:    movaps %xmm7, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
166 ; LINUX-X32-NEXT:    movaps %xmm6, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
167 ; LINUX-X32-NEXT:    movaps %xmm5, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
168 ; LINUX-X32-NEXT:    movaps %xmm4, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
169 ; LINUX-X32-NEXT:    movaps %xmm3, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
170 ; LINUX-X32-NEXT:    movaps %xmm2, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
171 ; LINUX-X32-NEXT:    movaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
172 ; LINUX-X32-NEXT:    movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
173 ; LINUX-X32-NEXT:    callq get_f
174 ; LINUX-X32-NEXT:    movl %eax, %r11d
175 ; LINUX-X32-NEXT:    movl %r14d, %edi
176 ; LINUX-X32-NEXT:    movq %rbx, %rsi
177 ; LINUX-X32-NEXT:    movq %rbp, %rdx
178 ; LINUX-X32-NEXT:    movq %r13, %rcx
179 ; LINUX-X32-NEXT:    movq %r12, %r8
180 ; LINUX-X32-NEXT:    movq %r15, %r9
181 ; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 # 16-byte Reload
182 ; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 # 16-byte Reload
183 ; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 # 16-byte Reload
184 ; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm3 # 16-byte Reload
185 ; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm4 # 16-byte Reload
186 ; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm5 # 16-byte Reload
187 ; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm6 # 16-byte Reload
188 ; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm7 # 16-byte Reload
189 ; LINUX-X32-NEXT:    movb {{[-0-9]+}}(%e{{[sb]}}p), %al # 1-byte Reload
190 ; LINUX-X32-NEXT:    addl $344, %esp # imm = 0x158
191 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 56
192 ; LINUX-X32-NEXT:    popq %rbx
193 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 48
194 ; LINUX-X32-NEXT:    popq %r12
195 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 40
196 ; LINUX-X32-NEXT:    popq %r13
197 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 32
198 ; LINUX-X32-NEXT:    popq %r14
199 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 24
200 ; LINUX-X32-NEXT:    popq %r15
201 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 16
202 ; LINUX-X32-NEXT:    popq %rbp
203 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 8
204 ; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
206 ; WINDOWS-LABEL: f_thunk:
207 ; WINDOWS:       # %bb.0:
208 ; WINDOWS-NEXT:    pushq %r14
209 ; WINDOWS-NEXT:    .seh_pushreg %r14
210 ; WINDOWS-NEXT:    pushq %rsi
211 ; WINDOWS-NEXT:    .seh_pushreg %rsi
212 ; WINDOWS-NEXT:    pushq %rdi
213 ; WINDOWS-NEXT:    .seh_pushreg %rdi
214 ; WINDOWS-NEXT:    pushq %rbp
215 ; WINDOWS-NEXT:    .seh_pushreg %rbp
216 ; WINDOWS-NEXT:    pushq %rbx
217 ; WINDOWS-NEXT:    .seh_pushreg %rbx
218 ; WINDOWS-NEXT:    subq $64, %rsp
219 ; WINDOWS-NEXT:    .seh_stackalloc 64
220 ; WINDOWS-NEXT:    .seh_endprologue
221 ; WINDOWS-NEXT:    movl %eax, %r14d
222 ; WINDOWS-NEXT:    movq %r9, %rsi
223 ; WINDOWS-NEXT:    movq %r8, %rdi
224 ; WINDOWS-NEXT:    movq %rdx, %rbx
225 ; WINDOWS-NEXT:    movq %rcx, %rbp
226 ; WINDOWS-NEXT:    movq %rdx, {{[0-9]+}}(%rsp)
227 ; WINDOWS-NEXT:    movq %r8, {{[0-9]+}}(%rsp)
228 ; WINDOWS-NEXT:    movq %r9, {{[0-9]+}}(%rsp)
229 ; WINDOWS-NEXT:    leaq {{[0-9]+}}(%rsp), %rax
230 ; WINDOWS-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
231 ; WINDOWS-NEXT:    callq get_f
232 ; WINDOWS-NEXT:    movq %rax, %r10
233 ; WINDOWS-NEXT:    movq %rbp, %rcx
234 ; WINDOWS-NEXT:    movq %rbx, %rdx
235 ; WINDOWS-NEXT:    movq %rdi, %r8
236 ; WINDOWS-NEXT:    movq %rsi, %r9
237 ; WINDOWS-NEXT:    movl %r14d, %eax
238 ; WINDOWS-NEXT:    addq $64, %rsp
239 ; WINDOWS-NEXT:    popq %rbx
240 ; WINDOWS-NEXT:    popq %rbp
241 ; WINDOWS-NEXT:    popq %rdi
242 ; WINDOWS-NEXT:    popq %rsi
243 ; WINDOWS-NEXT:    popq %r14
244 ; WINDOWS-NEXT:    rex64 jmpq *%r10 # TAILCALL
245 ; WINDOWS-NEXT:    .seh_handlerdata
246 ; WINDOWS-NEXT:    .text
247 ; WINDOWS-NEXT:    .seh_endproc
249 ; X86-NOSSE-LABEL: f_thunk:
250 ; X86-NOSSE:       # %bb.0:
251 ; X86-NOSSE-NEXT:    pushl %ebp
252 ; X86-NOSSE-NEXT:    movl %esp, %ebp
253 ; X86-NOSSE-NEXT:    pushl %esi
254 ; X86-NOSSE-NEXT:    andl $-16, %esp
255 ; X86-NOSSE-NEXT:    subl $48, %esp
256 ; X86-NOSSE-NEXT:    movl 8(%ebp), %esi
257 ; X86-NOSSE-NEXT:    leal 12(%ebp), %eax
258 ; X86-NOSSE-NEXT:    movl %eax, {{[0-9]+}}(%esp)
259 ; X86-NOSSE-NEXT:    movl %esi, (%esp)
260 ; X86-NOSSE-NEXT:    calll _get_f
261 ; X86-NOSSE-NEXT:    movl %esi, 8(%ebp)
262 ; X86-NOSSE-NEXT:    leal -4(%ebp), %esp
263 ; X86-NOSSE-NEXT:    popl %esi
264 ; X86-NOSSE-NEXT:    popl %ebp
265 ; X86-NOSSE-NEXT:    jmpl *%eax # TAILCALL
267 ; X86-SSE-LABEL: f_thunk:
268 ; X86-SSE:       # %bb.0:
269 ; X86-SSE-NEXT:    pushl %ebp
270 ; X86-SSE-NEXT:    movl %esp, %ebp
271 ; X86-SSE-NEXT:    pushl %esi
272 ; X86-SSE-NEXT:    andl $-16, %esp
273 ; X86-SSE-NEXT:    subl $96, %esp
274 ; X86-SSE-NEXT:    movaps %xmm2, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
275 ; X86-SSE-NEXT:    movaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
276 ; X86-SSE-NEXT:    movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
277 ; X86-SSE-NEXT:    movl 8(%ebp), %esi
278 ; X86-SSE-NEXT:    leal 12(%ebp), %eax
279 ; X86-SSE-NEXT:    movl %eax, {{[0-9]+}}(%esp)
280 ; X86-SSE-NEXT:    movl %esi, (%esp)
281 ; X86-SSE-NEXT:    calll _get_f
282 ; X86-SSE-NEXT:    movl %esi, 8(%ebp)
283 ; X86-SSE-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 # 16-byte Reload
284 ; X86-SSE-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 # 16-byte Reload
285 ; X86-SSE-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 # 16-byte Reload
286 ; X86-SSE-NEXT:    leal -4(%ebp), %esp
287 ; X86-SSE-NEXT:    popl %esi
288 ; X86-SSE-NEXT:    popl %ebp
289 ; X86-SSE-NEXT:    jmpl *%eax # TAILCALL
290   %ap = alloca [4 x i8*], align 16
291   %ap_i8 = bitcast [4 x i8*]* %ap to i8*
292   call void @llvm.va_start(i8* %ap_i8)
294   %fptr = call void(i8*, ...)*(i8*) @get_f(i8* %this)
295   musttail call void (i8*, ...) %fptr(i8* %this, ...)
296   ret void
299 ; Save and restore 6 GPRs, 8 XMMs, and AL around the call.
301 ; No regparms on normal x86 conventions.
303 ; This thunk shouldn't require any spills and reloads, assuming the register
304 ; allocator knows what it's doing.
306 define void @g_thunk(i8* %fptr_i8, ...) {
307 ; LINUX-LABEL: g_thunk:
308 ; LINUX:       # %bb.0:
309 ; LINUX-NEXT:    pushq %rax
310 ; LINUX-NEXT:    .cfi_def_cfa_offset 16
311 ; LINUX-NEXT:    popq %r11
312 ; LINUX-NEXT:    .cfi_def_cfa_offset 8
313 ; LINUX-NEXT:    jmpq *%rdi # TAILCALL
315 ; LINUX-X32-LABEL: g_thunk:
316 ; LINUX-X32:       # %bb.0:
317 ; LINUX-X32-NEXT:    pushq %rax
318 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 16
319 ; LINUX-X32-NEXT:    movl %edi, %r11d
320 ; LINUX-X32-NEXT:    addl $8, %esp
321 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 8
322 ; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
324 ; WINDOWS-LABEL: g_thunk:
325 ; WINDOWS:       # %bb.0:
326 ; WINDOWS-NEXT:    subq $40, %rsp
327 ; WINDOWS-NEXT:    .seh_stackalloc 40
328 ; WINDOWS-NEXT:    .seh_endprologue
329 ; WINDOWS-NEXT:    addq $40, %rsp
330 ; WINDOWS-NEXT:    rex64 jmpq *%rcx # TAILCALL
331 ; WINDOWS-NEXT:    .seh_handlerdata
332 ; WINDOWS-NEXT:    .text
333 ; WINDOWS-NEXT:    .seh_endproc
335 ; X86-LABEL: g_thunk:
336 ; X86:       # %bb.0:
337 ; X86-NEXT:    pushl %eax
338 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
339 ; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
340 ; X86-NEXT:    popl %ecx
341 ; X86-NEXT:    jmpl *%eax # TAILCALL
342   %fptr = bitcast i8* %fptr_i8 to void (i8*, ...)*
343   musttail call void (i8*, ...) %fptr(i8* %fptr_i8, ...)
344   ret void
347 ; Do a simple multi-exit multi-bb test.
349 %struct.Foo = type { i1, i8*, i8* }
351 @g = external global i32
353 define void @h_thunk(%struct.Foo* %this, ...) {
354 ; LINUX-LABEL: h_thunk:
355 ; LINUX:       # %bb.0:
356 ; LINUX-NEXT:    pushq %rax
357 ; LINUX-NEXT:    .cfi_def_cfa_offset 16
358 ; LINUX-NEXT:    cmpb $1, (%rdi)
359 ; LINUX-NEXT:    jne .LBB2_2
360 ; LINUX-NEXT:  # %bb.1: # %then
361 ; LINUX-NEXT:    movq 8(%rdi), %r11
362 ; LINUX-NEXT:    addq $8, %rsp
363 ; LINUX-NEXT:    .cfi_def_cfa_offset 8
364 ; LINUX-NEXT:    jmpq *%r11 # TAILCALL
365 ; LINUX-NEXT:  .LBB2_2: # %else
366 ; LINUX-NEXT:    .cfi_def_cfa_offset 16
367 ; LINUX-NEXT:    movq 16(%rdi), %r11
368 ; LINUX-NEXT:    movl $42, {{.*}}(%rip)
369 ; LINUX-NEXT:    addq $8, %rsp
370 ; LINUX-NEXT:    .cfi_def_cfa_offset 8
371 ; LINUX-NEXT:    jmpq *%r11 # TAILCALL
373 ; LINUX-X32-LABEL: h_thunk:
374 ; LINUX-X32:       # %bb.0:
375 ; LINUX-X32-NEXT:    pushq %rax
376 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 16
377 ; LINUX-X32-NEXT:    cmpb $1, (%edi)
378 ; LINUX-X32-NEXT:    jne .LBB2_2
379 ; LINUX-X32-NEXT:  # %bb.1: # %then
380 ; LINUX-X32-NEXT:    movl 4(%edi), %r11d
381 ; LINUX-X32-NEXT:    addl $8, %esp
382 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 8
383 ; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
384 ; LINUX-X32-NEXT:  .LBB2_2: # %else
385 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 16
386 ; LINUX-X32-NEXT:    movl 8(%edi), %r11d
387 ; LINUX-X32-NEXT:    movl $42, {{.*}}(%rip)
388 ; LINUX-X32-NEXT:    addl $8, %esp
389 ; LINUX-X32-NEXT:    .cfi_def_cfa_offset 8
390 ; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
392 ; WINDOWS-LABEL: h_thunk:
393 ; WINDOWS:       # %bb.0:
394 ; WINDOWS-NEXT:    subq $40, %rsp
395 ; WINDOWS-NEXT:    .seh_stackalloc 40
396 ; WINDOWS-NEXT:    .seh_endprologue
397 ; WINDOWS-NEXT:    cmpb $1, (%rcx)
398 ; WINDOWS-NEXT:    jne .LBB2_2
399 ; WINDOWS-NEXT:  # %bb.1: # %then
400 ; WINDOWS-NEXT:    movq 8(%rcx), %r10
401 ; WINDOWS-NEXT:    addq $40, %rsp
402 ; WINDOWS-NEXT:    rex64 jmpq *%r10 # TAILCALL
403 ; WINDOWS-NEXT:  .LBB2_2: # %else
404 ; WINDOWS-NEXT:    movq 16(%rcx), %r10
405 ; WINDOWS-NEXT:    movl $42, {{.*}}(%rip)
406 ; WINDOWS-NEXT:    addq $40, %rsp
407 ; WINDOWS-NEXT:    rex64 jmpq *%r10 # TAILCALL
408 ; WINDOWS-NEXT:    .seh_handlerdata
409 ; WINDOWS-NEXT:    .text
410 ; WINDOWS-NEXT:    .seh_endproc
412 ; X86-LABEL: h_thunk:
413 ; X86:       # %bb.0:
414 ; X86-NEXT:    pushl %eax
415 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
416 ; X86-NEXT:    cmpb $1, (%eax)
417 ; X86-NEXT:    jne LBB2_2
418 ; X86-NEXT:  # %bb.1: # %then
419 ; X86-NEXT:    movl 4(%eax), %ecx
420 ; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
421 ; X86-NEXT:    popl %eax
422 ; X86-NEXT:    jmpl *%ecx # TAILCALL
423 ; X86-NEXT:  LBB2_2: # %else
424 ; X86-NEXT:    movl 8(%eax), %ecx
425 ; X86-NEXT:    movl $42, _g
426 ; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
427 ; X86-NEXT:    popl %eax
428 ; X86-NEXT:    jmpl *%ecx # TAILCALL
429   %cond_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 0
430   %cond = load i1, i1* %cond_p
431   br i1 %cond, label %then, label %else
433 then:
434   %a_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 1
435   %a_i8 = load i8*, i8** %a_p
436   %a = bitcast i8* %a_i8 to void (%struct.Foo*, ...)*
437   musttail call void (%struct.Foo*, ...) %a(%struct.Foo* %this, ...)
438   ret void
440 else:
441   %b_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 2
442   %b_i8 = load i8*, i8** %b_p
443   %b = bitcast i8* %b_i8 to void (%struct.Foo*, ...)*
444   store i32 42, i32* @g
445   musttail call void (%struct.Foo*, ...) %b(%struct.Foo* %this, ...)
446   ret void