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