mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-07 12:30:57 +00:00
[X86] Enable shrink-wrapping by default, but keep it disabled for stack frames
without a frame pointer when unwind may happen. This is a workaround for a bug in the way we emit the CFI directives for frameless unwind information. See PR25614. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255175 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
28e18e1782
commit
d110e2b4a3
@ -2595,6 +2595,12 @@ bool X86FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const {
|
||||
return !flagsNeedToBePreservedBeforeTheTerminators(MBB);
|
||||
}
|
||||
|
||||
bool X86FrameLowering::enableShrinkWrapping(const MachineFunction &MF) const {
|
||||
// If we may need to emit frameless compact unwind information, give
|
||||
// up as this is currently broken: PR25614.
|
||||
return MF.getFunction()->hasFnAttribute(Attribute::NoUnwind) || hasFP(MF);
|
||||
}
|
||||
|
||||
MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers(
|
||||
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
DebugLoc DL, bool RestoreSP) const {
|
||||
|
@ -134,6 +134,9 @@ public:
|
||||
/// \p MBB will be correctly handled by the target.
|
||||
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override;
|
||||
|
||||
/// Returns true if the target will correctly handle shrink wrapping.
|
||||
bool enableShrinkWrapping(const MachineFunction &MF) const override;
|
||||
|
||||
/// convertArgMovsToPushes - This method tries to convert a call sequence
|
||||
/// that uses sub and mov instructions to put the argument onto the stack
|
||||
/// into a series of pushes.
|
||||
|
@ -57,19 +57,19 @@ entry:
|
||||
define <8 x float> @funcE() nounwind {
|
||||
; CHECK-LABEL: funcE:
|
||||
; CHECK: ## BB#0: ## %for_exit499
|
||||
; CHECK-NEXT: pushq %rbp
|
||||
; CHECK-NEXT: movq %rsp, %rbp
|
||||
; CHECK-NEXT: andq $-32, %rsp
|
||||
; CHECK-NEXT: subq $1312, %rsp ## imm = 0x520
|
||||
; CHECK-NEXT: xorl %eax, %eax
|
||||
; CHECK-NEXT: ## implicit-def: %YMM0
|
||||
; CHECK-NEXT: testb %al, %al
|
||||
; CHECK-NEXT: jne LBB4_2
|
||||
; CHECK-NEXT: ## BB#1: ## %load.i1247
|
||||
; CHECK-NEXT: pushq %rbp
|
||||
; CHECK-NEXT: movq %rsp, %rbp
|
||||
; CHECK-NEXT: andq $-32, %rsp
|
||||
; CHECK-NEXT: subq $1312, %rsp ## imm = 0x520
|
||||
; CHECK-NEXT: vbroadcastss {{[0-9]+}}(%rsp), %ymm0
|
||||
; CHECK-NEXT: LBB4_2: ## %__load_and_broadcast_32.exit1249
|
||||
; CHECK-NEXT: movq %rbp, %rsp
|
||||
; CHECK-NEXT: popq %rbp
|
||||
; CHECK-NEXT: LBB4_2: ## %__load_and_broadcast_32.exit1249
|
||||
; CHECK-NEXT: retq
|
||||
allocas:
|
||||
%udx495 = alloca [18 x [18 x float]], align 32
|
||||
|
@ -277,8 +277,8 @@ declare fastcc %union.tree_node* @default_conversion(%union.tree_node*) nounwind
|
||||
|
||||
; CHECK-LABEL: foo:
|
||||
; CHECK: callq func
|
||||
; CHECK-NEXT: .LBB4_2:
|
||||
; CHECK-NEXT: popq
|
||||
; CHECK-NEXT: .LBB4_2:
|
||||
; CHECK-NEXT: ret
|
||||
|
||||
define void @foo(i1* %V) nounwind {
|
||||
|
153
test/CodeGen/X86/x86-shrink-wrap-unwind.ll
Normal file
153
test/CodeGen/X86/x86-shrink-wrap-unwind.ll
Normal file
@ -0,0 +1,153 @@
|
||||
; RUN: llc %s -o - | FileCheck %s --check-prefix=CHECK
|
||||
;
|
||||
; This test checks that we do not use shrink-wrapping when
|
||||
; the function does not have any frame pointer and may unwind.
|
||||
; This is a workaround for a limitation in the emission of
|
||||
; the CFI directives, that are not correct in such case.
|
||||
; PR25614
|
||||
;
|
||||
; 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.
|
||||
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
|
||||
target triple = "x86_64-apple-macosx"
|
||||
|
||||
|
||||
; 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, [[ARG0CPY]]
|
||||
; 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
|
||||
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 = { "no-frame-pointer-elim"="false" }
|
||||
|
||||
; 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, [[ARG0CPY]]
|
||||
; 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 = { "no-frame-pointer-elim"="true" }
|
||||
|
||||
; 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, [[ARG0CPY]]
|
||||
; 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 = { "no-frame-pointer-elim"="false" nounwind }
|
Loading…
Reference in New Issue
Block a user