[llvm] [AArch64] Report SEH pseudos as zero-size (PR #219276)
Jonas Heinle via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 13:47:18 PDT 2026
https://github.com/Kataglyphis updated https://github.com/llvm/llvm-project/pull/219276
>From 40f1b36c642e7e5ea552b82976a2e5e31a0313d8 Mon Sep 17 00:00:00 2001
From: Jonas Heinle <jonasheinle at googlemail.com>
Date: Thu, 27 Aug 2026 21:07:22 +0200
Subject: [PATCH] [AArch64] Report SEH pseudos as zero-size
The SEH_* pseudos only emit unwind opcodes into .xdata, never a code
byte. They are not meta-instructions, so getInstSizeInBytes fell through
to the default case and reported each one as a normal 4-byte
instruction. A prologue emits one per saved register, so on Windows
every function's size estimate was inflated.
This one is conservative, not a miscompile: BranchRelaxation relaxes
branches it does not need to, and AArch64CompressJumpTables leaves jump
tables wider than they have to be.
Size = 0 in AArch64InstrInfo.td cannot express this. The default case
tests `if (Desc.getSize())`, so a declared zero reads as "unset" and
still gives 4. I tried that first and measured no change at all.
Assisted-by: Claude (Anthropic)
---
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 5 ++
.../CodeGen/AArch64/wineh-seh-pseudo-size.mir | 46 +++++++++++++++++++
2 files changed, 51 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/wineh-seh-pseudo-size.mir
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 43aab1400e81f..673ee8bd5949b 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -220,6 +220,11 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
if (MI.isMetaInstruction())
return 0;
+ // SEH pseudos only emit unwind opcodes into .xdata. Size = 0 in the .td does
+ // not work: the default case below treats getSize() == 0 as "unset".
+ if (isSEHInstruction(MI))
+ return 0;
+
// FIXME: We currently only handle pseudoinstructions that don't get expanded
// before the assembly printer.
unsigned NumBytes = 0;
diff --git a/llvm/test/CodeGen/AArch64/wineh-seh-pseudo-size.mir b/llvm/test/CodeGen/AArch64/wineh-seh-pseudo-size.mir
new file mode 100644
index 0000000000000..3f5ace721d7d2
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/wineh-seh-pseudo-size.mir
@@ -0,0 +1,46 @@
+# SEH pseudos only emit unwind opcodes into .xdata, so they must not be counted
+# as 4-byte instructions. The branch range is narrowed so that counting the ten
+# SEH_Nops here would push the TBZ out of range and relax it needlessly.
+# RUN: llc -mtriple=aarch64-pc-windows-msvc -run-pass branch-relaxation \
+# RUN: -aarch64-tbz-offset-bits=5 %s -o - | FileCheck %s
+
+# CHECK-LABEL: name: seh
+# CHECK: TBZW renamable $w0, 0, %bb.2
+# CHECK-NOT: TBNZW
+
+--- |
+ define void @seh(i32 %x, ptr %p) {
+ ret void
+ }
+...
+---
+name: seh
+tracksRegLiveness: true
+body: |
+ bb.0:
+ successors: %bb.1, %bb.2
+ liveins: $w0, $x1
+ TBZW renamable $w0, 0, %bb.2
+
+ bb.1:
+ successors: %bb.2
+ liveins: $x1
+ renamable $x2 = LDRXui renamable $x1, 0
+ renamable $x2 = LDRXui renamable $x1, 1
+ renamable $x2 = LDRXui renamable $x1, 2
+ renamable $x2 = LDRXui renamable $x1, 3
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ frame-setup SEH_Nop
+ B %bb.2
+
+ bb.2:
+ RET undef $lr
+...
More information about the llvm-commits
mailing list