[llvm] [DebugInfo] Handle trailing empty blocks when seeking prologue_end spot (PR #117320)
Jeremy Morse via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 25 10:57:06 PST 2024
https://github.com/jmorse updated https://github.com/llvm/llvm-project/pull/117320
>From 6cce004c4ff45df3d864a88c36582fca96cd74d3 Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Fri, 22 Nov 2024 11:58:34 +0000
Subject: [PATCH 1/2] [DebugInfo] Handle trailing empty blocks when seeking
prologue_end spot
The optimiser will produce empty blocks that are unconditionally executed
according to the CFG -- while it may not be meaningful code, and won't get
a prologue_end position, we need to not crash on this input.
---
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 57 +++++++++++--------
.../MIR/X86/dbg-prologue-backup-loc2.mir | 49 ++++++++++++++++
2 files changed, 83 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index affc72b5950fd9..09adf79dac4787 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -2192,14 +2192,42 @@ findPrologueEndLoc(const MachineFunction *MF) {
// better off synthesising an early prologue_end.
auto CurBlock = MF->begin();
auto CurInst = CurBlock->begin();
- while (true) {
+
+ // Find the initial instruction, we're guaranteed one by the caller.
+ while (CurBlock->empty())
+ CurInst = (++CurBlock)->begin();
+
+ // Helper function for stepping through the initial sequence of
+ // unconditionally executed instructions. The optimiser will also chuck in
+ // sequences of empty blocks alas.
+ auto getNextInst = [&CurBlock, &CurInst, MF]() -> bool {
+ // We've reached the end of the block. Did we just look at a terminator?
+ if (CurInst->isTerminator()) {
+ // Some kind of "real" control flow is occurring. At the very least
+ // we would have to start exploring the CFG, a good signal that the
+ // prologue is over.
+ return false;
+ }
+
+ // If we've already fallen through into a loop, don't fall through
+ // further, use a backup-location.
+ if (CurBlock->pred_size() > 1)
+ return false;
+
+ // Fall-through from entry to the next block. This is common at -O0 when
+ // there's no initialisation in the function. Bail if we're also at the
+ // end of the function, or the remaining blocks have no instructions.
// Skip empty blocks, in rare cases the entry can be empty.
- if (CurInst == CurBlock->end()) {
+ do {
++CurBlock;
- CurInst = CurBlock->begin();
- continue;
- }
+ if (CurBlock == MF->end())
+ return false;
+ } while (CurBlock->empty());
+ CurInst = CurBlock->begin();
+ return true;
+ };
+ while (true) {
// Check whether this non-meta instruction a good position for prologue_end.
if (!CurInst->isMetaInstruction()) {
auto FoundInst = ExamineInst(*CurInst);
@@ -2216,25 +2244,8 @@ findPrologueEndLoc(const MachineFunction *MF) {
continue;
}
- // We've reached the end of the block. Did we just look at a terminator?
- if (CurInst->isTerminator()) {
- // Some kind of "real" control flow is occurring. At the very least
- // we would have to start exploring the CFG, a good signal that the
- // prologue is over.
- break;
- }
-
- // If we've already fallen through into a loop, don't fall through
- // further, use a backup-location.
- if (CurBlock->pred_size() > 1)
- break;
-
- // Fall-through from entry to the next block. This is common at -O0 when
- // there's no initialisation in the function. Bail if we're also at the
- // end of the function.
- if (++CurBlock == MF->end())
+ if (!getNextInst())
break;
- CurInst = CurBlock->begin();
}
// We couldn't find any source-location, suggesting all meaningful information
diff --git a/llvm/test/DebugInfo/MIR/X86/dbg-prologue-backup-loc2.mir b/llvm/test/DebugInfo/MIR/X86/dbg-prologue-backup-loc2.mir
index c27655ac801316..29cdbc0853365b 100644
--- a/llvm/test/DebugInfo/MIR/X86/dbg-prologue-backup-loc2.mir
+++ b/llvm/test/DebugInfo/MIR/X86/dbg-prologue-backup-loc2.mir
@@ -31,6 +31,13 @@
# CHECK-NEXT: .LBB0_1:
# CHECK-LABEL: addl %esi, %edx
+## Second function in this file: test that we don't crash when having trailing
+## empty blocks and no location for a prologue. Test that a .loc is produced,
+## with an implicit-not check for there being no prologue_end.
+#
+# CHECK-LABEL: f:
+# CHECK: .loc 0 1234 0
+
--- |
; ModuleID = 'out2.ll'
@@ -66,6 +73,17 @@
ret i32 0, !dbg !17
}
+ define void @f() !dbg !18 {
+ entry:
+ %0 = call ptr @llvm.returnaddress(i32 0)
+ br label %do.body
+
+ do.body:
+ unreachable
+ }
+
+ declare ptr @llvm.returnaddress(i32 immarg)
+
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!6, !7}
!llvm.ident = !{!8}
@@ -88,6 +106,7 @@
!15 = distinct !DILexicalBlock(scope: !9, file: !3, line: 4, column: 15)
!16 = !DILocation(line: 6, column: 9, scope: !15)
!17 = !DILocation(line: 8, column: 3, scope: !9)
+ !18 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 37, type: !10, scopeLine: 1234, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2)
...
---
@@ -132,3 +151,33 @@ body: |
RET64 $eax, debug-location !17
...
+---
+name: f
+alignment: 16
+tracksRegLiveness: true
+noPhis: true
+isSSA: false
+noVRegs: true
+hasFakeUses: false
+tracksDebugUserValues: true
+frameInfo:
+ stackSize: 8
+ offsetAdjustment: -8
+ maxAlignment: 1
+ maxCallFrameSize: 0
+ isCalleeSavedInfoValid: true
+fixedStack:
+ - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 }
+machineFunctionInfo:
+ amxProgModel: None
+body: |
+ bb.0.entry:
+ frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
+ frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ frame-setup CFI_INSTRUCTION offset $rbp, -16
+ $rbp = frame-setup MOV64rr $rsp
+ frame-setup CFI_INSTRUCTION def_cfa_register $rbp
+
+ bb.1.do.body:
+
+...
>From d1899c0598ed349fffac3bdcfc5dbfa59733cd1d Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Mon, 25 Nov 2024 18:56:26 +0000
Subject: [PATCH 2/2] Review feedback
---
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 09adf79dac4787..e1291e2a14a66e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -2193,13 +2193,14 @@ findPrologueEndLoc(const MachineFunction *MF) {
auto CurBlock = MF->begin();
auto CurInst = CurBlock->begin();
- // Find the initial instruction, we're guaranteed one by the caller.
+ // Find the initial instruction, we're guaranteed one by the caller, but not
+ // which block it's in.
while (CurBlock->empty())
CurInst = (++CurBlock)->begin();
+ assert(CurInst != CurBlock->end());
// Helper function for stepping through the initial sequence of
- // unconditionally executed instructions. The optimiser will also chuck in
- // sequences of empty blocks alas.
+ // unconditionally executed instructions.
auto getNextInst = [&CurBlock, &CurInst, MF]() -> bool {
// We've reached the end of the block. Did we just look at a terminator?
if (CurInst->isTerminator()) {
@@ -2217,7 +2218,9 @@ findPrologueEndLoc(const MachineFunction *MF) {
// Fall-through from entry to the next block. This is common at -O0 when
// there's no initialisation in the function. Bail if we're also at the
// end of the function, or the remaining blocks have no instructions.
- // Skip empty blocks, in rare cases the entry can be empty.
+ // Skip empty blocks, in rare cases the entry can be empty, and
+ // other optimisations may add empty blocks that the control flow falls
+ // through.
do {
++CurBlock;
if (CurBlock == MF->end())
More information about the llvm-commits
mailing list