1084 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -verify-machineinstrs < %s -mtriple=i686-linux -mcpu=core2 -mattr=+sse2 | FileCheck %s --check-prefix=X863; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-linux -mcpu=core2 -mattr=+sse2 | FileCheck %s --check-prefix=X644; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-linux-gnux32 -mcpu=core2 -mattr=+sse2 | FileCheck %s --check-prefix=X325 6define dso_local void @t1(i32 %x) nounwind ssp {7; X86-LABEL: t1:8; X86: # %bb.0:9; X86-NEXT: jmp foo # TAILCALL10;11; X64-LABEL: t1:12; X64: # %bb.0:13; X64-NEXT: jmp foo # TAILCALL14;15; X32-LABEL: t1:16; X32: # %bb.0:17; X32-NEXT: jmp foo # TAILCALL18 tail call void @foo() nounwind19 ret void20}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 # TAILCALL28;29; X64-LABEL: t2:30; X64: # %bb.0:31; X64-NEXT: jmp foo2 # TAILCALL32;33; X32-LABEL: t2:34; X32: # %bb.0:35; X32-NEXT: jmp foo2 # TAILCALL36 %t0 = tail call i32 @foo2() nounwind37 ret void38}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 # TAILCALL46;47; X64-LABEL: t3:48; X64: # %bb.0:49; X64-NEXT: jmp foo3 # TAILCALL50;51; X32-LABEL: t3:52; X32: # %bb.0:53; X32-NEXT: jmp foo3 # TAILCALL54 %t0 = tail call i32 @foo3() nounwind55 ret void56}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, %esp64; X86-NEXT: movl $0, (%esp)65; X86-NEXT: calll *{{[0-9]+}}(%esp)66; X86-NEXT: addl $12, %esp67; X86-NEXT: retl68;69; X64-LABEL: t4:70; X64: # %bb.0:71; X64-NEXT: movq %rdi, %rax72; X64-NEXT: xorl %edi, %edi73; X64-NEXT: jmpq *%rax # TAILCALL74;75; X32-LABEL: t4:76; X32: # %bb.0:77; X32-NEXT: movq %rdi, %rax78; X32-NEXT: xorl %edi, %edi79; X32-NEXT: jmpq *%rax # TAILCALL80 tail call void %x(i32 0) nounwind81 ret void82}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) # TAILCALL88;89; X64-LABEL: t5:90; X64: # %bb.0:91; X64-NEXT: jmpq *%rdi # TAILCALL92;93; X32-LABEL: t5:94; X32: # %bb.0:95; X32-NEXT: jmpq *%rdi # TAILCALL96 tail call void %x() nounwind97 ret void98}99 100; Basically the same test as t5, except pass the function pointer on the stack101; 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) # TAILCALL107;108; X64-LABEL: t5_x64:109; X64: # %bb.0:110; X64-NEXT: jmpq *{{[0-9]+}}(%rsp) # TAILCALL111;112; X32-LABEL: t5_x64:113; X32: # %bb.0:114; X32-NEXT: movl {{[0-9]+}}(%esp), %eax115; X32-NEXT: jmpq *%rax # TAILCALL116 tail call void %x() nounwind117 ret void118}119 120 121define dso_local i32 @t6(i32 %x) nounwind ssp {122; X86-LABEL: t6:123; X86: # %bb.0:124; X86-NEXT: subl $12, %esp125; X86-NEXT: movl {{[0-9]+}}(%esp), %eax126; X86-NEXT: cmpl $9, %eax127; X86-NEXT: jg .LBB6_2128; X86-NEXT: # %bb.1: # %bb129; X86-NEXT: decl %eax130; X86-NEXT: movl %eax, (%esp)131; X86-NEXT: calll t6132; X86-NEXT: addl $12, %esp133; X86-NEXT: retl134; X86-NEXT: .LBB6_2: # %bb1135; X86-NEXT: addl $12, %esp136; X86-NEXT: jmp bar # TAILCALL137;138; X64-LABEL: t6:139; X64: # %bb.0:140; X64-NEXT: cmpl $9, %edi141; X64-NEXT: jg bar # TAILCALL142; X64-NEXT: # %bb.1: # %bb143; X64-NEXT: decl %edi144; X64-NEXT: jmp t6 # TAILCALL145;146; X32-LABEL: t6:147; X32: # %bb.0:148; X32-NEXT: cmpl $9, %edi149; X32-NEXT: jg bar # TAILCALL150; X32-NEXT: # %bb.1: # %bb151; X32-NEXT: decl %edi152; X32-NEXT: jmp t6 # TAILCALL153 %t0 = icmp slt i32 %x, 10154 br i1 %t0, label %bb, label %bb1155 156bb:157 %t1 = add nsw i32 %x, -1158 %t2 = tail call i32 @t6(i32 %t1) nounwind ssp159 ret i32 %t2160 161bb1:162 %t3 = tail call i32 @bar(i32 %x) nounwind163 ret i32 %t3164}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 # TAILCALL172;173; X64-LABEL: t7:174; X64: # %bb.0:175; X64-NEXT: jmp bar2 # TAILCALL176;177; X32-LABEL: t7:178; X32: # %bb.0:179; X32-NEXT: jmp bar2 # TAILCALL180 %t0 = tail call i32 @bar2(i32 %a, i32 %b, i32 %c) nounwind181 ret i32 %t0182}183 184declare dso_local i32 @bar2(i32, i32, i32)185 186define signext i16 @t8() nounwind ssp {187; X86-LABEL: t8:188; X86: # %bb.0: # %entry189; X86-NEXT: jmp bar3 # TAILCALL190;191; X64-LABEL: t8:192; X64: # %bb.0: # %entry193; X64-NEXT: jmp bar3 # TAILCALL194;195; X32-LABEL: t8:196; X32: # %bb.0: # %entry197; X32-NEXT: jmp bar3 # TAILCALL198entry:199 %0 = tail call signext i16 @bar3() nounwind ; <i16> [#uses=1]200 ret i16 %0201}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: # %entry208; X86-NEXT: subl $12, %esp209; X86-NEXT: movl $0, (%esp)210; X86-NEXT: calll *{{[0-9]+}}(%esp)211; X86-NEXT: addl $12, %esp212; X86-NEXT: retl213;214; X64-LABEL: t9:215; X64: # %bb.0: # %entry216; X64-NEXT: movq %rdi, %rax217; X64-NEXT: xorl %edi, %edi218; X64-NEXT: jmpq *%rax # TAILCALL219;220; X32-LABEL: t9:221; X32: # %bb.0: # %entry222; X32-NEXT: movq %rdi, %rax223; X32-NEXT: xorl %edi, %edi224; X32-NEXT: jmpq *%rax # TAILCALL225entry:226 %0 = tail call signext i16 %x(i32 0) nounwind227 ret i16 %0228}229 230define dso_local void @t10() nounwind ssp {231; X86-LABEL: t10:232; X86: # %bb.0: # %entry233; X86-NEXT: subl $12, %esp234; X86-NEXT: calll foo4235;236; X64-LABEL: t10:237; X64: # %bb.0: # %entry238; X64-NEXT: pushq %rax239; X64-NEXT: callq foo4240;241; X32-LABEL: t10:242; X32: # %bb.0: # %entry243; X32-NEXT: pushq %rax244; X32-NEXT: callq foo4245entry:246 %0 = tail call i32 @foo4() noreturn nounwind247 unreachable248}249 250declare dso_local i32 @foo4()251 252; In 32-bit mode, it's emitting a bunch of dead loads that are not being253; 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: # %entry258; X86-NEXT: cmpl $0, {{[0-9]+}}(%esp)259; X86-NEXT: jne foo5 # TAILCALL260; X86-NEXT: # %bb.1: # %bb6261; X86-NEXT: xorl %eax, %eax262; X86-NEXT: retl263;264; X64-LABEL: t11:265; X64: # %bb.0: # %entry266; X64-NEXT: testl %edi, %edi267; X64-NEXT: jne foo5 # TAILCALL268; X64-NEXT: # %bb.1: # %bb6269; X64-NEXT: xorl %eax, %eax270; X64-NEXT: retq271;272; X32-LABEL: t11:273; X32: # %bb.0: # %entry274; X32-NEXT: testl %edi, %edi275; X32-NEXT: jne foo5 # TAILCALL276; X32-NEXT: # %bb.1: # %bb6277; X32-NEXT: xorl %eax, %eax278; X32-NEXT: retq279entry:280 %0 = icmp eq i32 %x, 0281 br i1 %0, label %bb6, label %bb282 283bb:284 %1 = tail call i32 @foo5(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind285 ret i32 %1286 287bb6:288 ret i32 0289}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: # %entry298; X86-NEXT: cmpl $0, {{[0-9]+}}(%esp)299; X86-NEXT: jne foo6 # TAILCALL300; X86-NEXT: # %bb.1: # %bb2301; X86-NEXT: xorl %eax, %eax302; X86-NEXT: retl303;304; X64-LABEL: t12:305; X64: # %bb.0: # %entry306; X64-NEXT: testl %edi, %edi307; X64-NEXT: jne foo6 # TAILCALL308; X64-NEXT: # %bb.1: # %bb2309; X64-NEXT: xorl %eax, %eax310; X64-NEXT: retq311;312; X32-LABEL: t12:313; X32: # %bb.0: # %entry314; X32-NEXT: testl %edi, %edi315; X32-NEXT: jne foo6 # TAILCALL316; X32-NEXT: # %bb.1: # %bb2317; X32-NEXT: xorl %eax, %eax318; X32-NEXT: retq319entry:320 %0 = icmp eq i32 %x, 0321 br i1 %0, label %bb2, label %bb322 323bb:324 %1 = tail call i32 @foo6(i32 %x, i32 %y, ptr byval(%struct.t) align 4 %z) nounwind325 ret i32 %1326 327bb2:328 ret i32 0329}330 331declare dso_local i32 @foo6(i32, i32, ptr byval(%struct.t) align 4)332 333; rdar://r7717598334%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: # %entry340; X86-NEXT: subl $28, %esp341; X86-NEXT: movl {{[0-9]+}}(%esp), %eax342; X86-NEXT: movl 16(%eax), %ecx343; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp)344; X86-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero345; X86-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero346; X86-NEXT: movsd %xmm1, {{[0-9]+}}(%esp)347; X86-NEXT: movsd %xmm0, (%esp)348; X86-NEXT: xorl %ecx, %ecx349; X86-NEXT: calll foo7350; X86-NEXT: addl $28, %esp351; X86-NEXT: retl352;353; X64-LABEL: t13:354; X64: # %bb.0: # %entry355; X64-NEXT: pushq %rax356; X64-NEXT: subq $8, %rsp357; X64-NEXT: movl 16(%rdi), %eax358; X64-NEXT: movq (%rdi), %rcx359; X64-NEXT: movq 8(%rdi), %rdx360; X64-NEXT: xorl %edi, %edi361; X64-NEXT: pushq %rax362; X64-NEXT: pushq %rdx363; X64-NEXT: pushq %rcx364; X64-NEXT: callq foo7365; X64-NEXT: addq $32, %rsp366; X64-NEXT: popq %rcx367; X64-NEXT: retq368;369; X32-LABEL: t13:370; X32: # %bb.0: # %entry371; X32-NEXT: pushq %rax372; X32-NEXT: subl $8, %esp373; X32-NEXT: movl 16(%edi), %eax374; X32-NEXT: movq (%edi), %rcx375; X32-NEXT: movq 8(%edi), %rdx376; X32-NEXT: xorl %edi, %edi377; X32-NEXT: pushq %rax378; X32-NEXT: pushq %rdx379; X32-NEXT: pushq %rcx380; X32-NEXT: callq foo7381; X32-NEXT: addl $32, %esp382; X32-NEXT: movl %eax, %eax383; X32-NEXT: popq %rcx384; X32-NEXT: retq385entry:386 %0 = tail call fastcc ptr @foo7(ptr byval(%struct.cp) align 4 %yy, i8 signext 0) nounwind387 ret ptr %0388}389 390; rdar://6195379391; 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 ssp393 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: # %entry402; X86-NEXT: subl $12, %esp403; X86-NEXT: movl {{[0-9]+}}(%esp), %eax404; X86-NEXT: movl 20(%eax), %eax405; X86-NEXT: movl %eax, (%esp)406; X86-NEXT: calll *12(%eax)407; X86-NEXT: addl $12, %esp408; X86-NEXT: retl409;410; X64-LABEL: t14:411; X64: # %bb.0: # %entry412; X64-NEXT: movq 32(%rdi), %rdi413; X64-NEXT: jmpq *16(%rdi) # TAILCALL414;415; X32-LABEL: t14:416; X32: # %bb.0: # %entry417; X32-NEXT: movl 20(%edi), %edi418; X32-NEXT: movl 12(%edi), %eax419; X32-NEXT: jmpq *%rax # TAILCALL420entry: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) nounwind426 ret void427}428 429; rdar://7726868430%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 %esi436; X86-NEXT: subl $8, %esp437; X86-NEXT: movl {{[0-9]+}}(%esp), %esi438; X86-NEXT: movl %esi, %ecx439; X86-NEXT: calll f440; X86-NEXT: movl %esi, %eax441; X86-NEXT: addl $8, %esp442; X86-NEXT: popl %esi443; X86-NEXT: retl $4444;445; X64-LABEL: t15:446; X64: # %bb.0:447; X64-NEXT: jmp f # TAILCALL448;449; X32-LABEL: t15:450; X32: # %bb.0:451; X32-NEXT: jmp f # TAILCALL452 tail call fastcc void @f(ptr noalias sret(%struct.foo) %agg.result) nounwind453 ret void454}455 456declare dso_local void @f(ptr noalias sret(%struct.foo)) nounwind457 458define dso_local void @t16() nounwind ssp {459; X86-LABEL: t16:460; X86: # %bb.0: # %entry461; X86-NEXT: subl $12, %esp462; X86-NEXT: calll bar4463; X86-NEXT: fstp %st(0)464; X86-NEXT: addl $12, %esp465; X86-NEXT: retl466;467; X64-LABEL: t16:468; X64: # %bb.0: # %entry469; X64-NEXT: jmp bar4 # TAILCALL470;471; X32-LABEL: t16:472; X32: # %bb.0: # %entry473; X32-NEXT: jmp bar4 # TAILCALL474entry:475 %0 = tail call double @bar4() nounwind476 ret void477}478 479declare dso_local double @bar4()480 481; rdar://6283267482define dso_local void @t17() nounwind ssp {483; X86-LABEL: t17:484; X86: # %bb.0: # %entry485; X86-NEXT: jmp bar5 # TAILCALL486;487; X64-LABEL: t17:488; X64: # %bb.0: # %entry489; X64-NEXT: xorl %eax, %eax490; X64-NEXT: jmp bar5 # TAILCALL491;492; X32-LABEL: t17:493; X32: # %bb.0: # %entry494; X32-NEXT: xorl %eax, %eax495; X32-NEXT: jmp bar5 # TAILCALL496entry:497 tail call void (...) @bar5() nounwind498 ret void499}500 501declare dso_local void @bar5(...)502 503; rdar://7774847504define dso_local void @t18() nounwind ssp {505; X86-LABEL: t18:506; X86: # %bb.0: # %entry507; X86-NEXT: subl $12, %esp508; X86-NEXT: calll bar6509; X86-NEXT: fstp %st(0)510; X86-NEXT: addl $12, %esp511; X86-NEXT: retl512;513; X64-LABEL: t18:514; X64: # %bb.0: # %entry515; X64-NEXT: xorl %eax, %eax516; X64-NEXT: jmp bar6 # TAILCALL517;518; X32-LABEL: t18:519; X32: # %bb.0: # %entry520; X32-NEXT: xorl %eax, %eax521; X32-NEXT: jmp bar6 # TAILCALL522entry:523 %0 = tail call double (...) @bar6() nounwind524 ret void525}526 527declare dso_local double @bar6(...)528 529define dso_local void @t19() alignstack(32) nounwind {530; X86-LABEL: t19:531; X86: # %bb.0: # %entry532; X86-NEXT: pushl %ebp533; X86-NEXT: movl %esp, %ebp534; X86-NEXT: andl $-32, %esp535; X86-NEXT: subl $32, %esp536; X86-NEXT: calll foo537; X86-NEXT: movl %ebp, %esp538; X86-NEXT: popl %ebp539; X86-NEXT: retl540;541; X64-LABEL: t19:542; X64: # %bb.0: # %entry543; X64-NEXT: pushq %rbp544; X64-NEXT: movq %rsp, %rbp545; X64-NEXT: andq $-32, %rsp546; X64-NEXT: subq $32, %rsp547; X64-NEXT: callq foo548; X64-NEXT: movq %rbp, %rsp549; X64-NEXT: popq %rbp550; X64-NEXT: retq551;552; X32-LABEL: t19:553; X32: # %bb.0: # %entry554; X32-NEXT: pushq %rbp555; X32-NEXT: movl %esp, %ebp556; X32-NEXT: andl $-32, %esp557; X32-NEXT: subl $32, %esp558; X32-NEXT: callq foo559; X32-NEXT: movl %ebp, %esp560; X32-NEXT: popq %rbp561; X32-NEXT: retq562entry:563 tail call void @foo() nounwind564 ret void565}566 567; If caller / callee calling convention mismatch then check if the return568; values are returned in the same registers.569; rdar://7874780570 571define dso_local double @t20(double %x) nounwind {572; X86-LABEL: t20:573; X86: # %bb.0: # %entry574; X86-NEXT: subl $12, %esp575; X86-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero576; X86-NEXT: calll foo20577; X86-NEXT: movsd %xmm0, (%esp)578; X86-NEXT: fldl (%esp)579; X86-NEXT: addl $12, %esp580; X86-NEXT: retl581;582; X64-LABEL: t20:583; X64: # %bb.0: # %entry584; X64-NEXT: jmp foo20 # TAILCALL585;586; X32-LABEL: t20:587; X32: # %bb.0: # %entry588; X32-NEXT: jmp foo20 # TAILCALL589entry:590 %0 = tail call fastcc double @foo20(double %x) nounwind591 ret double %0592}593 594declare dso_local fastcc double @foo20(double) nounwind595 596; bug 28417597define fastcc void @t21_sret_to_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind {598; X86-LABEL: t21_sret_to_sret:599; X86: # %bb.0:600; X86-NEXT: jmp t21_f_sret # TAILCALL601;602; X64-LABEL: t21_sret_to_sret:603; X64: # %bb.0:604; X64-NEXT: jmp t21_f_sret # TAILCALL605;606; X32-LABEL: t21_sret_to_sret:607; X32: # %bb.0:608; X32-NEXT: jmp t21_f_sret # TAILCALL609 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind610 ret void611}612 613define fastcc void @t21_sret_to_sret_more_args(ptr noalias sret(%struct.foo) %agg.result, i32 %a, i32 %b) nounwind {614; X86-LABEL: t21_sret_to_sret_more_args:615; X86: # %bb.0:616; X86-NEXT: jmp f_sret@PLT # TAILCALL617;618; X64-LABEL: t21_sret_to_sret_more_args:619; X64: # %bb.0:620; X64-NEXT: jmp f_sret@PLT # TAILCALL621;622; X32-LABEL: t21_sret_to_sret_more_args:623; X32: # %bb.0:624; X32-NEXT: jmp f_sret@PLT # TAILCALL625 tail call fastcc void @f_sret(ptr noalias sret(%struct.foo) %agg.result, i32 %a, i32 %b) nounwind626 ret void627}628 629define fastcc void @t21_sret_to_sret_second_arg_sret(ptr noalias %agg.result, ptr noalias sret(%struct.foo) %ret) nounwind {630; X86-LABEL: t21_sret_to_sret_second_arg_sret:631; X86: # %bb.0:632; X86-NEXT: movl %edx, %ecx633; X86-NEXT: jmp t21_f_sret # TAILCALL634;635; X64-LABEL: t21_sret_to_sret_second_arg_sret:636; X64: # %bb.0:637; X64-NEXT: movq %rsi, %rdi638; X64-NEXT: jmp t21_f_sret # TAILCALL639;640; X32-LABEL: t21_sret_to_sret_second_arg_sret:641; X32: # %bb.0:642; X32-NEXT: movq %rsi, %rdi643; X32-NEXT: jmp t21_f_sret # TAILCALL644 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind645 ret void646}647 648define fastcc void @t21_sret_to_sret_more_args2(ptr noalias sret(%struct.foo) %agg.result, i32 %a, i32 %b) nounwind {649; X86-LABEL: t21_sret_to_sret_more_args2:650; X86: # %bb.0:651; X86-NEXT: pushl %esi652; X86-NEXT: subl $8, %esp653; X86-NEXT: movl %ecx, %esi654; X86-NEXT: movl {{[0-9]+}}(%esp), %eax655; X86-NEXT: movl %edx, (%esp)656; X86-NEXT: movl %eax, %edx657; X86-NEXT: calll f_sret@PLT658; X86-NEXT: movl %esi, %eax659; X86-NEXT: addl $8, %esp660; X86-NEXT: popl %esi661; X86-NEXT: retl662;663; X64-LABEL: t21_sret_to_sret_more_args2:664; X64: # %bb.0:665; X64-NEXT: movl %esi, %eax666; X64-NEXT: movl %edx, %esi667; X64-NEXT: movl %eax, %edx668; X64-NEXT: jmp f_sret@PLT # TAILCALL669;670; X32-LABEL: t21_sret_to_sret_more_args2:671; X32: # %bb.0:672; X32-NEXT: movl %esi, %eax673; X32-NEXT: movl %edx, %esi674; X32-NEXT: movl %eax, %edx675; X32-NEXT: jmp f_sret@PLT # TAILCALL676 tail call fastcc void @f_sret(ptr noalias sret(%struct.foo) %agg.result, i32 %b, i32 %a) nounwind677 ret void678}679 680 681define fastcc void @t21_sret_to_sret_args_mismatch(ptr noalias sret(%struct.foo) %agg.result, ptr noalias %ret) nounwind {682; X86-LABEL: t21_sret_to_sret_args_mismatch:683; X86: # %bb.0:684; X86-NEXT: pushl %esi685; X86-NEXT: subl $8, %esp686; X86-NEXT: movl %ecx, %esi687; X86-NEXT: movl %edx, %ecx688; X86-NEXT: calll t21_f_sret689; X86-NEXT: movl %esi, %eax690; X86-NEXT: addl $8, %esp691; X86-NEXT: popl %esi692; X86-NEXT: retl693;694; X64-LABEL: t21_sret_to_sret_args_mismatch:695; X64: # %bb.0:696; X64-NEXT: pushq %rbx697; X64-NEXT: movq %rdi, %rbx698; X64-NEXT: movq %rsi, %rdi699; X64-NEXT: callq t21_f_sret700; X64-NEXT: movq %rbx, %rax701; X64-NEXT: popq %rbx702; X64-NEXT: retq703;704; X32-LABEL: t21_sret_to_sret_args_mismatch:705; X32: # %bb.0:706; X32-NEXT: pushq %rbx707; X32-NEXT: movq %rdi, %rbx708; X32-NEXT: movq %rsi, %rdi709; X32-NEXT: callq t21_f_sret710; X32-NEXT: movl %ebx, %eax711; X32-NEXT: popq %rbx712; X32-NEXT: retq713 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind714 ret void715}716 717define fastcc void @t21_sret_to_sret_args_mismatch2(ptr noalias sret(%struct.foo) %agg.result, ptr noalias %ret) nounwind {718; X86-LABEL: t21_sret_to_sret_args_mismatch2:719; X86: # %bb.0:720; X86-NEXT: pushl %esi721; X86-NEXT: subl $8, %esp722; X86-NEXT: movl %ecx, %esi723; X86-NEXT: movl %edx, %ecx724; X86-NEXT: calll t21_f_sret725; X86-NEXT: movl %esi, %eax726; X86-NEXT: addl $8, %esp727; X86-NEXT: popl %esi728; X86-NEXT: retl729;730; X64-LABEL: t21_sret_to_sret_args_mismatch2:731; X64: # %bb.0:732; X64-NEXT: pushq %rbx733; X64-NEXT: movq %rdi, %rbx734; X64-NEXT: movq %rsi, %rdi735; X64-NEXT: callq t21_f_sret736; X64-NEXT: movq %rbx, %rax737; X64-NEXT: popq %rbx738; X64-NEXT: retq739;740; X32-LABEL: t21_sret_to_sret_args_mismatch2:741; X32: # %bb.0:742; X32-NEXT: pushq %rbx743; X32-NEXT: movq %rdi, %rbx744; X32-NEXT: movq %rsi, %rdi745; X32-NEXT: callq t21_f_sret746; X32-NEXT: movl %ebx, %eax747; X32-NEXT: popq %rbx748; X32-NEXT: retq749 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %ret) nounwind750 ret void751}752 753define fastcc void @t21_sret_to_sret_arg_mismatch(ptr noalias sret(%struct.foo) %agg.result) nounwind {754; X86-LABEL: t21_sret_to_sret_arg_mismatch:755; X86: # %bb.0:756; X86-NEXT: pushl %esi757; X86-NEXT: subl $8, %esp758; X86-NEXT: movl %ecx, %esi759; X86-NEXT: calll ret_struct@PLT760; X86-NEXT: movl %eax, %ecx761; X86-NEXT: calll t21_f_sret762; X86-NEXT: movl %esi, %eax763; X86-NEXT: addl $8, %esp764; X86-NEXT: popl %esi765; X86-NEXT: retl766;767; X64-LABEL: t21_sret_to_sret_arg_mismatch:768; X64: # %bb.0:769; X64-NEXT: pushq %rbx770; X64-NEXT: movq %rdi, %rbx771; X64-NEXT: callq ret_struct@PLT772; X64-NEXT: movq %rax, %rdi773; X64-NEXT: callq t21_f_sret774; X64-NEXT: movq %rbx, %rax775; X64-NEXT: popq %rbx776; X64-NEXT: retq777;778; X32-LABEL: t21_sret_to_sret_arg_mismatch:779; X32: # %bb.0:780; X32-NEXT: pushq %rbx781; X32-NEXT: movq %rdi, %rbx782; X32-NEXT: callq ret_struct@PLT783; X32-NEXT: movl %eax, %edi784; X32-NEXT: callq t21_f_sret785; X32-NEXT: movl %ebx, %eax786; X32-NEXT: popq %rbx787; X32-NEXT: retq788 %a = call fastcc ptr @ret_struct()789 tail call fastcc void @t21_f_sret(ptr noalias sret(%struct.foo) %a) nounwind790 ret void791}792 793define fastcc void @t21_sret_to_sret_structs_mismatch(ptr noalias sret(%struct.foo) %agg.result, ptr noalias %a) nounwind {794; X86-LABEL: t21_sret_to_sret_structs_mismatch:795; X86: # %bb.0:796; X86-NEXT: pushl %edi797; X86-NEXT: pushl %esi798; X86-NEXT: pushl %eax799; X86-NEXT: movl %edx, %esi800; X86-NEXT: movl %ecx, %edi801; X86-NEXT: calll ret_struct@PLT802; X86-NEXT: movl %esi, %ecx803; X86-NEXT: movl %eax, %edx804; X86-NEXT: calll t21_f_sret2805; X86-NEXT: movl %edi, %eax806; X86-NEXT: addl $4, %esp807; X86-NEXT: popl %esi808; X86-NEXT: popl %edi809; X86-NEXT: retl810;811; X64-LABEL: t21_sret_to_sret_structs_mismatch:812; X64: # %bb.0:813; X64-NEXT: pushq %r14814; X64-NEXT: pushq %rbx815; X64-NEXT: pushq %rax816; X64-NEXT: movq %rsi, %rbx817; X64-NEXT: movq %rdi, %r14818; X64-NEXT: callq ret_struct@PLT819; X64-NEXT: movq %rbx, %rdi820; X64-NEXT: movq %rax, %rsi821; X64-NEXT: callq t21_f_sret2822; X64-NEXT: movq %r14, %rax823; X64-NEXT: addq $8, %rsp824; X64-NEXT: popq %rbx825; X64-NEXT: popq %r14826; X64-NEXT: retq827;828; X32-LABEL: t21_sret_to_sret_structs_mismatch:829; X32: # %bb.0:830; X32-NEXT: pushq %r14831; X32-NEXT: pushq %rbx832; X32-NEXT: pushq %rax833; X32-NEXT: movq %rsi, %rbx834; X32-NEXT: movq %rdi, %r14835; X32-NEXT: callq ret_struct@PLT836; X32-NEXT: movl %eax, %esi837; X32-NEXT: movq %rbx, %rdi838; X32-NEXT: callq t21_f_sret2839; X32-NEXT: movl %r14d, %eax840; X32-NEXT: addl $8, %esp841; X32-NEXT: popq %rbx842; X32-NEXT: popq %r14843; X32-NEXT: retq844 %b = call fastcc ptr @ret_struct()845 tail call fastcc void @t21_f_sret2(ptr noalias sret(%struct.foo) %a, ptr noalias %b) nounwind846 ret void847}848 849declare ccc ptr @ret_struct() nounwind850 851 852define fastcc void @t21_sret_to_non_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind {853; X86-LABEL: t21_sret_to_non_sret:854; X86: # %bb.0:855; X86-NEXT: pushl %esi856; X86-NEXT: subl $8, %esp857; X86-NEXT: movl %ecx, %esi858; X86-NEXT: calll t21_f_non_sret859; X86-NEXT: movl %esi, %eax860; X86-NEXT: addl $8, %esp861; X86-NEXT: popl %esi862; X86-NEXT: retl863;864; X64-LABEL: t21_sret_to_non_sret:865; X64: # %bb.0:866; X64-NEXT: pushq %rbx867; X64-NEXT: movq %rdi, %rbx868; X64-NEXT: callq t21_f_non_sret869; X64-NEXT: movq %rbx, %rax870; X64-NEXT: popq %rbx871; X64-NEXT: retq872;873; X32-LABEL: t21_sret_to_non_sret:874; X32: # %bb.0:875; X32-NEXT: pushq %rbx876; X32-NEXT: movq %rdi, %rbx877; X32-NEXT: callq t21_f_non_sret878; X32-NEXT: movl %ebx, %eax879; X32-NEXT: popq %rbx880; X32-NEXT: retq881 tail call fastcc void @t21_f_non_sret(ptr %agg.result) nounwind882 ret void883}884 885define ccc void @t22_non_sret_to_sret(ptr %agg.result) nounwind {886; i686 not tailcallable, as sret is callee-pop here.887; X86-LABEL: t22_non_sret_to_sret:888; X86: # %bb.0:889; X86-NEXT: subl $12, %esp890; X86-NEXT: movl {{[0-9]+}}(%esp), %eax891; X86-NEXT: movl %eax, (%esp)892; X86-NEXT: calll t22_f_sret@PLT893; X86-NEXT: addl $8, %esp894; X86-NEXT: retl895;896; X64-LABEL: t22_non_sret_to_sret:897; X64: # %bb.0:898; X64-NEXT: jmp t22_f_sret@PLT # TAILCALL899;900; X32-LABEL: t22_non_sret_to_sret:901; X32: # %bb.0:902; X32-NEXT: jmp t22_f_sret@PLT # TAILCALL903 tail call ccc void @t22_f_sret(ptr noalias sret(%struct.foo) %agg.result) nounwind904 ret void905}906 907; Not tailcallable, caller and callee have different return types.908define void @t23_sret_to_non_sret(ptr noalias sret(%struct.foo) align 4 %agg.result, ptr %arg) {909; X86-LABEL: t23_sret_to_non_sret:910; X86: # %bb.0:911; X86-NEXT: pushl %esi912; X86-NEXT: .cfi_def_cfa_offset 8913; X86-NEXT: subl $8, %esp914; X86-NEXT: .cfi_def_cfa_offset 16915; X86-NEXT: .cfi_offset %esi, -8916; X86-NEXT: movl {{[0-9]+}}(%esp), %esi917; X86-NEXT: movl {{[0-9]+}}(%esp), %eax918; X86-NEXT: movl %eax, (%esp)919; X86-NEXT: calll callee_1@PLT920; X86-NEXT: movl %esi, %eax921; X86-NEXT: addl $8, %esp922; X86-NEXT: .cfi_def_cfa_offset 8923; X86-NEXT: popl %esi924; X86-NEXT: .cfi_def_cfa_offset 4925; X86-NEXT: retl $4926;927; X64-LABEL: t23_sret_to_non_sret:928; X64: # %bb.0:929; X64-NEXT: pushq %rbx930; X64-NEXT: .cfi_def_cfa_offset 16931; X64-NEXT: .cfi_offset %rbx, -16932; X64-NEXT: movq %rdi, %rbx933; X64-NEXT: movq %rsi, %rdi934; X64-NEXT: callq callee_1@PLT935; X64-NEXT: movq %rbx, %rax936; X64-NEXT: popq %rbx937; X64-NEXT: .cfi_def_cfa_offset 8938; X64-NEXT: retq939;940; X32-LABEL: t23_sret_to_non_sret:941; X32: # %bb.0:942; X32-NEXT: pushq %rbx943; X32-NEXT: .cfi_def_cfa_offset 16944; X32-NEXT: .cfi_offset %rbx, -16945; X32-NEXT: movq %rdi, %rbx946; X32-NEXT: movq %rsi, %rdi947; X32-NEXT: callq callee_1@PLT948; X32-NEXT: movl %ebx, %eax949; X32-NEXT: popq %rbx950; X32-NEXT: .cfi_def_cfa_offset 8951; X32-NEXT: retq952 tail call void @callee_1(ptr %arg)953 ret void954}955 956; Not tailcallable, caller and callee have the same return type, but different return values.957define void @t24_sret_to_sret_different_val(ptr noalias sret(%struct.foo) align 4 %agg.result, ptr %arg) {958; X86-LABEL: t24_sret_to_sret_different_val:959; X86: # %bb.0:960; X86-NEXT: pushl %esi961; X86-NEXT: .cfi_def_cfa_offset 8962; X86-NEXT: subl $24, %esp963; X86-NEXT: .cfi_def_cfa_offset 32964; X86-NEXT: .cfi_offset %esi, -8965; X86-NEXT: movl {{[0-9]+}}(%esp), %esi966; X86-NEXT: xorps %xmm0, %xmm0967; X86-NEXT: movsd %xmm0, 8(%esi)968; X86-NEXT: movsd %xmm0, (%esi)969; X86-NEXT: leal {{[0-9]+}}(%esp), %eax970; X86-NEXT: movl %eax, (%esp)971; X86-NEXT: calll callee_2@PLT972; X86-NEXT: subl $4, %esp973; X86-NEXT: movl %esi, %eax974; X86-NEXT: addl $24, %esp975; X86-NEXT: .cfi_def_cfa_offset 8976; X86-NEXT: popl %esi977; X86-NEXT: .cfi_def_cfa_offset 4978; X86-NEXT: retl $4979;980; X64-LABEL: t24_sret_to_sret_different_val:981; X64: # %bb.0:982; X64-NEXT: pushq %rbx983; X64-NEXT: .cfi_def_cfa_offset 16984; X64-NEXT: subq $16, %rsp985; X64-NEXT: .cfi_def_cfa_offset 32986; X64-NEXT: .cfi_offset %rbx, -16987; X64-NEXT: movq %rdi, %rbx988; X64-NEXT: movq $0, 8(%rdi)989; X64-NEXT: movq $0, (%rdi)990; X64-NEXT: movq %rsp, %rdi991; X64-NEXT: callq callee_2@PLT992; X64-NEXT: movq %rbx, %rax993; X64-NEXT: addq $16, %rsp994; X64-NEXT: .cfi_def_cfa_offset 16995; X64-NEXT: popq %rbx996; X64-NEXT: .cfi_def_cfa_offset 8997; X64-NEXT: retq998;999; X32-LABEL: t24_sret_to_sret_different_val:1000; X32: # %bb.0:1001; X32-NEXT: pushq %rbx1002; X32-NEXT: .cfi_def_cfa_offset 161003; X32-NEXT: subl $16, %esp1004; X32-NEXT: .cfi_def_cfa_offset 321005; X32-NEXT: .cfi_offset %rbx, -161006; X32-NEXT: movq %rdi, %rbx1007; X32-NEXT: movq $0, 8(%ebx)1008; X32-NEXT: movq $0, (%ebx)1009; X32-NEXT: movl %esp, %edi1010; X32-NEXT: callq callee_2@PLT1011; X32-NEXT: movl %ebx, %eax1012; X32-NEXT: addl $16, %esp1013; X32-NEXT: .cfi_def_cfa_offset 161014; X32-NEXT: popq %rbx1015; X32-NEXT: .cfi_def_cfa_offset 81016; X32-NEXT: retq1017 %callee.return = alloca %struct.foo, align 41018 tail call void @llvm.memset.p0.i64(ptr align 4 %agg.result, i8 0, i64 16, i1 false)1019 tail call void @callee_2(ptr sret(%struct.foo) align 4 %callee.return)1020 ret void1021}1022 1023; Not tailcallable, caller and callee have the same return type, but different return values.1024define void @t25_sret_to_sret_different_val(ptr noalias sret(%struct.foo) align 8 %agg.result, ptr %arg) {1025; X86-LABEL: t25_sret_to_sret_different_val:1026; X86: # %bb.0:1027; X86-NEXT: pushl %esi1028; X86-NEXT: .cfi_def_cfa_offset 81029; X86-NEXT: subl $8, %esp1030; X86-NEXT: .cfi_def_cfa_offset 161031; X86-NEXT: .cfi_offset %esi, -81032; X86-NEXT: movl {{[0-9]+}}(%esp), %esi1033; X86-NEXT: movl {{[0-9]+}}(%esp), %eax1034; X86-NEXT: movl %eax, (%esp)1035; X86-NEXT: calll callee_2@PLT1036; X86-NEXT: subl $4, %esp1037; X86-NEXT: movl %esi, %eax1038; X86-NEXT: addl $8, %esp1039; X86-NEXT: .cfi_def_cfa_offset 81040; X86-NEXT: popl %esi1041; X86-NEXT: .cfi_def_cfa_offset 41042; X86-NEXT: retl $41043;1044; X64-LABEL: t25_sret_to_sret_different_val:1045; X64: # %bb.0:1046; X64-NEXT: pushq %rbx1047; X64-NEXT: .cfi_def_cfa_offset 161048; X64-NEXT: .cfi_offset %rbx, -161049; X64-NEXT: movq %rdi, %rbx1050; X64-NEXT: movq %rsi, %rdi1051; X64-NEXT: callq callee_2@PLT1052; X64-NEXT: movq %rbx, %rax1053; X64-NEXT: popq %rbx1054; X64-NEXT: .cfi_def_cfa_offset 81055; X64-NEXT: retq1056;1057; X32-LABEL: t25_sret_to_sret_different_val:1058; X32: # %bb.0:1059; X32-NEXT: pushq %rbx1060; X32-NEXT: .cfi_def_cfa_offset 161061; X32-NEXT: .cfi_offset %rbx, -161062; X32-NEXT: movq %rdi, %rbx1063; X32-NEXT: movq %rsi, %rdi1064; X32-NEXT: callq callee_2@PLT1065; X32-NEXT: movl %ebx, %eax1066; X32-NEXT: popq %rbx1067; X32-NEXT: .cfi_def_cfa_offset 81068; X32-NEXT: retq1069 tail call void @callee_2(ptr sret(%struct.foo) align 8 %arg)1070 ret void1071}1072 1073declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)1074declare void @callee_1(ptr)1075declare void @callee_2(ptr noalias sret(%struct.foo))1076 1077declare dso_local fastcc void @t21_f_sret(ptr noalias sret(%struct.foo)) nounwind1078declare dso_local fastcc void @t21_f_sret2(ptr noalias sret(%struct.foo), ptr noalias) nounwind1079declare dso_local fastcc void @t21_f_non_sret(ptr) nounwind1080 1081declare ccc void @t22_f_sret(ptr noalias sret(%struct.foo)) nounwind1082 1083declare ccc void @f_sret(ptr noalias sret(%struct.foo), i32, i32) nounwind1084