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