X86, Win64: Allow 'mov' to restore the stack pointer if we have a FP
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 25 Feb 2015 21:13:37 +0000 (21:13 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 25 Feb 2015 21:13:37 +0000 (21:13 +0000)
The Win64 epilogue structure is very restrictive, it permits a very
small number of opcodes and none of them are 'mov'.

This means that given:
  mov %rbp, %rsp
  pop %rbp

The mov isn't the epilogue, only the pop is.  This is problematic unless
a frame pointer is present in which case we are free to do whatever we'd
like in the "body" of the function.  If a frame pointer is present,
unwinding will undo the prologue operations in reverse order regardless
of the fact that we are at an instruction which is reseting the stack
pointer.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230543 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86FrameLowering.cpp
test/CodeGen/X86/win64_eh.ll

index 040b91a4e1df675f095d63e41a5713562c7b58a5..cead0995330bcf23587f170f1287f0b48b6e2fe1 100644 (file)
@@ -1074,21 +1074,20 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
   if (RegInfo->needsStackRealignment(MF) || MFI->hasVarSizedObjects()) {
     if (RegInfo->needsStackRealignment(MF))
       MBBI = FirstCSPop;
-    if (IsWinEH) {
-      // There are only two legal forms of epilogue:
-      // - add SEHAllocationSize, %rsp
-      // - lea SEHAllocationSize(%FramePtr), %rsp
-      //
-      // We are *not* permitted to use 'mov %FramePtr, %rsp' because the Win64
-      // unwinder will not recognize 'mov' as an epilogue instruction.
-      unsigned SEHFrameOffset = calculateSetFPREG(SEHStackAllocAmt);
-      addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::LEA64r), StackPtr),
-                   FramePtr, false, SEHStackAllocAmt - SEHFrameOffset);
-      --MBBI;
-    } else if (CSSize != 0) {
+    unsigned SEHFrameOffset = calculateSetFPREG(SEHStackAllocAmt);
+    uint64_t LEAAmount = IsWinEH ? SEHStackAllocAmt - SEHFrameOffset : -CSSize;
+
+    // There are only two legal forms of epilogue:
+    // - add SEHAllocationSize, %rsp
+    // - lea SEHAllocationSize(%FramePtr), %rsp
+    //
+    // 'mov %FramePtr, %rsp' will not be recognized as an epilogue sequence.
+    // However, we may use this sequence if we have a frame pointer because the
+    // effects of the prologue can safely be undone.
+    if (LEAAmount != 0) {
       unsigned Opc = getLEArOpcode(Uses64BitFramePtr);
       addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr),
-                   FramePtr, false, -CSSize);
+                   FramePtr, false, LEAAmount);
       --MBBI;
     } else {
       unsigned Opc = (Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr);
index 597127a6998c1fd9e84aec1c598e594520e2d6db..b67ad58e0d088dc53ac457963cb57289bd380290 100644 (file)
@@ -167,7 +167,7 @@ entry:
 ; WIN64: andq  $-64, %rsp
 ; WIN64: movaps  -32(%rbp), %xmm6        # 16-byte Reload
 ; WIN64: movaps  -16(%rbp), %xmm7        # 16-byte Reload
-; WIN64: leaq  (%rbp), %rsp
+; WIN64: movq  %rbp, %rsp
 ; WIN64: popq  %rbx
 ; WIN64: popq  %rdi
 ; WIN64: popq  %rbp