Skip to content

Commit 9f51ebf

Browse files
committed
Next iteration of the algorithm
1 parent 1004659 commit 9f51ebf

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
@@ -125,6 +125,14 @@ DILocation *DILocation::getMergedLocations(ArrayRef<DILocation *> Locs) {
125125
return Merged;
126126
}
127127

128+
static DILexicalBlockBase *cloneAndReplaceParentScope(DILexicalBlockBase *LBB,
129+
DIScope *NewParent) {
130+
TempMDNode ClonedScope = LBB->clone();
131+
cast<DILexicalBlockBase>(*ClonedScope).replaceScope(NewParent);
132+
return cast<DILexicalBlockBase>(
133+
MDNode::replaceWithUniqued(std::move(ClonedScope)));
134+
}
135+
128136
using LineColumn = std::pair<unsigned /* Line */, unsigned /* Column */>;
129137

130138
/// Returns the location of DILocalScope, if present, or a default value.
@@ -141,6 +149,82 @@ static LineColumn getLocalScopeLocationOr(DIScope *S, LineColumn Default) {
141149
llvm_unreachable("Unhandled type of DILocalScope.");
142150
}
143151

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

227-
// Return the nearest common scope inside a subprogram.
228-
auto GetNearestCommonScope =
229-
[](const DILocation *L1,
230-
const DILocation *L2) -> std::pair<DIScope *, LineColumn> {
231-
DIScope *S1 = L1->getScope();
232-
DIScope *S2 = L2->getScope();
233-
234-
SmallMapVector<std::pair<DIFile *, LineColumn>,
235-
SmallSetVector<DIScope *, 8>, 8>
236-
Scopes;
237-
238-
// When matching DILexicalBlockFile's, ignore column numbers, so that
239-
// DILocation's having different columns within the same
240-
// DILexicalBlockFile will match.
241-
auto getLocForBlockFile = [](LineColumn L) {
242-
L.second = 0;
243-
return L;
244-
};
245-
246-
LineColumn Loc1(L1->getLine(), L1->getColumn());
247-
for (; S1; S1 = S1->getScope()) {
248-
Loc1 = getLocalScopeLocationOr(S1, getLocForBlockFile(Loc1));
249-
Scopes[{S1->getFile(), Loc1}].insert(S1);
250-
251-
if (isa<DISubprogram>(S1))
252-
break;
253-
}
254-
255-
LineColumn Loc2(L2->getLine(), L2->getColumn());
256-
for (; S2; S2 = S2->getScope()) {
257-
Loc2 = getLocalScopeLocationOr(S2, getLocForBlockFile(Loc2));
258-
259-
auto ScopesAtLoc = Scopes.find({S2->getFile(), Loc2});
260-
// No scope found with the same file, line and column as S2.
261-
if (ScopesAtLoc == Scopes.end())
262-
continue;
263-
264-
// Return S2 if it is L1's parent.
265-
if (ScopesAtLoc->second.contains(S2))
266-
return std::make_pair(S2, Loc2);
267-
268-
// Return any L1's parent with the same file, line and column as S2.
269-
if (!ScopesAtLoc->second.empty())
270-
return std::make_pair(*ScopesAtLoc->second.begin(), Loc2);
271-
272-
if (isa<DISubprogram>(S2))
273-
break;
274-
}
275-
276-
return std::make_pair(nullptr,
277-
LineColumn(L2->getLine(), L2->getColumn()));
278-
};
279-
280-
auto [Scope, ScopeLoc] = GetNearestCommonScope(L1, L2);
311+
// Find nearest common scope inside subprogram.
312+
DIScope *Scope = getNearestMatchingScope<EqualScopesMatcher>(L1, L2).first;
281313
assert(Scope && "No common scope in the same subprogram?");
282314

283-
// Use inclusion location if files are different.
315+
// Try using the nearest scope with common location if files are different.
284316
if (Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile()) {
285-
return DILocation::get(C, ScopeLoc.first, ScopeLoc.second, Scope,
286-
InlinedAt);
317+
auto [CommonLocScope, CommonLoc] =
318+
getNearestMatchingScope<ScopeLocationsMatcher>(L1, L2);
319+
320+
// If CommonLocScope is a DILexicalBlockBase, clone it and locate
321+
// a new scope inside the nearest common scope to preserve
322+
// lexical blocks structure.
323+
if (auto *LBB = dyn_cast<DILexicalBlockBase>(CommonLocScope);
324+
LBB && LBB != Scope)
325+
CommonLocScope = cloneAndReplaceParentScope(LBB, Scope);
326+
327+
Scope = CommonLocScope;
328+
329+
// If files are still different, assume that L1 and L2 were "included"
330+
// from CommonLoc. Use it as merged location.
331+
if (Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile())
332+
return DILocation::get(C, CommonLoc.first, CommonLoc.second,
333+
CommonLocScope, InlinedAt);
287334
}
288335

289336
bool SameLine = L1->getLine() == L2->getLine();
@@ -1243,10 +1290,8 @@ DILocalScope *DILocalScope::cloneScopeForSubprogram(
12431290
// cached result).
12441291
DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
12451292
for (DIScope *ScopeToUpdate : reverse(ScopeChain)) {
1246-
TempMDNode ClonedScope = ScopeToUpdate->clone();
1247-
cast<DILexicalBlockBase>(*ClonedScope).replaceScope(UpdatedScope);
1248-
UpdatedScope =
1249-
cast<DIScope>(MDNode::replaceWithUniqued(std::move(ClonedScope)));
1293+
UpdatedScope = cloneAndReplaceParentScope(
1294+
cast<DILexicalBlockBase>(ScopeToUpdate), UpdatedScope);
12501295
Cache[ScopeToUpdate] = UpdatedScope;
12511296
}
12521297

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)