[llvm] [CodeGen][MachineOutliner] Ignore debug instructions when checking pa… (PR #227971)
Yongqiang Tian via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 23:23:36 PDT 2026
https://github.com/yqtian-se created https://github.com/llvm/llvm-project/pull/227971
…tchable exits
isMBBSafeToOutlineFrom checks the instruction before a return for PATCHABLE_FUNCTION_EXIT and PATCHABLE_TAIL_CALL. A debug instruction between the patchable instruction and the return currently hides it and allows the block to be outlined.
Use prev_nodbg for the backward check while preserving the existing treatment of pseudo probes. Retain the direct-adjacency coverage and add a regression with a DBG_VALUE between PATCHABLE_FUNCTION_EXIT and RET.
Fixes #227922
Assisted-by: OpenAI Codex 5.6 Sol
Assisted-by: Claude (review)
>From 565bcdabc693aa82ef675fac78aa2b9931844417 Mon Sep 17 00:00:00 2001
From: Yongqiang Tian <yqtian668 at gmail.com>
Date: Thu, 1 Oct 2026 06:19:05 +0000
Subject: [PATCH] [CodeGen][MachineOutliner] Ignore debug instructions when
checking patchable exits
isMBBSafeToOutlineFrom checks the instruction before a return for
PATCHABLE_FUNCTION_EXIT and PATCHABLE_TAIL_CALL. A debug instruction between
the patchable instruction and the return currently hides it and allows the
block to be outlined.
Use prev_nodbg for the backward check while preserving the existing treatment
of pseudo probes. Retain the direct-adjacency coverage and add a regression
with a DBG_VALUE between PATCHABLE_FUNCTION_EXIT and RET.
Fixes #227922
Assisted-by: OpenAI Codex 5.6 Sol
Assisted-by: Claude (review)
---
llvm/lib/CodeGen/TargetInstrInfo.cpp | 2 +-
.../AArch64/machine-outliner-patchable.mir | 87 +++++++++++++++++++
2 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 92fc628e888e5..096626d20416e 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -2221,7 +2221,7 @@ bool TargetInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
return false;
if (Last != First && Last->isReturn()) {
- --Last;
+ Last = prev_nodbg(Last, First, /*SkipPseudoOp=*/false);
if (Last->getOpcode() == TargetOpcode::PATCHABLE_FUNCTION_EXIT ||
Last->getOpcode() == TargetOpcode::PATCHABLE_TAIL_CALL)
return false;
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-patchable.mir b/llvm/test/CodeGen/AArch64/machine-outliner-patchable.mir
index 6e957bceb8f4f..910f4c940330b 100644
--- a/llvm/test/CodeGen/AArch64/machine-outliner-patchable.mir
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-patchable.mir
@@ -16,6 +16,9 @@
call void @foo(i32 5, i32 6, i32 7, i32 8)
ret void
}
+
+ define void @xray2() #1 !dbg !3 { ret void, !dbg !9 }
+ define void @xray3() #1 !dbg !10 { ret void, !dbg !13 }
; Function Attrs: nounwind
define void @xray1(i1 %a) #1 {
@@ -34,6 +37,24 @@
attributes #0 = { minsize }
attributes #1 = { nounwind "function-instrument"="xray-always" }
+ !llvm.dbg.cu = !{!0}
+ !llvm.module.flags = !{!2}
+
+ !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "llvm", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+ !1 = !DIFile(filename: "machine-outliner-patchable.mir", directory: "/")
+ !2 = !{i32 2, !"Debug Info Version", i32 3}
+ !3 = distinct !DISubprogram(name: "xray2", linkageName: "xray2", scope: !1, file: !1, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !6)
+ !4 = !DISubroutineType(types: !5)
+ !5 = !{}
+ !6 = !{!7}
+ !7 = !DILocalVariable(name: "x", scope: !3, file: !1, line: 1, type: !8)
+ !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+ !9 = !DILocation(line: 1, column: 1, scope: !3)
+ !10 = distinct !DISubprogram(name: "xray3", linkageName: "xray3", scope: !1, file: !1, line: 2, type: !4, scopeLine: 2, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+ !11 = !{!12}
+ !12 = !DILocalVariable(name: "x", scope: !10, file: !1, line: 2, type: !8)
+ !13 = !DILocation(line: 2, column: 1, scope: !10)
+
...
---
name: xray0
@@ -94,6 +115,72 @@ body: |
...
---
+name: xray2
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16,
+ stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+machineFunctionInfo:
+ hasRedZone: false
+body: |
+ ; CHECK-LABEL: name: xray2
+ ; CHECK: bb.0:
+ ; CHECK: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0)
+ ; CHECK-NEXT: $w0 = MOVZWi 1, 0
+ ; CHECK-NEXT: $w1 = MOVZWi 2, 0
+ ; CHECK-NEXT: BL @foo, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit-def $sp
+ ; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0)
+ ; CHECK-NEXT: PATCHABLE_FUNCTION_EXIT
+ ; CHECK-NEXT: DBG_VALUE 1, $noreg, !{{[0-9]+}}, !DIExpression()
+ ; CHECK-NEXT: RET undef $lr
+
+ bb.0:
+ liveins: $lr
+
+ early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0)
+ $w0 = MOVZWi 1, 0
+ $w1 = MOVZWi 2, 0
+ BL @foo, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit-def $sp
+ early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0)
+ PATCHABLE_FUNCTION_EXIT
+ DBG_VALUE 1, $noreg, !7, !DIExpression(), debug-location !9
+ RET undef $lr
+...
+---
+name: xray3
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16,
+ stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+machineFunctionInfo:
+ hasRedZone: false
+body: |
+ ; CHECK-LABEL: name: xray3
+ ; CHECK: bb.0:
+ ; CHECK: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0)
+ ; CHECK-NEXT: $w0 = MOVZWi 1, 0
+ ; CHECK-NEXT: $w1 = MOVZWi 2, 0
+ ; CHECK-NEXT: BL @foo, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit-def $sp
+ ; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0)
+ ; CHECK-NEXT: PATCHABLE_FUNCTION_EXIT
+ ; CHECK-NEXT: DBG_VALUE 1, $noreg, !{{[0-9]+}}, !DIExpression()
+ ; CHECK-NEXT: RET undef $lr
+
+ bb.0:
+ liveins: $lr
+
+ early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0)
+ $w0 = MOVZWi 1, 0
+ $w1 = MOVZWi 2, 0
+ BL @foo, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit-def $sp
+ early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0)
+ PATCHABLE_FUNCTION_EXIT
+ DBG_VALUE 1, $noreg, !12, !DIExpression(), debug-location !13
+ RET undef $lr
+...
+---
name: xray1
tracksRegLiveness: true
liveins:
More information about the llvm-commits
mailing list