[llvm] d464edd - [X86][Win64] Avoid statepoints prior to SEH epilogue

Markus Böck via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 15 13:47:36 PST 2023


Author: Markus Böck
Date: 2023-02-15T22:47:28+01:00
New Revision: d464edde9571817fbaa02f07082c3fdde22aebbc

URL: https://github.com/llvm/llvm-project/commit/d464edde9571817fbaa02f07082c3fdde22aebbc
DIFF: https://github.com/llvm/llvm-project/commit/d464edde9571817fbaa02f07082c3fdde22aebbc.diff

LOG: [X86][Win64] Avoid statepoints prior to SEH epilogue

This patchs purpose is very similar to https://reviews.llvm.org/D119644

The gist of the issue is that SEH unwinding has certain invariants around call instructions. One of those is that a call instruction must not be immediately followed by the function epilogue. Failing to do so leads to Windows' unwinder not recognizing the frame and skipping it when unwinding the stack.

LLVM ensures this invariant by inserting a noop after a call prior to an epilogue. The implementation however, makes the unfortunate assumption that pseudo instructions may not be calls, leading to statepoints being skipped and no noop being inserted.
This patch fixes that issue by only skipping over pseudo instructions that aren't calls.

Differential Revision: https://reviews.llvm.org/D143812

Added: 
    

Modified: 
    llvm/lib/Target/X86/X86MCInstLower.cpp
    llvm/test/CodeGen/X86/win64-seh-epilogue-statepoint.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index 97ec866455964..02ed68b661f2c 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -2714,9 +2714,10 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
     for (MBBI = PrevCrossBBInst(MBBI);
          MBBI != MachineBasicBlock::const_iterator();
          MBBI = PrevCrossBBInst(MBBI)) {
-      // Conservatively assume that pseudo instructions don't emit code and keep
-      // looking for a call. We may emit an unnecessary nop in some cases.
-      if (!MBBI->isPseudo()) {
+      // Pseudo instructions that aren't a call are assumed to not emit any
+      // code. If they do, we worst case generate unnecessary noops after a
+      // call.
+      if (MBBI->isCall() || !MBBI->isPseudo()) {
         if (MBBI->isCall())
           EmitAndCountInstruction(MCInstBuilder(X86::NOOP));
         break;

diff  --git a/llvm/test/CodeGen/X86/win64-seh-epilogue-statepoint.ll b/llvm/test/CodeGen/X86/win64-seh-epilogue-statepoint.ll
index a524bfcb52069..7f487a026fac2 100644
--- a/llvm/test/CodeGen/X86/win64-seh-epilogue-statepoint.ll
+++ b/llvm/test/CodeGen/X86/win64-seh-epilogue-statepoint.ll
@@ -9,6 +9,7 @@ define i32 @foobar() gc "statepoint-example" personality ptr @__gxx_personality_
 ; CHECK-NEXT:    .seh_endprologue
 ; CHECK-NEXT:    callq bar
 ; CHECK-NEXT:  .Ltmp0:
+; CHECK-NEXT:    nop
 ; CHECK-NEXT:    addq $40, %rsp
 ; CHECK-NEXT:    retq
 ; CHECK-NEXT:    .seh_endproc


        


More information about the llvm-commits mailing list