mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
c34a7c7b51
The current compact unwind scheme does not work when the prologue is not at the start (the instructions before the prologue cannot be described). (Technically this is fixable, but it requires multiple compact unwind descriptors for one function.) rL255175 chose to not perform shrink-wrapping for no-frame-pointer functions not marked as nounwind to work around PR25614. This is overly limited, as platforms not supporting compact unwind (all non-Darwin) does not need the workaround. This patch restricts the limitation to compact unwind platforms. Reviewed By: qcolombet Differential Revision: https://reviews.llvm.org/D89930
330 lines
9.0 KiB
LLVM
330 lines
9.0 KiB
LLVM
; RUN: llc -mtriple=x86_64-apple-darwin10.6 < %s | FileCheck %s
|
|
; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s --check-prefix=NOCOMPACTUNWIND
|
|
;
|
|
; Note: This test cannot be merged with the shrink-wrapping tests
|
|
; because the booleans set on the command line take precedence on
|
|
; the target logic that disable shrink-wrapping.
|
|
|
|
; The current compact unwind scheme does not work when the prologue is not at
|
|
; the start (the instructions before the prologue cannot be described).
|
|
; Currently we choose to not perform shrink-wrapping for functions without FP
|
|
; not marked as nounwind. PR25614
|
|
;
|
|
; No shrink-wrapping should occur here, until the CFI information are fixed.
|
|
; CHECK-LABEL: framelessUnwind:
|
|
;
|
|
; Prologue code.
|
|
; (What we push does not matter. It should be some random sratch register.)
|
|
; CHECK: pushq
|
|
;
|
|
; Compare the arguments and jump to exit.
|
|
; After the prologue is set.
|
|
; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]]
|
|
; CHECK-NEXT: cmpl %esi, %edi
|
|
; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
|
|
;
|
|
; Store %a in the alloca.
|
|
; CHECK: movl [[ARG0CPY]], 4(%rsp)
|
|
; Set the alloca address in the second argument.
|
|
; CHECK-NEXT: leaq 4(%rsp), %rsi
|
|
; Set the first argument to zero.
|
|
; CHECK-NEXT: xorl %edi, %edi
|
|
; CHECK-NEXT: callq _doSomething
|
|
;
|
|
; CHECK: [[EXIT_LABEL]]:
|
|
;
|
|
; Without shrink-wrapping, epilogue is in the exit block.
|
|
; Epilogue code. (What we pop does not matter.)
|
|
; CHECK-NEXT: popq
|
|
;
|
|
; CHECK-NEXT: retq
|
|
|
|
; On a platform which does not support compact unwind, shrink wrapping is enabled.
|
|
; NOCOMPACTUNWIND-LABEL: framelessUnwind:
|
|
; NOCOMPACTUNWIND-NOT: pushq
|
|
; NOCOMPACTUNWIND: # %bb.1:
|
|
; NOCOMPACTUNWIND-NEXT: pushq %rax
|
|
define i32 @framelessUnwind(i32 %a, i32 %b) #0 {
|
|
%tmp = alloca i32, align 4
|
|
%tmp2 = icmp slt i32 %a, %b
|
|
br i1 %tmp2, label %true, label %false
|
|
|
|
true:
|
|
store i32 %a, i32* %tmp, align 4
|
|
%tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
|
|
br label %false
|
|
|
|
false:
|
|
%tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
|
|
ret i32 %tmp.0
|
|
}
|
|
|
|
declare i32 @doSomething(i32, i32*)
|
|
|
|
attributes #0 = { "frame-pointer"="none" }
|
|
|
|
; Shrink-wrapping should occur here. We have a frame pointer.
|
|
; CHECK-LABEL: frameUnwind:
|
|
;
|
|
; Compare the arguments and jump to exit.
|
|
; No prologue needed.
|
|
;
|
|
; Compare the arguments and jump to exit.
|
|
; After the prologue is set.
|
|
; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]]
|
|
; CHECK-NEXT: cmpl %esi, %edi
|
|
; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
|
|
;
|
|
; Prologue code.
|
|
; CHECK: pushq %rbp
|
|
; CHECK: movq %rsp, %rbp
|
|
;
|
|
; Store %a in the alloca.
|
|
; CHECK: movl [[ARG0CPY]], -4(%rbp)
|
|
; Set the alloca address in the second argument.
|
|
; CHECK-NEXT: leaq -4(%rbp), %rsi
|
|
; Set the first argument to zero.
|
|
; CHECK-NEXT: xorl %edi, %edi
|
|
; CHECK-NEXT: callq _doSomething
|
|
;
|
|
; Epilogue code. (What we pop does not matter.)
|
|
; CHECK: popq %rbp
|
|
;
|
|
; CHECK: [[EXIT_LABEL]]:
|
|
; CHECK-NEXT: retq
|
|
define i32 @frameUnwind(i32 %a, i32 %b) #1 {
|
|
%tmp = alloca i32, align 4
|
|
%tmp2 = icmp slt i32 %a, %b
|
|
br i1 %tmp2, label %true, label %false
|
|
|
|
true:
|
|
store i32 %a, i32* %tmp, align 4
|
|
%tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
|
|
br label %false
|
|
|
|
false:
|
|
%tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
|
|
ret i32 %tmp.0
|
|
}
|
|
|
|
attributes #1 = { "frame-pointer"="all" }
|
|
|
|
; Shrink-wrapping should occur here. We do not have to unwind.
|
|
; CHECK-LABEL: framelessnoUnwind:
|
|
;
|
|
; Compare the arguments and jump to exit.
|
|
; No prologue needed.
|
|
;
|
|
; Compare the arguments and jump to exit.
|
|
; After the prologue is set.
|
|
; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]]
|
|
; CHECK-NEXT: cmpl %esi, %edi
|
|
; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
|
|
;
|
|
; Prologue code.
|
|
; (What we push does not matter. It should be some random sratch register.)
|
|
; CHECK: pushq
|
|
;
|
|
; Store %a in the alloca.
|
|
; CHECK: movl [[ARG0CPY]], 4(%rsp)
|
|
; Set the alloca address in the second argument.
|
|
; CHECK-NEXT: leaq 4(%rsp), %rsi
|
|
; Set the first argument to zero.
|
|
; CHECK-NEXT: xorl %edi, %edi
|
|
; CHECK-NEXT: callq _doSomething
|
|
;
|
|
; Epilogue code.
|
|
; CHECK-NEXT: addq
|
|
;
|
|
; CHECK: [[EXIT_LABEL]]:
|
|
; CHECK-NEXT: retq
|
|
define i32 @framelessnoUnwind(i32 %a, i32 %b) #2 {
|
|
%tmp = alloca i32, align 4
|
|
%tmp2 = icmp slt i32 %a, %b
|
|
br i1 %tmp2, label %true, label %false
|
|
|
|
true:
|
|
store i32 %a, i32* %tmp, align 4
|
|
%tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
|
|
br label %false
|
|
|
|
false:
|
|
%tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
|
|
ret i32 %tmp.0
|
|
}
|
|
|
|
attributes #2 = { "frame-pointer"="none" nounwind }
|
|
|
|
|
|
; Check that we generate correct code for segmented stack.
|
|
; We used to emit the code at the entry point of the function
|
|
; instead of just before the prologue.
|
|
; For now, shrink-wrapping is disabled on segmented stack functions: PR26107.
|
|
;
|
|
; CHECK-LABEL: segmentedStack:
|
|
; CHECK: cmpq
|
|
; CHECK-NEXT: jbe [[ENTRY_LABEL:LBB[0-9_]+]]
|
|
;
|
|
; In PR26107, we use to drop these two basic blocks, because
|
|
; the segmentedStack entry block was jumping directly to
|
|
; the place where the prologue is actually needed, which is
|
|
; the call to memcmp.
|
|
; Then, those two basic blocks did not have any predecessors
|
|
; anymore and were removed.
|
|
;
|
|
; Check if vk1 is null
|
|
; CHECK: testq %rdi, %rdi
|
|
; CHECK-NEXT: je [[STRINGS_EQUAL:LBB[0-9_]+]]
|
|
;
|
|
; Check if vk2 is null
|
|
; CHECK: testq %rsi, %rsi
|
|
; CHECK-NEXT: je [[STRINGS_EQUAL]]
|
|
;
|
|
; CHECK: [[STRINGS_EQUAL]]
|
|
; CHECK: popq
|
|
;
|
|
; CHECK: [[ENTRY_LABEL]]:
|
|
; CHECK: callq ___morestack
|
|
; CHECK-NEXT: retq
|
|
;
|
|
|
|
define zeroext i1 @segmentedStack(i8* readonly %vk1, i8* readonly %vk2, i64 %key_size) #5 {
|
|
entry:
|
|
%cmp.i = icmp eq i8* %vk1, null
|
|
%cmp1.i = icmp eq i8* %vk2, null
|
|
%brmerge.i = or i1 %cmp.i, %cmp1.i
|
|
%cmp1.mux.i = and i1 %cmp.i, %cmp1.i
|
|
br i1 %brmerge.i, label %__go_ptr_strings_equal.exit, label %if.end4.i
|
|
|
|
if.end4.i: ; preds = %entry
|
|
%tmp = getelementptr inbounds i8, i8* %vk1, i64 8
|
|
%tmp1 = bitcast i8* %tmp to i64*
|
|
%tmp2 = load i64, i64* %tmp1, align 8
|
|
%tmp3 = getelementptr inbounds i8, i8* %vk2, i64 8
|
|
%tmp4 = bitcast i8* %tmp3 to i64*
|
|
%tmp5 = load i64, i64* %tmp4, align 8
|
|
%cmp.i.i = icmp eq i64 %tmp2, %tmp5
|
|
br i1 %cmp.i.i, label %land.rhs.i.i, label %__go_ptr_strings_equal.exit
|
|
|
|
land.rhs.i.i: ; preds = %if.end4.i
|
|
%tmp6 = bitcast i8* %vk2 to i8**
|
|
%tmp7 = load i8*, i8** %tmp6, align 8
|
|
%tmp8 = bitcast i8* %vk1 to i8**
|
|
%tmp9 = load i8*, i8** %tmp8, align 8
|
|
%call.i.i = tail call i32 @memcmp(i8* %tmp9, i8* %tmp7, i64 %tmp2) #5
|
|
%cmp4.i.i = icmp eq i32 %call.i.i, 0
|
|
br label %__go_ptr_strings_equal.exit
|
|
|
|
__go_ptr_strings_equal.exit: ; preds = %land.rhs.i.i, %if.end4.i, %entry
|
|
%retval.0.i = phi i1 [ %cmp1.mux.i, %entry ], [ false, %if.end4.i ], [ %cmp4.i.i, %land.rhs.i.i ]
|
|
ret i1 %retval.0.i
|
|
}
|
|
|
|
; Function Attrs: nounwind readonly
|
|
declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) #5
|
|
|
|
attributes #5 = { nounwind readonly ssp uwtable "split-stack" }
|
|
|
|
; Check that correctly take into account the jumps to landing pad.
|
|
; We used to consider function that may throw like regular
|
|
; function calls.
|
|
; Therefore, in this example, we were happily inserting the epilogue
|
|
; right after the call to throw_exception. Because of that we would not
|
|
; execute the epilogue when an execption occur and bad things will
|
|
; happen.
|
|
; PR36513
|
|
;
|
|
; CHECK-LABEL: with_nounwind:
|
|
; Prologue
|
|
; CHECK: push
|
|
;
|
|
; Jump to throw_exception:
|
|
; CHECK-NEXT: .cfi_def_cfa_offset
|
|
; CHECK-NEXT: testb $1, %dil
|
|
; CHECK-NEXT: jne [[THROW_LABEL:LBB[0-9_]+]]
|
|
; Else return exit
|
|
; CHECK: popq
|
|
; CHECK-NEXT: retq
|
|
;
|
|
; CHECK-NEXT: [[THROW_LABEL]]:
|
|
; CHECK: callq _throw_exception
|
|
; Unreachable block...
|
|
;
|
|
; Epilogue must be after the landing pad.
|
|
; CHECK-NOT: popq
|
|
;
|
|
; Look for the landing pad label.
|
|
; CHECK: LBB{{[0-9_]+}}:
|
|
; Epilogue on the landing pad
|
|
; CHECK: popq
|
|
; CHECK-NEXT: retq
|
|
define void @with_nounwind(i1 %cond) nounwind personality i32 (...)* @my_personality {
|
|
entry:
|
|
br i1 %cond, label %throw, label %return
|
|
|
|
throw:
|
|
invoke void @throw_exception()
|
|
to label %unreachable unwind label %landing
|
|
|
|
unreachable:
|
|
unreachable
|
|
|
|
landing:
|
|
%pad = landingpad { i8*, i32 }
|
|
catch i8* null
|
|
ret void
|
|
|
|
return:
|
|
ret void
|
|
}
|
|
|
|
; Check landing pad again.
|
|
; This time checks that we can shrink-wrap when the epilogue does not
|
|
; span accross several blocks.
|
|
;
|
|
; CHECK-LABEL: with_nounwind_same_succ:
|
|
;
|
|
; Jump to throw_exception:
|
|
; CHECK: testb $1, %dil
|
|
; CHECK-NEXT: je [[RET_LABEL:LBB[0-9_]+]]
|
|
;
|
|
; Prologue
|
|
; CHECK: push
|
|
; CHECK: callq _throw_exception
|
|
;
|
|
; Fallthrough label
|
|
; CHECK: [[FALLTHROUGH_LABEL:LBB[0-9_]+]]
|
|
; CHECK: nop
|
|
; CHECK: popq
|
|
;
|
|
; CHECK: [[RET_LABEL]]
|
|
; CHECK: retq
|
|
;
|
|
; Look for the landing pad label.
|
|
; CHECK: LBB{{[0-9_]+}}:
|
|
; Landing pad jumps to fallthrough
|
|
; CHECK: jmp [[FALLTHROUGH_LABEL]]
|
|
define void @with_nounwind_same_succ(i1 %cond) nounwind personality i32 (...)* @my_personality2 {
|
|
entry:
|
|
br i1 %cond, label %throw, label %return
|
|
|
|
throw:
|
|
invoke void @throw_exception()
|
|
to label %fallthrough unwind label %landing
|
|
landing:
|
|
%pad = landingpad { i8*, i32 }
|
|
catch i8* null
|
|
br label %fallthrough
|
|
|
|
fallthrough:
|
|
tail call void asm "nop", ""()
|
|
br label %return
|
|
|
|
return:
|
|
ret void
|
|
}
|
|
|
|
declare void @throw_exception()
|
|
declare i32 @my_personality(...)
|
|
declare i32 @my_personality2(...)
|