[llvm] r282185 - Win64: Don't emit unwind info for "leaf" functions (PR30337)

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 22 12:50:06 PDT 2016


Author: hans
Date: Thu Sep 22 14:50:05 2016
New Revision: 282185

URL: http://llvm.org/viewvc/llvm-project?rev=282185&view=rev
Log:
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

Added:
    llvm/trunk/test/CodeGen/X86/win64_eh_leaf.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/MachineFunction.h
    llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
    llvm/trunk/lib/Target/X86/X86FrameLowering.cpp
    llvm/trunk/lib/Target/X86/X86MCInstLower.cpp
    llvm/trunk/test/CodeGen/X86/coalescer-win64.ll
    llvm/trunk/test/CodeGen/X86/pr24374.ll
    llvm/trunk/test/CodeGen/X86/seh-catchpad.ll
    llvm/trunk/test/CodeGen/X86/win64_eh.ll

Modified: llvm/trunk/include/llvm/CodeGen/MachineFunction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFunction.h?rev=282185&r1=282184&r2=282185&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineFunction.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineFunction.h Thu Sep 22 14:50:05 2016
@@ -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; }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp?rev=282185&r1=282184&r2=282185&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp Thu Sep 22 14:50:05 2016
@@ -90,7 +90,7 @@ void WinException::beginFunction(const M
 
   // 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;

Modified: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=282185&r1=282184&r2=282185&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp Thu Sep 22 14:50:05 2016
@@ -935,6 +935,7 @@ void X86FrameLowering::emitPrologue(Mach
       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(Mach
     }
 
     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(Mach
     }
 
     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(Mach
     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(Mach
 
     // 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(Mach
           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(Mach
     }
   }
 
-  if (NeedsWinCFI)
+  if (NeedsWinCFI && HasWinCFI)
     BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_EndPrologue))
         .setMIFlag(MachineInstr::FrameSetup);
 
@@ -1396,6 +1403,9 @@ void X86FrameLowering::emitPrologue(Mach
   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(Mach
   // 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)) {

Modified: llvm/trunk/lib/Target/X86/X86MCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCInstLower.cpp?rev=282185&r1=282184&r2=282185&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86MCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86MCInstLower.cpp Thu Sep 22 14:50:05 2016
@@ -1420,37 +1420,45 @@ void X86AsmPrinter::EmitInstruction(cons
     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);

Modified: llvm/trunk/test/CodeGen/X86/coalescer-win64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/coalescer-win64.ll?rev=282185&r1=282184&r2=282185&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/coalescer-win64.ll (original)
+++ llvm/trunk/test/CodeGen/X86/coalescer-win64.ll Thu Sep 22 14:50:05 2016
@@ -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

Modified: llvm/trunk/test/CodeGen/X86/pr24374.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pr24374.ll?rev=282185&r1=282184&r2=282185&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/pr24374.ll (original)
+++ llvm/trunk/test/CodeGen/X86/pr24374.ll Thu Sep 22 14:50:05 2016
@@ -31,7 +31,6 @@ define void @g() {
   unreachable
 }
 ; CHECK-LABEL: g:
-; CHECK:       .seh_proc g
-; CHECK:       .seh_endproc
+; CHECK: ud2
 
 attributes #0 = { nounwind }

Modified: llvm/trunk/test/CodeGen/X86/seh-catchpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-catchpad.ll?rev=282185&r1=282184&r2=282185&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-catchpad.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-catchpad.ll Thu Sep 22 14:50:05 2016
@@ -171,10 +171,7 @@ entry:
 }
 
 ; CHECK: "?filt$0 at 0@main@@":                     # @"\01?filt$0 at 0@main@@"
-; CHECK: .seh_proc "?filt$0 at 0@main@@"
-; CHECK:         .seh_endprologue
 ; CHECK:         jmp       filt  # TAILCALL
-; CHECK:         .seh_handlerdata
 
 declare i32 @filt() #1
 

Modified: llvm/trunk/test/CodeGen/X86/win64_eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win64_eh.ll?rev=282185&r1=282184&r2=282185&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win64_eh.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win64_eh.ll Thu Sep 22 14:50:05 2016
@@ -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 {

Added: llvm/trunk/test/CodeGen/X86/win64_eh_leaf.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win64_eh_leaf.ll?rev=282185&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win64_eh_leaf.ll (added)
+++ llvm/trunk/test/CodeGen/X86/win64_eh_leaf.ll Thu Sep 22 14:50:05 2016
@@ -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
+}




More information about the llvm-commits mailing list