Skip to content

Commit 91d7ca9

Browse files
authored
[DebugInfo] Remap extracted DIAssignIDs in hotcoldsplit (#91940)
Fix #91814 When instructions are extracted into a new function the `DIAssignID` metadata uses and attachments need to be remapped so that the stores and assignment markers don't link to stores and assignment markers in the original function. This matches existing inlining behaviour for DIAssignIDs.
1 parent c5b0da9 commit 91d7ca9

File tree

5 files changed

+84
-21
lines changed

5 files changed

+84
-21
lines changed

llvm/include/llvm/IR/DebugInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,10 @@ bool calculateFragmentIntersect(
268268
uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign,
269269
std::optional<DIExpression::FragmentInfo> &Result);
270270

271+
/// Replace DIAssignID uses and attachments with IDs from \p Map.
272+
/// If an ID is unmapped a new ID is generated and added to \p Map.
273+
void remapAssignID(DenseMap<DIAssignID *, DIAssignID *> &Map, Instruction &I);
274+
271275
/// Helper struct for trackAssignments, below. We don't use the similar
272276
/// DebugVariable class because trackAssignments doesn't (yet?) understand
273277
/// partial variables (fragment info) as input and want to make that clear and

llvm/lib/IR/DebugInfo.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,30 @@ bool at::calculateFragmentIntersect(
21302130
SliceSizeInBits, DVRAssign, Result);
21312131
}
21322132

2133+
/// Update inlined instructions' DIAssignID metadata. We need to do this
2134+
/// otherwise a function inlined more than once into the same function
2135+
/// will cause DIAssignID to be shared by many instructions.
2136+
void at::remapAssignID(DenseMap<DIAssignID *, DIAssignID *> &Map,
2137+
Instruction &I) {
2138+
auto GetNewID = [&Map](Metadata *Old) {
2139+
DIAssignID *OldID = cast<DIAssignID>(Old);
2140+
if (DIAssignID *NewID = Map.lookup(OldID))
2141+
return NewID;
2142+
DIAssignID *NewID = DIAssignID::getDistinct(OldID->getContext());
2143+
Map[OldID] = NewID;
2144+
return NewID;
2145+
};
2146+
// If we find a DIAssignID attachment or use, replace it with a new version.
2147+
for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
2148+
if (DVR.isDbgAssign())
2149+
DVR.setAssignId(GetNewID(DVR.getAssignID()));
2150+
}
2151+
if (auto *ID = I.getMetadata(LLVMContext::MD_DIAssignID))
2152+
I.setMetadata(LLVMContext::MD_DIAssignID, GetNewID(ID));
2153+
else if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I))
2154+
DAI->setAssignId(GetNewID(DAI->getAssignID()));
2155+
}
2156+
21332157
/// Collect constant properies (base, size, offset) of \p StoreDest.
21342158
/// Return std::nullopt if any properties are not constants or the
21352159
/// offset from the base pointer is negative.

llvm/lib/Transforms/Utils/CodeExtractor.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,8 +1678,9 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
16781678
DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
16791679
DIB.finalizeSubprogram(NewSP);
16801680

1681-
// Fix up the scope information attached to the line locations in the new
1682-
// function.
1681+
// Fix up the scope information attached to the line locations and the
1682+
// debug assignment metadata in the new function.
1683+
DenseMap<DIAssignID *, DIAssignID *> AssignmentIDMap;
16831684
for (Instruction &I : instructions(NewFunc)) {
16841685
if (const DebugLoc &DL = I.getDebugLoc())
16851686
I.setDebugLoc(
@@ -1695,6 +1696,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
16951696
return MD;
16961697
};
16971698
updateLoopMetadataDebugLocations(I, updateLoopInfoLoc);
1699+
at::remapAssignID(AssignmentIDMap, I);
16981700
}
16991701
if (!TheCall.getDebugLoc())
17001702
TheCall.setDebugLoc(DILocation::get(Ctx, 0, 0, OldSP));

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,29 +1888,12 @@ static void trackInlinedStores(Function::iterator Start, Function::iterator End,
18881888
/// otherwise a function inlined more than once into the same function
18891889
/// will cause DIAssignID to be shared by many instructions.
18901890
static void fixupAssignments(Function::iterator Start, Function::iterator End) {
1891-
// Map {Old, New} metadata. Not used directly - use GetNewID.
18921891
DenseMap<DIAssignID *, DIAssignID *> Map;
1893-
auto GetNewID = [&Map](Metadata *Old) {
1894-
DIAssignID *OldID = cast<DIAssignID>(Old);
1895-
if (DIAssignID *NewID = Map.lookup(OldID))
1896-
return NewID;
1897-
DIAssignID *NewID = DIAssignID::getDistinct(OldID->getContext());
1898-
Map[OldID] = NewID;
1899-
return NewID;
1900-
};
19011892
// Loop over all the inlined instructions. If we find a DIAssignID
19021893
// attachment or use, replace it with a new version.
19031894
for (auto BBI = Start; BBI != End; ++BBI) {
1904-
for (Instruction &I : *BBI) {
1905-
for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
1906-
if (DVR.isDbgAssign())
1907-
DVR.setAssignId(GetNewID(DVR.getAssignID()));
1908-
}
1909-
if (auto *ID = I.getMetadata(LLVMContext::MD_DIAssignID))
1910-
I.setMetadata(LLVMContext::MD_DIAssignID, GetNewID(ID));
1911-
else if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I))
1912-
DAI->setAssignId(GetNewID(DAI->getAssignID()));
1913-
}
1895+
for (Instruction &I : *BBI)
1896+
at::remapAssignID(Map, I);
19141897
}
19151898
}
19161899
#undef DEBUG_TYPE
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
; RUN: opt %s -passes=hotcoldsplit -S | FileCheck %s
2+
3+
;; Check the extracted DIAssignID gets remapped.
4+
5+
; CHECK-LABEL: define void @_foo()
6+
; CHECK: common.ret:
7+
; CHECK-NEXT: dbg.assign(metadata i64 0, metadata ![[#]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64), metadata ![[ID1:[0-9]+]], {{.*}}, metadata !DIExpression())
8+
9+
; CHECK-LABEL: define internal void @_foo.cold.1()
10+
; CHECK: store i64 0, ptr null, align 8, !DIAssignID ![[ID2:[0-9]+]]
11+
12+
; CHECK-DAG: ![[ID1]] = distinct !DIAssignID()
13+
; CHECK-DAG: ![[ID2]] = distinct !DIAssignID()
14+
15+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
16+
target triple = "x86_64-unknown-linux-gnu"
17+
18+
define void @_foo() !dbg !4 {
19+
entry:
20+
br i1 false, label %if.then7, label %common.ret
21+
22+
common.ret: ; preds = %entry
23+
call void @llvm.dbg.assign(metadata i64 0, metadata !7, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64), metadata !12, metadata ptr null, metadata !DIExpression()), !dbg !13
24+
ret void
25+
26+
if.then7: ; preds = %entry
27+
%call21 = load i1, ptr null, align 4294967296
28+
store i64 0, ptr null, align 8, !DIAssignID !12
29+
unreachable
30+
}
31+
32+
declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
33+
34+
!llvm.dbg.cu = !{!0}
35+
!llvm.module.flags = !{!3}
36+
37+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
38+
!1 = !DIFile(filename: "file.cpp", directory: "foo")
39+
!2 = !{}
40+
!3 = !{i32 2, !"Debug Info Version", i32 3}
41+
!4 = distinct !DISubprogram(name: "foo", linkageName: "_foo", scope: !5, file: !1, line: 425, type: !6, scopeLine: 425, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
42+
!5 = !DINamespace(name: "llvm", scope: null)
43+
!6 = distinct !DISubroutineType(types: !2)
44+
!7 = !DILocalVariable(name: "Path", scope: !4, file: !1, line: 436, type: !8)
45+
!8 = !DIDerivedType(tag: DW_TAG_typedef, name: "string", scope: !9, file: !1, line: 79, baseType: !10)
46+
!9 = !DINamespace(name: "std", scope: null)
47+
!10 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "basic_string<char, std::char_traits<char>, std::allocator<char> >", scope: !11, file: !1, line: 85, size: 256, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2, templateParams: !2, identifier: "_ZTSNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE")
48+
!11 = !DINamespace(name: "__cxx11", scope: !9, exportSymbols: true)
49+
!12 = distinct !DIAssignID()
50+
!13 = !DILocation(line: 0, scope: !4)

0 commit comments

Comments
 (0)