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
7
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.
11
12declare void @llvm.va_start(i8*) nounwind
13
14declare void(i8*, ...)* @get_f(i8* %this)
15
16define 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:    movaps %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
41; LINUX-NEXT:    movaps %xmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
42; LINUX-NEXT:    movaps %xmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
43; LINUX-NEXT:    movaps %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
44; LINUX-NEXT:    movaps %xmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
45; LINUX-NEXT:    movaps %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
46; LINUX-NEXT:    movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
47; LINUX-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
48; LINUX-NEXT:    movb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
49; LINUX-NEXT:    movq %r9, %r15
50; LINUX-NEXT:    movq %r8, %r12
51; LINUX-NEXT:    movq %rcx, %r13
52; LINUX-NEXT:    movq %rdx, %rbp
53; LINUX-NEXT:    movq %rsi, %rbx
54; LINUX-NEXT:    movq %rdi, %r14
55; LINUX-NEXT:    movq %rsi, {{[0-9]+}}(%rsp)
56; LINUX-NEXT:    movq %rdx, {{[0-9]+}}(%rsp)
57; LINUX-NEXT:    movq %rcx, {{[0-9]+}}(%rsp)
58; LINUX-NEXT:    movq %r8, {{[0-9]+}}(%rsp)
59; LINUX-NEXT:    movq %r9, {{[0-9]+}}(%rsp)
60; LINUX-NEXT:    testb %al, %al
61; LINUX-NEXT:    je .LBB0_2
62; LINUX-NEXT:  # %bb.1:
63; LINUX-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
64; LINUX-NEXT:    movaps %xmm1, {{[0-9]+}}(%rsp)
65; LINUX-NEXT:    movaps %xmm2, {{[0-9]+}}(%rsp)
66; LINUX-NEXT:    movaps %xmm3, {{[0-9]+}}(%rsp)
67; LINUX-NEXT:    movaps %xmm4, {{[0-9]+}}(%rsp)
68; LINUX-NEXT:    movaps %xmm5, {{[0-9]+}}(%rsp)
69; LINUX-NEXT:    movaps %xmm6, {{[0-9]+}}(%rsp)
70; LINUX-NEXT:    movaps %xmm7, {{[0-9]+}}(%rsp)
71; LINUX-NEXT:  .LBB0_2:
72; LINUX-NEXT:    leaq {{[0-9]+}}(%rsp), %rax
73; LINUX-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
74; LINUX-NEXT:    leaq {{[0-9]+}}(%rsp), %rax
75; LINUX-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
76; LINUX-NEXT:    movabsq $206158430216, %rax # imm = 0x3000000008
77; LINUX-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
78; LINUX-NEXT:    callq get_f@PLT
79; LINUX-NEXT:    movq %rax, %r11
80; LINUX-NEXT:    movq %r14, %rdi
81; LINUX-NEXT:    movq %rbx, %rsi
82; LINUX-NEXT:    movq %rbp, %rdx
83; LINUX-NEXT:    movq %r13, %rcx
84; LINUX-NEXT:    movq %r12, %r8
85; LINUX-NEXT:    movq %r15, %r9
86; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
87; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
88; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
89; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload
90; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload
91; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm5 # 16-byte Reload
92; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm6 # 16-byte Reload
93; LINUX-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm7 # 16-byte Reload
94; LINUX-NEXT:    movb {{[-0-9]+}}(%r{{[sb]}}p), %al # 1-byte Reload
95; LINUX-NEXT:    addq $360, %rsp # imm = 0x168
96; LINUX-NEXT:    .cfi_def_cfa_offset 56
97; LINUX-NEXT:    popq %rbx
98; LINUX-NEXT:    .cfi_def_cfa_offset 48
99; LINUX-NEXT:    popq %r12
100; LINUX-NEXT:    .cfi_def_cfa_offset 40
101; LINUX-NEXT:    popq %r13
102; LINUX-NEXT:    .cfi_def_cfa_offset 32
103; LINUX-NEXT:    popq %r14
104; LINUX-NEXT:    .cfi_def_cfa_offset 24
105; LINUX-NEXT:    popq %r15
106; LINUX-NEXT:    .cfi_def_cfa_offset 16
107; LINUX-NEXT:    popq %rbp
108; LINUX-NEXT:    .cfi_def_cfa_offset 8
109; LINUX-NEXT:    jmpq *%r11 # TAILCALL
110;
111; LINUX-X32-LABEL: f_thunk:
112; LINUX-X32:       # %bb.0:
113; LINUX-X32-NEXT:    pushq %rbp
114; LINUX-X32-NEXT:    .cfi_def_cfa_offset 16
115; LINUX-X32-NEXT:    pushq %r15
116; LINUX-X32-NEXT:    .cfi_def_cfa_offset 24
117; LINUX-X32-NEXT:    pushq %r14
118; LINUX-X32-NEXT:    .cfi_def_cfa_offset 32
119; LINUX-X32-NEXT:    pushq %r13
120; LINUX-X32-NEXT:    .cfi_def_cfa_offset 40
121; LINUX-X32-NEXT:    pushq %r12
122; LINUX-X32-NEXT:    .cfi_def_cfa_offset 48
123; LINUX-X32-NEXT:    pushq %rbx
124; LINUX-X32-NEXT:    .cfi_def_cfa_offset 56
125; LINUX-X32-NEXT:    subl $344, %esp # imm = 0x158
126; LINUX-X32-NEXT:    .cfi_def_cfa_offset 400
127; LINUX-X32-NEXT:    .cfi_offset %rbx, -56
128; LINUX-X32-NEXT:    .cfi_offset %r12, -48
129; LINUX-X32-NEXT:    .cfi_offset %r13, -40
130; LINUX-X32-NEXT:    .cfi_offset %r14, -32
131; LINUX-X32-NEXT:    .cfi_offset %r15, -24
132; LINUX-X32-NEXT:    .cfi_offset %rbp, -16
133; LINUX-X32-NEXT:    movaps %xmm7, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
134; LINUX-X32-NEXT:    movaps %xmm6, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
135; LINUX-X32-NEXT:    movaps %xmm5, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
136; LINUX-X32-NEXT:    movaps %xmm4, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
137; LINUX-X32-NEXT:    movaps %xmm3, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
138; LINUX-X32-NEXT:    movaps %xmm2, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
139; LINUX-X32-NEXT:    movaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
140; LINUX-X32-NEXT:    movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
141; LINUX-X32-NEXT:    movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill
142; LINUX-X32-NEXT:    movq %r9, %r15
143; LINUX-X32-NEXT:    movq %r8, %r12
144; LINUX-X32-NEXT:    movq %rcx, %r13
145; LINUX-X32-NEXT:    movq %rdx, %rbp
146; LINUX-X32-NEXT:    movq %rsi, %rbx
147; LINUX-X32-NEXT:    movq %rdi, %r14
148; LINUX-X32-NEXT:    movq %rsi, {{[0-9]+}}(%esp)
149; LINUX-X32-NEXT:    movq %rdx, {{[0-9]+}}(%esp)
150; LINUX-X32-NEXT:    movq %rcx, {{[0-9]+}}(%esp)
151; LINUX-X32-NEXT:    movq %r8, {{[0-9]+}}(%esp)
152; LINUX-X32-NEXT:    movq %r9, {{[0-9]+}}(%esp)
153; LINUX-X32-NEXT:    testb %al, %al
154; LINUX-X32-NEXT:    je .LBB0_2
155; LINUX-X32-NEXT:  # %bb.1:
156; LINUX-X32-NEXT:    movaps %xmm0, {{[0-9]+}}(%esp)
157; LINUX-X32-NEXT:    movaps %xmm1, {{[0-9]+}}(%esp)
158; LINUX-X32-NEXT:    movaps %xmm2, {{[0-9]+}}(%esp)
159; LINUX-X32-NEXT:    movaps %xmm3, {{[0-9]+}}(%esp)
160; LINUX-X32-NEXT:    movaps %xmm4, {{[0-9]+}}(%esp)
161; LINUX-X32-NEXT:    movaps %xmm5, {{[0-9]+}}(%esp)
162; LINUX-X32-NEXT:    movaps %xmm6, {{[0-9]+}}(%esp)
163; LINUX-X32-NEXT:    movaps %xmm7, {{[0-9]+}}(%esp)
164; LINUX-X32-NEXT:  .LBB0_2:
165; LINUX-X32-NEXT:    leal {{[0-9]+}}(%rsp), %eax
166; LINUX-X32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
167; LINUX-X32-NEXT:    leal {{[0-9]+}}(%rsp), %eax
168; LINUX-X32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
169; LINUX-X32-NEXT:    movabsq $206158430216, %rax # imm = 0x3000000008
170; LINUX-X32-NEXT:    movq %rax, {{[0-9]+}}(%esp)
171; LINUX-X32-NEXT:    callq get_f@PLT
172; LINUX-X32-NEXT:    movl %eax, %r11d
173; LINUX-X32-NEXT:    movq %r14, %rdi
174; LINUX-X32-NEXT:    movq %rbx, %rsi
175; LINUX-X32-NEXT:    movq %rbp, %rdx
176; LINUX-X32-NEXT:    movq %r13, %rcx
177; LINUX-X32-NEXT:    movq %r12, %r8
178; LINUX-X32-NEXT:    movq %r15, %r9
179; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 # 16-byte Reload
180; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 # 16-byte Reload
181; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 # 16-byte Reload
182; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm3 # 16-byte Reload
183; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm4 # 16-byte Reload
184; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm5 # 16-byte Reload
185; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm6 # 16-byte Reload
186; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm7 # 16-byte Reload
187; LINUX-X32-NEXT:    movb {{[-0-9]+}}(%e{{[sb]}}p), %al # 1-byte Reload
188; LINUX-X32-NEXT:    addl $344, %esp # imm = 0x158
189; LINUX-X32-NEXT:    .cfi_def_cfa_offset 56
190; LINUX-X32-NEXT:    popq %rbx
191; LINUX-X32-NEXT:    .cfi_def_cfa_offset 48
192; LINUX-X32-NEXT:    popq %r12
193; LINUX-X32-NEXT:    .cfi_def_cfa_offset 40
194; LINUX-X32-NEXT:    popq %r13
195; LINUX-X32-NEXT:    .cfi_def_cfa_offset 32
196; LINUX-X32-NEXT:    popq %r14
197; LINUX-X32-NEXT:    .cfi_def_cfa_offset 24
198; LINUX-X32-NEXT:    popq %r15
199; LINUX-X32-NEXT:    .cfi_def_cfa_offset 16
200; LINUX-X32-NEXT:    popq %rbp
201; LINUX-X32-NEXT:    .cfi_def_cfa_offset 8
202; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
203;
204; WINDOWS-LABEL: f_thunk:
205; WINDOWS:       # %bb.0:
206; WINDOWS-NEXT:    pushq %r14
207; WINDOWS-NEXT:    .seh_pushreg %r14
208; WINDOWS-NEXT:    pushq %rsi
209; WINDOWS-NEXT:    .seh_pushreg %rsi
210; WINDOWS-NEXT:    pushq %rdi
211; WINDOWS-NEXT:    .seh_pushreg %rdi
212; WINDOWS-NEXT:    pushq %rbx
213; WINDOWS-NEXT:    .seh_pushreg %rbx
214; WINDOWS-NEXT:    subq $72, %rsp
215; WINDOWS-NEXT:    .seh_stackalloc 72
216; WINDOWS-NEXT:    .seh_endprologue
217; WINDOWS-NEXT:    movq %r9, %r14
218; WINDOWS-NEXT:    movq %r8, %rdi
219; WINDOWS-NEXT:    movq %rdx, %rbx
220; WINDOWS-NEXT:    movq %rcx, %rsi
221; WINDOWS-NEXT:    movq %rdx, {{[0-9]+}}(%rsp)
222; WINDOWS-NEXT:    movq %r8, {{[0-9]+}}(%rsp)
223; WINDOWS-NEXT:    movq %r9, {{[0-9]+}}(%rsp)
224; WINDOWS-NEXT:    leaq {{[0-9]+}}(%rsp), %rax
225; WINDOWS-NEXT:    movq %rax, {{[0-9]+}}(%rsp)
226; WINDOWS-NEXT:    callq get_f
227; WINDOWS-NEXT:    movq %rsi, %rcx
228; WINDOWS-NEXT:    movq %rbx, %rdx
229; WINDOWS-NEXT:    movq %rdi, %r8
230; WINDOWS-NEXT:    movq %r14, %r9
231; WINDOWS-NEXT:    addq $72, %rsp
232; WINDOWS-NEXT:    popq %rbx
233; WINDOWS-NEXT:    popq %rdi
234; WINDOWS-NEXT:    popq %rsi
235; WINDOWS-NEXT:    popq %r14
236; WINDOWS-NEXT:    rex64 jmpq *%rax # TAILCALL
237; WINDOWS-NEXT:    .seh_endproc
238;
239; X86-NOSSE-LABEL: f_thunk:
240; X86-NOSSE:       # %bb.0:
241; X86-NOSSE-NEXT:    pushl %ebp
242; X86-NOSSE-NEXT:    movl %esp, %ebp
243; X86-NOSSE-NEXT:    pushl %esi
244; X86-NOSSE-NEXT:    andl $-16, %esp
245; X86-NOSSE-NEXT:    subl $32, %esp
246; X86-NOSSE-NEXT:    movl 8(%ebp), %esi
247; X86-NOSSE-NEXT:    leal 12(%ebp), %eax
248; X86-NOSSE-NEXT:    movl %eax, (%esp)
249; X86-NOSSE-NEXT:    pushl %esi
250; X86-NOSSE-NEXT:    calll _get_f
251; X86-NOSSE-NEXT:    addl $4, %esp
252; X86-NOSSE-NEXT:    movl %esi, 8(%ebp)
253; X86-NOSSE-NEXT:    leal -4(%ebp), %esp
254; X86-NOSSE-NEXT:    popl %esi
255; X86-NOSSE-NEXT:    popl %ebp
256; X86-NOSSE-NEXT:    jmpl *%eax # TAILCALL
257;
258; X86-SSE-LABEL: f_thunk:
259; X86-SSE:       # %bb.0:
260; X86-SSE-NEXT:    pushl %ebp
261; X86-SSE-NEXT:    movl %esp, %ebp
262; X86-SSE-NEXT:    pushl %esi
263; X86-SSE-NEXT:    andl $-16, %esp
264; X86-SSE-NEXT:    subl $80, %esp
265; X86-SSE-NEXT:    movaps %xmm2, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
266; X86-SSE-NEXT:    movaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
267; X86-SSE-NEXT:    movaps %xmm0, (%esp) # 16-byte Spill
268; X86-SSE-NEXT:    movl 8(%ebp), %esi
269; X86-SSE-NEXT:    leal 12(%ebp), %eax
270; X86-SSE-NEXT:    movl %eax, {{[0-9]+}}(%esp)
271; X86-SSE-NEXT:    pushl %esi
272; X86-SSE-NEXT:    calll _get_f
273; X86-SSE-NEXT:    addl $4, %esp
274; X86-SSE-NEXT:    movl %esi, 8(%ebp)
275; X86-SSE-NEXT:    movaps (%esp), %xmm0 # 16-byte Reload
276; X86-SSE-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 # 16-byte Reload
277; X86-SSE-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 # 16-byte Reload
278; X86-SSE-NEXT:    leal -4(%ebp), %esp
279; X86-SSE-NEXT:    popl %esi
280; X86-SSE-NEXT:    popl %ebp
281; X86-SSE-NEXT:    jmpl *%eax # TAILCALL
282  %ap = alloca [4 x i8*], align 16
283  %ap_i8 = bitcast [4 x i8*]* %ap to i8*
284  call void @llvm.va_start(i8* %ap_i8)
285
286  %fptr = call void(i8*, ...)*(i8*) @get_f(i8* %this)
287  musttail call void (i8*, ...) %fptr(i8* %this, ...)
288  ret void
289}
290
291; Save and restore 6 GPRs, 8 XMMs, and AL around the call.
292
293; No regparms on normal x86 conventions.
294
295; This thunk shouldn't require any spills and reloads, assuming the register
296; allocator knows what it's doing.
297
298define void @g_thunk(i8* %fptr_i8, ...) {
299; LINUX-LABEL: g_thunk:
300; LINUX:       # %bb.0:
301; LINUX-NEXT:    jmpq *%rdi # TAILCALL
302;
303; LINUX-X32-LABEL: g_thunk:
304; LINUX-X32:       # %bb.0:
305; LINUX-X32-NEXT:    jmpq *%rdi # TAILCALL
306;
307; WINDOWS-LABEL: g_thunk:
308; WINDOWS:       # %bb.0:
309; WINDOWS-NEXT:    rex64 jmpq *%rcx # TAILCALL
310;
311; X86-LABEL: g_thunk:
312; X86:       # %bb.0:
313; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
314; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
315; X86-NEXT:    jmpl *%eax # TAILCALL
316  %fptr = bitcast i8* %fptr_i8 to void (i8*, ...)*
317  musttail call void (i8*, ...) %fptr(i8* %fptr_i8, ...)
318  ret void
319}
320
321; Do a simple multi-exit multi-bb test.
322
323%struct.Foo = type { i1, i8*, i8* }
324
325@g = external dso_local global i32
326
327define void @h_thunk(%struct.Foo* %this, ...) {
328; LINUX-LABEL: h_thunk:
329; LINUX:       # %bb.0:
330; LINUX-NEXT:    cmpb $1, (%rdi)
331; LINUX-NEXT:    jne .LBB2_2
332; LINUX-NEXT:  # %bb.1: # %then
333; LINUX-NEXT:    movq 8(%rdi), %r11
334; LINUX-NEXT:    jmpq *%r11 # TAILCALL
335; LINUX-NEXT:  .LBB2_2: # %else
336; LINUX-NEXT:    movq 16(%rdi), %r11
337; LINUX-NEXT:    movl $42, g(%rip)
338; LINUX-NEXT:    jmpq *%r11 # TAILCALL
339;
340; LINUX-X32-LABEL: h_thunk:
341; LINUX-X32:       # %bb.0:
342; LINUX-X32-NEXT:    cmpb $1, (%edi)
343; LINUX-X32-NEXT:    jne .LBB2_2
344; LINUX-X32-NEXT:  # %bb.1: # %then
345; LINUX-X32-NEXT:    movl 4(%edi), %r11d
346; LINUX-X32-NEXT:    movl %edi, %edi
347; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
348; LINUX-X32-NEXT:  .LBB2_2: # %else
349; LINUX-X32-NEXT:    movl 8(%edi), %r11d
350; LINUX-X32-NEXT:    movl $42, g(%rip)
351; LINUX-X32-NEXT:    movl %edi, %edi
352; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
353;
354; WINDOWS-LABEL: h_thunk:
355; WINDOWS:       # %bb.0:
356; WINDOWS-NEXT:    cmpb $1, (%rcx)
357; WINDOWS-NEXT:    jne .LBB2_2
358; WINDOWS-NEXT:  # %bb.1: # %then
359; WINDOWS-NEXT:    movq 8(%rcx), %rax
360; WINDOWS-NEXT:    rex64 jmpq *%rax # TAILCALL
361; WINDOWS-NEXT:  .LBB2_2: # %else
362; WINDOWS-NEXT:    movq 16(%rcx), %rax
363; WINDOWS-NEXT:    movl $42, g(%rip)
364; WINDOWS-NEXT:    rex64 jmpq *%rax # TAILCALL
365;
366; X86-LABEL: h_thunk:
367; X86:       # %bb.0:
368; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
369; X86-NEXT:    cmpb $1, (%eax)
370; X86-NEXT:    jne LBB2_2
371; X86-NEXT:  # %bb.1: # %then
372; X86-NEXT:    movl 4(%eax), %ecx
373; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
374; X86-NEXT:    jmpl *%ecx # TAILCALL
375; X86-NEXT:  LBB2_2: # %else
376; X86-NEXT:    movl 8(%eax), %ecx
377; X86-NEXT:    movl $42, _g
378; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
379; X86-NEXT:    jmpl *%ecx # TAILCALL
380  %cond_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 0
381  %cond = load i1, i1* %cond_p
382  br i1 %cond, label %then, label %else
383
384then:
385  %a_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 1
386  %a_i8 = load i8*, i8** %a_p
387  %a = bitcast i8* %a_i8 to void (%struct.Foo*, ...)*
388  musttail call void (%struct.Foo*, ...) %a(%struct.Foo* %this, ...)
389  ret void
390
391else:
392  %b_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 2
393  %b_i8 = load i8*, i8** %b_p
394  %b = bitcast i8* %b_i8 to void (%struct.Foo*, ...)*
395  store i32 42, i32* @g
396  musttail call void (%struct.Foo*, ...) %b(%struct.Foo* %this, ...)
397  ret void
398}
399