[llvm] [X86] Don't skip frame setup/destroy on SEH pseudos and regenerate tests (PR #225445)
Mikołaj Piróg via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 23 05:50:07 PDT 2026
https://github.com/mikolaj-pirog updated https://github.com/llvm/llvm-project/pull/225445
>From 151bcee08391fa0efceed10ba78a32071b85329b Mon Sep 17 00:00:00 2001
From: "Pirog, Mikolaj Maciej" <mikolaj.maciej.pirog at intel.com>
Date: Tue, 22 Sep 2026 17:50:36 +0200
Subject: [PATCH 1/2] Use framesetup/destroy on SEH pseudos and regenrate tests
---
llvm/lib/Target/X86/X86FrameLowering.cpp | 9 ++-
llvm/lib/Target/X86/X86WinEHUnwindV2.cpp | 6 +-
.../test/CodeGen/X86/taildup-callsiteinfo.mir | 4 +-
.../CodeGen/X86/win64-eh-empty-block-2.mir | 8 +--
.../CodeGen/X86/win64-eh-unwindv2-errors.mir | 56 +++++++--------
...win64-eh-unwindv2-push-pop-stack-alloc.mir | 36 +++++-----
.../win64-eh-unwindv2-too-many-epilogs.mir | 42 ++++++------
.../X86/win64-eh-unwindv2-too-many-instr.mir | 40 ++++++-----
.../win64-eh-unwindv3-too-many-epilog-ops.mir | 68 +++++++++----------
.../win64-eh-unwindv3-too-many-prolog-ops.mir | 4 +-
.../MIR/X86/instr-ref-join-def-vphi.mir | 4 +-
11 files changed, 146 insertions(+), 131 deletions(-)
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index fad665e31bbe59..5e120a9c9f22b2 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -2753,7 +2753,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
}
// For V3, SEH_BeginEpilogue must be emitted before any epilog SEH pseudos.
- BuildMI(MBB, EpilogStart, DL, TII.get(X86::SEH_BeginEpilogue));
+ BuildMI(MBB, EpilogStart, DL, TII.get(X86::SEH_BeginEpilogue))
+ .setMIFlag(MachineInstr::FrameDestroy);
}
// If dynamic alloca is used, then reset esp to point to the last callee-saved
@@ -2816,7 +2817,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
// For V1/V2, emit SEH_BeginEpilogue after stack restore code.
if (!IsWin64UnwindV3 && NeedsWin64CFI && MF.hasWinCFI())
- BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_BeginEpilogue));
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_BeginEpilogue))
+ .setMIFlag(MachineInstr::FrameDestroy);
if (!HasFP && NeedsDwarfCFI) {
MBBI = FirstCSPop;
@@ -2863,7 +2865,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
BuildMI(MBB, Terminator, DL, TII.get(X86::TILERELEASE));
if (NeedsWin64CFI && MF.hasWinCFI())
- BuildMI(MBB, Terminator, DL, TII.get(X86::SEH_EndEpilogue));
+ BuildMI(MBB, Terminator, DL, TII.get(X86::SEH_EndEpilogue))
+ .setMIFlag(MachineInstr::FrameDestroy);
}
StackOffset X86FrameLowering::getFrameIndexReference(const MachineFunction &MF,
diff --git a/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp b/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
index 79b91206e9d5b1..cf291634e7d9be 100644
--- a/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
+++ b/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
@@ -418,7 +418,8 @@ bool runX86WinEHUnwindV2(MachineFunction &MF) {
MachineBasicBlock &MBB = *Info.UnwindV2StartLocation->getParent();
const DebugLoc &DL = Info.UnwindV2StartLocation->getDebugLoc();
BuildMI(MBB, Info.UnwindV2StartLocation, DL,
- TII->get(X86::SEH_UnwindV2Start));
+ TII->get(X86::SEH_UnwindV2Start))
+ .setMIFlag(MachineInstr::FrameDestroy);
if ((LastUnwindInfoEndPosition - Info.ApproximateInstructionPosition >=
InstructionCountThreshold) ||
@@ -438,7 +439,8 @@ bool runX86WinEHUnwindV2(MachineFunction &MF) {
MachineBasicBlock &FirstMBB = MF.front();
BuildMI(FirstMBB, FirstMBB.front(), findDebugLoc(FirstMBB),
TII->get(X86::SEH_UnwindVersion))
- .addImm(2);
+ .addImm(2)
+ .setMIFlag(MachineInstr::FrameSetup);
return true;
}
diff --git a/llvm/test/CodeGen/X86/taildup-callsiteinfo.mir b/llvm/test/CodeGen/X86/taildup-callsiteinfo.mir
index 93991799aeb2a9..8aa25324a8cb3f 100644
--- a/llvm/test/CodeGen/X86/taildup-callsiteinfo.mir
+++ b/llvm/test/CodeGen/X86/taildup-callsiteinfo.mir
@@ -68,9 +68,9 @@ body: |
liveins: $ecx
CALL64pcrel32 @alloc, csr_win64, implicit $rsp, implicit $ssp, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rsp = frame-destroy ADD64ri8 $rsp, 40, implicit-def dead $eflags
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
TAILJMPd64 @f2, csr_win64, implicit $rsp, implicit $ssp, implicit $rsp, implicit $ssp
...
diff --git a/llvm/test/CodeGen/X86/win64-eh-empty-block-2.mir b/llvm/test/CodeGen/X86/win64-eh-empty-block-2.mir
index b97bccd11705d0..6efb7aa59ea861 100644
--- a/llvm/test/CodeGen/X86/win64-eh-empty-block-2.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-empty-block-2.mir
@@ -170,10 +170,10 @@ body: |
bb.8.return (machine-block-address-taken):
$eax = MOV32rm $rbp, 1, $noreg, -12, $noreg :: (load (s32) from %stack.0)
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rsp = frame-destroy ADD64ri8 $rsp, 48, implicit-def dead $eflags
$rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 $eax
bb.1.if.then:
@@ -216,10 +216,10 @@ body: |
frame-setup SEH_EndPrologue
MOV32mi $rbp, 1, $noreg, -12, $noreg, 1 :: (store (s32) into %stack.0)
$rax = LEA64r $rip, 0, $noreg, %bb.8, $noreg
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rsp = frame-destroy ADD64ri8 $rsp, 32, implicit-def dead $eflags
$rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
CATCHRET %bb.8, %bb.0
...
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir b/llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir
index 32023d1d85f253..dc224d31a138a2 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir
@@ -36,8 +36,8 @@ body: |
$rsp = frame-setup SUB64ri32 $rsp, 40, implicit-def dead $eflags
frame-setup SEH_StackAlloc 40
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -74,9 +74,9 @@ body: |
frame-setup PUSH64r killed $rdi, implicit-def $rsp, implicit $rsp
frame-setup SEH_PushReg 55
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -109,9 +109,9 @@ name: dealloc_no_alloc
body: |
bb.0.entry:
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rsp = frame-destroy ADD64ri32 $rsp, 40, implicit-def dead $eflags
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -146,8 +146,8 @@ name: dealloc_after_epilog
body: |
bb.0.entry:
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
$rsp = frame-destroy ADD64ri32 $rsp, 40, implicit-def dead $eflags
RET64
...
@@ -185,10 +185,10 @@ body: |
$rsp = frame-setup SUB64ri32 $rsp, 40, implicit-def dead $eflags
frame-setup SEH_StackAlloc 40
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$rsp = frame-destroy ADD64ri32 $rsp, 40, implicit-def dead $eflags
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -221,9 +221,9 @@ name: mov_no_setframe
body: |
bb.0.entry:
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rsp = MOV64rr $rbp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -260,8 +260,8 @@ body: |
$rbp = MOV64rr $rsp
frame-setup SEH_SetFrame 52, 0
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
$rsp = MOV64rr $rbp
RET64
...
@@ -299,10 +299,10 @@ body: |
$rbp = MOV64rr $rsp
frame-setup SEH_SetFrame 52, 0
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$rsp = MOV64rr $rbp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -339,10 +339,10 @@ body: |
$rsp = frame-setup SUB64ri32 $rsp, 40, implicit-def dead $eflags
frame-setup SEH_StackAlloc 40
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rsp = frame-destroy ADD64ri32 $rsp, 40, implicit-def dead $eflags
$rsp = MOV64rr $rbp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -377,10 +377,10 @@ body: |
frame-setup PUSH64r killed $rdi, implicit-def $rsp, implicit $rsp
frame-setup SEH_PushReg 55
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$rsi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -417,10 +417,10 @@ body: |
frame-setup PUSH64r killed $rsi, implicit-def $rsp, implicit $rsp
frame-setup SEH_PushReg 60
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$rsi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
@@ -453,8 +453,8 @@ name: pop_after_epilog
body: |
bb.0.entry:
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
RET64
...
@@ -488,8 +488,8 @@ name: instr_after_epilog
body: |
bb.0.entry:
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
$ecx = MOV32rr killed $eax
RET64
...
@@ -527,10 +527,10 @@ body: |
$rsp = frame-setup SUB64ri32 $rsp, 40, implicit-def dead $eflags
frame-setup SEH_StackAlloc 40
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rsp = frame-destroy ADD64ri32 $rsp, 20, implicit-def dead $eflags
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$rsp = frame-destroy ADD64ri32 $rsp, 20, implicit-def dead $eflags
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv2-push-pop-stack-alloc.mir b/llvm/test/CodeGen/X86/win64-eh-unwindv2-push-pop-stack-alloc.mir
index 8207ba3d97bd66..cb30162b70d162 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv2-push-pop-stack-alloc.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv2-push-pop-stack-alloc.mir
@@ -12,35 +12,35 @@
# CHECK-LABEL: name: push_pop_same
# CHECK: body:
# CHECK-NEXT: bb.0
-# CHECK-NEXT: SEH_UnwindVersion 2
+# CHECK-NEXT: frame-setup SEH_UnwindVersion 2
# CHECK-NEXT: frame-setup PUSH64r undef $rax
# CHECK-NEXT: frame-setup SEH_StackAlloc 8
# CHECK-NEXT: frame-setup SEH_EndPrologue
-# CHECK-NEXT: SEH_BeginEpilogue
+# CHECK-NEXT: frame-destroy SEH_BeginEpilogue
# CHECK-NEXT: $rax = frame-destroy
-# CHECK-NEXT: SEH_UnwindV2Start
-# CHECK-NEXT: SEH_EndEpilogue
+# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
+# CHECK-NEXT: frame-destroy SEH_EndEpilogue
# CHECK-NEXT: RET64
# Pushes and pops a different register.
# CHECK-LABEL: name: push_pop_different
# CHECK: body:
# CHECK-NEXT: bb.0
-# CHECK-NEXT: SEH_UnwindVersion 2
+# CHECK-NEXT: frame-setup SEH_UnwindVersion 2
# CHECK-NEXT: frame-setup PUSH64r undef $rax
# CHECK-NEXT: frame-setup SEH_StackAlloc 8
# CHECK-NEXT: frame-setup SEH_EndPrologue
-# CHECK: SEH_BeginEpilogue
+# CHECK: frame-destroy SEH_BeginEpilogue
# CHECK-NEXT: $rcx = frame-destroy POP64r
-# CHECK-NEXT: SEH_UnwindV2Start
-# CHECK-NEXT: SEH_EndEpilogue
+# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
+# CHECK-NEXT: frame-destroy SEH_EndEpilogue
# CHECK-NEXT: RET64 $eax
# Pushes in the prolog, adds in the epilog.
# CHECK-LABEL: name: push_add
# CHECK: body:
# CHECK-NEXT: bb.0
-# CHECK-NEXT: SEH_UnwindVersion 2
+# CHECK-NEXT: frame-setup SEH_UnwindVersion 2
# CHECK-NEXT: frame-setup PUSH64r killed $r15
# CHECK-NEXT: frame-setup SEH_PushReg 126
# CHECK-NEXT: frame-setup PUSH64r killed $r14
@@ -54,15 +54,15 @@
# CHECK-NEXT: frame-setup PUSH64r undef $rax
# CHECK-NEXT: frame-setup SEH_StackAlloc 8
# CHECK-NEXT: frame-setup SEH_EndPrologue
-# CHECK: SEH_BeginEpilogue
+# CHECK: frame-destroy SEH_BeginEpilogue
# CHECK-NEXT: $rsp = frame-destroy ADD64ri32 $rsp, 8
-# CHECK-NEXT: SEH_UnwindV2Start
+# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
# CHECK-NEXT: $rbx = frame-destroy POP64r
# CHECK-NEXT: $rdi = frame-destroy POP64r
# CHECK-NEXT: $rsi = frame-destroy POP64r
# CHECK-NEXT: $r14 = frame-destroy POP64r
# CHECK-NEXT: $r15 = frame-destroy POP64r
-# CHECK-NEXT: SEH_EndEpilogue
+# CHECK-NEXT: frame-destroy SEH_EndEpilogue
# CHECK-NEXT: RET64
--- |
@@ -97,9 +97,9 @@ body: |
frame-setup PUSH64r undef $rax, implicit-def $rsp, implicit $rsp
frame-setup SEH_StackAlloc 8
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rax = frame-destroy POP64r implicit-def $rsp, implicit $rsp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
---
@@ -112,9 +112,9 @@ body: |
renamable $edx = KILL $edx, implicit-def $rdx
renamable $ecx = KILL $ecx, implicit-def $rcx
renamable $eax = LEA64_32r killed renamable $rcx, 1, killed renamable $rdx, 0, $noreg
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rcx = frame-destroy POP64r implicit-def $rsp, implicit $rsp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 $eax
...
---
@@ -189,13 +189,13 @@ body: |
MOV64mr renamable $r8, 1, $noreg, 8, $noreg, killed renamable $r9 :: (store (s64) into %ir.out + 8, basealign 16)
MOV64mr renamable $r8, 1, $noreg, 16, $noreg, killed renamable $rax :: (store (s64) into %ir.out + 16, align 16)
MOV64mr killed renamable $r8, 1, $noreg, 24, $noreg, killed renamable $rdx :: (store (s64) into %ir.out + 24, basealign 16)
- SEH_BeginEpilogue
+ frame-destroy SEH_BeginEpilogue
$rsp = frame-destroy ADD64ri32 $rsp, 8, implicit-def dead $eflags
$rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$rsi = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$r14 = frame-destroy POP64r implicit-def $rsp, implicit $rsp
$r15 = frame-destroy POP64r implicit-def $rsp, implicit $rsp
- SEH_EndEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir b/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir
index 8edc43c83f1951..d3ddb882ebc59b 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir
@@ -17,8 +17,10 @@
# RUN: -check-prefixes=ALLOWMORE,CHECK
# CHECK-LABEL: too_many_epilogs
-# CHECK: SEH_UnwindVersion 2
-# CHECK: SEH_UnwindV2Start
+# CHECK: frame-setup SEH_UnwindVersion 2
+# CHECK: frame-destroy SEH_BeginEpilogue
+# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
+# CHECK-NEXT: frame-destroy SEH_EndEpilogue
# If we restricted the number of unwind codes, then we expect to use chained
# infos.
@@ -52,40 +54,40 @@ name: too_many_epilogs
body: |
bb.0.entry:
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !10
bb.1:
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
bb.2:
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
bb.3:
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
bb.4:
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
bb.5:
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
bb.6:
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
bb.7:
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
bb.8:
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
...
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-instr.mir b/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-instr.mir
index 44d89356ecae7e..aaae584eb42ce4 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-instr.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-instr.mir
@@ -45,25 +45,25 @@ name: too_many_instr
body: |
bb.0.entry:
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !10
bb.1:
$rcx = MOV64rr $rax
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !11
bb.2:
$rcx = MOV64rr $rax
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !12
bb.3:
$rcx = MOV64rr $rax
$rcx = MOV64rr $rax
$rcx = MOV64rr $rax
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64 debug-location !13
...
@@ -73,24 +73,32 @@ body: |
# bb.1 + bb.2 have enough instructions that bb.0 has its own info.
# ALLOWLESS: SEH_SplitChainedAtEndOfBlock
# ALLOWMORE-NOT: SEH_SplitChainedAtEndOfBlock
-# CHECK: SEH_UnwindV2Start
-# CHECK: RET64 debug-location !10
+# CHECK: frame-destroy SEH_BeginEpilogue
+# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
+# CHECK-NEXT: frame-destroy SEH_EndEpilogue
+# CHECK-NEXT: RET64 debug-location !10
# CHECK-LABEL: bb.1
# bb.2 doesn't fill the current info, so bb.1 gets added as well.
# CHECK-NOT: SEH_SplitChainedAtEndOfBlock
-# CHECK: SEH_UnwindV2Start
-# CHECK: RET64 debug-location !DILocation(line: 3, column: 1, scope: !6)
+# CHECK: frame-destroy SEH_BeginEpilogue
+# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
+# CHECK-NEXT: frame-destroy SEH_EndEpilogue
+# CHECK-NEXT: RET64 debug-location !DILocation(line: 3, column: 1, scope: !6)
# CHECK-LABEL: bb.2
# bb.3 has enough instructions by itself that bb.2 needs to split.
# ALLOWLESS-NEXT: SEH_SplitChainedAtEndOfBlock
# ALLOWMORE-NOT: SEH_SplitChainedAtEndOfBlock
-# CHECK: SEH_UnwindV2Start
-# CHECK: RET64 debug-location !DILocation(line: 4, column: 1, scope: !6)
+# CHECK: frame-destroy SEH_BeginEpilogue
+# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
+# CHECK-NEXT: frame-destroy SEH_EndEpilogue
+# CHECK-NEXT: RET64 debug-location !DILocation(line: 4, column: 1, scope: !6)
# CHECK-LABEL: bb.3
# Never split at the end.
# CHECK-NOT: SEH_SplitChainedAtEndOfBlock
-# CHECK: SEH_UnwindV2Start
-# CHECK: RET64 debug-location !DILocation(line: 5, column: 1, scope: !6)
+# CHECK: frame-destroy SEH_BeginEpilogue
+# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
+# CHECK-NEXT: frame-destroy SEH_EndEpilogue
+# CHECK-NEXT: RET64 debug-location !DILocation(line: 5, column: 1, scope: !6)
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv3-too-many-epilog-ops.mir b/llvm/test/CodeGen/X86/win64-eh-unwindv3-too-many-epilog-ops.mir
index 99d72faa834a12..0c49f6a49874ba 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv3-too-many-epilog-ops.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv3-too-many-epilog-ops.mir
@@ -23,39 +23,39 @@ body: |
bb.0.entry:
frame-setup SEH_PushReg 51
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_StackAlloc 8
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_StackAlloc 8
+ frame-destroy SEH_EndEpilogue
RET64
...
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv3-too-many-prolog-ops.mir b/llvm/test/CodeGen/X86/win64-eh-unwindv3-too-many-prolog-ops.mir
index fcfd32ab006251..1fa47e443ab9d0 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv3-too-many-prolog-ops.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv3-too-many-prolog-ops.mir
@@ -53,7 +53,7 @@ body: |
frame-setup SEH_StackAlloc 8
frame-setup SEH_StackAlloc 8
frame-setup SEH_EndPrologue
- SEH_BeginEpilogue
- SEH_EndEpilogue
+ frame-destroy SEH_BeginEpilogue
+ frame-destroy SEH_EndEpilogue
RET64
...
diff --git a/llvm/test/DebugInfo/MIR/X86/instr-ref-join-def-vphi.mir b/llvm/test/DebugInfo/MIR/X86/instr-ref-join-def-vphi.mir
index 431325aea7db0b..16ff022b2c022c 100644
--- a/llvm/test/DebugInfo/MIR/X86/instr-ref-join-def-vphi.mir
+++ b/llvm/test/DebugInfo/MIR/X86/instr-ref-join-def-vphi.mir
@@ -233,11 +233,11 @@ body: |
liveins: $esi
$eax = MOV32rr killed $esi, debug-location !35
- SEH_BeginEpilogue debug-location !35
+ frame-destroy SEH_BeginEpilogue debug-location !35
$rsp = frame-destroy ADD64ri8 $rsp, 40, implicit-def dead $eflags, debug-location !35
$rdi = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !35
$rsi = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !35
- SEH_EndEpilogue debug-location !35
+ frame-destroy SEH_EndEpilogue debug-location !35
RET64 $eax, debug-location !35
...
>From b38a7e43311adca0b0c6824caba79abdfdbc3e94 Mon Sep 17 00:00:00 2001
From: "Pirog, Mikolaj Maciej" <mikolaj.maciej.pirog at intel.com>
Date: Wed, 23 Sep 2026 13:05:19 +0200
Subject: [PATCH 2/2] Mark split chain pseudos as frame destroy as well
---
llvm/lib/Target/X86/X86WinEHUnwindV2.cpp | 3 ++-
llvm/lib/Target/X86/X86WinEHUnwindV3.cpp | 3 ++-
.../X86/win64-eh-unwindv2-too-many-epilogs.mir | 2 +-
.../X86/win64-eh-unwindv2-too-many-instr.mir | 4 ++--
.../X86/win64-eh-unwindv3-split-large.ll | 18 ++++++++++++++++++
5 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp b/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
index cf291634e7d9be..bfab37f4871c6c 100644
--- a/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
+++ b/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
@@ -425,7 +425,8 @@ bool runX86WinEHUnwindV2(MachineFunction &MF) {
InstructionCountThreshold) ||
(UnwindCodeCount >= UnwindCodeThreshold)) {
BuildMI(MBB, MBB.begin(), DL,
- TII->get(X86::SEH_SplitChainedAtEndOfBlock));
+ TII->get(X86::SEH_SplitChainedAtEndOfBlock))
+ .setMIFlag(MachineInstr::FrameDestroy);
LastUnwindInfoEndPosition = Info.ApproximateInstructionPosition;
// Doesn't reset to 0, as the prolog unwind codes are now in this info.
UnwindCodeCount = FI.ApproximatePrologCodeCount + 1;
diff --git a/llvm/lib/Target/X86/X86WinEHUnwindV3.cpp b/llvm/lib/Target/X86/X86WinEHUnwindV3.cpp
index 97529c5c5e7951..11d14696cc2932 100644
--- a/llvm/lib/Target/X86/X86WinEHUnwindV3.cpp
+++ b/llvm/lib/Target/X86/X86WinEHUnwindV3.cpp
@@ -309,7 +309,8 @@ bool X86WinEHUnwindV3::runOnMachineFunction(MachineFunction &MF) {
auto SplitAfter = [&](const EpilogSplitPoint &Epilog) {
MachineBasicBlock *MBB = Epilog.BeginEpilog->getParent();
BuildMI(*MBB, MBB->begin(), Epilog.BeginEpilog->getDebugLoc(),
- TII->get(X86::SEH_SplitChainedAtEndOfBlock));
+ TII->get(X86::SEH_SplitChainedAtEndOfBlock))
+ .setMIFlag(MachineInstr::FrameDestroy);
SubFragmentSplits++;
Changed = true;
};
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir b/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir
index d3ddb882ebc59b..6488f34c0512b5 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir
@@ -24,7 +24,7 @@
# If we restricted the number of unwind codes, then we expect to use chained
# infos.
-# ALLOWLESS: SEH_SplitChainedAtEndOfBlock
+# ALLOWLESS: frame-destroy SEH_SplitChainedAtEndOfBlock
# ALLOWMORE-NOT: SEH_SplitChainedAtEndOfBlock
--- |
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-instr.mir b/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-instr.mir
index aaae584eb42ce4..ea31e65494ea73 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-instr.mir
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-instr.mir
@@ -71,7 +71,7 @@ body: |
# CHECK-LABEL: too_many_instr
# CHECK-LABEL: bb.0.entry:
# bb.1 + bb.2 have enough instructions that bb.0 has its own info.
-# ALLOWLESS: SEH_SplitChainedAtEndOfBlock
+# ALLOWLESS: frame-destroy SEH_SplitChainedAtEndOfBlock
# ALLOWMORE-NOT: SEH_SplitChainedAtEndOfBlock
# CHECK: frame-destroy SEH_BeginEpilogue
# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
@@ -88,7 +88,7 @@ body: |
# CHECK-LABEL: bb.2
# bb.3 has enough instructions by itself that bb.2 needs to split.
-# ALLOWLESS-NEXT: SEH_SplitChainedAtEndOfBlock
+# ALLOWLESS-NEXT: frame-destroy SEH_SplitChainedAtEndOfBlock
# ALLOWMORE-NOT: SEH_SplitChainedAtEndOfBlock
# CHECK: frame-destroy SEH_BeginEpilogue
# CHECK-NEXT: frame-destroy SEH_UnwindV2Start
diff --git a/llvm/test/CodeGen/X86/win64-eh-unwindv3-split-large.ll b/llvm/test/CodeGen/X86/win64-eh-unwindv3-split-large.ll
index 50b36fb9edc1d2..f75891d4cbdd6f 100644
--- a/llvm/test/CodeGen/X86/win64-eh-unwindv3-split-large.ll
+++ b/llvm/test/CodeGen/X86/win64-eh-unwindv3-split-large.ll
@@ -3,6 +3,9 @@
; RUN: llc -mtriple=x86_64-unknown-windows-msvc \
; RUN: -x86-wineh-unwindv3-instr-avg-size=100000 -filetype=obj %s -o - \
; RUN: | llvm-readobj --unwind - | FileCheck %s --check-prefix=OBJ
+; RUN: llc -mtriple=x86_64-unknown-windows-msvc \
+; RUN: -x86-wineh-unwindv3-instr-avg-size=100000 \
+; RUN: -stop-after=x86-wineh-unwindv3 -o - %s | FileCheck %s --check-prefix=MIR
; Test V3 *size-based* sub-fragment splitting (the "Unwind v2 style" heuristic).
; With a very small distance threshold, every epilog is forced into its own
@@ -28,6 +31,21 @@ declare i32 @c(i32)
; CHECK: .seh_endepilogue
; CHECK: .seh_endproc
+; MIR-LABEL: name: three_epilogs
+; MIR: frame-setup SEH_EndPrologue
+; MIR: frame-destroy SEH_SplitChainedAtEndOfBlock
+; MIR: frame-destroy SEH_BeginEpilogue
+; MIR-NEXT: frame-destroy SEH_StackAlloc 40
+; MIR: frame-destroy SEH_EndEpilogue
+; MIR: frame-destroy SEH_SplitChainedAtEndOfBlock
+; MIR: frame-destroy SEH_BeginEpilogue
+; MIR-NEXT: frame-destroy SEH_StackAlloc 40
+; MIR: frame-destroy SEH_EndEpilogue
+; MIR: frame-destroy SEH_SplitChainedAtEndOfBlock
+; MIR: frame-destroy SEH_BeginEpilogue
+; MIR-NEXT: frame-destroy SEH_StackAlloc 40
+; MIR: frame-destroy SEH_EndEpilogue
+
; Each epilog ends up in its own fragment with a small, in-range, tail-relative
; (negative) EpilogOffset. The main fragment holds the prolog; each subsequent
; fragment is an epilog-only chained fragment, and the trailing code after the
More information about the llvm-commits
mailing list