Skip to content

Commit dbdd828

Browse files
Merge pull request #5777 from felipepiovezan/felipe/cherrypick_hotcold_fixes_0421
[CherryPick] Fixes for HotColdSplit debug information propagation
2 parents d43270b + ac681a3 commit dbdd828

File tree

8 files changed

+186
-19
lines changed

8 files changed

+186
-19
lines changed

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,6 +1590,13 @@ class DILocalScope : public DIScope {
15901590
/// chain.
15911591
DISubprogram *getSubprogram() const;
15921592

1593+
/// Traverses the scope chain rooted at RootScope until it hits a Subprogram,
1594+
/// recreating the chain with "NewSP" instead.
1595+
static DILocalScope *
1596+
cloneScopeForSubprogram(DILocalScope &RootScope, DISubprogram &NewSP,
1597+
LLVMContext &Ctx,
1598+
DenseMap<const MDNode *, MDNode *> &Cache);
1599+
15931600
/// Get the first non DILexicalBlockFile scope of this scope.
15941601
///
15951602
/// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the
@@ -2126,6 +2133,11 @@ class DILexicalBlockBase : public DILocalScope {
21262133

21272134
Metadata *getRawScope() const { return getOperand(1); }
21282135

2136+
void replaceScope(DIScope *Scope) {
2137+
assert(!isUniqued());
2138+
setOperand(1, Scope);
2139+
}
2140+
21292141
static bool classof(const Metadata *MD) {
21302142
return MD->getMetadataID() == DILexicalBlockKind ||
21312143
MD->getMetadataID() == DILexicalBlockFileKind;

llvm/include/llvm/IR/DebugLoc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ namespace llvm {
8686
/// Gets the inlined-at scope for a DebugLoc.
8787
MDNode *getInlinedAtScope() const;
8888

89+
/// Rebuild the entire inline-at chain by replacing the subprogram at the
90+
/// end of the chain with NewSP.
91+
static DebugLoc
92+
replaceInlinedAtSubprogram(const DebugLoc &DL, DISubprogram &NewSP,
93+
LLVMContext &Ctx,
94+
DenseMap<const MDNode *, MDNode *> &Cache);
95+
8996
/// Find the debug info location for the start of the function.
9097
///
9198
/// Walk up the scope chain of given debug loc and find line number info

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,35 @@ DILocalScope *DILocalScope::getNonLexicalBlockFileScope() const {
937937
return const_cast<DILocalScope *>(this);
938938
}
939939

940+
DILocalScope *DILocalScope::cloneScopeForSubprogram(
941+
DILocalScope &RootScope, DISubprogram &NewSP, LLVMContext &Ctx,
942+
DenseMap<const MDNode *, MDNode *> &Cache) {
943+
SmallVector<DIScope *> ScopeChain;
944+
DIScope *CachedResult = nullptr;
945+
946+
for (DIScope *Scope = &RootScope; !isa<DISubprogram>(Scope);
947+
Scope = Scope->getScope()) {
948+
if (auto It = Cache.find(Scope); It != Cache.end()) {
949+
CachedResult = cast<DIScope>(It->second);
950+
break;
951+
}
952+
ScopeChain.push_back(Scope);
953+
}
954+
955+
// Recreate the scope chain, bottom-up, starting at the new subprogram (or a
956+
// cached result).
957+
DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
958+
for (DIScope *ScopeToUpdate : reverse(ScopeChain)) {
959+
TempMDNode ClonedScope = ScopeToUpdate->clone();
960+
cast<DILexicalBlockBase>(*ClonedScope).replaceScope(UpdatedScope);
961+
UpdatedScope =
962+
cast<DIScope>(MDNode::replaceWithUniqued(std::move(ClonedScope)));
963+
Cache[ScopeToUpdate] = UpdatedScope;
964+
}
965+
966+
return cast<DILocalScope>(UpdatedScope);
967+
}
968+
940969
DISubprogram::DISPFlags DISubprogram::getFlag(StringRef Flag) {
941970
return StringSwitch<DISPFlags>(Flag)
942971
#define HANDLE_DISP_FLAG(ID, NAME) .Case("DISPFlag" #NAME, SPFlag##NAME)

llvm/lib/IR/DebugLoc.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,46 @@ void DebugLoc::setImplicitCode(bool ImplicitCode) {
6767
}
6868
}
6969

70+
DebugLoc DebugLoc::replaceInlinedAtSubprogram(
71+
const DebugLoc &RootLoc, DISubprogram &NewSP, LLVMContext &Ctx,
72+
DenseMap<const MDNode *, MDNode *> &Cache) {
73+
SmallVector<DILocation *> LocChain;
74+
DILocation *CachedResult = nullptr;
75+
76+
// Collect the inline chain, stopping if we find a location that has already
77+
// been processed.
78+
for (DILocation *Loc = RootLoc; Loc; Loc = Loc->getInlinedAt()) {
79+
if (auto It = Cache.find(Loc); It != Cache.end()) {
80+
CachedResult = cast<DILocation>(It->second);
81+
break;
82+
}
83+
LocChain.push_back(Loc);
84+
}
85+
86+
DILocation *UpdatedLoc = CachedResult;
87+
if (!UpdatedLoc) {
88+
// If no cache hits, then back() is the end of the inline chain, that is,
89+
// the DILocation whose scope ends in the Subprogram to be replaced.
90+
DILocation *LocToUpdate = LocChain.pop_back_val();
91+
DIScope *NewScope = DILocalScope::cloneScopeForSubprogram(
92+
*LocToUpdate->getScope(), NewSP, Ctx, Cache);
93+
UpdatedLoc = DILocation::get(Ctx, LocToUpdate->getLine(),
94+
LocToUpdate->getColumn(), NewScope);
95+
Cache[LocToUpdate] = UpdatedLoc;
96+
}
97+
98+
// Recreate the location chain, bottom-up, starting at the new scope (or a
99+
// cached result).
100+
for (const DILocation *LocToUpdate : reverse(LocChain)) {
101+
UpdatedLoc =
102+
DILocation::get(Ctx, LocToUpdate->getLine(), LocToUpdate->getColumn(),
103+
LocToUpdate->getScope(), UpdatedLoc);
104+
Cache[LocToUpdate] = UpdatedLoc;
105+
}
106+
107+
return UpdatedLoc;
108+
}
109+
70110
DebugLoc DebugLoc::appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt,
71111
LLVMContext &Ctx,
72112
DenseMap<const MDNode *, MDNode *> &Cache) {

llvm/lib/Transforms/Utils/CodeExtractor.cpp

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,18 +1551,25 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
15511551
// point to a variable in the wrong scope.
15521552
SmallDenseMap<DINode *, DINode *> RemappedMetadata;
15531553
SmallVector<Instruction *, 4> DebugIntrinsicsToDelete;
1554+
DenseMap<const MDNode *, MDNode *> Cache;
15541555
for (Instruction &I : instructions(NewFunc)) {
15551556
auto *DII = dyn_cast<DbgInfoIntrinsic>(&I);
15561557
if (!DII)
15571558
continue;
15581559

1559-
// Point the intrinsic to a fresh label within the new function.
1560+
// Point the intrinsic to a fresh label within the new function if the
1561+
// intrinsic was not inlined from some other function.
15601562
if (auto *DLI = dyn_cast<DbgLabelInst>(&I)) {
1563+
if (DLI->getDebugLoc().getInlinedAt())
1564+
continue;
15611565
DILabel *OldLabel = DLI->getLabel();
15621566
DINode *&NewLabel = RemappedMetadata[OldLabel];
1563-
if (!NewLabel)
1564-
NewLabel = DILabel::get(Ctx, NewSP, OldLabel->getName(),
1567+
if (!NewLabel) {
1568+
DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram(
1569+
*OldLabel->getScope(), *NewSP, Ctx, Cache);
1570+
NewLabel = DILabel::get(Ctx, NewScope, OldLabel->getName(),
15651571
OldLabel->getFile(), OldLabel->getLine());
1572+
}
15661573
DLI->setArgOperand(0, MetadataAsValue::get(Ctx, NewLabel));
15671574
continue;
15681575
}
@@ -1583,17 +1590,23 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
15831590
DebugIntrinsicsToDelete.push_back(DVI);
15841591
continue;
15851592
}
1586-
1587-
// Point the intrinsic to a fresh variable within the new function.
1588-
DILocalVariable *OldVar = DVI->getVariable();
1589-
DINode *&NewVar = RemappedMetadata[OldVar];
1590-
if (!NewVar)
1591-
NewVar = DIB.createAutoVariable(
1592-
NewSP, OldVar->getName(), OldVar->getFile(), OldVar->getLine(),
1593-
OldVar->getType(), /*AlwaysPreserve=*/false, DINode::FlagZero,
1594-
OldVar->getAlignInBits());
1595-
DVI->setVariable(cast<DILocalVariable>(NewVar));
1593+
// If the variable was in the scope of the old function, i.e. it was not
1594+
// inlined, point the intrinsic to a fresh variable within the new function.
1595+
if (!DVI->getDebugLoc().getInlinedAt()) {
1596+
DILocalVariable *OldVar = DVI->getVariable();
1597+
DINode *&NewVar = RemappedMetadata[OldVar];
1598+
if (!NewVar) {
1599+
DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram(
1600+
*OldVar->getScope(), *NewSP, Ctx, Cache);
1601+
NewVar = DIB.createAutoVariable(
1602+
NewScope, OldVar->getName(), OldVar->getFile(), OldVar->getLine(),
1603+
OldVar->getType(), /*AlwaysPreserve=*/false, DINode::FlagZero,
1604+
OldVar->getAlignInBits());
1605+
}
1606+
DVI->setVariable(cast<DILocalVariable>(NewVar));
1607+
}
15961608
}
1609+
15971610
for (auto *DII : DebugIntrinsicsToDelete)
15981611
DII->eraseFromParent();
15991612
DIB.finalizeSubprogram(NewSP);
@@ -1602,13 +1615,13 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
16021615
// function.
16031616
for (Instruction &I : instructions(NewFunc)) {
16041617
if (const DebugLoc &DL = I.getDebugLoc())
1605-
I.setDebugLoc(DILocation::get(Ctx, DL.getLine(), DL.getCol(), NewSP));
1618+
I.setDebugLoc(
1619+
DebugLoc::replaceInlinedAtSubprogram(DL, *NewSP, Ctx, Cache));
16061620

16071621
// Loop info metadata may contain line locations. Fix them up.
1608-
auto updateLoopInfoLoc = [&Ctx, NewSP](Metadata *MD) -> Metadata * {
1622+
auto updateLoopInfoLoc = [&Ctx, &Cache, NewSP](Metadata *MD) -> Metadata * {
16091623
if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
1610-
return DILocation::get(Ctx, Loc->getLine(), Loc->getColumn(), NewSP,
1611-
nullptr);
1624+
return DebugLoc::replaceInlinedAtSubprogram(Loc, *NewSP, Ctx, Cache);
16121625
return MD;
16131626
};
16141627
updateLoopMetadataDebugLocations(I, updateLoopInfoLoc);

llvm/test/Transforms/HotColdSplit/split-out-dbg-label.ll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@ target triple = "x86_64-apple-macosx10.14.0"
1212

1313
; CHECK-LABEL: define {{.*}}@foo.cold.1
1414
; CHECK: llvm.dbg.label(metadata [[LABEL:![0-9]+]]), !dbg [[LINE:![0-9]+]]
15+
; CHECK: llvm.dbg.label(metadata [[LABEL_IN_INLINE_ME:![0-9]+]]), !dbg [[LINE2:![0-9]+]]
16+
; CHECK: llvm.dbg.label(metadata [[SCOPED_LABEL:![0-9]+]]), !dbg [[LINE]]
1517

1618
; CHECK: [[FILE:![0-9]+]] = !DIFile
19+
; CHECK: [[INLINE_ME_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "inline_me"
1720
; CHECK: [[SCOPE:![0-9]+]] = distinct !DISubprogram(name: "foo.cold.1"
1821
; CHECK: [[LINE]] = !DILocation(line: 1, column: 1, scope: [[SCOPE]]
1922
; CHECK: [[LABEL]] = !DILabel(scope: [[SCOPE]], name: "bye", file: [[FILE]], line: 28
23+
; CHECK: [[LABEL_IN_INLINE_ME]] = !DILabel(scope: [[INLINE_ME_SCOPE]], name: "label_in_@inline_me", file: [[FILE]], line: 29
24+
; CHECK: [[LINE2]] = !DILocation(line: 2, column: 2, scope: [[INLINE_ME_SCOPE]], inlinedAt: [[LINE]]
25+
; CHECK: [[SCOPED_LABEL]] = !DILabel(scope: [[SCOPE_IN_FOO:![0-9]+]], name: "scoped_label_in_foo", file: [[FILE]], line: 30
26+
; CHECK: [[SCOPE_IN_FOO]] = !DILexicalBlock(scope: [[SCOPE]], file: [[FILE]], line: 31, column: 31)
2027

2128
define void @foo(i32 %arg1) !dbg !6 {
2229
entry:
@@ -28,6 +35,8 @@ if.then: ; preds = %entry
2835

2936
if.end: ; preds = %entry
3037
call void @llvm.dbg.label(metadata !12), !dbg !11
38+
call void @llvm.dbg.label(metadata !14), !dbg !15
39+
call void @llvm.dbg.label(metadata !16), !dbg !11
3140
call void @sink()
3241
ret void
3342
}
@@ -36,6 +45,10 @@ declare void @llvm.dbg.label(metadata)
3645

3746
declare void @sink() cold
3847

48+
define void @inline_me() !dbg !13 {
49+
ret void
50+
}
51+
3952
!llvm.dbg.cu = !{!0}
4053
!llvm.debugify = !{!3, !4}
4154
!llvm.module.flags = !{!5}
@@ -53,3 +66,8 @@ declare void @sink() cold
5366
!10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
5467
!11 = !DILocation(line: 1, column: 1, scope: !6)
5568
!12 = !DILabel(scope: !6, name: "bye", file: !1, line: 28)
69+
!13 = distinct !DISubprogram(name: "inline_me", linkageName: "inline_me", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)
70+
!14 = !DILabel(scope: !13, name: "label_in_@inline_me", file: !1, line: 29)
71+
!15 = !DILocation(line: 2, column: 2, scope: !13, inlinedAt: !11)
72+
!16 = !DILabel(scope: !17, name: "scoped_label_in_foo", file: !1, line: 30)
73+
!17 = distinct !DILexicalBlock(scope: !6, file: !1, line: 31, column: 31)

llvm/test/Transforms/HotColdSplit/transfer-debug-info.ll

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,42 @@ target triple = "x86_64-apple-macosx10.14.0"
2828
; - Expressions inside of dbg.value intrinsics are preserved
2929
; CHECK-NEXT: llvm.dbg.value(metadata i32 [[ADD1]], metadata [[VAR1]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value)
3030

31+
; CHECK-NEXT: call void @sink(i32 [[ADD1]]), !dbg [[LINE2:![0-9]+]]
32+
; CHECK-NEXT: call void @sink(i32 [[ADD1]]), !dbg [[LINE3:![0-9]+]]
33+
34+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[ADD1]]
35+
; CHECK-SAME: metadata [[VAR_FROM_INLINE_ME:![0-9]+]]
36+
; CHECK-SAME: !dbg [[LINE2]]
37+
38+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[ADD1]]
39+
; CHECK-SAME: metadata [[VAR2:![0-9]+]]
40+
; CHECK-SAME: !dbg [[LINE4:![0-9]+]]
41+
42+
3143
; - The DISubprogram for @foo.cold.1 has an empty DISubroutineType
3244
; CHECK: [[FILE:![0-9]+]] = !DIFile(filename: "<stdin>"
3345
; CHECK: [[EMPTY_MD:![0-9]+]] = !{}
3446
; CHECK: [[EMPTY_TYPE:![0-9]+]] = !DISubroutineType(types: [[EMPTY_MD]])
47+
; CHECK: [[INLINE_ME_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "inline_me"
3548
; CHECK: [[NEWSCOPE:![0-9]+]] = distinct !DISubprogram(name: "foo.cold.1", linkageName: "foo.cold.1", scope: null, file: [[FILE]], type: [[EMPTY_TYPE]], spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized
3649

3750
; - Line locations in @foo.cold.1 point to the new scope for @foo.cold.1
3851
; CHECK: [[LINE1]] = !DILocation(line: 1, column: 1, scope: [[NEWSCOPE]])
3952

53+
; CHECK: [[LINE2]] = !DILocation(line: 2, column: 2, scope: [[INLINE_ME_SCOPE]]
54+
; CHECK-SAME: inlinedAt: [[LINE3]]
55+
; CHECK: [[LINE3]] = !DILocation(line: 3, column: 3, scope: [[INLINED_SCOPE1:![0-9]*]]
56+
; CHECK: [[INLINED_SCOPE1]] = !DILexicalBlock(scope: [[INLINED_SCOPE2:![0-9]*]], file: [[FILE]], line: 4, column: 4)
57+
; CHECK: [[INLINED_SCOPE2]] = !DILexicalBlock(scope: [[NEWSCOPE]], file: [[FILE]], line: 5, column: 5)
58+
59+
; CHECK: [[VAR_FROM_INLINE_ME]] = !DILocalVariable(name: "var_from_inline_me",
60+
; CHECK-SAME: scope: [[INLINE_ME_SCOPE]]
61+
62+
; CHECK: [[VAR2]] = !DILocalVariable(name: "var_from_scope_in_foo",
63+
; CHECK-SAME: scope: [[NEWSCOPE2:![0-9]+]]
64+
; CHECK: [[NEWSCOPE2]] = !DILexicalBlock(scope: [[NEWSCOPE]], file: [[FILE]], line: 7, column: 7)
65+
; CHECK: [[LINE4]] = !DILocation(line: 6, column: 6, scope: [[NEWSCOPE2]]
66+
4067
define void @foo(i32 %arg1) !dbg !6 {
4168
entry:
4269
%var = add i32 0, 0, !dbg !11
@@ -52,13 +79,21 @@ if.end: ; preds = %entry
5279
call void @sink(i32 %add1), !dbg !11
5380
call void @llvm.dbg.value(metadata i32 %add1, metadata !9, metadata !DIExpression()), !dbg !11
5481
call void @llvm.dbg.value(metadata i32 %add1, metadata !9, metadata !DIExpression(DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value)), !dbg !11
82+
call void @sink(i32 %add1), !dbg !13 ; inlined from @inline_me
83+
call void @sink(i32 %add1), !dbg !14 ; not inlined, but inside some scope of foo
84+
call void @llvm.dbg.value(metadata i32 %add1, metadata !17, metadata !DIExpression()), !dbg !13 ; variable from @inline_me, should preserve scope in !17.
85+
call void @llvm.dbg.value(metadata i32 %add1, metadata !18, metadata !DIExpression()), !dbg !19 ; variable not inlined, but inside some scope of foo
5586
ret void
5687
}
5788

5889
declare void @llvm.dbg.value(metadata, metadata, metadata)
5990

6091
declare void @sink(i32) cold
6192

93+
define void @inline_me() !dbg !12{
94+
ret void
95+
}
96+
6297
!llvm.dbg.cu = !{!0}
6398
!llvm.debugify = !{!3, !4}
6499
!llvm.module.flags = !{!5}
@@ -75,3 +110,12 @@ declare void @sink(i32) cold
75110
!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
76111
!10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
77112
!11 = !DILocation(line: 1, column: 1, scope: !6)
113+
!12 = distinct !DISubprogram(name: "inline_me", linkageName: "inline_me", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)
114+
!13 = !DILocation(line: 2, column: 2, scope: !12, inlinedAt: !14)
115+
!14 = !DILocation(line: 3, column: 3, scope: !15)
116+
!15 = distinct !DILexicalBlock(scope: !16, file: !1, line: 4, column: 4)
117+
!16 = distinct !DILexicalBlock(scope: !6, file: !1, line: 5, column: 5)
118+
!17 = !DILocalVariable(name: "var_from_inline_me", scope: !12, file: !1, line: 1, type: !10)
119+
!18 = !DILocalVariable(name: "var_from_scope_in_foo", scope: !20, file: !1, line: 1, type: !10)
120+
!19 = !DILocation(line: 6, column: 6, scope: !20)
121+
!20 = distinct !DILexicalBlock(scope: !6, file: !1, line: 7, column: 7)

llvm/test/Transforms/HotColdSplit/update-split-loop-metadata.ll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ target triple = "x86_64-apple-macosx10.14.0"
1111

1212
; The scope for these debug locations should be @basic.cold.1, not @basic.
1313
; CHECK: [[SCOPE:![0-9]+]] = distinct !DISubprogram(name: "basic.cold.1"
14-
; CHECK: [[LOOP_MD]] = distinct !{[[LOOP_MD]], [[LINE:![0-9]+]], [[LINE]]}
14+
; CHECK: [[LOOP_MD]] = distinct !{[[LOOP_MD]], [[LINE:![0-9]+]], [[LINE2:![0-9]+]]}
1515
; CHECK: [[LINE]] = !DILocation(line: 1, column: 1, scope: [[SCOPE]])
16+
; CHECK: [[LINE2]] = !DILocation(line: 2, column: 2, scope: [[LEX_SCOPE:![0-9]+]])
17+
; CHECK: [[LEX_SCOPE]] = !DILexicalBlock(scope: [[SCOPE]], file: !{{[0-9]+}}, line: 3, column: 3)
1618

1719
define void @basic(i32* %p, i32 %k) !dbg !6 {
1820
entry:
@@ -55,4 +57,6 @@ declare void @sink() cold
5557
!7 = !DISubroutineType(types: !2)
5658
!8 = !{}
5759
!9 = !DILocation(line: 1, column: 1, scope: !6)
58-
!10 = distinct !{!10, !9, !9}
60+
!10 = distinct !{!10, !9, !11}
61+
!11 = !DILocation(line: 2, column: 2, scope: !12)
62+
!12 = !DILexicalBlock(scope: !6, file: !1, line: 3, column: 3)

0 commit comments

Comments
 (0)