Skip to content

Commit 7354123

Browse files
authored
[KeyInstr] Use DISubprogram's is-key-instructions-on flag at DWARF emission (#144104)
Patch 2/4 adding bitcode support. A non-key-instructions function inlined into a key-instructions function uses non-key-instructions is_stmt placement (without `findForceIsStmtInstrs`). A key-instructions function inlined into a non-key-instructions function currently results in falling back to non-key-instructions for the inlined scope too. Both of these concessions (not using `findForceIsStmtInstrs` in the 1st case, and not using Key Instructions for the inlined scope in the 2nd) are for performance reasons; to do the right thing we'd need to run both `findForceIsStmtInstrs` and `computeKeyInstructions` - in case that's controversial I've got a separate PR for that: PR 144103.
1 parent ed391f1 commit 7354123

File tree

2 files changed

+123
-5
lines changed

2 files changed

+123
-5
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,10 @@ static cl::opt<DwarfDebug::MinimizeAddrInV5> MinimizeAddrInV5Option(
169169
"Stuff")),
170170
cl::init(DwarfDebug::MinimizeAddrInV5::Default));
171171

172-
static cl::opt<bool> KeyInstructionsAreStmts("dwarf-use-key-instructions",
173-
cl::Hidden, cl::init(false));
172+
/// Set to false to ignore Key Instructions metadata.
173+
static cl::opt<bool> KeyInstructionsAreStmts(
174+
"dwarf-use-key-instructions", cl::Hidden, cl::init(true),
175+
cl::desc("Set to false to ignore Key Instructions metadata"));
174176

175177
static constexpr unsigned ULEB128PadSize = 4;
176178

@@ -2077,8 +2079,18 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
20772079
unsigned LastAsmLine =
20782080
Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
20792081

2082+
// There may be a mixture of scopes using and not using Key Instructions.
2083+
// Not-Key-Instructions functions inlined into Key Instructions functions
2084+
// should use not-key is_stmt handling. Key Instructions functions inlined
2085+
// into not-key-instructions functions currently fall back to not-key
2086+
// handling to avoid having to run computeKeyInstructions for all functions
2087+
// (which will impact non-key-instructions builds).
2088+
// TODO: Investigate the performance impact of doing that.
2089+
bool ScopeUsesKeyInstructions =
2090+
KeyInstructionsAreStmts && DL && SP->getKeyInstructionsEnabled();
2091+
20802092
bool IsKey = false;
2081-
if (KeyInstructionsAreStmts && DL && DL.getLine())
2093+
if (ScopeUsesKeyInstructions && DL && DL.getLine())
20822094
IsKey = KeyInstructions.contains(MI);
20832095

20842096
if (!DL && MI == PrologEndLoc) {
@@ -2158,7 +2170,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
21582170
PrologEndLoc = nullptr;
21592171
}
21602172

2161-
if (KeyInstructionsAreStmts) {
2173+
if (ScopeUsesKeyInstructions) {
21622174
if (IsKey)
21632175
Flags |= DWARF2_FLAG_IS_STMT;
21642176
} else {
@@ -2651,7 +2663,14 @@ void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) {
26512663
PrologEndLoc = emitInitialLocDirective(
26522664
*MF, Asm->OutStreamer->getContext().getDwarfCompileUnitID());
26532665

2654-
if (KeyInstructionsAreStmts)
2666+
// If this function wasn't built with Key Instructions but has a function
2667+
// inlined into it that was, we treat the inlined instance as if it wasn't
2668+
// built with Key Instructions. If this function was built with Key
2669+
// Instructions but a function inlined into it wasn't then we continue to use
2670+
// Key Instructions for this function and fall back to non-key behaviour for
2671+
// the inlined function (except it doesn't benefit from
2672+
// findForceIsStmtInstrs).
2673+
if (KeyInstructionsAreStmts && SP->getKeyInstructionsEnabled())
26552674
computeKeyInstructions(MF);
26562675
else
26572676
findForceIsStmtInstrs(MF);
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# RUN: llc %s --start-after=livedebugvalues --dwarf-use-key-instructions --filetype=obj -o - \
2+
# RUN: | llvm-objdump -d - --no-show-raw-insn \
3+
# RUN: | FileCheck %s --check-prefix=OBJ
4+
5+
# RUN: llc %s --start-after=livedebugvalues --dwarf-use-key-instructions --filetype=obj -o - \
6+
# RUN: | llvm-dwarfdump - --debug-line \
7+
# RUN: | FileCheck %s --check-prefix=DBG
8+
9+
# Test is_stmt emission for a key-instructions function inlined into a
10+
# not-key-instructions function, and vice versa.
11+
12+
--- |
13+
target triple = "x86_64-unknown-linux-gnu"
14+
15+
define hidden noundef i32 @key() local_unnamed_addr !dbg !5 {
16+
entry:
17+
ret i32 0
18+
}
19+
20+
define hidden noundef i32 @not_key() local_unnamed_addr !dbg !9 {
21+
entry:
22+
ret i32 0
23+
}
24+
25+
!llvm.dbg.cu = !{!0}
26+
!llvm.module.flags = !{!2, !3}
27+
!llvm.ident = !{!4}
28+
29+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_17, file: !1, producer: "clang version 21.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None)
30+
!1 = !DIFile(filename: "test.cpp", directory: "/")
31+
!2 = !{i32 7, !"Dwarf Version", i32 5}
32+
!3 = !{i32 2, !"Debug Info Version", i32 3}
33+
!4 = !{!"clang version 21.0.0"}
34+
!5 = distinct !DISubprogram(name: "key", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, keyInstructions: true)
35+
!6 = !DISubroutineType(types: !7)
36+
!7 = !{}
37+
!9 = distinct !DISubprogram(name: "not_key", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, keyInstructions: false)
38+
!10 = distinct !DILocation(line: 5, scope: !5)
39+
!11 = distinct !DILocation(line: 9, scope: !9)
40+
...
41+
---
42+
name: key
43+
alignment: 16
44+
body: |
45+
bb.0.entry:
46+
47+
; OBJ: 0000000000000000 <key>:
48+
; OBJ-NEXT: 0: movl $0x1, %eax
49+
; OBJ-NEXT: 5: movl $0x2, %eax
50+
; OBJ-NEXT: a: movl $0x3, %eax
51+
; OBJ-NEXT: f: movl $0x4, %eax
52+
; OBJ-NEXT: 14: movl $0x5, %eax
53+
; OBJ-NEXT: 19: retq
54+
;
55+
; DBG: Address Line Column File ISA Discriminator OpIndex Flags
56+
; DBG-NEXT: ------------------ ------ ------ ------ --- ------------- ------- -------------
57+
; DBG-NEXT: 0x0000000000000000 1 0 0 0 0 0 is_stmt prologue_end
58+
; DBG-NEXT: 0x0000000000000005 2 0 0 0 0 0 is_stmt
59+
; DBG-NEXT: 0x000000000000000a 2 0 0 0 0 0
60+
; DBG-NEXT: 0x000000000000000f 3 0 0 0 0 0 is_stmt
61+
; DBG-NEXT: 0x0000000000000014 3 0 0 0 0 0
62+
;
63+
$eax = MOV32ri 1, debug-location !DILocation(line: 1, scope: !5) ; is_stmt (prologue_end)
64+
$eax = MOV32ri 2, debug-location !DILocation(line: 2, scope: !5, atomGroup: 1, atomRank: 1) ; is_stmt (key)
65+
$eax = MOV32ri 3, debug-location !DILocation(line: 2, scope: !9, inlinedAt: !10)
66+
$eax = MOV32ri 4, debug-location !DILocation(line: 3, scope: !9, inlinedAt: !10) ; is_stmt (not_key)
67+
$eax = MOV32ri 5, debug-location !DILocation(line: 3, scope: !5, atomGroup: 1, atomRank: 2) ; is_stmt (key)
68+
RET64 $eax, debug-location !DILocation(line: 3, scope: !5, atomGroup: 1, atomRank: 1)
69+
...
70+
---
71+
name: not_key
72+
alignment: 16
73+
body: |
74+
bb.0.entry:
75+
76+
; OBJ: 0000000000000020 <not_key>:
77+
; OBJ-NEXT: 20: movl $0x1, %eax
78+
; OBJ-NEXT: 25: movl $0x2, %eax
79+
; OBJ-NEXT: 2a: movl $0x3, %eax
80+
; OBJ-NEXT: 2f: retq
81+
;
82+
; TODO: Currently key inlined into not-key is treated as not-key. Investigate
83+
; performance implications of honouring the flag in this scenario.
84+
;
85+
; Address Line Column File ISA Discriminator OpIndex Flags
86+
; ------------------ ------ ------ ------ --- ------------- ------- -------------
87+
; DBG-NEXT: 0x0000000000000020 1 0 0 0 0 0 is_stmt prologue_end
88+
; DBG-NEXT: 0x0000000000000025 2 0 0 0 0 0 is_stmt
89+
; DBG-NEXT: 0x000000000000002a 3 0 0 0 0 0 is_stmt
90+
; DBG-NEXT: 0x000000000000002f 3 0 0 0 0 0
91+
;
92+
; NOTE: The `is_stmt` comments at the end of the lines reflects what we want
93+
; to see if the TODO above is resolved.
94+
;
95+
$eax = MOV32ri 1, debug-location !DILocation(line: 1, scope: !9) ; is_stmt (prologue_end)
96+
$eax = MOV32ri 2, debug-location !DILocation(line: 2, scope: !5, inlinedAt: !11, atomGroup: 1, atomRank: 2)
97+
$eax = MOV32ri 3, debug-location !DILocation(line: 3, scope: !5, inlinedAt: !11, atomGroup: 1, atomRank: 1) ; is_stmt (key)
98+
RET64 $eax, debug-location !DILocation(line: 3, scope: !9)
99+
...

0 commit comments

Comments
 (0)