Skip to content

Commit 9fb92c0

Browse files
committed
Next iteration of the algorithm
1 parent 5fdbac3 commit 9fb92c0

File tree

4 files changed

+124
-73
lines changed

4 files changed

+124
-73
lines changed

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 106 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ DILocation *DILocation::getMergedLocations(ArrayRef<DILocation *> Locs) {
118118
return Merged;
119119
}
120120

121+
static DILexicalBlockBase *cloneAndReplaceParentScope(DILexicalBlockBase *LBB,
122+
DIScope *NewParent) {
123+
TempMDNode ClonedScope = LBB->clone();
124+
cast<DILexicalBlockBase>(*ClonedScope).replaceScope(NewParent);
125+
return cast<DILexicalBlockBase>(
126+
MDNode::replaceWithUniqued(std::move(ClonedScope)));
127+
}
128+
121129
using LineColumn = std::pair<unsigned /* Line */, unsigned /* Column */>;
122130

123131
/// Returns the location of DILocalScope, if present, or a default value.
@@ -134,6 +142,82 @@ static LineColumn getLocalScopeLocationOr(DIScope *S, LineColumn Default) {
134142
llvm_unreachable("Unhandled type of DILocalScope.");
135143
}
136144

145+
// Returns the nearest matching scope inside a subprogram.
146+
template <typename MatcherT>
147+
static std::pair<DIScope *, LineColumn>
148+
getNearestMatchingScope(const DILocation *L1, const DILocation *L2) {
149+
MatcherT Matcher;
150+
151+
DIScope *S1 = L1->getScope();
152+
DIScope *S2 = L2->getScope();
153+
154+
// When matching DILexicalBlockFile's, ignore column numbers, so that
155+
// DILocation's having different columns within the same
156+
// DILexicalBlockFile will match.
157+
auto GetLocForBlockFile = [](LineColumn L) {
158+
L.second = 0;
159+
return L;
160+
};
161+
162+
LineColumn Loc1(L1->getLine(), L1->getColumn());
163+
for (; S1; S1 = S1->getScope()) {
164+
Loc1 = getLocalScopeLocationOr(S1, GetLocForBlockFile(Loc1));
165+
Matcher.insert(S1, Loc1);
166+
if (isa<DISubprogram>(S1))
167+
break;
168+
}
169+
170+
LineColumn Loc2(L2->getLine(), L2->getColumn());
171+
for (; S2; S2 = S2->getScope()) {
172+
Loc2 = getLocalScopeLocationOr(S2, GetLocForBlockFile(Loc2));
173+
174+
if (DIScope *S = Matcher.match(S2, Loc2))
175+
return std::make_pair(S, Loc2);
176+
177+
if (isa<DISubprogram>(S2))
178+
break;
179+
}
180+
return std::make_pair(nullptr, LineColumn(L2->getLine(), L2->getColumn()));
181+
}
182+
183+
// Matches equal scopes.
184+
struct EqualScopesMatcher {
185+
SmallPtrSet<DIScope *, 8> Scopes;
186+
187+
void insert(DIScope *S, LineColumn Loc) { Scopes.insert(S); }
188+
189+
DIScope *match(DIScope *S, LineColumn Loc) {
190+
return Scopes.contains(S) ? S : nullptr;
191+
}
192+
};
193+
194+
// Matches scopes with the same location.
195+
struct ScopeLocationsMatcher {
196+
SmallMapVector<std::pair<DIFile *, LineColumn>, SmallSetVector<DIScope *, 8>,
197+
8>
198+
Scopes;
199+
200+
void insert(DIScope *S, LineColumn Loc) {
201+
Scopes[{S->getFile(), Loc}].insert(S);
202+
}
203+
204+
DIScope *match(DIScope *S, LineColumn Loc) {
205+
auto ScopesAtLoc = Scopes.find({S->getFile(), Loc});
206+
// No scope found with the given location.
207+
if (ScopesAtLoc == Scopes.end())
208+
return nullptr;
209+
210+
// Prefer S over other scopes with the same location.
211+
if (ScopesAtLoc->second.contains(S))
212+
return S;
213+
214+
if (!ScopesAtLoc->second.empty())
215+
return *ScopesAtLoc->second.begin();
216+
217+
llvm_unreachable("Scopes must not have empty entries.");
218+
}
219+
};
220+
137221
DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) {
138222
if (!LocA || !LocB)
139223
return nullptr;
@@ -203,66 +287,29 @@ DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) {
203287
if (L1->getScope()->getSubprogram() != L2->getScope()->getSubprogram())
204288
return nullptr;
205289

206-
// Return the nearest common scope inside a subprogram.
207-
auto GetNearestCommonScope =
208-
[](const DILocation *L1,
209-
const DILocation *L2) -> std::pair<DIScope *, LineColumn> {
210-
DIScope *S1 = L1->getScope();
211-
DIScope *S2 = L2->getScope();
212-
213-
SmallMapVector<std::pair<DIFile *, LineColumn>,
214-
SmallSetVector<DIScope *, 8>, 8>
215-
Scopes;
216-
217-
// When matching DILexicalBlockFile's, ignore column numbers, so that
218-
// DILocation's having different columns within the same
219-
// DILexicalBlockFile will match.
220-
auto getLocForBlockFile = [](LineColumn L) {
221-
L.second = 0;
222-
return L;
223-
};
224-
225-
LineColumn Loc1(L1->getLine(), L1->getColumn());
226-
for (; S1; S1 = S1->getScope()) {
227-
Loc1 = getLocalScopeLocationOr(S1, getLocForBlockFile(Loc1));
228-
Scopes[{S1->getFile(), Loc1}].insert(S1);
229-
230-
if (isa<DISubprogram>(S1))
231-
break;
232-
}
233-
234-
LineColumn Loc2(L2->getLine(), L2->getColumn());
235-
for (; S2; S2 = S2->getScope()) {
236-
Loc2 = getLocalScopeLocationOr(S2, getLocForBlockFile(Loc2));
237-
238-
auto ScopesAtLoc = Scopes.find({S2->getFile(), Loc2});
239-
// No scope found with the same file, line and column as S2.
240-
if (ScopesAtLoc == Scopes.end())
241-
continue;
242-
243-
// Return S2 if it is L1's parent.
244-
if (ScopesAtLoc->second.contains(S2))
245-
return std::make_pair(S2, Loc2);
246-
247-
// Return any L1's parent with the same file, line and column as S2.
248-
if (!ScopesAtLoc->second.empty())
249-
return std::make_pair(*ScopesAtLoc->second.begin(), Loc2);
250-
251-
if (isa<DISubprogram>(S2))
252-
break;
253-
}
254-
255-
return std::make_pair(nullptr,
256-
LineColumn(L2->getLine(), L2->getColumn()));
257-
};
258-
259-
auto [Scope, ScopeLoc] = GetNearestCommonScope(L1, L2);
290+
// Find nearest common scope inside subprogram.
291+
DIScope *Scope = getNearestMatchingScope<EqualScopesMatcher>(L1, L2).first;
260292
assert(Scope && "No common scope in the same subprogram?");
261293

262-
// Use inclusion location if files are different.
294+
// Try using the nearest scope with common location if files are different.
263295
if (Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile()) {
264-
return DILocation::get(C, ScopeLoc.first, ScopeLoc.second, Scope,
265-
InlinedAt);
296+
auto [CommonLocScope, CommonLoc] =
297+
getNearestMatchingScope<ScopeLocationsMatcher>(L1, L2);
298+
299+
// If CommonLocScope is a DILexicalBlockBase, clone it and locate
300+
// a new scope inside the nearest common scope to preserve
301+
// lexical blocks structure.
302+
if (auto *LBB = dyn_cast<DILexicalBlockBase>(CommonLocScope);
303+
LBB && LBB != Scope)
304+
CommonLocScope = cloneAndReplaceParentScope(LBB, Scope);
305+
306+
Scope = CommonLocScope;
307+
308+
// If files are still different, assume that L1 and L2 were "included"
309+
// from CommonLoc. Use it as merged location.
310+
if (Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile())
311+
return DILocation::get(C, CommonLoc.first, CommonLoc.second,
312+
CommonLocScope, InlinedAt);
266313
}
267314

268315
bool SameLine = L1->getLine() == L2->getLine();
@@ -1179,10 +1226,8 @@ DILocalScope *DILocalScope::cloneScopeForSubprogram(
11791226
// cached result).
11801227
DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
11811228
for (DIScope *ScopeToUpdate : reverse(ScopeChain)) {
1182-
TempMDNode ClonedScope = ScopeToUpdate->clone();
1183-
cast<DILexicalBlockBase>(*ClonedScope).replaceScope(UpdatedScope);
1184-
UpdatedScope =
1185-
cast<DIScope>(MDNode::replaceWithUniqued(std::move(ClonedScope)));
1229+
UpdatedScope = cloneAndReplaceParentScope(
1230+
cast<DILexicalBlockBase>(ScopeToUpdate), UpdatedScope);
11861231
Cache[ScopeToUpdate] = UpdatedScope;
11871232
}
11881233

llvm/test/DebugInfo/AArch64/merge-nested-block-loc.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ if.end: ; preds = %if.else, %if.then
7474
; CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "foo", scope: [[FILE1:![0-9]+]], file: [[FILE1]], line: 1
7575
; CHECK: [[FILE1]] = !DIFile(filename: "1.c", directory: "")
7676
; CHECK: [[PHILOC]] = !DILocation(line: 42, column: 3, scope: [[LBF:![0-9]+]])
77-
; CHECK: [[LBF]] = !DILexicalBlockFile(scope: [[LB1:![0-9]+]], file: [[FILE2:![0-9]+]], discriminator: 0)
77+
; CHECK: [[LBF]] = !DILexicalBlockFile(scope: [[LB:![0-9]+]], file: [[FILE2:![0-9]+]], discriminator: 0)
7878
; CHECK: [[FILE2]] = !DIFile(filename: "m.c", directory: "")
79-
; CHECK: [[LB1]] = distinct !DILexicalBlock(scope: [[LB2:![0-9]+]], file: [[FILE1]], line: 3, column: 21)
80-
; CHECK: [[LB2]] = distinct !DILexicalBlock(scope: [[SP]], file: [[FILE1]], line: 3, column: 7)
79+
; CHECK: [[LB]] = distinct !DILexicalBlock(scope: [[SP]], file: [[FILE1]], line: 3, column: 7)

llvm/test/DebugInfo/AArch64/merge-nested-block-loc2.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ if.end: ; preds = %if.else, %do.body
125125
; CHECK: [[FILE_MAIN:![0-9]+]] = !DIFile(filename: "main.c"
126126
; CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "foo", scope: [[FILE_MAIN]], file: [[FILE_MAIN]], line: 1
127127
; CHECK: [[PHILOC]] = !DILocation(line: 300, column: 4, scope: [[BLOCK_Y:![0-9]+]])
128-
; CHECK-NEXT: [[BLOCK_Y]] = distinct !DILexicalBlock(scope: [[LBF_Y:![0-9]+]], file: [[FILE_Y:![0-9]+]], line: 300, column: 4)
128+
; CHECK-NEXT: [[BLOCK_Y]] = !DILexicalBlock(scope: [[BLOCK_MAIN:![0-9]+]], file: [[FILE_Y:![0-9]+]], line: 300, column: 4)
129129
; CHECK-NEXT: [[FILE_Y]] = !DIFile(filename: "y.c"
130-
; CHECK: [[LBF_Y]] = !DILexicalBlockFile(scope: [[BLOCK2_MAIN:![0-9]+]], file: [[FILE_Y]], discriminator: 0)
131-
; CHECK-NEXT: [[BLOCK2_MAIN]] = distinct !DILexicalBlock(scope: [[BLOCK1_MAIN:![0-9]+]], file: [[FILE_MAIN]], line: 3, column: 21)
132-
; CHECK: [[BLOCK1_MAIN]] = distinct !DILexicalBlock(scope: [[SP]], file: [[FILE_MAIN]], line: 3, column: 7)
130+
; CHECK: [[BLOCK_MAIN]] = distinct !DILexicalBlock(scope: [[SP]], file: [[FILE_MAIN]], line: 3, column: 7)

llvm/unittests/IR/MetadataTest.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,9 +1000,9 @@ TEST_F(DILocationTest, Merge) {
10001000
auto *A = DILocation::get(Context, 1, 6, LBF);
10011001
auto *B = DILocation::get(Context, 2, 7, LBF);
10021002
auto *M = DILocation::getMergedLocation(A, B);
1003-
EXPECT_EQ(3u, M->getLine());
1004-
EXPECT_EQ(4u, M->getColumn());
1005-
EXPECT_EQ(S, M->getScope());
1003+
EXPECT_EQ(0u, M->getLine());
1004+
EXPECT_EQ(0u, M->getColumn());
1005+
EXPECT_EQ(LBF, M->getScope());
10061006
}
10071007

10081008
{
@@ -1084,10 +1084,15 @@ TEST_F(DILocationTest, Merge) {
10841084
auto *LBF2 = DILexicalBlockFile::get(Context, LB2, F2, 0);
10851085
auto *A = DILocation::get(Context, 1, 6, LBF1);
10861086
auto *B = DILocation::get(Context, 1, 6, LBF2);
1087+
llvm::errs() << "Check\n";
10871088
auto *M = DILocation::getMergedLocation(A, B);
1089+
M->dump();
1090+
M->getScope()->dump();
1091+
LBF1->dump();
10881092
EXPECT_EQ(1u, M->getLine());
10891093
EXPECT_EQ(6u, M->getColumn());
1090-
EXPECT_EQ(LBF1, M->getScope());
1094+
EXPECT_EQ(LBF1->getFile(), M->getScope()->getFile());
1095+
EXPECT_EQ(N, M->getScope()->getScope());
10911096
}
10921097

10931098
{
@@ -1167,9 +1172,13 @@ TEST_F(DILocationTest, Merge) {
11671172
auto *A = DILocation::get(Context, 41, 7, Block2[0]);
11681173
auto *B = DILocation::get(Context, 51, 8, Block2[1]);
11691174
auto *M = DILocation::getMergedLocation(A, B);
1175+
auto *MScope = dyn_cast<DILexicalBlock>(M->getScope());
11701176
EXPECT_EQ(30u, M->getLine());
11711177
EXPECT_EQ(4u, M->getColumn());
1172-
EXPECT_EQ(Block1[0], M->getScope());
1178+
EXPECT_EQ(Block1[0]->getFile(), MScope->getFile());
1179+
EXPECT_EQ(Block1[0]->getLine(), MScope->getLine());
1180+
EXPECT_EQ(Block1[0]->getColumn(), MScope->getColumn());
1181+
EXPECT_EQ(LBCommon, MScope->getScope());
11731182
}
11741183

11751184
{

0 commit comments

Comments
 (0)