In function spillFPBP we already try to skip terminator, but there is a logic error, so when there is only terminator instruction in the MBB, it still tries to save/restore fp/bp around it if the terminator clobbers fp/bp, for example a tail call with ghc calling convention. Now this patch really skips terminator even if it is the only instruction in the MBB.
190 lines
5.8 KiB
LLVM
190 lines
5.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
|
|
; RUN: llc -mtriple=x86_64-pc-linux -stackrealign -verify-machineinstrs < %s | FileCheck %s
|
|
|
|
; Calling convention ghccc uses ebp to pass parameter, so calling a function
|
|
; using ghccc clobbers ebp. We should save and restore ebp around such a call
|
|
; if ebp is used as frame pointer.
|
|
|
|
declare ghccc i32 @external(i32)
|
|
|
|
; Basic test with ghccc calling convention.
|
|
define i32 @test1(i32 %0, i32 %1) {
|
|
; CHECK-LABEL: test1:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: pushq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 16
|
|
; CHECK-NEXT: .cfi_offset %rbp, -16
|
|
; CHECK-NEXT: movq %rsp, %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_register %rbp
|
|
; CHECK-NEXT: pushq %r15
|
|
; CHECK-NEXT: pushq %r14
|
|
; CHECK-NEXT: pushq %r13
|
|
; CHECK-NEXT: pushq %r12
|
|
; CHECK-NEXT: pushq %rbx
|
|
; CHECK-NEXT: andq $-16, %rsp
|
|
; CHECK-NEXT: subq $16, %rsp
|
|
; CHECK-NEXT: .cfi_offset %rbx, -56
|
|
; CHECK-NEXT: .cfi_offset %r12, -48
|
|
; CHECK-NEXT: .cfi_offset %r13, -40
|
|
; CHECK-NEXT: .cfi_offset %r14, -32
|
|
; CHECK-NEXT: .cfi_offset %r15, -24
|
|
; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
|
|
; CHECK-NEXT: pushq %rbp
|
|
; CHECK-NEXT: pushq %rax
|
|
; CHECK-NEXT: .cfi_remember_state
|
|
; CHECK-NEXT: .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #
|
|
; CHECK-NEXT: movl %esi, %ebp
|
|
; CHECK-NEXT: movq %rdi, %r13
|
|
; CHECK-NEXT: callq external@PLT
|
|
; CHECK-NEXT: addq $8, %rsp
|
|
; CHECK-NEXT: popq %rbp
|
|
; CHECK-NEXT: .cfi_restore_state
|
|
; CHECK-NEXT: leaq -40(%rbp), %rsp
|
|
; CHECK-NEXT: popq %rbx
|
|
; CHECK-NEXT: popq %r12
|
|
; CHECK-NEXT: popq %r13
|
|
; CHECK-NEXT: popq %r14
|
|
; CHECK-NEXT: popq %r15
|
|
; CHECK-NEXT: popq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa %rsp, 8
|
|
; CHECK-NEXT: retq
|
|
%x = call ghccc i32 @external(i32 %0, i32 %1)
|
|
ret i32 %x
|
|
}
|
|
|
|
; Calling convention hipe has similar behavior. It clobbers rbp but not rbx.
|
|
|
|
declare cc 11 i64 @hipe1(i64)
|
|
declare cc 11 i64 @hipe2(i64, i64, i64, i64, i64, i64, i64)
|
|
|
|
; Basic test with hipe calling convention.
|
|
define i64 @test2(i64 %a0, i64 %a1) {
|
|
; CHECK-LABEL: test2:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: pushq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 16
|
|
; CHECK-NEXT: .cfi_offset %rbp, -16
|
|
; CHECK-NEXT: movq %rsp, %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_register %rbp
|
|
; CHECK-NEXT: pushq %r15
|
|
; CHECK-NEXT: pushq %r14
|
|
; CHECK-NEXT: pushq %r13
|
|
; CHECK-NEXT: pushq %r12
|
|
; CHECK-NEXT: pushq %rbx
|
|
; CHECK-NEXT: andq $-16, %rsp
|
|
; CHECK-NEXT: subq $16, %rsp
|
|
; CHECK-NEXT: .cfi_offset %rbx, -56
|
|
; CHECK-NEXT: .cfi_offset %r12, -48
|
|
; CHECK-NEXT: .cfi_offset %r13, -40
|
|
; CHECK-NEXT: .cfi_offset %r14, -32
|
|
; CHECK-NEXT: .cfi_offset %r15, -24
|
|
; CHECK-NEXT: pushq %rbp
|
|
; CHECK-NEXT: pushq %rax
|
|
; CHECK-NEXT: .cfi_remember_state
|
|
; CHECK-NEXT: .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #
|
|
; CHECK-NEXT: movq %rsi, %rbp
|
|
; CHECK-NEXT: movq %rdi, %r15
|
|
; CHECK-NEXT: callq hipe1@PLT
|
|
; CHECK-NEXT: addq $8, %rsp
|
|
; CHECK-NEXT: popq %rbp
|
|
; CHECK-NEXT: .cfi_restore_state
|
|
; CHECK-NEXT: movq %r15, %rax
|
|
; CHECK-NEXT: leaq -40(%rbp), %rsp
|
|
; CHECK-NEXT: popq %rbx
|
|
; CHECK-NEXT: popq %r12
|
|
; CHECK-NEXT: popq %r13
|
|
; CHECK-NEXT: popq %r14
|
|
; CHECK-NEXT: popq %r15
|
|
; CHECK-NEXT: popq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa %rsp, 8
|
|
; CHECK-NEXT: retq
|
|
%x = call cc 11 i64 @hipe1(i64 %a0, i64 %a1)
|
|
ret i64 %x
|
|
}
|
|
|
|
@buf = dso_local global [20 x ptr] zeroinitializer, align 16
|
|
|
|
; longjmp modifies fp, it is expected behavior, wo should not save/restore fp
|
|
; around it.
|
|
define void @test4() {
|
|
; CHECK-LABEL: test4:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: pushq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 16
|
|
; CHECK-NEXT: .cfi_offset %rbp, -16
|
|
; CHECK-NEXT: movq %rsp, %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_register %rbp
|
|
; CHECK-NEXT: pushq %r15
|
|
; CHECK-NEXT: pushq %r14
|
|
; CHECK-NEXT: pushq %r13
|
|
; CHECK-NEXT: pushq %r12
|
|
; CHECK-NEXT: pushq %rbx
|
|
; CHECK-NEXT: andq $-16, %rsp
|
|
; CHECK-NEXT: subq $16, %rsp
|
|
; CHECK-NEXT: .cfi_offset %rbx, -56
|
|
; CHECK-NEXT: .cfi_offset %r12, -48
|
|
; CHECK-NEXT: .cfi_offset %r13, -40
|
|
; CHECK-NEXT: .cfi_offset %r14, -32
|
|
; CHECK-NEXT: .cfi_offset %r15, -24
|
|
; CHECK-NEXT: xorl %r13d, %r13d
|
|
; CHECK-NEXT: pushq %rbp
|
|
; CHECK-NEXT: pushq %rax
|
|
; CHECK-NEXT: .cfi_remember_state
|
|
; CHECK-NEXT: .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #
|
|
; CHECK-NEXT: callq external@PLT
|
|
; CHECK-NEXT: addq $8, %rsp
|
|
; CHECK-NEXT: popq %rbp
|
|
; CHECK-NEXT: .cfi_restore_state
|
|
; CHECK-NEXT: movq buf(%rip), %rbp
|
|
; CHECK-NEXT: movq buf+8(%rip), %rax
|
|
; CHECK-NEXT: movq buf+16(%rip), %rsp
|
|
; CHECK-NEXT: jmpq *%rax
|
|
entry:
|
|
%x = call ghccc i32 @external(i32 0)
|
|
call void @llvm.eh.sjlj.longjmp(ptr @buf)
|
|
unreachable
|
|
}
|
|
|
|
declare ghccc void @tail()
|
|
|
|
; We should not save/restore fp/bp around terminator.
|
|
define ghccc void @test5() {
|
|
; CHECK-LABEL: test5:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: pushq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 16
|
|
; CHECK-NEXT: .cfi_offset %rbp, -16
|
|
; CHECK-NEXT: movq %rsp, %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_register %rbp
|
|
; CHECK-NEXT: andq $-8, %rsp
|
|
; CHECK-NEXT: xorl %eax, %eax
|
|
; CHECK-NEXT: testb %al, %al
|
|
; CHECK-NEXT: jne .LBB3_2
|
|
; CHECK-NEXT: # %bb.1: # %then
|
|
; CHECK-NEXT: movq $0, (%rax)
|
|
; CHECK-NEXT: movq %rbp, %rsp
|
|
; CHECK-NEXT: popq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa %rsp, 8
|
|
; CHECK-NEXT: retq
|
|
; CHECK-NEXT: .LBB3_2: # %else
|
|
; CHECK-NEXT: .cfi_def_cfa %rbp, 16
|
|
; CHECK-NEXT: movq %rbp, %rsp
|
|
; CHECK-NEXT: popq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa %rsp, 8
|
|
; CHECK-NEXT: jmp tail@PLT # TAILCALL
|
|
entry:
|
|
br i1 undef, label %then, label %else
|
|
|
|
then:
|
|
store i64 0, ptr undef
|
|
br label %exit
|
|
|
|
else:
|
|
musttail call ghccc void @tail()
|
|
ret void
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|