xref: /llvm-project/llvm/test/CodeGen/X86/musttail-varargs.ll (revision c9017bc79397e12734b58165273ae70f328d0002)
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(ptr) nounwind
13
14declare ptr @get_f(ptr %this)
15
16define void @f_thunk(ptr %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:    movb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
41; LINUX-NEXT:    movaps %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
42; LINUX-NEXT:    movaps %xmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
43; LINUX-NEXT:    movaps %xmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
44; LINUX-NEXT:    movaps %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
45; LINUX-NEXT:    movaps %xmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
46; LINUX-NEXT:    movaps %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
47; LINUX-NEXT:    movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
48; LINUX-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
49; LINUX-NEXT:    movq %r9, %r14
50; LINUX-NEXT:    movq %r8, %r15
51; LINUX-NEXT:    movq %rcx, %r12
52; LINUX-NEXT:    movq %rdx, %r13
53; LINUX-NEXT:    movq %rsi, %rbp
54; LINUX-NEXT:    movq %rdi, %rbx
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 %rbx, %rdi
81; LINUX-NEXT:    movq %rbp, %rsi
82; LINUX-NEXT:    movq %r13, %rdx
83; LINUX-NEXT:    movq %r12, %rcx
84; LINUX-NEXT:    movq %r15, %r8
85; LINUX-NEXT:    movzbl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 1-byte Folded Reload
86; LINUX-NEXT:    movq %r14, %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:    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:    movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill
134; LINUX-X32-NEXT:    movaps %xmm7, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
135; LINUX-X32-NEXT:    movaps %xmm6, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
136; LINUX-X32-NEXT:    movaps %xmm5, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
137; LINUX-X32-NEXT:    movaps %xmm4, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
138; LINUX-X32-NEXT:    movaps %xmm3, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
139; LINUX-X32-NEXT:    movaps %xmm2, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
140; LINUX-X32-NEXT:    movaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
141; LINUX-X32-NEXT:    movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill
142; LINUX-X32-NEXT:    movq %r9, %r14
143; LINUX-X32-NEXT:    movq %r8, %r15
144; LINUX-X32-NEXT:    movq %rcx, %r12
145; LINUX-X32-NEXT:    movq %rdx, %r13
146; LINUX-X32-NEXT:    movq %rsi, %rbp
147; LINUX-X32-NEXT:    movq %rdi, %rbx
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 %rbx, %rdi
174; LINUX-X32-NEXT:    movq %rbp, %rsi
175; LINUX-X32-NEXT:    movq %r13, %rdx
176; LINUX-X32-NEXT:    movq %r12, %rcx
177; LINUX-X32-NEXT:    movq %r15, %r8
178; LINUX-X32-NEXT:    movzbl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 1-byte Folded Reload
179; LINUX-X32-NEXT:    movq %r14, %r9
180; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 # 16-byte Reload
181; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 # 16-byte Reload
182; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 # 16-byte Reload
183; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm3 # 16-byte Reload
184; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm4 # 16-byte Reload
185; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm5 # 16-byte Reload
186; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm6 # 16-byte Reload
187; LINUX-X32-NEXT:    movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm7 # 16-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, %rsi
218; WINDOWS-NEXT:    movq %r8, %rdi
219; WINDOWS-NEXT:    movq %rdx, %rbx
220; WINDOWS-NEXT:    movq %rcx, %r14
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 %r14, %rcx
228; WINDOWS-NEXT:    movq %rbx, %rdx
229; WINDOWS-NEXT:    movq %rdi, %r8
230; WINDOWS-NEXT:    movq %rsi, %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 ptr], align 16
283  call void @llvm.va_start(ptr %ap)
284
285  %fptr = call ptr(ptr) @get_f(ptr %this)
286  musttail call void (ptr, ...) %fptr(ptr %this, ...)
287  ret void
288}
289
290; Save and restore 6 GPRs, 8 XMMs, and AL around the call.
291
292; No regparms on normal x86 conventions.
293
294; This thunk shouldn't require any spills and reloads, assuming the register
295; allocator knows what it's doing.
296
297define void @g_thunk(ptr %fptr_i8, ...) {
298; LINUX-LABEL: g_thunk:
299; LINUX:       # %bb.0:
300; LINUX-NEXT:    jmpq *%rdi # TAILCALL
301;
302; LINUX-X32-LABEL: g_thunk:
303; LINUX-X32:       # %bb.0:
304; LINUX-X32-NEXT:    jmpq *%rdi # TAILCALL
305;
306; WINDOWS-LABEL: g_thunk:
307; WINDOWS:       # %bb.0:
308; WINDOWS-NEXT:    rex64 jmpq *%rcx # TAILCALL
309;
310; X86-LABEL: g_thunk:
311; X86:       # %bb.0:
312; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
313; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
314; X86-NEXT:    jmpl *%eax # TAILCALL
315  musttail call void (ptr, ...) %fptr_i8(ptr %fptr_i8, ...)
316  ret void
317}
318
319; Do a simple multi-exit multi-bb test.
320
321%struct.Foo = type { i1, ptr, ptr }
322
323@g = external dso_local global i32
324
325define void @h_thunk(ptr %this, ...) {
326; LINUX-LABEL: h_thunk:
327; LINUX:       # %bb.0:
328; LINUX-NEXT:    cmpb $1, (%rdi)
329; LINUX-NEXT:    jne .LBB2_2
330; LINUX-NEXT:  # %bb.1: # %then
331; LINUX-NEXT:    movq 8(%rdi), %r11
332; LINUX-NEXT:    jmpq *%r11 # TAILCALL
333; LINUX-NEXT:  .LBB2_2: # %else
334; LINUX-NEXT:    movq 16(%rdi), %r11
335; LINUX-NEXT:    movl $42, g(%rip)
336; LINUX-NEXT:    jmpq *%r11 # TAILCALL
337;
338; LINUX-X32-LABEL: h_thunk:
339; LINUX-X32:       # %bb.0:
340; LINUX-X32-NEXT:    cmpb $1, (%edi)
341; LINUX-X32-NEXT:    jne .LBB2_2
342; LINUX-X32-NEXT:  # %bb.1: # %then
343; LINUX-X32-NEXT:    movl 4(%edi), %r11d
344; LINUX-X32-NEXT:    movl %edi, %edi
345; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
346; LINUX-X32-NEXT:  .LBB2_2: # %else
347; LINUX-X32-NEXT:    movl 8(%edi), %r11d
348; LINUX-X32-NEXT:    movl $42, g(%rip)
349; LINUX-X32-NEXT:    movl %edi, %edi
350; LINUX-X32-NEXT:    jmpq *%r11 # TAILCALL
351;
352; WINDOWS-LABEL: h_thunk:
353; WINDOWS:       # %bb.0:
354; WINDOWS-NEXT:    cmpb $1, (%rcx)
355; WINDOWS-NEXT:    jne .LBB2_2
356; WINDOWS-NEXT:  # %bb.1: # %then
357; WINDOWS-NEXT:    movq 8(%rcx), %rax
358; WINDOWS-NEXT:    rex64 jmpq *%rax # TAILCALL
359; WINDOWS-NEXT:  .LBB2_2: # %else
360; WINDOWS-NEXT:    movq 16(%rcx), %rax
361; WINDOWS-NEXT:    movl $42, g(%rip)
362; WINDOWS-NEXT:    rex64 jmpq *%rax # TAILCALL
363;
364; X86-LABEL: h_thunk:
365; X86:       # %bb.0:
366; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
367; X86-NEXT:    cmpb $1, (%eax)
368; X86-NEXT:    jne LBB2_2
369; X86-NEXT:  # %bb.1: # %then
370; X86-NEXT:    movl 4(%eax), %ecx
371; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
372; X86-NEXT:    jmpl *%ecx # TAILCALL
373; X86-NEXT:  LBB2_2: # %else
374; X86-NEXT:    movl 8(%eax), %ecx
375; X86-NEXT:    movl $42, _g
376; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
377; X86-NEXT:    jmpl *%ecx # TAILCALL
378  %cond = load i1, ptr %this
379  br i1 %cond, label %then, label %else
380
381then:
382  %a_p = getelementptr %struct.Foo, ptr %this, i32 0, i32 1
383  %a_i8 = load ptr, ptr %a_p
384  musttail call void (ptr, ...) %a_i8(ptr %this, ...)
385  ret void
386
387else:
388  %b_p = getelementptr %struct.Foo, ptr %this, i32 0, i32 2
389  %b_i8 = load ptr, ptr %b_p
390  store i32 42, ptr @g
391  musttail call void (ptr, ...) %b_i8(ptr %this, ...)
392  ret void
393}
394