[llvm] [X86] Refuse machine outlining under Windows CFI (PR #225263)

Demetrios Chiuratto Agourakis via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 18:54:21 PDT 2026


https://github.com/agourakis82 created https://github.com/llvm/llvm-project/pull/225263

### Summary
The X86 machine outliner did not refuse functions that use Windows CFI. Outlining from WinEH/SEH-bearing code can corrupt `.seh_*` frame state around MSVC C++ EH funclets, producing assembler failures such as `.seh_startepilogue` before `.seh_endprologue` and stray `.seh_endepilogue` (#213862).

AArch64 already has an explicit fence:

```cpp
// FIXME: Teach the outliner to generate/handle Windows unwind info.
if (MF.getTarget().getMCAsmInfo().usesWindowsCFI())
  return false;
```

This PR mirrors that fence in `X86InstrInfo::isFunctionSafeToOutlineFrom`.

### Why this shape
Teaching the outliner to correctly rewrite Windows unwind/funclet metadata is a much larger project. Until that exists, refusing to outline under `usesWindowsCFI()` is the correctness-preserving fix (same policy AArch64 already shipped).

### Test plan
- New: `llvm/test/CodeGen/X86/machine-outliner-windows-cfi.ll`
  - Windows MSVC triple: no `OUTLINED_FUNCTION`
  - Darwin triple: outlining still happens

Fixes #213862

>From 71878d3aba7899f67fbf3606d4e81890e9796298 Mon Sep 17 00:00:00 2001
From: Demetrios Chiuratto Agourakis <demetrios at agourakis.med.br>
Date: Tue, 22 Sep 2026 01:54:10 +0000
Subject: [PATCH] [X86] Refuse machine outlining under Windows CFI

AArch64 already declines to outline from functions when
usesWindowsCFI() is true because the outliner does not yet generate or
preserve Windows unwind info. X86 lacked the same fence, allowing the
machine outliner to rewrite WinEH/SEH-bearing code and emit illegal
.seh_* sequences around funclets (#213862).

Mirror the AArch64 safety check in X86InstrInfo::isFunctionSafeToOutlineFrom.

Fixes #213862
---
 llvm/lib/Target/X86/X86InstrInfo.cpp          |  7 ++++
 .../X86/machine-outliner-windows-cfi.ll       | 36 +++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/machine-outliner-windows-cfi.ll

diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 09a8ae6107020..7032764eeddad 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -10841,6 +10841,13 @@ bool X86InstrInfo::isFunctionSafeToOutlineFrom(
   if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
     return false;
 
+  // FIXME: Teach the outliner to generate/handle Windows unwind info.
+  // Without this fence, outlining from WinEH/SEH-bearing code can corrupt
+  // .seh_* frame state (llvm/llvm-project#213862). AArch64 already refuses
+  // outlining when usesWindowsCFI() is true.
+  if (MF.getTarget().getMCAsmInfo().usesWindowsCFI())
+    return false;
+
   // This function is viable for outlining, so return true.
   return true;
 }
diff --git a/llvm/test/CodeGen/X86/machine-outliner-windows-cfi.ll b/llvm/test/CodeGen/X86/machine-outliner-windows-cfi.ll
new file mode 100644
index 0000000000000..5ca540daf2729
--- /dev/null
+++ b/llvm/test/CodeGen/X86/machine-outliner-windows-cfi.ll
@@ -0,0 +1,36 @@
+; RUN: llc -enable-machine-outliner -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s
+; RUN: llc -enable-machine-outliner -mtriple=x86_64-apple-darwin < %s | FileCheck %s --check-prefix=DARWIN
+
+; X86 previously outlined from Windows-CFI functions, which can corrupt .seh_*
+; frame state around WinEH/funclets (#213862). Mirror AArch64 and refuse
+; outlining when usesWindowsCFI() is true.
+
+define i32 @f1(i32 %a, i32 %b) nounwind {
+entry:
+  %a2 = mul i32 %a, %b
+  %a3 = add i32 %a2, %b
+  %a4 = mul i32 %a3, %a2
+  %a5 = add i32 %a4, %a3
+  ret i32 %a5
+}
+
+define i32 @f2(i32 %a, i32 %b) nounwind {
+entry:
+  %a2 = mul i32 %a, %b
+  %a3 = add i32 %a2, %b
+  %a4 = mul i32 %a3, %a2
+  %a5 = add i32 %a4, %a3
+  ret i32 %a5
+}
+
+; CHECK-LABEL: f1:
+; CHECK-NOT: OUTLINED_FUNCTION
+; CHECK: imull
+; CHECK-LABEL: f2:
+; CHECK-NOT: OUTLINED_FUNCTION
+; CHECK: imull
+
+; DARWIN-LABEL: _f1:
+; DARWIN: OUTLINED_FUNCTION
+; DARWIN-LABEL: _f2:
+; DARWIN: OUTLINED_FUNCTION



More information about the llvm-commits mailing list