xref: /llvm-project/llvm/test/CodeGen/X86/sibcall.ll (revision ee5585ed09aff2e54cb540fad4c33f0c93626b1b)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs < %s -mtriple=i686-linux   -mcpu=core2 -mattr=+sse2 | FileCheck %s --check-prefix=X86
3; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-linux -mcpu=core2 -mattr=+sse2 | FileCheck %s --check-prefix=X64
4; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-linux-gnux32 -mcpu=core2 -mattr=+sse2  | FileCheck %s --check-prefix=X32
5
6define dso_local void @t1(i32 %x) nounwind ssp {
7; X86-LABEL: t1:
8; X86:       # %bb.0:
9; X86-NEXT:    jmp foo # TAILCALL
10;
11; X64-LABEL: t1:
12; X64:       # %bb.0:
13; X64-NEXT:    jmp foo # TAILCALL
14;
15; X32-LABEL: t1:
16; X32:       # %bb.0:
17; X32-NEXT:    jmp foo # TAILCALL
18  tail call void @foo() nounwind
19  ret void
20}
21
22declare dso_local void @foo()
23
24define dso_local void @t2() nounwind ssp {
25; X86-LABEL: t2:
26; X86:       # %bb.0:
27; X86-NEXT:    jmp foo2 # TAILCALL
28;
29; X64-LABEL: t2:
30; X64:       # %bb.0:
31; X64-NEXT:    jmp foo2 # TAILCALL
32;
33; X32-LABEL: t2:
34; X32:       # %bb.0:
35; X32-NEXT:    jmp foo2 # TAILCALL
36  %t0 = tail call i32 @foo2() nounwind
37  ret void
38}
39
40declare dso_local i32 @foo2()
41
42define dso_local void @t3() nounwind ssp {
43; X86-LABEL: t3:
44; X86:       # %bb.0:
45; X86-NEXT:    jmp foo3 # TAILCALL
46;
47; X64-LABEL: t3:
48; X64:       # %bb.0:
49; X64-NEXT:    jmp foo3 # TAILCALL
50;
51; X32-LABEL: t3:
52; X32:       # %bb.0:
53; X32-NEXT:    jmp foo3 # TAILCALL
54  %t0 = tail call i32 @foo3() nounwind
55  ret void
56}
57
58declare dso_local i32 @foo3()
59
60define dso_local void @t4(ptr nocapture %x) nounwind ssp {
61; X86-LABEL: t4:
62; X86:       # %bb.0:
63; X86-NEXT:    subl $12, %esp
64; X86-NEXT:    movl $0, (%esp)
65; X86-NEXT:    calll *{{[0-9]+}}(%esp)
66; X86-NEXT:    addl $12, %esp
67; X86-NEXT:    retl
68;
69; X64-LABEL: t4:
70; X64:       # %bb.0:
71; X64-NEXT:    movq %rdi, %rax
72; X64-NEXT:    xorl %edi, %edi
73; X64-NEXT:    jmpq *%rax # TAILCALL
74;
75; X32-LABEL: t4:
76; X32:       # %bb.0:
77; X32-NEXT:    movq %rdi, %rax
78; X32-NEXT:    xorl %edi, %edi
79; X32-NEXT:    jmpq *%rax # TAILCALL
80  tail call void %x(i32 0) nounwind
81  ret void
82}
83
84define dso_local void @t5(ptr nocapture %x) nounwind ssp {
85; X86-LABEL: t5:
86; X86:       # %bb.0:
87; X86-NEXT:    jmpl *{{[0-9]+}}(%esp) # TAILCALL
88;
89; X64-LABEL: t5:
90; X64:       # %bb.0:
91; X64-NEXT:    jmpq *%rdi # TAILCALL
92;
93; X32-LABEL: t5:
94; X32:       # %bb.0:
95; X32-NEXT:    jmpq *%rdi # TAILCALL
96  tail call void %x() nounwind
97  ret void
98}
99
100; Basically the same test as t5, except pass the function pointer on the stack
101; for x86_64.
102
103define dso_local void @t5_x64(i32, i32, i32, i32, i32, i32, ptr nocapture %x) nounwind ssp {
104; X86-LABEL: t5_x64:
105; X86:       # %bb.0:
106; X86-NEXT:    jmpl *{{[0-9]+}}(%esp) # TAILCALL
107;
108; X64-LABEL: t5_x64:
109; X64:       # %bb.0:
110; X64-NEXT:    jmpq *{{[0-9]+}}(%rsp) # TAILCALL
111;
112; X32-LABEL: t5_x64:
113; X32:       # %bb.0:
114; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
115; X32-NEXT:    jmpq *%rax # TAILCALL
116  tail call void %x() nounwind
117  ret void
118}
119
120
121define dso_local i32 @t6(i32 %x) nounwind ssp {
122; X86-LABEL: t6:
123; X86:       # %bb.0:
124; X86-NEXT:    subl $12, %esp
125; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
126; X86-NEXT:    cmpl $9, %eax
127; X86-NEXT:    jg .LBB6_2
128; X86-NEXT:  # %bb.1: # %bb
129; X86-NEXT:    decl %eax
130; X86-NEXT:    movl %eax, (%esp)
131; X86-NEXT:    calll t6
132; X86-NEXT:    addl $12, %esp
133; X86-NEXT:    retl
134; X86-NEXT:  .LBB6_2: # %bb1
135; X86-NEXT:    addl $12, %esp
136; X86-NEXT:    jmp bar # TAILCALL
137;
138; X64-LABEL: t6:
139; X64:       # %bb.0:
140; X64-NEXT:    cmpl $9, %edi
141; X64-NEXT:    jg bar # TAILCALL
142; X64-NEXT:  # %bb.1: # %bb
143; X64-NEXT:    decl %edi
144; X64-NEXT:    jmp t6 # TAILCALL
145;
146; X32-LABEL: t6:
147; X32:       # %bb.0:
148; X32-NEXT:    cmpl $9, %edi
149; X32-NEXT:    jg bar # TAILCALL
150; X32-NEXT:  # %bb.1: # %bb
151; X32-NEXT:    decl %edi
152; X32-NEXT:    jmp t6 # TAILCALL
153  %t0 = icmp slt i32 %x, 10
154  br i1 %t0, label %bb, label %bb1
155
156bb:
157  %t1 = add nsw i32 %x, -1
158  %t2 = tail call i32 @t6(i32 %t1) nounwind ssp
159  ret i32 %t2
160
161bb1:
162  %t3 = tail call i32 @bar(i32 %x) nounwind
163  ret i32 %t3
164}
165
166declare dso_local i32 @bar(i32)
167
168define dso_local i32 @t7(i32 %a, i32 %b, i32 %c) nounwind ssp {
169; X86-LABEL: t7:
170; X86:       # %bb.0:
171; X86-NEXT:    jmp bar2 # TAILCALL
172;
173; X64-LABEL: t7:
174; X64:       # %bb.0:
175; X64-NEXT:    jmp bar2 # TAILCALL
176;
177; X32-LABEL: t7:
178; X32:       # %bb.0:
179; X32-NEXT:    jmp bar2 # TAILCALL
180  %t0 = tail call i32 @bar2(i32 %a, i32 %b, i32 %c) nounwind
181  ret i32 %t0
182}
183
184declare dso_local i32 @bar2(i32, i32, i32)
185
186define signext i16 @t8() nounwind ssp {
187; X86-LABEL: t8:
188; X86:       # %bb.0: # %entry
189; X86-NEXT:    jmp bar3 # TAILCALL
190;
191; X64-LABEL: t8:
192; X64:       # %bb.0: # %entry
193; X64-NEXT:    jmp bar3 # TAILCALL
194;
195; X32-LABEL: t8:
196; X32:       # %bb.0: # %entry
197; X32-NEXT:    jmp bar3 # TAILCALL
198entry:
199  %0 = tail call signext i16 @bar3() nounwind      ; <i16> [#uses=1]
200  ret i16 %0
201}
202
203declare dso_local signext i16 @bar3()
204
205define signext i16 @t9(ptr nocapture %x) nounwind ssp {
206; X86-LABEL: t9:
207; X86:       # %bb.0: # %entry
208; X86-NEXT:    subl $12, %esp
209; X86-NEXT:    movl $0, (%esp)
210; X86-NEXT:    calll *{{[0-9]+}}(%esp)
211; X86-NEXT:    addl $12, %esp
212; X86-NEXT:    retl
213;
214; X64-LABEL: t9:
215; X64:       # %bb.0: # %entry
216; X64-NEXT:    movq %rdi, %rax
217; X64-NEXT:    xorl %edi, %edi
218; X64-NEXT:    jmpq *%rax # TAILCALL
219;
220; X32-LABEL: t9:
221; X32:       # %bb.0: # %entry
222; X32-NEXT:    movq %rdi, %rax
223; X32-NEXT:    xorl %edi, %edi
224; X32-NEXT:    jmpq *%rax # TAILCALL
225entry:
226  %0 = tail call signext i16 %x(i32 0) nounwind
227  ret i16 %0
228}
229
230define dso_local void @t10() nounwind ssp {
231; X86-LABEL: t10:
232; X86:       # %bb.0: # %entry
233; X86-NEXT:    subl $12, %esp
234; X86-NEXT:    calll foo4
235;
236; X64-LABEL: t10:
237; X64:       # %bb.0: # %entry
238; X64-NEXT:    pushq %rax
239; X64-NEXT:    callq foo4
240;
241; X32-LABEL: t10:
242; X32:       # %bb.0: # %entry
243; X32-NEXT:    pushq %rax
244; X32-NEXT:    callq foo4
245entry:
246  %0 = tail call i32 @foo4() noreturn nounwind
247  unreachable
248}
249
250declare dso_local i32 @foo4()
251
252; In 32-bit mode, it's emitting a bunch of dead loads that are not being
253; eliminated currently.
254
255define dso_local i32 @t11(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind ssp {
256; X86-LABEL: t11:
257; X86:       # %bb.0: # %entry
258; X86-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
259; X86-NEXT:    jne foo5 # TAILCALL
260; X86-NEXT:  # %bb.1: # %bb6
261; X86-NEXT:    xorl %eax, %eax
262; X86-NEXT:    retl
263;
264; X64-LABEL: t11:
265; X64:       # %bb.0: # %entry
266; X64-NEXT:    testl %edi, %edi
267; X64-NEXT:    jne foo5 # TAILCALL
268; X64-NEXT:  # %bb.1: # %bb6
269; X64-NEXT:    xorl %eax, %eax
270; X64-NEXT:    retq
271;
272; X32-LABEL: t11:
273; X32:       # %bb.0: # %entry
274; X32-NEXT:    testl %edi, %edi
275; X32-NEXT:    jne foo5 # TAILCALL
276; X32-NEXT:  # %bb.1: # %bb6
277; X32-NEXT:    xorl %eax, %eax
278; X32-NEXT:    retq
279entry:
280  %0 = icmp eq i32 %x, 0
281  br i1 %0, label %bb6, label %bb
282
283bb:
284  %1 = tail call i32 @foo5(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind
285  ret i32 %1
286
287bb6:
288  ret i32 0
289}
290
291declare dso_local i32 @foo5(i32, i32, i32, i32, i32)
292
293%struct.t = type { i32, i32, i32, i32, i32 }
294
295define dso_local i32 @t12(i32 %x, i32 %y, ptr byval(%struct.t) align 4 %z) nounwind ssp {
296; X86-LABEL: t12:
297; X86:       # %bb.0: # %entry
298; X86-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
299; X86-NEXT:    jne foo6 # TAILCALL
300; X86-NEXT:  # %bb.1: # %bb2
301; X86-NEXT:    xorl %eax, %eax
302; X86-NEXT:    retl
303;
304; X64-LABEL: t12:
305; X64:       # %bb.0: # %entry
306; X64-NEXT:    testl %edi, %edi
307; X64-NEXT:    jne foo6 # TAILCALL
308; X64-NEXT:  # %bb.1: # %bb2
309; X64-NEXT:    xorl %eax, %eax
310; X64-NEXT:    retq
311;
312; X32-LABEL: t12:
313; X32:       # %bb.0: # %entry
314; X32-NEXT:    testl %edi, %edi
315; X32-NEXT:    jne foo6 # TAILCALL
316; X32-NEXT:  # %bb.1: # %bb2
317; X32-NEXT:    xorl %eax, %eax
318; X32-NEXT:    retq
319entry:
320  %0 = icmp eq i32 %x, 0
321  br i1 %0, label %bb2, label %bb
322
323bb:
324  %1 = tail call i32 @foo6(i32 %x, i32 %y, ptr byval(%struct.t) align 4 %z) nounwind
325  ret i32 %1
326
327bb2:
328  ret i32 0
329}
330
331declare dso_local i32 @foo6(i32, i32, ptr byval(%struct.t) align 4)
332
333; rdar://r7717598
334%struct.ns = type { i32, i32 }
335%struct.cp = type { float, float, float, float, float }
336
337define ptr @t13(ptr %yy) nounwind ssp {
338; X86-LABEL: t13:
339; X86:       # %bb.0: # %entry
340; X86-NEXT:    subl $28, %esp
341; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
342; X86-NEXT:    movl 16(%eax), %ecx
343; X86-NEXT:    movl %ecx, {{[0-9]+}}(%esp)
344; X86-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
345; X86-NEXT:    movsd {{.*#+}} xmm1 = mem[0],zero
346; X86-NEXT:    movsd %xmm1, {{[0-9]+}}(%esp)
347; X86-NEXT:    movsd %xmm0, (%esp)
348; X86-NEXT:    xorl %ecx, %ecx
349; X86-NEXT:    calll foo7
350; X86-NEXT:    addl $28, %esp
351; X86-NEXT:    retl
352;
353; X64-LABEL: t13:
354; X64:       # %bb.0: # %entry
355; X64-NEXT:    pushq %rax
356; X64-NEXT:    subq $8, %rsp
357; X64-NEXT:    movl 16(%rdi), %eax
358; X64-NEXT:    movq (%rdi), %rcx
359; X64-NEXT:    movq 8(%rdi), %rdx
360; X64-NEXT:    xorl %edi, %edi
361; X64-NEXT:    pushq %rax
362; X64-NEXT:    pushq %rdx
363; X64-NEXT:    pushq %rcx
364; X64-NEXT:    callq foo7
365; X64-NEXT:    addq $32, %rsp
366; X64-NEXT:    popq %rcx
367; X64-NEXT:    retq
368;
369; X32-LABEL: t13:
370; X32:       # %bb.0: # %entry
371; X32-NEXT:    pushq %rax
372; X32-NEXT:    subl $8, %esp
373; X32-NEXT:    movl 16(%edi), %eax
374; X32-NEXT:    movq (%edi), %rcx
375; X32-NEXT:    movq 8(%edi), %rdx
376; X32-NEXT:    xorl %edi, %edi
377; X32-NEXT:    pushq %rax
378; X32-NEXT:    pushq %rdx
379; X32-NEXT:    pushq %rcx
380; X32-NEXT:    callq foo7
381; X32-NEXT:    addl $32, %esp
382; X32-NEXT:    movl %eax, %eax
383; X32-NEXT:    popq %rcx
384; X32-NEXT:    retq
385entry:
386  %0 = tail call fastcc ptr @foo7(ptr byval(%struct.cp) align 4 %yy, i8 signext 0) nounwind
387  ret ptr %0
388}
389
390; rdar://6195379
391; llvm can't do sibcall for this in 32-bit mode (yet).
392declare dso_local fastcc ptr @foo7(ptr byval(%struct.cp) align 4, i8 signext) nounwind ssp
393
394%struct.__block_descriptor = type { i64, i64 }
395%struct.__block_descriptor_withcopydispose = type { i64, i64, ptr, ptr }
396%struct.__block_literal_1 = type { ptr, i32, i32, ptr, ptr }
397%struct.__block_literal_2 = type { ptr, i32, i32, ptr, ptr, ptr }
398
399define dso_local void @t14(ptr nocapture %.block_descriptor) nounwind ssp {
400; X86-LABEL: t14:
401; X86:       # %bb.0: # %entry
402; X86-NEXT:    subl $12, %esp
403; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
404; X86-NEXT:    movl 20(%eax), %eax
405; X86-NEXT:    movl %eax, (%esp)
406; X86-NEXT:    calll *12(%eax)
407; X86-NEXT:    addl $12, %esp
408; X86-NEXT:    retl
409;
410; X64-LABEL: t14:
411; X64:       # %bb.0: # %entry
412; X64-NEXT:    movq 32(%rdi), %rdi
413; X64-NEXT:    jmpq *16(%rdi) # TAILCALL
414;
415; X32-LABEL: t14:
416; X32:       # %bb.0: # %entry
417; X32-NEXT:    movl 20(%edi), %edi
418; X32-NEXT:    movl 12(%edi), %eax
419; X32-NEXT:    jmpq *%rax # TAILCALL
420entry:
421  %0 = getelementptr inbounds %struct.__block_literal_2, ptr %.block_descriptor, i64 0, i32 5 ; <ptr> [#uses=1]
422  %1 = load ptr, ptr %0, align 8                 ; <ptr> [#uses=2]
423  %2 = getelementptr inbounds %struct.__block_literal_1, ptr %1, i64 0, i32 3 ; <ptr> [#uses=1]
424  %3 = load ptr, ptr %2, align 8                      ; <ptr> [#uses=1]
425  tail call void %3(ptr %1) nounwind
426  ret void
427}
428
429; rdar://7726868
430%struct.foo = type { [4 x i32] }
431
432define dso_local void @t15(ptr noalias sret(%struct.foo) %agg.result) nounwind  {
433; X86-LABEL: t15:
434; X86:       # %bb.0:
435; X86-NEXT:    pushl %esi
436; X86-NEXT:    subl $8, %esp
437; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
438; X86-NEXT:    movl %esi, %ecx
439; X86-NEXT:    calll f
440; X86-NEXT:    movl %esi, %eax
441; X86-NEXT:    addl $8, %esp
442; X86-NEXT:    popl %esi
443; X86-NEXT:    retl $4
444;
445; X64-LABEL: t15:
446; X64:       # %bb.0:
447; X64-NEXT:    pushq %rbx
448; X64-NEXT:    movq %rdi, %rbx
449; X64-NEXT:    callq f
450; X64-NEXT:    movq %rbx, %rax
451; X64-NEXT:    popq %rbx
452; X64-NEXT:    retq
453;
454; X32-LABEL: t15:
455; X32:       # %bb.0:
456; X32-NEXT:    pushq %rbx
457; X32-NEXT:    movq %rdi, %rbx
458; X32-NEXT:    callq f
459; X32-NEXT:    movl %ebx, %eax
460; X32-NEXT:    popq %rbx
461; X32-NEXT:    retq
462  tail call fastcc void @f(ptr noalias sret(%struct.foo) %agg.result) nounwind
463  ret void
464}
465
466declare dso_local void @f(ptr noalias sret(%struct.foo)) nounwind
467
468define dso_local void @t16() nounwind ssp {
469; X86-LABEL: t16:
470; X86:       # %bb.0: # %entry
471; X86-NEXT:    subl $12, %esp
472; X86-NEXT:    calll bar4
473; X86-NEXT:    fstp %st(0)
474; X86-NEXT:    addl $12, %esp
475; X86-NEXT:    retl
476;
477; X64-LABEL: t16:
478; X64:       # %bb.0: # %entry
479; X64-NEXT:    jmp bar4 # TAILCALL
480;
481; X32-LABEL: t16:
482; X32:       # %bb.0: # %entry
483; X32-NEXT:    jmp bar4 # TAILCALL
484entry:
485  %0 = tail call double @bar4() nounwind
486  ret void
487}
488
489declare dso_local double @bar4()
490
491; rdar://6283267
492define dso_local void @t17() nounwind ssp {
493; X86-LABEL: t17:
494; X86:       # %bb.0: # %entry
495; X86-NEXT:    jmp bar5 # TAILCALL
496;
497; X64-LABEL: t17:
498; X64:       # %bb.0: # %entry
499; X64-NEXT:    xorl %eax, %eax
500; X64-NEXT:    jmp bar5 # TAILCALL
501;
502; X32-LABEL: t17:
503; X32:       # %bb.0: # %entry
504; X32-NEXT:    xorl %eax, %eax
505; X32-NEXT:    jmp bar5 # TAILCALL
506entry:
507  tail call void (...) @bar5() nounwind
508  ret void
509}
510
511declare dso_local void @bar5(...)
512
513; rdar://7774847
514define dso_local void @t18() nounwind ssp {
515; X86-LABEL: t18:
516; X86:       # %bb.0: # %entry
517; X86-NEXT:    subl $12, %esp
518; X86-NEXT:    calll bar6
519; X86-NEXT:    fstp %st(0)
520; X86-NEXT:    addl $12, %esp
521; X86-NEXT:    retl
522;
523; X64-LABEL: t18:
524; X64:       # %bb.0: # %entry
525; X64-NEXT:    xorl %eax, %eax
526; X64-NEXT:    jmp bar6 # TAILCALL
527;
528; X32-LABEL: t18:
529; X32:       # %bb.0: # %entry
530; X32-NEXT:    xorl %eax, %eax
531; X32-NEXT:    jmp bar6 # TAILCALL
532entry:
533  %0 = tail call double (...) @bar6() nounwind
534  ret void
535}
536
537declare dso_local double @bar6(...)
538
539define dso_local void @t19() alignstack(32) nounwind {
540; X86-LABEL: t19:
541; X86:       # %bb.0: # %entry
542; X86-NEXT:    pushl %ebp
543; X86-NEXT:    movl %esp, %ebp
544; X86-NEXT:    andl $-32, %esp
545; X86-NEXT:    subl $32, %esp
546; X86-NEXT:    calll foo
547; X86-NEXT:    movl %ebp, %esp
548; X86-NEXT:    popl %ebp
549; X86-NEXT:    retl
550;
551; X64-LABEL: t19:
552; X64:       # %bb.0: # %entry
553; X64-NEXT:    pushq %rbp
554; X64-NEXT:    movq %rsp, %rbp
555; X64-NEXT:    andq $-32, %rsp
556; X64-NEXT:    subq $32, %rsp
557; X64-NEXT:    callq foo
558; X64-NEXT:    movq %rbp, %rsp
559; X64-NEXT:    popq %rbp
560; X64-NEXT:    retq
561;
562; X32-LABEL: t19:
563; X32:       # %bb.0: # %entry
564; X32-NEXT:    pushq %rbp
565; X32-NEXT:    movl %esp, %ebp
566; X32-NEXT:    andl $-32, %esp
567; X32-NEXT:    subl $32, %esp
568; X32-NEXT:    callq foo
569; X32-NEXT:    movl %ebp, %esp
570; X32-NEXT:    popq %rbp
571; X32-NEXT:    retq
572entry:
573  tail call void @foo() nounwind
574  ret void
575}
576
577; If caller / callee calling convention mismatch then check if the return
578; values are returned in the same registers.
579; rdar://7874780
580
581define dso_local double @t20(double %x) nounwind {
582; X86-LABEL: t20:
583; X86:       # %bb.0: # %entry
584; X86-NEXT:    subl $12, %esp
585; X86-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
586; X86-NEXT:    calll foo20
587; X86-NEXT:    movsd %xmm0, (%esp)
588; X86-NEXT:    fldl (%esp)
589; X86-NEXT:    addl $12, %esp
590; X86-NEXT:    retl
591;
592; X64-LABEL: t20:
593; X64:       # %bb.0: # %entry
594; X64-NEXT:    jmp foo20 # TAILCALL
595;
596; X32-LABEL: t20:
597; X32:       # %bb.0: # %entry
598; X32-NEXT:    jmp foo20 # TAILCALL
599entry:
600  %0 = tail call fastcc double @foo20(double %x) nounwind
601  ret double %0
602}
603
604declare dso_local fastcc double @foo20(double) nounwind
605
606; bug 28417
607define fastcc void @t21_sret_to_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind  {
608; X86-LABEL: t21_sret_to_sret:
609; X86:       # %bb.0:
610; X86-NEXT:    pushl %esi
611; X86-NEXT:    subl $8, %esp
612; X86-NEXT:    movl %ecx, %esi
613; X86-NEXT:    calll t21_f_sret
614; X86-NEXT:    movl %esi, %eax
615; X86-NEXT:    addl $8, %esp
616; X86-NEXT:    popl %esi
617; X86-NEXT:    retl
618;
619; X64-LABEL: t21_sret_to_sret:
620; X64:       # %bb.0:
621; X64-NEXT:    pushq %rbx
622; X64-NEXT:    movq %rdi, %rbx
623; X64-NEXT:    callq t21_f_sret
624; X64-NEXT:    movq %rbx, %rax
625; X64-NEXT:    popq %rbx
626; X64-NEXT:    retq
627;
628; X32-LABEL: t21_sret_to_sret:
629; X32:       # %bb.0:
630; X32-NEXT:    pushq %rbx
631; X32-NEXT:    movq %rdi, %rbx
632; X32-NEXT:    callq t21_f_sret
633; X32-NEXT:    movl %ebx, %eax
634; X32-NEXT:    popq %rbx
635; X32-NEXT:    retq
636  tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind
637  ret void
638}
639
640define fastcc void @t21_sret_to_sret_more_args(ptr noalias sret(%struct.foo) %agg.result, i32 %a, i32 %b) nounwind  {
641; X86-LABEL: t21_sret_to_sret_more_args:
642; X86:       # %bb.0:
643; X86-NEXT:    pushl %esi
644; X86-NEXT:    subl $8, %esp
645; X86-NEXT:    movl %ecx, %esi
646; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
647; X86-NEXT:    movl %eax, (%esp)
648; X86-NEXT:    calll f_sret@PLT
649; X86-NEXT:    movl %esi, %eax
650; X86-NEXT:    addl $8, %esp
651; X86-NEXT:    popl %esi
652; X86-NEXT:    retl
653;
654; X64-LABEL: t21_sret_to_sret_more_args:
655; X64:       # %bb.0:
656; X64-NEXT:    pushq %rbx
657; X64-NEXT:    movq %rdi, %rbx
658; X64-NEXT:    callq f_sret@PLT
659; X64-NEXT:    movq %rbx, %rax
660; X64-NEXT:    popq %rbx
661; X64-NEXT:    retq
662;
663; X32-LABEL: t21_sret_to_sret_more_args:
664; X32:       # %bb.0:
665; X32-NEXT:    pushq %rbx
666; X32-NEXT:    movq %rdi, %rbx
667; X32-NEXT:    callq f_sret@PLT
668; X32-NEXT:    movl %ebx, %eax
669; X32-NEXT:    popq %rbx
670; X32-NEXT:    retq
671  tail call fastcc void @f_sret(ptr noalias sret(%struct.foo) %agg.result, i32 %a, i32 %b) nounwind
672  ret void
673}
674
675define fastcc void @t21_sret_to_sret_second_arg_sret(ptr noalias %agg.result, ptr noalias sret(%struct.foo) %ret) nounwind  {
676; X86-LABEL: t21_sret_to_sret_second_arg_sret:
677; X86:       # %bb.0:
678; X86-NEXT:    pushl %esi
679; X86-NEXT:    subl $8, %esp
680; X86-NEXT:    movl %edx, %esi
681; X86-NEXT:    movl %edx, %ecx
682; X86-NEXT:    calll t21_f_sret
683; X86-NEXT:    movl %esi, %eax
684; X86-NEXT:    addl $8, %esp
685; X86-NEXT:    popl %esi
686; X86-NEXT:    retl
687;
688; X64-LABEL: t21_sret_to_sret_second_arg_sret:
689; X64:       # %bb.0:
690; X64-NEXT:    pushq %rbx
691; X64-NEXT:    movq %rsi, %rbx
692; X64-NEXT:    movq %rsi, %rdi
693; X64-NEXT:    callq t21_f_sret
694; X64-NEXT:    movq %rbx, %rax
695; X64-NEXT:    popq %rbx
696; X64-NEXT:    retq
697;
698; X32-LABEL: t21_sret_to_sret_second_arg_sret:
699; X32:       # %bb.0:
700; X32-NEXT:    pushq %rbx
701; X32-NEXT:    movq %rsi, %rbx
702; X32-NEXT:    movq %rsi, %rdi
703; X32-NEXT:    callq t21_f_sret
704; X32-NEXT:    movl %ebx, %eax
705; X32-NEXT:    popq %rbx
706; X32-NEXT:    retq
707  tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind
708  ret void
709}
710
711define fastcc void @t21_sret_to_sret_more_args2(ptr noalias sret(%struct.foo) %agg.result, i32 %a, i32 %b) nounwind  {
712; X86-LABEL: t21_sret_to_sret_more_args2:
713; X86:       # %bb.0:
714; X86-NEXT:    pushl %esi
715; X86-NEXT:    subl $8, %esp
716; X86-NEXT:    movl %ecx, %esi
717; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
718; X86-NEXT:    movl %edx, (%esp)
719; X86-NEXT:    movl %eax, %edx
720; X86-NEXT:    calll f_sret@PLT
721; X86-NEXT:    movl %esi, %eax
722; X86-NEXT:    addl $8, %esp
723; X86-NEXT:    popl %esi
724; X86-NEXT:    retl
725;
726; X64-LABEL: t21_sret_to_sret_more_args2:
727; X64:       # %bb.0:
728; X64-NEXT:    pushq %rbx
729; X64-NEXT:    movl %esi, %eax
730; X64-NEXT:    movq %rdi, %rbx
731; X64-NEXT:    movl %edx, %esi
732; X64-NEXT:    movl %eax, %edx
733; X64-NEXT:    callq f_sret@PLT
734; X64-NEXT:    movq %rbx, %rax
735; X64-NEXT:    popq %rbx
736; X64-NEXT:    retq
737;
738; X32-LABEL: t21_sret_to_sret_more_args2:
739; X32:       # %bb.0:
740; X32-NEXT:    pushq %rbx
741; X32-NEXT:    movl %esi, %eax
742; X32-NEXT:    movq %rdi, %rbx
743; X32-NEXT:    movl %edx, %esi
744; X32-NEXT:    movl %eax, %edx
745; X32-NEXT:    callq f_sret@PLT
746; X32-NEXT:    movl %ebx, %eax
747; X32-NEXT:    popq %rbx
748; X32-NEXT:    retq
749  tail call fastcc void @f_sret(ptr noalias sret(%struct.foo) %agg.result, i32 %b, i32 %a) nounwind
750  ret void
751}
752
753
754define fastcc void @t21_sret_to_sret_args_mismatch(ptr noalias sret(%struct.foo) %agg.result, ptr noalias %ret) nounwind  {
755; X86-LABEL: t21_sret_to_sret_args_mismatch:
756; X86:       # %bb.0:
757; X86-NEXT:    pushl %esi
758; X86-NEXT:    subl $8, %esp
759; X86-NEXT:    movl %ecx, %esi
760; X86-NEXT:    movl %edx, %ecx
761; X86-NEXT:    calll t21_f_sret
762; X86-NEXT:    movl %esi, %eax
763; X86-NEXT:    addl $8, %esp
764; X86-NEXT:    popl %esi
765; X86-NEXT:    retl
766;
767; X64-LABEL: t21_sret_to_sret_args_mismatch:
768; X64:       # %bb.0:
769; X64-NEXT:    pushq %rbx
770; X64-NEXT:    movq %rdi, %rbx
771; X64-NEXT:    movq %rsi, %rdi
772; X64-NEXT:    callq t21_f_sret
773; X64-NEXT:    movq %rbx, %rax
774; X64-NEXT:    popq %rbx
775; X64-NEXT:    retq
776;
777; X32-LABEL: t21_sret_to_sret_args_mismatch:
778; X32:       # %bb.0:
779; X32-NEXT:    pushq %rbx
780; X32-NEXT:    movq %rdi, %rbx
781; X32-NEXT:    movq %rsi, %rdi
782; X32-NEXT:    callq t21_f_sret
783; X32-NEXT:    movl %ebx, %eax
784; X32-NEXT:    popq %rbx
785; X32-NEXT:    retq
786  tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind
787  ret void
788}
789
790define fastcc void @t21_sret_to_sret_args_mismatch2(ptr noalias sret(%struct.foo) %agg.result, ptr noalias %ret) nounwind  {
791; X86-LABEL: t21_sret_to_sret_args_mismatch2:
792; X86:       # %bb.0:
793; X86-NEXT:    pushl %esi
794; X86-NEXT:    subl $8, %esp
795; X86-NEXT:    movl %ecx, %esi
796; X86-NEXT:    movl %edx, %ecx
797; X86-NEXT:    calll t21_f_sret
798; X86-NEXT:    movl %esi, %eax
799; X86-NEXT:    addl $8, %esp
800; X86-NEXT:    popl %esi
801; X86-NEXT:    retl
802;
803; X64-LABEL: t21_sret_to_sret_args_mismatch2:
804; X64:       # %bb.0:
805; X64-NEXT:    pushq %rbx
806; X64-NEXT:    movq %rdi, %rbx
807; X64-NEXT:    movq %rsi, %rdi
808; X64-NEXT:    callq t21_f_sret
809; X64-NEXT:    movq %rbx, %rax
810; X64-NEXT:    popq %rbx
811; X64-NEXT:    retq
812;
813; X32-LABEL: t21_sret_to_sret_args_mismatch2:
814; X32:       # %bb.0:
815; X32-NEXT:    pushq %rbx
816; X32-NEXT:    movq %rdi, %rbx
817; X32-NEXT:    movq %rsi, %rdi
818; X32-NEXT:    callq t21_f_sret
819; X32-NEXT:    movl %ebx, %eax
820; X32-NEXT:    popq %rbx
821; X32-NEXT:    retq
822  tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind
823  ret void
824}
825
826define fastcc void @t21_sret_to_sret_arg_mismatch(ptr noalias sret(%struct.foo) %agg.result) nounwind  {
827; X86-LABEL: t21_sret_to_sret_arg_mismatch:
828; X86:       # %bb.0:
829; X86-NEXT:    pushl %esi
830; X86-NEXT:    subl $8, %esp
831; X86-NEXT:    movl %ecx, %esi
832; X86-NEXT:    calll ret_struct@PLT
833; X86-NEXT:    movl %eax, %ecx
834; X86-NEXT:    calll t21_f_sret
835; X86-NEXT:    movl %esi, %eax
836; X86-NEXT:    addl $8, %esp
837; X86-NEXT:    popl %esi
838; X86-NEXT:    retl
839;
840; X64-LABEL: t21_sret_to_sret_arg_mismatch:
841; X64:       # %bb.0:
842; X64-NEXT:    pushq %rbx
843; X64-NEXT:    movq %rdi, %rbx
844; X64-NEXT:    callq ret_struct@PLT
845; X64-NEXT:    movq %rax, %rdi
846; X64-NEXT:    callq t21_f_sret
847; X64-NEXT:    movq %rbx, %rax
848; X64-NEXT:    popq %rbx
849; X64-NEXT:    retq
850;
851; X32-LABEL: t21_sret_to_sret_arg_mismatch:
852; X32:       # %bb.0:
853; X32-NEXT:    pushq %rbx
854; X32-NEXT:    movq %rdi, %rbx
855; X32-NEXT:    callq ret_struct@PLT
856; X32-NEXT:    movl %eax, %edi
857; X32-NEXT:    callq t21_f_sret
858; X32-NEXT:    movl %ebx, %eax
859; X32-NEXT:    popq %rbx
860; X32-NEXT:    retq
861  %a = call fastcc ptr @ret_struct()
862  tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %a) nounwind
863  ret void
864}
865
866define fastcc void @t21_sret_to_sret_structs_mismatch(ptr noalias sret(%struct.foo) %agg.result, ptr noalias %a) nounwind  {
867; X86-LABEL: t21_sret_to_sret_structs_mismatch:
868; X86:       # %bb.0:
869; X86-NEXT:    pushl %edi
870; X86-NEXT:    pushl %esi
871; X86-NEXT:    pushl %eax
872; X86-NEXT:    movl %edx, %esi
873; X86-NEXT:    movl %ecx, %edi
874; X86-NEXT:    calll ret_struct@PLT
875; X86-NEXT:    movl %esi, %ecx
876; X86-NEXT:    movl %eax, %edx
877; X86-NEXT:    calll t21_f_sret2
878; X86-NEXT:    movl %edi, %eax
879; X86-NEXT:    addl $4, %esp
880; X86-NEXT:    popl %esi
881; X86-NEXT:    popl %edi
882; X86-NEXT:    retl
883;
884; X64-LABEL: t21_sret_to_sret_structs_mismatch:
885; X64:       # %bb.0:
886; X64-NEXT:    pushq %r14
887; X64-NEXT:    pushq %rbx
888; X64-NEXT:    pushq %rax
889; X64-NEXT:    movq %rsi, %rbx
890; X64-NEXT:    movq %rdi, %r14
891; X64-NEXT:    callq ret_struct@PLT
892; X64-NEXT:    movq %rbx, %rdi
893; X64-NEXT:    movq %rax, %rsi
894; X64-NEXT:    callq t21_f_sret2
895; X64-NEXT:    movq %r14, %rax
896; X64-NEXT:    addq $8, %rsp
897; X64-NEXT:    popq %rbx
898; X64-NEXT:    popq %r14
899; X64-NEXT:    retq
900;
901; X32-LABEL: t21_sret_to_sret_structs_mismatch:
902; X32:       # %bb.0:
903; X32-NEXT:    pushq %r14
904; X32-NEXT:    pushq %rbx
905; X32-NEXT:    pushq %rax
906; X32-NEXT:    movq %rsi, %rbx
907; X32-NEXT:    movq %rdi, %r14
908; X32-NEXT:    callq ret_struct@PLT
909; X32-NEXT:    movl %eax, %esi
910; X32-NEXT:    movq %rbx, %rdi
911; X32-NEXT:    callq t21_f_sret2
912; X32-NEXT:    movl %r14d, %eax
913; X32-NEXT:    addl $8, %esp
914; X32-NEXT:    popq %rbx
915; X32-NEXT:    popq %r14
916; X32-NEXT:    retq
917  %b = call fastcc ptr @ret_struct()
918  tail call fastcc void @t21_f_sret2(ptr noalias sret(%struct.foo) %a, ptr noalias %b) nounwind
919  ret void
920}
921
922declare ccc ptr @ret_struct() nounwind
923
924
925define fastcc void @t21_sret_to_non_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind  {
926; X86-LABEL: t21_sret_to_non_sret:
927; X86:       # %bb.0:
928; X86-NEXT:    pushl %esi
929; X86-NEXT:    subl $8, %esp
930; X86-NEXT:    movl %ecx, %esi
931; X86-NEXT:    calll t21_f_non_sret
932; X86-NEXT:    movl %esi, %eax
933; X86-NEXT:    addl $8, %esp
934; X86-NEXT:    popl %esi
935; X86-NEXT:    retl
936;
937; X64-LABEL: t21_sret_to_non_sret:
938; X64:       # %bb.0:
939; X64-NEXT:    pushq %rbx
940; X64-NEXT:    movq %rdi, %rbx
941; X64-NEXT:    callq t21_f_non_sret
942; X64-NEXT:    movq %rbx, %rax
943; X64-NEXT:    popq %rbx
944; X64-NEXT:    retq
945;
946; X32-LABEL: t21_sret_to_non_sret:
947; X32:       # %bb.0:
948; X32-NEXT:    pushq %rbx
949; X32-NEXT:    movq %rdi, %rbx
950; X32-NEXT:    callq t21_f_non_sret
951; X32-NEXT:    movl %ebx, %eax
952; X32-NEXT:    popq %rbx
953; X32-NEXT:    retq
954  tail call fastcc void @t21_f_non_sret(ptr %agg.result) nounwind
955  ret void
956}
957
958define ccc void @t22_non_sret_to_sret(ptr %agg.result) nounwind  {
959; i686 not tailcallable, as sret is callee-pop here.
960; X86-LABEL: t22_non_sret_to_sret:
961; X86:       # %bb.0:
962; X86-NEXT:    subl $12, %esp
963; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
964; X86-NEXT:    movl %eax, (%esp)
965; X86-NEXT:    calll t22_f_sret@PLT
966; X86-NEXT:    addl $8, %esp
967; X86-NEXT:    retl
968;
969; X64-LABEL: t22_non_sret_to_sret:
970; X64:       # %bb.0:
971; X64-NEXT:    jmp t22_f_sret@PLT # TAILCALL
972;
973; X32-LABEL: t22_non_sret_to_sret:
974; X32:       # %bb.0:
975; X32-NEXT:    jmp t22_f_sret@PLT # TAILCALL
976  tail call ccc void @t22_f_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind
977  ret void
978}
979
980declare dso_local fastcc void @t21_f_sret(ptr noalias sret(%struct.foo)) nounwind
981declare dso_local fastcc void @t21_f_sret2(ptr noalias sret(%struct.foo), ptr noalias) nounwind
982declare dso_local fastcc void @t21_f_non_sret(ptr) nounwind
983
984declare ccc void @t22_f_sret(ptr noalias sret(%struct.foo)) nounwind
985
986declare ccc void @f_sret(ptr noalias sret(%struct.foo), i32, i32) nounwind
987