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