summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2016-09-22 19:50:05 +0000
committerHans Wennborg <hans@hanshq.net>2016-09-22 19:50:05 +0000
commitc4b1d20ba2952e1699ec5c44dd532fa8e9bf042c (patch)
treeeca5d64e9c70e9dd6885eefe355720a4a09ad88b /llvm
parent0201a9e94e3e95baf0e2d818e79c3f63b8fef558 (diff)
downloadbcm5719-llvm-c4b1d20ba2952e1699ec5c44dd532fa8e9bf042c.tar.gz
bcm5719-llvm-c4b1d20ba2952e1699ec5c44dd532fa8e9bf042c.zip
Win64: Don't emit unwind info for "leaf" functions (PR30337)
According to MSDN (see the PR), functions which don't touch any callee-saved registers (including %rsp) don't need any unwind info. This patch makes LLVM not emit unwind info for such functions, to save binary size. Differential Revision: https://reviews.llvm.org/D24748 llvm-svn: 282185
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/CodeGen/MachineFunction.h10
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/WinException.cpp2
-rw-r--r--llvm/lib/Target/X86/X86FrameLowering.cpp16
-rw-r--r--llvm/lib/Target/X86/X86MCInstLower.cpp8
-rw-r--r--llvm/test/CodeGen/X86/coalescer-win64.ll4
-rw-r--r--llvm/test/CodeGen/X86/pr24374.ll3
-rw-r--r--llvm/test/CodeGen/X86/seh-catchpad.ll3
-rw-r--r--llvm/test/CodeGen/X86/win64_eh.ll6
-rw-r--r--llvm/test/CodeGen/X86/win64_eh_leaf.ll31
9 files changed, 69 insertions, 14 deletions
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index 01a11df068d..6665afd987f 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/IR/DebugLoc.h"
@@ -234,6 +235,9 @@ class MachineFunction {
/// True if the function includes any inline assembly.
bool HasInlineAsm = false;
+ /// True if any WinCFI instruction have been emitted in this function.
+ Optional<bool> HasWinCFI;
+
/// Current high-level properties of the IR of the function (e.g. is in SSA
/// form or whether registers have been allocated)
MachineFunctionProperties Properties;
@@ -372,6 +376,12 @@ public:
HasInlineAsm = B;
}
+ bool hasWinCFI() const {
+ assert(HasWinCFI.hasValue() && "HasWinCFI not set yet!");
+ return *HasWinCFI;
+ }
+ void setHasWinCFI(bool v) { HasWinCFI = v; }
+
/// Get the function properties
const MachineFunctionProperties &getProperties() const { return Properties; }
MachineFunctionProperties &getProperties() { return Properties; }
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index 8faf53fbfb3..72f8a217c88 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -90,7 +90,7 @@ void WinException::beginFunction(const MachineFunction *MF) {
// If we're not using CFI, we don't want the CFI or the personality, but we
// might want EH tables if we had EH pads.
- if (!Asm->MAI->usesWindowsCFI()) {
+ if (!Asm->MAI->usesWindowsCFI() || (!MF->hasWinCFI() && !Per)) {
shouldEmitLSDA = hasEHFunclets;
shouldEmitPersonality = false;
return;
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 39419950412..9a0d5213d24 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -935,6 +935,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
STI.isTarget64BitILP32()
? getX86SubSuperRegister(FramePtr, 64) : FramePtr;
unsigned BasePtr = TRI->getBaseRegister();
+ bool HasWinCFI = false;
// Debug location must be unknown since the first debug location is used
// to determine the end of the prologue.
@@ -1063,6 +1064,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
}
if (NeedsWinCFI) {
+ HasWinCFI = true;
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg))
.addImm(FramePtr)
.setMIFlag(MachineInstr::FrameSetup);
@@ -1124,6 +1126,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
}
if (NeedsWinCFI) {
+ HasWinCFI = true;
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)).addImm(Reg).setMIFlag(
MachineInstr::FrameSetup);
}
@@ -1209,10 +1212,12 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false);
}
- if (NeedsWinCFI && NumBytes)
+ if (NeedsWinCFI && NumBytes) {
+ HasWinCFI = true;
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_StackAlloc))
.addImm(NumBytes)
.setMIFlag(MachineInstr::FrameSetup);
+ }
int SEHFrameOffset = 0;
unsigned SPOrEstablisher;
@@ -1259,6 +1264,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
// If this is not a funclet, emit the CFI describing our frame pointer.
if (NeedsWinCFI && !IsFunclet) {
+ HasWinCFI = true;
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame))
.addImm(FramePtr)
.addImm(SEHFrameOffset)
@@ -1295,6 +1301,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
int Offset = getFrameIndexReference(MF, FI, IgnoredFrameReg);
Offset += SEHFrameOffset;
+ HasWinCFI = true;
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SaveXMM))
.addImm(Reg)
.addImm(Offset)
@@ -1304,7 +1311,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
}
}
- if (NeedsWinCFI)
+ if (NeedsWinCFI && HasWinCFI)
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_EndPrologue))
.setMIFlag(MachineInstr::FrameSetup);
@@ -1396,6 +1403,9 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
if (Fn->getCallingConv() == CallingConv::X86_INTR)
BuildMI(MBB, MBBI, DL, TII.get(X86::CLD))
.setMIFlag(MachineInstr::FrameSetup);
+
+ // At this point we know if the function has WinCFI or not.
+ MF.setHasWinCFI(HasWinCFI);
}
bool X86FrameLowering::canUseLEAForSPInEpilogue(
@@ -1630,7 +1640,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
// into the epilogue. To cope with that, we insert an epilogue marker here,
// then replace it with a 'nop' if it ends up immediately after a CALL in the
// final emitted code.
- if (NeedsWinCFI)
+ if (NeedsWinCFI && MF.hasWinCFI())
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_Epilogue));
if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) {
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index 7dfe9f2829a..8f4616851cd 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -1420,37 +1420,45 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
case X86::SEH_PushReg:
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
OutStreamer->EmitWinCFIPushReg(RI->getSEHRegNum(MI->getOperand(0).getImm()));
return;
case X86::SEH_SaveReg:
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
OutStreamer->EmitWinCFISaveReg(RI->getSEHRegNum(MI->getOperand(0).getImm()),
MI->getOperand(1).getImm());
return;
case X86::SEH_SaveXMM:
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
OutStreamer->EmitWinCFISaveXMM(RI->getSEHRegNum(MI->getOperand(0).getImm()),
MI->getOperand(1).getImm());
return;
case X86::SEH_StackAlloc:
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
OutStreamer->EmitWinCFIAllocStack(MI->getOperand(0).getImm());
return;
case X86::SEH_SetFrame:
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
OutStreamer->EmitWinCFISetFrame(RI->getSEHRegNum(MI->getOperand(0).getImm()),
MI->getOperand(1).getImm());
return;
case X86::SEH_PushFrame:
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
OutStreamer->EmitWinCFIPushFrame(MI->getOperand(0).getImm());
return;
case X86::SEH_EndPrologue:
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
OutStreamer->EmitWinCFIEndProlog();
return;
case X86::SEH_Epilogue: {
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
MachineBasicBlock::const_iterator MBBI(MI);
// Check if preceded by a call and emit nop if so.
for (MBBI = PrevCrossBBInst(MBBI);
diff --git a/llvm/test/CodeGen/X86/coalescer-win64.ll b/llvm/test/CodeGen/X86/coalescer-win64.ll
index ff084ae5b9e..f43605d45b1 100644
--- a/llvm/test/CodeGen/X86/coalescer-win64.ll
+++ b/llvm/test/CodeGen/X86/coalescer-win64.ll
@@ -11,6 +11,6 @@ entry:
}
; CHECK-LABEL: test1{{$}}
-; CHECK: .seh_proc test1{{$}}
+; CHECK-NOT: .seh_proc test1
; CHECK: rex64 jmpq *fnptr(%rip)
-; CHECK: .seh_endproc
+; CHECK-NOT: .seh_endproc
diff --git a/llvm/test/CodeGen/X86/pr24374.ll b/llvm/test/CodeGen/X86/pr24374.ll
index 7f331e10396..dab3b3f4159 100644
--- a/llvm/test/CodeGen/X86/pr24374.ll
+++ b/llvm/test/CodeGen/X86/pr24374.ll
@@ -31,7 +31,6 @@ define void @g() {
unreachable
}
; CHECK-LABEL: g:
-; CHECK: .seh_proc g
-; CHECK: .seh_endproc
+; CHECK: ud2
attributes #0 = { nounwind }
diff --git a/llvm/test/CodeGen/X86/seh-catchpad.ll b/llvm/test/CodeGen/X86/seh-catchpad.ll
index 4b2a9f9b6d8..99ed454cfb0 100644
--- a/llvm/test/CodeGen/X86/seh-catchpad.ll
+++ b/llvm/test/CodeGen/X86/seh-catchpad.ll
@@ -171,10 +171,7 @@ entry:
}
; CHECK: "?filt$0@0@main@@": # @"\01?filt$0@0@main@@"
-; CHECK: .seh_proc "?filt$0@0@main@@"
-; CHECK: .seh_endprologue
; CHECK: jmp filt # TAILCALL
-; CHECK: .seh_handlerdata
declare i32 @filt() #1
diff --git a/llvm/test/CodeGen/X86/win64_eh.ll b/llvm/test/CodeGen/X86/win64_eh.ll
index 9421f00c810..e51ef0516ea 100644
--- a/llvm/test/CodeGen/X86/win64_eh.ll
+++ b/llvm/test/CodeGen/X86/win64_eh.ll
@@ -8,10 +8,10 @@ entry:
ret void
}
; WIN64-LABEL: foo0:
-; WIN64: .seh_proc foo0
-; WIN64: .seh_endprologue
+; WIN64-NOT: .seh_proc foo0
+; WIN64-NOT: .seh_endprologue
; WIN64: ret
-; WIN64: .seh_endproc
+; WIN64-NOT: .seh_endproc
; Checks a small stack allocation
define void @foo1() uwtable {
diff --git a/llvm/test/CodeGen/X86/win64_eh_leaf.ll b/llvm/test/CodeGen/X86/win64_eh_leaf.ll
new file mode 100644
index 00000000000..21a423ab36a
--- /dev/null
+++ b/llvm/test/CodeGen/X86/win64_eh_leaf.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -O1 -mtriple=x86_64-pc-win32 | FileCheck %s -check-prefix=ASM
+; RUN: llc < %s -O1 -mtriple=x86_64-pc-win32 -filetype=obj -o %t
+; RUN: llvm-readobj -unwind %t | FileCheck %s -check-prefix=READOBJ
+
+declare void @g(i32)
+
+define i32 @not_leaf(i32) uwtable {
+entry:
+ call void @g(i32 42)
+ ret i32 42
+
+; ASM-LABEL: not_leaf:
+; ASM: .seh
+
+; READOBJ: RuntimeFunction {
+; READOBJ-NEXT: StartAddress: not_leaf
+; READOBJ-NEXT: EndAddress: not_leaf
+}
+
+define void @leaf_func(i32) uwtable {
+entry:
+ tail call void @g(i32 42)
+ ret void
+
+; A Win64 "leaf" function gets no .seh directives in the asm.
+; ASM-LABEL: leaf_func:
+; ASM-NOT: .seh
+
+; and no unwind info in the object file.
+; READOBJ-NOT: leaf_func
+}
OpenPOWER on IntegriCloud