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
6 define dso_local void @t1(i32 %x) nounwind ssp {
9 ; X86-NEXT: jmp foo # TAILCALL
13 ; X64-NEXT: jmp foo # TAILCALL
17 ; X32-NEXT: jmp foo # TAILCALL
18 tail call void @foo() nounwind
22 declare dso_local void @foo()
24 define dso_local void @t2() nounwind ssp {
27 ; X86-NEXT: jmp foo2 # TAILCALL
31 ; X64-NEXT: jmp foo2 # TAILCALL
35 ; X32-NEXT: jmp foo2 # TAILCALL
36 %t0 = tail call i32 @foo2() nounwind
40 declare dso_local i32 @foo2()
42 define dso_local void @t3() nounwind ssp {
45 ; X86-NEXT: jmp foo3 # TAILCALL
49 ; X64-NEXT: jmp foo3 # TAILCALL
53 ; X32-NEXT: jmp foo3 # TAILCALL
54 %t0 = tail call i32 @foo3() nounwind
58 declare dso_local i32 @foo3()
60 define dso_local void @t4(ptr nocapture %x) nounwind ssp {
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
71 ; X64-NEXT: movq %rdi, %rax
72 ; X64-NEXT: xorl %edi, %edi
73 ; X64-NEXT: jmpq *%rax # TAILCALL
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
84 define dso_local void @t5(ptr nocapture %x) nounwind ssp {
87 ; X86-NEXT: jmpl *{{[0-9]+}}(%esp) # TAILCALL
91 ; X64-NEXT: jmpq *%rdi # TAILCALL
95 ; X32-NEXT: jmpq *%rdi # TAILCALL
96 tail call void %x() nounwind
100 ; Basically the same test as t5, except pass the function pointer on the stack
103 define dso_local void @t5_x64(i32, i32, i32, i32, i32, i32, ptr nocapture %x) nounwind ssp {
106 ; X86-NEXT: jmpl *{{[0-9]+}}(%esp) # TAILCALL
110 ; X64-NEXT: jmpq *{{[0-9]+}}(%rsp) # TAILCALL
114 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
115 ; X32-NEXT: jmpq *%rax # TAILCALL
116 tail call void %x() nounwind
121 define dso_local i32 @t6(i32 %x) nounwind ssp {
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)
132 ; X86-NEXT: addl $12, %esp
134 ; X86-NEXT: .LBB6_2: # %bb1
135 ; X86-NEXT: addl $12, %esp
136 ; X86-NEXT: jmp bar # TAILCALL
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
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
157 %t1 = add nsw i32 %x, -1
158 %t2 = tail call i32 @t6(i32 %t1) nounwind ssp
162 %t3 = tail call i32 @bar(i32 %x) nounwind
166 declare dso_local i32 @bar(i32)
168 define dso_local i32 @t7(i32 %a, i32 %b, i32 %c) nounwind ssp {
171 ; X86-NEXT: jmp bar2 # TAILCALL
175 ; X64-NEXT: jmp bar2 # TAILCALL
179 ; X32-NEXT: jmp bar2 # TAILCALL
180 %t0 = tail call i32 @bar2(i32 %a, i32 %b, i32 %c) nounwind
184 declare dso_local i32 @bar2(i32, i32, i32)
186 define signext i16 @t8() nounwind ssp {
188 ; X86: # %bb.0: # %entry
189 ; X86-NEXT: jmp bar3 # TAILCALL
192 ; X64: # %bb.0: # %entry
193 ; X64-NEXT: jmp bar3 # TAILCALL
196 ; X32: # %bb.0: # %entry
197 ; X32-NEXT: jmp bar3 # TAILCALL
199 %0 = tail call signext i16 @bar3() nounwind ; <i16> [#uses=1]
203 declare dso_local signext i16 @bar3()
205 define signext i16 @t9(ptr nocapture %x) nounwind ssp {
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
215 ; X64: # %bb.0: # %entry
216 ; X64-NEXT: movq %rdi, %rax
217 ; X64-NEXT: xorl %edi, %edi
218 ; X64-NEXT: jmpq *%rax # TAILCALL
221 ; X32: # %bb.0: # %entry
222 ; X32-NEXT: movq %rdi, %rax
223 ; X32-NEXT: xorl %edi, %edi
224 ; X32-NEXT: jmpq *%rax # TAILCALL
226 %0 = tail call signext i16 %x(i32 0) nounwind
230 define dso_local void @t10() nounwind ssp {
232 ; X86: # %bb.0: # %entry
233 ; X86-NEXT: subl $12, %esp
234 ; X86-NEXT: calll foo4
237 ; X64: # %bb.0: # %entry
238 ; X64-NEXT: pushq %rax
239 ; X64-NEXT: callq foo4
242 ; X32: # %bb.0: # %entry
243 ; X32-NEXT: pushq %rax
244 ; X32-NEXT: callq foo4
246 %0 = tail call i32 @foo4() noreturn nounwind
250 declare dso_local i32 @foo4()
252 ; In 32-bit mode, it's emitting a bunch of dead loads that are not being
253 ; eliminated currently.
255 define dso_local i32 @t11(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind ssp {
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
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
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
280 %0 = icmp eq i32 %x, 0
281 br i1 %0, label %bb6, label %bb
284 %1 = tail call i32 @foo5(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind
291 declare dso_local i32 @foo5(i32, i32, i32, i32, i32)
293 %struct.t = type { i32, i32, i32, i32, i32 }
295 define dso_local i32 @t12(i32 %x, i32 %y, ptr byval(%struct.t) align 4 %z) nounwind ssp {
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
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
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
320 %0 = icmp eq i32 %x, 0
321 br i1 %0, label %bb2, label %bb
324 %1 = tail call i32 @foo6(i32 %x, i32 %y, ptr byval(%struct.t) align 4 %z) nounwind
331 declare dso_local i32 @foo6(i32, i32, ptr byval(%struct.t) align 4)
334 %struct.ns = type { i32, i32 }
335 %struct.cp = type { float, float, float, float, float }
337 define ptr @t13(ptr %yy) nounwind ssp {
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
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
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
386 %0 = tail call fastcc ptr @foo7(ptr byval(%struct.cp) align 4 %yy, i8 signext 0) nounwind
391 ; llvm can't do sibcall for this in 32-bit mode (yet).
392 declare dso_local fastcc ptr @foo7(ptr byval(%struct.cp) align 4, i8 signext) nounwind ssp
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 }
399 define dso_local void @t14(ptr nocapture %.block_descriptor) nounwind ssp {
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
411 ; X64: # %bb.0: # %entry
412 ; X64-NEXT: movq 32(%rdi), %rdi
413 ; X64-NEXT: jmpq *16(%rdi) # TAILCALL
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
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
430 %struct.foo = type { [4 x i32] }
432 define dso_local void @t15(ptr noalias sret(%struct.foo) %agg.result) nounwind {
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
440 ; X86-NEXT: movl %esi, %eax
441 ; X86-NEXT: addl $8, %esp
442 ; X86-NEXT: popl %esi
447 ; X64-NEXT: pushq %rbx
448 ; X64-NEXT: movq %rdi, %rbx
450 ; X64-NEXT: movq %rbx, %rax
451 ; X64-NEXT: popq %rbx
456 ; X32-NEXT: pushq %rbx
457 ; X32-NEXT: movq %rdi, %rbx
459 ; X32-NEXT: movl %ebx, %eax
460 ; X32-NEXT: popq %rbx
462 tail call fastcc void @f(ptr noalias sret(%struct.foo) %agg.result) nounwind
466 declare dso_local void @f(ptr noalias sret(%struct.foo)) nounwind
468 define dso_local void @t16() nounwind ssp {
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
478 ; X64: # %bb.0: # %entry
479 ; X64-NEXT: jmp bar4 # TAILCALL
482 ; X32: # %bb.0: # %entry
483 ; X32-NEXT: jmp bar4 # TAILCALL
485 %0 = tail call double @bar4() nounwind
489 declare dso_local double @bar4()
492 define dso_local void @t17() nounwind ssp {
494 ; X86: # %bb.0: # %entry
495 ; X86-NEXT: jmp bar5 # TAILCALL
498 ; X64: # %bb.0: # %entry
499 ; X64-NEXT: xorl %eax, %eax
500 ; X64-NEXT: jmp bar5 # TAILCALL
503 ; X32: # %bb.0: # %entry
504 ; X32-NEXT: xorl %eax, %eax
505 ; X32-NEXT: jmp bar5 # TAILCALL
507 tail call void (...) @bar5() nounwind
511 declare dso_local void @bar5(...)
514 define dso_local void @t18() nounwind ssp {
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
524 ; X64: # %bb.0: # %entry
525 ; X64-NEXT: xorl %eax, %eax
526 ; X64-NEXT: jmp bar6 # TAILCALL
529 ; X32: # %bb.0: # %entry
530 ; X32-NEXT: xorl %eax, %eax
531 ; X32-NEXT: jmp bar6 # TAILCALL
533 %0 = tail call double (...) @bar6() nounwind
537 declare dso_local double @bar6(...)
539 define dso_local void @t19() alignstack(32) nounwind {
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
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
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
573 tail call void @foo() nounwind
577 ; If caller / callee calling convention mismatch then check if the return
578 ; values are returned in the same registers.
581 define dso_local double @t20(double %x) nounwind {
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
593 ; X64: # %bb.0: # %entry
594 ; X64-NEXT: jmp foo20 # TAILCALL
597 ; X32: # %bb.0: # %entry
598 ; X32-NEXT: jmp foo20 # TAILCALL
600 %0 = tail call fastcc double @foo20(double %x) nounwind
604 declare dso_local fastcc double @foo20(double) nounwind
607 define fastcc void @t21_sret_to_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind {
608 ; X86-LABEL: t21_sret_to_sret:
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
619 ; X64-LABEL: t21_sret_to_sret:
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
628 ; X32-LABEL: t21_sret_to_sret:
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
636 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind
640 define 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:
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
654 ; X64-LABEL: t21_sret_to_sret_more_args:
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
663 ; X32-LABEL: t21_sret_to_sret_more_args:
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
671 tail call fastcc void @f_sret(ptr noalias sret(%struct.foo) %agg.result, i32 %a, i32 %b) nounwind
675 define 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:
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
688 ; X64-LABEL: t21_sret_to_sret_second_arg_sret:
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
698 ; X32-LABEL: t21_sret_to_sret_second_arg_sret:
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
707 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind
711 define 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:
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
726 ; X64-LABEL: t21_sret_to_sret_more_args2:
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
738 ; X32-LABEL: t21_sret_to_sret_more_args2:
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
749 tail call fastcc void @f_sret(ptr noalias sret(%struct.foo) %agg.result, i32 %b, i32 %a) nounwind
754 define 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:
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
767 ; X64-LABEL: t21_sret_to_sret_args_mismatch:
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
777 ; X32-LABEL: t21_sret_to_sret_args_mismatch:
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
786 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind
790 define 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:
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
803 ; X64-LABEL: t21_sret_to_sret_args_mismatch2:
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
813 ; X32-LABEL: t21_sret_to_sret_args_mismatch2:
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
822 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind
826 define 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:
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
840 ; X64-LABEL: t21_sret_to_sret_arg_mismatch:
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
851 ; X32-LABEL: t21_sret_to_sret_arg_mismatch:
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
861 %a = call fastcc ptr @ret_struct()
862 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %a) nounwind
866 define 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:
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
884 ; X64-LABEL: t21_sret_to_sret_structs_mismatch:
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
901 ; X32-LABEL: t21_sret_to_sret_structs_mismatch:
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
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
922 declare ccc ptr @ret_struct() nounwind
925 define fastcc void @t21_sret_to_non_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind {
926 ; X86-LABEL: t21_sret_to_non_sret:
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
937 ; X64-LABEL: t21_sret_to_non_sret:
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
946 ; X32-LABEL: t21_sret_to_non_sret:
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
954 tail call fastcc void @t21_f_non_sret(ptr %agg.result) nounwind
958 define 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:
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
969 ; X64-LABEL: t22_non_sret_to_sret:
971 ; X64-NEXT: jmp t22_f_sret@PLT # TAILCALL
973 ; X32-LABEL: t22_non_sret_to_sret:
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
980 declare dso_local fastcc void @t21_f_sret(ptr noalias sret(%struct.foo)) nounwind
981 declare dso_local fastcc void @t21_f_sret2(ptr noalias sret(%struct.foo), ptr noalias) nounwind
982 declare dso_local fastcc void @t21_f_non_sret(ptr) nounwind
984 declare ccc void @t22_f_sret(ptr noalias sret(%struct.foo)) nounwind
986 declare ccc void @f_sret(ptr noalias sret(%struct.foo), i32, i32) nounwind