188 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 42; RUN: llc -mtriple=x86_64-pc-linux -stackrealign -verify-machineinstrs < %s | FileCheck %s3 4; Calling convention ghccc uses ebp to pass parameter, so calling a function5; using ghccc clobbers ebp. We should save and restore ebp around such a call6; if ebp is used as frame pointer.7 8declare ghccc i32 @external(i32)9 10; Basic test with ghccc calling convention.11define i32 @test1(i32 %0, i32 %1) {12; CHECK-LABEL: test1:13; CHECK: # %bb.0:14; CHECK-NEXT: pushq %rbp15; CHECK-NEXT: .cfi_def_cfa_offset 1616; CHECK-NEXT: .cfi_offset %rbp, -1617; CHECK-NEXT: movq %rsp, %rbp18; CHECK-NEXT: .cfi_def_cfa_register %rbp19; CHECK-NEXT: pushq %r1520; CHECK-NEXT: pushq %r1421; CHECK-NEXT: pushq %r1322; CHECK-NEXT: pushq %r1223; CHECK-NEXT: pushq %rbx24; CHECK-NEXT: andq $-16, %rsp25; CHECK-NEXT: subq $16, %rsp26; CHECK-NEXT: .cfi_offset %rbx, -5627; CHECK-NEXT: .cfi_offset %r12, -4828; CHECK-NEXT: .cfi_offset %r13, -4029; CHECK-NEXT: .cfi_offset %r14, -3230; CHECK-NEXT: .cfi_offset %r15, -2431; CHECK-NEXT: # kill: def $edi killed $edi def $rdi32; CHECK-NEXT: pushq %rbp33; CHECK-NEXT: pushq %rax34; CHECK-NEXT: .cfi_remember_state35; CHECK-NEXT: .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #36; CHECK-NEXT: movl %esi, %ebp37; CHECK-NEXT: movq %rdi, %r1338; CHECK-NEXT: callq external@PLT39; CHECK-NEXT: addq $8, %rsp40; CHECK-NEXT: popq %rbp41; CHECK-NEXT: .cfi_restore_state42; CHECK-NEXT: leaq -40(%rbp), %rsp43; CHECK-NEXT: popq %rbx44; CHECK-NEXT: popq %r1245; CHECK-NEXT: popq %r1346; CHECK-NEXT: popq %r1447; CHECK-NEXT: popq %r1548; CHECK-NEXT: popq %rbp49; CHECK-NEXT: .cfi_def_cfa %rsp, 850; CHECK-NEXT: retq51 %x = call ghccc i32 @external(i32 %0, i32 %1)52 ret i32 %x53}54 55; Calling convention hipe has similar behavior. It clobbers rbp but not rbx.56 57declare cc 11 i64 @hipe1(i64)58declare cc 11 i64 @hipe2(i64, i64, i64, i64, i64, i64, i64)59 60; Basic test with hipe calling convention.61define i64 @test2(i64 %a0, i64 %a1) {62; CHECK-LABEL: test2:63; CHECK: # %bb.0:64; CHECK-NEXT: pushq %rbp65; CHECK-NEXT: .cfi_def_cfa_offset 1666; CHECK-NEXT: .cfi_offset %rbp, -1667; CHECK-NEXT: movq %rsp, %rbp68; CHECK-NEXT: .cfi_def_cfa_register %rbp69; CHECK-NEXT: pushq %r1570; CHECK-NEXT: pushq %r1471; CHECK-NEXT: pushq %r1372; CHECK-NEXT: pushq %r1273; CHECK-NEXT: pushq %rbx74; CHECK-NEXT: andq $-16, %rsp75; CHECK-NEXT: subq $16, %rsp76; CHECK-NEXT: .cfi_offset %rbx, -5677; CHECK-NEXT: .cfi_offset %r12, -4878; CHECK-NEXT: .cfi_offset %r13, -4079; CHECK-NEXT: .cfi_offset %r14, -3280; CHECK-NEXT: .cfi_offset %r15, -2481; CHECK-NEXT: pushq %rbp82; CHECK-NEXT: pushq %rax83; CHECK-NEXT: .cfi_remember_state84; CHECK-NEXT: .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #85; CHECK-NEXT: movq %rsi, %rbp86; CHECK-NEXT: movq %rdi, %r1587; CHECK-NEXT: callq hipe1@PLT88; CHECK-NEXT: addq $8, %rsp89; CHECK-NEXT: popq %rbp90; CHECK-NEXT: .cfi_restore_state91; CHECK-NEXT: movq %r15, %rax92; CHECK-NEXT: leaq -40(%rbp), %rsp93; CHECK-NEXT: popq %rbx94; CHECK-NEXT: popq %r1295; CHECK-NEXT: popq %r1396; CHECK-NEXT: popq %r1497; CHECK-NEXT: popq %r1598; CHECK-NEXT: popq %rbp99; CHECK-NEXT: .cfi_def_cfa %rsp, 8100; CHECK-NEXT: retq101 %x = call cc 11 i64 @hipe1(i64 %a0, i64 %a1)102 ret i64 %x103}104 105@buf = dso_local global [20 x ptr] zeroinitializer, align 16106 107; longjmp modifies fp, it is expected behavior, wo should not save/restore fp108; around it.109define void @test4() {110; CHECK-LABEL: test4:111; CHECK: # %bb.0: # %entry112; CHECK-NEXT: pushq %rbp113; CHECK-NEXT: .cfi_def_cfa_offset 16114; CHECK-NEXT: .cfi_offset %rbp, -16115; CHECK-NEXT: movq %rsp, %rbp116; CHECK-NEXT: .cfi_def_cfa_register %rbp117; CHECK-NEXT: pushq %r15118; CHECK-NEXT: pushq %r14119; CHECK-NEXT: pushq %r13120; CHECK-NEXT: pushq %r12121; CHECK-NEXT: pushq %rbx122; CHECK-NEXT: andq $-16, %rsp123; CHECK-NEXT: subq $16, %rsp124; CHECK-NEXT: .cfi_offset %rbx, -56125; CHECK-NEXT: .cfi_offset %r12, -48126; CHECK-NEXT: .cfi_offset %r13, -40127; CHECK-NEXT: .cfi_offset %r14, -32128; CHECK-NEXT: .cfi_offset %r15, -24129; CHECK-NEXT: xorl %r13d, %r13d130; CHECK-NEXT: pushq %rbp131; CHECK-NEXT: pushq %rax132; CHECK-NEXT: .cfi_remember_state133; CHECK-NEXT: .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #134; CHECK-NEXT: callq external@PLT135; CHECK-NEXT: addq $8, %rsp136; CHECK-NEXT: popq %rbp137; CHECK-NEXT: .cfi_restore_state138; CHECK-NEXT: movq buf(%rip), %rbp139; CHECK-NEXT: movq buf+8(%rip), %rax140; CHECK-NEXT: movq buf+16(%rip), %rsp141; CHECK-NEXT: jmpq *%rax142entry:143 %x = call ghccc i32 @external(i32 0)144 call void @llvm.eh.sjlj.longjmp(ptr @buf)145 unreachable146}147 148declare ghccc void @tail()149 150; We should not save/restore fp/bp around terminator.151define ghccc void @test5() {152; CHECK-LABEL: test5:153; CHECK: # %bb.0: # %entry154; CHECK-NEXT: pushq %rbp155; CHECK-NEXT: .cfi_def_cfa_offset 16156; CHECK-NEXT: .cfi_offset %rbp, -16157; CHECK-NEXT: movq %rsp, %rbp158; CHECK-NEXT: .cfi_def_cfa_register %rbp159; CHECK-NEXT: andq $-8, %rsp160; CHECK-NEXT: testb %al, %al161; CHECK-NEXT: jne .LBB3_2162; CHECK-NEXT: # %bb.1: # %then163; CHECK-NEXT: movq $0, (%rax)164; CHECK-NEXT: movq %rbp, %rsp165; CHECK-NEXT: popq %rbp166; CHECK-NEXT: .cfi_def_cfa %rsp, 8167; CHECK-NEXT: retq168; CHECK-NEXT: .LBB3_2: # %else169; CHECK-NEXT: .cfi_def_cfa %rbp, 16170; CHECK-NEXT: movq %rbp, %rsp171; CHECK-NEXT: popq %rbp172; CHECK-NEXT: .cfi_def_cfa %rsp, 8173; CHECK-NEXT: jmp tail@PLT # TAILCALL174entry:175 br i1 poison, label %then, label %else176 177then:178 store i64 0, ptr undef179 br label %exit180 181else:182 musttail call ghccc void @tail()183 ret void184 185exit:186 ret void187}188