1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-linux | FileCheck %s --check-prefix=LINUX 3; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-linux-gnux32 | FileCheck %s --check-prefix=LINUX-X32 4; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-windows | FileCheck %s --check-prefix=WINDOWS 5; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=i686-windows | FileCheck %s --check-prefix=X86 --check-prefix=X86-NOSSE 6; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=i686-windows -mattr=+sse2 | FileCheck %s --check-prefix=X86 --check-prefix=X86-SSE 7 8; Test that we actually spill and reload all arguments in the variadic argument 9; pack. Doing a normal call will clobber all argument registers, and we will 10; spill around it. A simple adjustment should not require any XMM spills. 11 12declare void @llvm.va_start(i8*) nounwind 13 14declare void(i8*, ...)* @get_f(i8* %this) 15 16define void @f_thunk(i8* %this, ...) { 17 ; Use va_start so that we exercise the combination. 18; LINUX-LABEL: f_thunk: 19; LINUX: # %bb.0: 20; LINUX-NEXT: pushq %rbp 21; LINUX-NEXT: .cfi_def_cfa_offset 16 22; LINUX-NEXT: pushq %r15 23; LINUX-NEXT: .cfi_def_cfa_offset 24 24; LINUX-NEXT: pushq %r14 25; LINUX-NEXT: .cfi_def_cfa_offset 32 26; LINUX-NEXT: pushq %r13 27; LINUX-NEXT: .cfi_def_cfa_offset 40 28; LINUX-NEXT: pushq %r12 29; LINUX-NEXT: .cfi_def_cfa_offset 48 30; LINUX-NEXT: pushq %rbx 31; LINUX-NEXT: .cfi_def_cfa_offset 56 32; LINUX-NEXT: subq $360, %rsp # imm = 0x168 33; LINUX-NEXT: .cfi_def_cfa_offset 416 34; LINUX-NEXT: .cfi_offset %rbx, -56 35; LINUX-NEXT: .cfi_offset %r12, -48 36; LINUX-NEXT: .cfi_offset %r13, -40 37; LINUX-NEXT: .cfi_offset %r14, -32 38; LINUX-NEXT: .cfi_offset %r15, -24 39; LINUX-NEXT: .cfi_offset %rbp, -16 40; LINUX-NEXT: movq %r9, %r15 41; LINUX-NEXT: movq %r8, %r12 42; LINUX-NEXT: movq %rcx, %r13 43; LINUX-NEXT: movq %rdx, %rbp 44; LINUX-NEXT: movq %rsi, %rbx 45; LINUX-NEXT: movq %rdi, %r14 46; LINUX-NEXT: movb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill 47; LINUX-NEXT: testb %al, %al 48; LINUX-NEXT: je .LBB0_2 49; LINUX-NEXT: # %bb.1: 50; LINUX-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp) 51; LINUX-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp) 52; LINUX-NEXT: movaps %xmm2, {{[0-9]+}}(%rsp) 53; LINUX-NEXT: movaps %xmm3, {{[0-9]+}}(%rsp) 54; LINUX-NEXT: movaps %xmm4, {{[0-9]+}}(%rsp) 55; LINUX-NEXT: movaps %xmm5, {{[0-9]+}}(%rsp) 56; LINUX-NEXT: movaps %xmm6, {{[0-9]+}}(%rsp) 57; LINUX-NEXT: movaps %xmm7, {{[0-9]+}}(%rsp) 58; LINUX-NEXT: .LBB0_2: 59; LINUX-NEXT: movq %r15, {{[0-9]+}}(%rsp) 60; LINUX-NEXT: movq %r12, {{[0-9]+}}(%rsp) 61; LINUX-NEXT: movq %r13, {{[0-9]+}}(%rsp) 62; LINUX-NEXT: movq %rbp, {{[0-9]+}}(%rsp) 63; LINUX-NEXT: movq %rbx, {{[0-9]+}}(%rsp) 64; LINUX-NEXT: leaq {{[0-9]+}}(%rsp), %rax 65; LINUX-NEXT: movq %rax, {{[0-9]+}}(%rsp) 66; LINUX-NEXT: leaq {{[0-9]+}}(%rsp), %rax 67; LINUX-NEXT: movq %rax, {{[0-9]+}}(%rsp) 68; LINUX-NEXT: movabsq $206158430216, %rax # imm = 0x3000000008 69; LINUX-NEXT: movq %rax, {{[0-9]+}}(%rsp) 70; LINUX-NEXT: movq %r14, %rdi 71; LINUX-NEXT: movaps %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill 72; LINUX-NEXT: movaps %xmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill 73; LINUX-NEXT: movaps %xmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill 74; LINUX-NEXT: movaps %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill 75; LINUX-NEXT: movaps %xmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill 76; LINUX-NEXT: movaps %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill 77; LINUX-NEXT: movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill 78; LINUX-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill 79; LINUX-NEXT: callq get_f 80; LINUX-NEXT: movq %rax, %r11 81; LINUX-NEXT: movq %r14, %rdi 82; LINUX-NEXT: movq %rbx, %rsi 83; LINUX-NEXT: movq %rbp, %rdx 84; LINUX-NEXT: movq %r13, %rcx 85; LINUX-NEXT: movq %r12, %r8 86; LINUX-NEXT: movq %r15, %r9 87; LINUX-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload 88; LINUX-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload 89; LINUX-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload 90; LINUX-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload 91; LINUX-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload 92; LINUX-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm5 # 16-byte Reload 93; LINUX-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm6 # 16-byte Reload 94; LINUX-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm7 # 16-byte Reload 95; LINUX-NEXT: movb {{[-0-9]+}}(%r{{[sb]}}p), %al # 1-byte Reload 96; LINUX-NEXT: addq $360, %rsp # imm = 0x168 97; LINUX-NEXT: .cfi_def_cfa_offset 56 98; LINUX-NEXT: popq %rbx 99; LINUX-NEXT: .cfi_def_cfa_offset 48 100; LINUX-NEXT: popq %r12 101; LINUX-NEXT: .cfi_def_cfa_offset 40 102; LINUX-NEXT: popq %r13 103; LINUX-NEXT: .cfi_def_cfa_offset 32 104; LINUX-NEXT: popq %r14 105; LINUX-NEXT: .cfi_def_cfa_offset 24 106; LINUX-NEXT: popq %r15 107; LINUX-NEXT: .cfi_def_cfa_offset 16 108; LINUX-NEXT: popq %rbp 109; LINUX-NEXT: .cfi_def_cfa_offset 8 110; LINUX-NEXT: jmpq *%r11 # TAILCALL 111; 112; LINUX-X32-LABEL: f_thunk: 113; LINUX-X32: # %bb.0: 114; LINUX-X32-NEXT: pushq %rbp 115; LINUX-X32-NEXT: .cfi_def_cfa_offset 16 116; LINUX-X32-NEXT: pushq %r15 117; LINUX-X32-NEXT: .cfi_def_cfa_offset 24 118; LINUX-X32-NEXT: pushq %r14 119; LINUX-X32-NEXT: .cfi_def_cfa_offset 32 120; LINUX-X32-NEXT: pushq %r13 121; LINUX-X32-NEXT: .cfi_def_cfa_offset 40 122; LINUX-X32-NEXT: pushq %r12 123; LINUX-X32-NEXT: .cfi_def_cfa_offset 48 124; LINUX-X32-NEXT: pushq %rbx 125; LINUX-X32-NEXT: .cfi_def_cfa_offset 56 126; LINUX-X32-NEXT: subl $344, %esp # imm = 0x158 127; LINUX-X32-NEXT: .cfi_def_cfa_offset 400 128; LINUX-X32-NEXT: .cfi_offset %rbx, -56 129; LINUX-X32-NEXT: .cfi_offset %r12, -48 130; LINUX-X32-NEXT: .cfi_offset %r13, -40 131; LINUX-X32-NEXT: .cfi_offset %r14, -32 132; LINUX-X32-NEXT: .cfi_offset %r15, -24 133; LINUX-X32-NEXT: .cfi_offset %rbp, -16 134; LINUX-X32-NEXT: movq %r9, %r15 135; LINUX-X32-NEXT: movq %r8, %r12 136; LINUX-X32-NEXT: movq %rcx, %r13 137; LINUX-X32-NEXT: movq %rdx, %rbp 138; LINUX-X32-NEXT: movq %rsi, %rbx 139; LINUX-X32-NEXT: movl %edi, %r14d 140; LINUX-X32-NEXT: movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill 141; LINUX-X32-NEXT: testb %al, %al 142; LINUX-X32-NEXT: je .LBB0_2 143; LINUX-X32-NEXT: # %bb.1: 144; LINUX-X32-NEXT: movaps %xmm0, {{[0-9]+}}(%esp) 145; LINUX-X32-NEXT: movaps %xmm1, {{[0-9]+}}(%esp) 146; LINUX-X32-NEXT: movaps %xmm2, {{[0-9]+}}(%esp) 147; LINUX-X32-NEXT: movaps %xmm3, {{[0-9]+}}(%esp) 148; LINUX-X32-NEXT: movaps %xmm4, {{[0-9]+}}(%esp) 149; LINUX-X32-NEXT: movaps %xmm5, {{[0-9]+}}(%esp) 150; LINUX-X32-NEXT: movaps %xmm6, {{[0-9]+}}(%esp) 151; LINUX-X32-NEXT: movaps %xmm7, {{[0-9]+}}(%esp) 152; LINUX-X32-NEXT: .LBB0_2: 153; LINUX-X32-NEXT: movq %r15, {{[0-9]+}}(%esp) 154; LINUX-X32-NEXT: movq %r12, {{[0-9]+}}(%esp) 155; LINUX-X32-NEXT: movq %r13, {{[0-9]+}}(%esp) 156; LINUX-X32-NEXT: movq %rbp, {{[0-9]+}}(%esp) 157; LINUX-X32-NEXT: movq %rbx, {{[0-9]+}}(%esp) 158; LINUX-X32-NEXT: leal {{[0-9]+}}(%rsp), %eax 159; LINUX-X32-NEXT: movl %eax, {{[0-9]+}}(%esp) 160; LINUX-X32-NEXT: leal {{[0-9]+}}(%rsp), %eax 161; LINUX-X32-NEXT: movl %eax, {{[0-9]+}}(%esp) 162; LINUX-X32-NEXT: movabsq $206158430216, %rax # imm = 0x3000000008 163; LINUX-X32-NEXT: movq %rax, {{[0-9]+}}(%esp) 164; LINUX-X32-NEXT: movl %r14d, %edi 165; LINUX-X32-NEXT: movaps %xmm7, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 166; LINUX-X32-NEXT: movaps %xmm6, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 167; LINUX-X32-NEXT: movaps %xmm5, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 168; LINUX-X32-NEXT: movaps %xmm4, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 169; LINUX-X32-NEXT: movaps %xmm3, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 170; LINUX-X32-NEXT: movaps %xmm2, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 171; LINUX-X32-NEXT: movaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 172; LINUX-X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 173; LINUX-X32-NEXT: callq get_f 174; LINUX-X32-NEXT: movl %eax, %r11d 175; LINUX-X32-NEXT: movl %r14d, %edi 176; LINUX-X32-NEXT: movq %rbx, %rsi 177; LINUX-X32-NEXT: movq %rbp, %rdx 178; LINUX-X32-NEXT: movq %r13, %rcx 179; LINUX-X32-NEXT: movq %r12, %r8 180; LINUX-X32-NEXT: movq %r15, %r9 181; LINUX-X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 # 16-byte Reload 182; LINUX-X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 # 16-byte Reload 183; LINUX-X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 # 16-byte Reload 184; LINUX-X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm3 # 16-byte Reload 185; LINUX-X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm4 # 16-byte Reload 186; LINUX-X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm5 # 16-byte Reload 187; LINUX-X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm6 # 16-byte Reload 188; LINUX-X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm7 # 16-byte Reload 189; LINUX-X32-NEXT: movb {{[-0-9]+}}(%e{{[sb]}}p), %al # 1-byte Reload 190; LINUX-X32-NEXT: addl $344, %esp # imm = 0x158 191; LINUX-X32-NEXT: .cfi_def_cfa_offset 56 192; LINUX-X32-NEXT: popq %rbx 193; LINUX-X32-NEXT: .cfi_def_cfa_offset 48 194; LINUX-X32-NEXT: popq %r12 195; LINUX-X32-NEXT: .cfi_def_cfa_offset 40 196; LINUX-X32-NEXT: popq %r13 197; LINUX-X32-NEXT: .cfi_def_cfa_offset 32 198; LINUX-X32-NEXT: popq %r14 199; LINUX-X32-NEXT: .cfi_def_cfa_offset 24 200; LINUX-X32-NEXT: popq %r15 201; LINUX-X32-NEXT: .cfi_def_cfa_offset 16 202; LINUX-X32-NEXT: popq %rbp 203; LINUX-X32-NEXT: .cfi_def_cfa_offset 8 204; LINUX-X32-NEXT: jmpq *%r11 # TAILCALL 205; 206; WINDOWS-LABEL: f_thunk: 207; WINDOWS: # %bb.0: 208; WINDOWS-NEXT: pushq %r14 209; WINDOWS-NEXT: .seh_pushreg 14 210; WINDOWS-NEXT: pushq %rsi 211; WINDOWS-NEXT: .seh_pushreg 6 212; WINDOWS-NEXT: pushq %rdi 213; WINDOWS-NEXT: .seh_pushreg 7 214; WINDOWS-NEXT: pushq %rbp 215; WINDOWS-NEXT: .seh_pushreg 5 216; WINDOWS-NEXT: pushq %rbx 217; WINDOWS-NEXT: .seh_pushreg 3 218; WINDOWS-NEXT: subq $64, %rsp 219; WINDOWS-NEXT: .seh_stackalloc 64 220; WINDOWS-NEXT: .seh_endprologue 221; WINDOWS-NEXT: movl %eax, %r14d 222; WINDOWS-NEXT: movq %r9, %rsi 223; WINDOWS-NEXT: movq %r8, %rdi 224; WINDOWS-NEXT: movq %rdx, %rbx 225; WINDOWS-NEXT: movq %rcx, %rbp 226; WINDOWS-NEXT: movq %r9, {{[0-9]+}}(%rsp) 227; WINDOWS-NEXT: movq %r8, {{[0-9]+}}(%rsp) 228; WINDOWS-NEXT: movq %rdx, {{[0-9]+}}(%rsp) 229; WINDOWS-NEXT: leaq {{[0-9]+}}(%rsp), %rax 230; WINDOWS-NEXT: movq %rax, {{[0-9]+}}(%rsp) 231; WINDOWS-NEXT: callq get_f 232; WINDOWS-NEXT: movq %rax, %r10 233; WINDOWS-NEXT: movq %rbp, %rcx 234; WINDOWS-NEXT: movq %rbx, %rdx 235; WINDOWS-NEXT: movq %rdi, %r8 236; WINDOWS-NEXT: movq %rsi, %r9 237; WINDOWS-NEXT: movl %r14d, %eax 238; WINDOWS-NEXT: addq $64, %rsp 239; WINDOWS-NEXT: popq %rbx 240; WINDOWS-NEXT: popq %rbp 241; WINDOWS-NEXT: popq %rdi 242; WINDOWS-NEXT: popq %rsi 243; WINDOWS-NEXT: popq %r14 244; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL 245; WINDOWS-NEXT: .seh_handlerdata 246; WINDOWS-NEXT: .text 247; WINDOWS-NEXT: .seh_endproc 248; 249; X86-NOSSE-LABEL: f_thunk: 250; X86-NOSSE: # %bb.0: 251; X86-NOSSE-NEXT: pushl %ebp 252; X86-NOSSE-NEXT: movl %esp, %ebp 253; X86-NOSSE-NEXT: pushl %esi 254; X86-NOSSE-NEXT: andl $-16, %esp 255; X86-NOSSE-NEXT: subl $48, %esp 256; X86-NOSSE-NEXT: movl 8(%ebp), %esi 257; X86-NOSSE-NEXT: leal 12(%ebp), %eax 258; X86-NOSSE-NEXT: movl %eax, {{[0-9]+}}(%esp) 259; X86-NOSSE-NEXT: movl %esi, (%esp) 260; X86-NOSSE-NEXT: calll _get_f 261; X86-NOSSE-NEXT: movl %esi, 8(%ebp) 262; X86-NOSSE-NEXT: leal -4(%ebp), %esp 263; X86-NOSSE-NEXT: popl %esi 264; X86-NOSSE-NEXT: popl %ebp 265; X86-NOSSE-NEXT: jmpl *%eax # TAILCALL 266; 267; X86-SSE-LABEL: f_thunk: 268; X86-SSE: # %bb.0: 269; X86-SSE-NEXT: pushl %ebp 270; X86-SSE-NEXT: movl %esp, %ebp 271; X86-SSE-NEXT: pushl %esi 272; X86-SSE-NEXT: andl $-16, %esp 273; X86-SSE-NEXT: subl $96, %esp 274; X86-SSE-NEXT: movaps %xmm2, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 275; X86-SSE-NEXT: movaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 276; X86-SSE-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) # 16-byte Spill 277; X86-SSE-NEXT: movl 8(%ebp), %esi 278; X86-SSE-NEXT: leal 12(%ebp), %eax 279; X86-SSE-NEXT: movl %eax, {{[0-9]+}}(%esp) 280; X86-SSE-NEXT: movl %esi, (%esp) 281; X86-SSE-NEXT: calll _get_f 282; X86-SSE-NEXT: movl %esi, 8(%ebp) 283; X86-SSE-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 # 16-byte Reload 284; X86-SSE-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 # 16-byte Reload 285; X86-SSE-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 # 16-byte Reload 286; X86-SSE-NEXT: leal -4(%ebp), %esp 287; X86-SSE-NEXT: popl %esi 288; X86-SSE-NEXT: popl %ebp 289; X86-SSE-NEXT: jmpl *%eax # TAILCALL 290 %ap = alloca [4 x i8*], align 16 291 %ap_i8 = bitcast [4 x i8*]* %ap to i8* 292 call void @llvm.va_start(i8* %ap_i8) 293 294 %fptr = call void(i8*, ...)*(i8*) @get_f(i8* %this) 295 musttail call void (i8*, ...) %fptr(i8* %this, ...) 296 ret void 297} 298 299; Save and restore 6 GPRs, 8 XMMs, and AL around the call. 300 301; No regparms on normal x86 conventions. 302 303; This thunk shouldn't require any spills and reloads, assuming the register 304; allocator knows what it's doing. 305 306define void @g_thunk(i8* %fptr_i8, ...) { 307; LINUX-LABEL: g_thunk: 308; LINUX: # %bb.0: 309; LINUX-NEXT: pushq %rax 310; LINUX-NEXT: .cfi_def_cfa_offset 16 311; LINUX-NEXT: popq %r11 312; LINUX-NEXT: .cfi_def_cfa_offset 8 313; LINUX-NEXT: jmpq *%rdi # TAILCALL 314; 315; LINUX-X32-LABEL: g_thunk: 316; LINUX-X32: # %bb.0: 317; LINUX-X32-NEXT: pushq %rax 318; LINUX-X32-NEXT: .cfi_def_cfa_offset 16 319; LINUX-X32-NEXT: movl %edi, %r11d 320; LINUX-X32-NEXT: addl $8, %esp 321; LINUX-X32-NEXT: .cfi_def_cfa_offset 8 322; LINUX-X32-NEXT: jmpq *%r11 # TAILCALL 323; 324; WINDOWS-LABEL: g_thunk: 325; WINDOWS: # %bb.0: 326; WINDOWS-NEXT: subq $40, %rsp 327; WINDOWS-NEXT: .seh_stackalloc 40 328; WINDOWS-NEXT: .seh_endprologue 329; WINDOWS-NEXT: addq $40, %rsp 330; WINDOWS-NEXT: rex64 jmpq *%rcx # TAILCALL 331; WINDOWS-NEXT: .seh_handlerdata 332; WINDOWS-NEXT: .text 333; WINDOWS-NEXT: .seh_endproc 334; 335; X86-LABEL: g_thunk: 336; X86: # %bb.0: 337; X86-NEXT: pushl %eax 338; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 339; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) 340; X86-NEXT: popl %ecx 341; X86-NEXT: jmpl *%eax # TAILCALL 342 %fptr = bitcast i8* %fptr_i8 to void (i8*, ...)* 343 musttail call void (i8*, ...) %fptr(i8* %fptr_i8, ...) 344 ret void 345} 346 347; Do a simple multi-exit multi-bb test. 348 349%struct.Foo = type { i1, i8*, i8* } 350 351@g = external global i32 352 353define void @h_thunk(%struct.Foo* %this, ...) { 354; LINUX-LABEL: h_thunk: 355; LINUX: # %bb.0: 356; LINUX-NEXT: pushq %rax 357; LINUX-NEXT: .cfi_def_cfa_offset 16 358; LINUX-NEXT: cmpb $1, (%rdi) 359; LINUX-NEXT: jne .LBB2_2 360; LINUX-NEXT: # %bb.1: # %then 361; LINUX-NEXT: movq 8(%rdi), %r11 362; LINUX-NEXT: addq $8, %rsp 363; LINUX-NEXT: .cfi_def_cfa_offset 8 364; LINUX-NEXT: jmpq *%r11 # TAILCALL 365; LINUX-NEXT: .LBB2_2: # %else 366; LINUX-NEXT: .cfi_def_cfa_offset 16 367; LINUX-NEXT: movq 16(%rdi), %r11 368; LINUX-NEXT: movl $42, {{.*}}(%rip) 369; LINUX-NEXT: addq $8, %rsp 370; LINUX-NEXT: .cfi_def_cfa_offset 8 371; LINUX-NEXT: jmpq *%r11 # TAILCALL 372; 373; LINUX-X32-LABEL: h_thunk: 374; LINUX-X32: # %bb.0: 375; LINUX-X32-NEXT: pushq %rax 376; LINUX-X32-NEXT: .cfi_def_cfa_offset 16 377; LINUX-X32-NEXT: cmpb $1, (%edi) 378; LINUX-X32-NEXT: jne .LBB2_2 379; LINUX-X32-NEXT: # %bb.1: # %then 380; LINUX-X32-NEXT: movl 4(%edi), %r11d 381; LINUX-X32-NEXT: addl $8, %esp 382; LINUX-X32-NEXT: .cfi_def_cfa_offset 8 383; LINUX-X32-NEXT: jmpq *%r11 # TAILCALL 384; LINUX-X32-NEXT: .LBB2_2: # %else 385; LINUX-X32-NEXT: .cfi_def_cfa_offset 16 386; LINUX-X32-NEXT: movl 8(%edi), %r11d 387; LINUX-X32-NEXT: movl $42, {{.*}}(%rip) 388; LINUX-X32-NEXT: addl $8, %esp 389; LINUX-X32-NEXT: .cfi_def_cfa_offset 8 390; LINUX-X32-NEXT: jmpq *%r11 # TAILCALL 391; 392; WINDOWS-LABEL: h_thunk: 393; WINDOWS: # %bb.0: 394; WINDOWS-NEXT: subq $40, %rsp 395; WINDOWS-NEXT: .seh_stackalloc 40 396; WINDOWS-NEXT: .seh_endprologue 397; WINDOWS-NEXT: cmpb $1, (%rcx) 398; WINDOWS-NEXT: jne .LBB2_2 399; WINDOWS-NEXT: # %bb.1: # %then 400; WINDOWS-NEXT: movq 8(%rcx), %r10 401; WINDOWS-NEXT: addq $40, %rsp 402; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL 403; WINDOWS-NEXT: .LBB2_2: # %else 404; WINDOWS-NEXT: movq 16(%rcx), %r10 405; WINDOWS-NEXT: movl $42, {{.*}}(%rip) 406; WINDOWS-NEXT: addq $40, %rsp 407; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL 408; WINDOWS-NEXT: .seh_handlerdata 409; WINDOWS-NEXT: .text 410; WINDOWS-NEXT: .seh_endproc 411; 412; X86-LABEL: h_thunk: 413; X86: # %bb.0: 414; X86-NEXT: pushl %eax 415; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 416; X86-NEXT: cmpb $1, (%eax) 417; X86-NEXT: jne LBB2_2 418; X86-NEXT: # %bb.1: # %then 419; X86-NEXT: movl 4(%eax), %ecx 420; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) 421; X86-NEXT: popl %eax 422; X86-NEXT: jmpl *%ecx # TAILCALL 423; X86-NEXT: LBB2_2: # %else 424; X86-NEXT: movl 8(%eax), %ecx 425; X86-NEXT: movl $42, _g 426; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) 427; X86-NEXT: popl %eax 428; X86-NEXT: jmpl *%ecx # TAILCALL 429 %cond_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 0 430 %cond = load i1, i1* %cond_p 431 br i1 %cond, label %then, label %else 432 433then: 434 %a_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 1 435 %a_i8 = load i8*, i8** %a_p 436 %a = bitcast i8* %a_i8 to void (%struct.Foo*, ...)* 437 musttail call void (%struct.Foo*, ...) %a(%struct.Foo* %this, ...) 438 ret void 439 440else: 441 %b_p = getelementptr %struct.Foo, %struct.Foo* %this, i32 0, i32 2 442 %b_i8 = load i8*, i8** %b_p 443 %b = bitcast i8* %b_i8 to void (%struct.Foo*, ...)* 444 store i32 42, i32* @g 445 musttail call void (%struct.Foo*, ...) %b(%struct.Foo* %this, ...) 446 ret void 447} 448