• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:    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 %r15, {{[0-9]+}}(%rsp)
60; LINUX-NEXT:    movq %r12, {{[0-9]+}}(%rsp)
61; LINUX-NEXT:    movq %r13, {{[0-9]+}}(%rsp)
62; LINUX-NEXT:    movq %rbp, {{[0-9]+}}(%rsp)
63; LINUX-NEXT:    movq %rbx, {{[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
111;
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 %r15, {{[0-9]+}}(%esp)
154; LINUX-X32-NEXT:    movq %r12, {{[0-9]+}}(%esp)
155; LINUX-X32-NEXT:    movq %r13, {{[0-9]+}}(%esp)
156; LINUX-X32-NEXT:    movq %rbp, {{[0-9]+}}(%esp)
157; LINUX-X32-NEXT:    movq %rbx, {{[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
205;
206; WINDOWS-LABEL: f_thunk:
207; WINDOWS:       # %bb.0:
208; WINDOWS-NEXT:    pushq %r14
209; WINDOWS-NEXT:    .seh_pushreg 14
210; WINDOWS-NEXT:    pushq %rsi
211; WINDOWS-NEXT:    .seh_pushreg 6
212; WINDOWS-NEXT:    pushq %rdi
213; WINDOWS-NEXT:    .seh_pushreg 7
214; WINDOWS-NEXT:    pushq %rbp
215; WINDOWS-NEXT:    .seh_pushreg 5
216; WINDOWS-NEXT:    pushq %rbx
217; WINDOWS-NEXT:    .seh_pushreg 3
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 %r9, {{[0-9]+}}(%rsp)
227; WINDOWS-NEXT:    movq %r8, {{[0-9]+}}(%rsp)
228; WINDOWS-NEXT:    movq %rdx, {{[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
248;
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
266;
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)
293
294  %fptr = call void(i8*, ...)*(i8*) @get_f(i8* %this)
295  musttail call void (i8*, ...) %fptr(i8* %this, ...)
296  ret void
297}
298
299; Save and restore 6 GPRs, 8 XMMs, and AL around the call.
300
301; No regparms on normal x86 conventions.
302
303; This thunk shouldn't require any spills and reloads, assuming the register
304; allocator knows what it's doing.
305
306define 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
314;
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
323;
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
334;
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
345}
346
347; Do a simple multi-exit multi-bb test.
348
349%struct.Foo = type { i1, i8*, i8* }
350
351@g = external global i32
352
353define 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
372;
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
391;
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
411;
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
432
433then:
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
439
440else:
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
447}
448