Skip to content

Commit d6f0fe8

Browse files
jmmartinezzhang2amd
authored andcommitted
[DebugInfo] getMergedLocation: Maintain the line number if they match
getMergedLocation returns a 'line 0' DILocaiton if the two locations being merged don't perfecly match, even if they are in the same line but a different column. This commit adds support to keep the line number if it matches (but only the column differs). The merged column number is the leftmost between the two. Reviewed By: dblaikie, orlando Differential Revision: https://reviews.llvm.org/D135166 Change-Id: Ia3be858f1587722d8cb9ab7046f869ea2063424f
1 parent 4fb628b commit d6f0fe8

File tree

4 files changed

+195
-56
lines changed

4 files changed

+195
-56
lines changed

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,18 +1737,18 @@ class DILocation : public MDNode {
17371737

17381738
/// When two instructions are combined into a single instruction we also
17391739
/// need to combine the original locations into a single location.
1740+
/// When the locations are the same we can use either location.
1741+
/// When they differ, we need a third location which is distinct from either.
1742+
/// If they share a common scope, use this scope and compare the line/column
1743+
/// pair of the locations with the common scope:
1744+
/// * if both match, keep the line and column;
1745+
/// * if only the line number matches, keep the line and set the column as 0;
1746+
/// * otherwise set line and column as 0.
1747+
/// If they do not share a common scope the location is ambiguous and can't be
1748+
/// represented in a line entry. In this case, set line and column as 0 and
1749+
/// use the scope of any location.
17401750
///
1741-
/// When the locations are the same we can use either location. When they
1742-
/// differ, we need a third location which is distinct from either. If they
1743-
/// have the same file/line but have a different discriminator we could
1744-
/// create a location with a new discriminator. If they are from different
1745-
/// files/lines the location is ambiguous and can't be represented in a line
1746-
/// entry. In this case, if \p GenerateLocation is true, we will set the
1747-
/// merged debug location as line 0 of the nearest common scope where the two
1748-
/// locations are inlined from.
1749-
///
1750-
/// \p GenerateLocation: Whether the merged location can be generated when
1751-
/// \p LocA and \p LocB differ.
1751+
/// \p LocA \p LocB: The locations to be merged.
17521752
static const DILocation *getMergedLocation(const DILocation *LocA,
17531753
const DILocation *LocB);
17541754

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,34 +108,64 @@ const DILocation *DILocation::getMergedLocation(const DILocation *LocA,
108108
if (LocA == LocB)
109109
return LocA;
110110

111-
SmallSet<std::pair<DIScope *, DILocation *>, 5> Locations;
111+
LLVMContext &C = LocA->getContext();
112+
SmallDenseMap<std::pair<DILocalScope *, DILocation *>,
113+
std::pair<unsigned, unsigned>, 4>
114+
Locations;
115+
112116
DIScope *S = LocA->getScope();
113117
DILocation *L = LocA->getInlinedAt();
114-
while (S) {
115-
Locations.insert(std::make_pair(S, L));
118+
unsigned Line = LocA->getLine();
119+
unsigned Col = LocA->getColumn();
120+
121+
// Walk from the current source locaiton until the file scope;
122+
// then, do the same for the inlined-at locations.
123+
auto AdvanceToParentLoc = [&S, &L, &Line, &Col]() {
116124
S = S->getScope();
117125
if (!S && L) {
126+
Line = L->getLine();
127+
Col = L->getColumn();
118128
S = L->getScope();
119129
L = L->getInlinedAt();
120130
}
131+
};
132+
133+
while (S) {
134+
if (auto *LS = dyn_cast<DILocalScope>(S))
135+
Locations.try_emplace(std::make_pair(LS, L), std::make_pair(Line, Col));
136+
AdvanceToParentLoc();
121137
}
138+
139+
// Walk the source locations of LocB until a match with LocA is found.
122140
S = LocB->getScope();
123141
L = LocB->getInlinedAt();
142+
Line = LocB->getLine();
143+
Col = LocB->getColumn();
124144
while (S) {
125-
if (Locations.count(std::make_pair(S, L)))
126-
break;
127-
S = S->getScope();
128-
if (!S && L) {
129-
S = L->getScope();
130-
L = L->getInlinedAt();
145+
if (auto *LS = dyn_cast<DILocalScope>(S)) {
146+
auto MatchLoc = Locations.find(std::make_pair(LS, L));
147+
if (MatchLoc != Locations.end()) {
148+
// If the lines match, keep the line, but set the column to '0'
149+
// If the lines don't match, pick a "line 0" location but keep
150+
// the current scope and inlined-at.
151+
bool SameLine = Line == MatchLoc->second.first;
152+
bool SameCol = Col == MatchLoc->second.second;
153+
Line = SameLine ? Line : 0;
154+
Col = SameLine && SameCol ? Col : 0;
155+
break;
156+
}
131157
}
158+
AdvanceToParentLoc();
132159
}
133160

134-
// If the two locations are irreconsilable, just pick one. This is misleading,
135-
// but on the other hand, it's a "line 0" location.
136-
if (!S || !isa<DILocalScope>(S))
161+
if (!S) {
162+
// If the two locations are irreconsilable, pick any scope,
163+
// and return a "line 0" location.
164+
Line = Col = 0;
137165
S = LocA->getScope();
138-
return DILocation::get(LocA->getContext(), 0, 0, S, L);
166+
}
167+
168+
return DILocation::get(C, Line, Col, S, L);
139169
}
140170

141171
Optional<unsigned> DILocation::encodeDiscriminator(unsigned BD, unsigned DF,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; RUN: opt -simplifycfg -S < %s | FileCheck %s
2+
;
3+
; Simplified from the following code:
4+
; int foo() {
5+
; if(c) { return a; } else { return b; }
6+
; }
7+
define i32 @foo(i32 %c, i32 %a, i32 %b) !dbg !4 {
8+
; CHECK: define i32 @foo({{.*}}) !dbg [[FOO_SUBPROGRAM:![0-9]+]]
9+
; CHECK-NEXT: entry:
10+
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C:%.*]], 0, !dbg [[DBG_CMP:![0-9]+]]
11+
; CHECK-NEXT: [[A_B:%.*]] = select i1 [[TOBOOL]], i32 [[A:%.*]], i32 [[B:%.*]]
12+
; CHECK-NEXT: ret i32 [[A_B]], !dbg [[DBG_RET:![0-9]+]]
13+
; CHECK: [[DBG_CMP]] = !DILocation(line: 2, column: 1, scope: [[FOO_SUBPROGRAM]])
14+
; CHECK: [[DBG_RET]] = !DILocation(line: 4, scope: [[FOO_SUBPROGRAM]])
15+
entry:
16+
%tobool = icmp ne i32 %c, 0, !dbg !7
17+
br i1 %tobool, label %cond.true, label %cond.false, !dbg !8
18+
19+
cond.true: ; preds = %entry
20+
ret i32 %a, !dbg !9
21+
22+
cond.false: ; preds = %entry
23+
ret i32 %b, !dbg !10
24+
}
25+
26+
!llvm.dbg.cu = !{!0}
27+
!llvm.module.flags = !{!2, !3}
28+
29+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 16.0.0)", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None)
30+
!1 = !DIFile(filename: "test.c", directory: "/")
31+
!2 = !{i32 7, !"Dwarf Version", i32 5}
32+
!3 = !{i32 2, !"Debug Info Version", i32 3}
33+
!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !5, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !6)
34+
!5 = !DISubroutineType(types: !6)
35+
!6 = !{}
36+
!7 = !DILocation(line: 2, column: 1, scope: !4)
37+
!8 = !DILocation(line: 3, column: 1, scope: !4)
38+
!9 = !DILocation(line: 4, column: 1, scope: !4)
39+
!10 = !DILocation(line: 4, column: 2, scope: !4)

llvm/unittests/IR/MetadataTest.cpp

Lines changed: 102 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -917,31 +917,6 @@ TEST_F(MDNodeTest, deleteTemporaryWithTrackingRef) {
917917

918918
typedef MetadataTest DILocationTest;
919919

920-
TEST_F(DILocationTest, Overflow) {
921-
DISubprogram *N = getSubprogram();
922-
{
923-
DILocation *L = DILocation::get(Context, 2, 7, N);
924-
EXPECT_EQ(2u, L->getLine());
925-
EXPECT_EQ(7u, L->getColumn());
926-
}
927-
unsigned U16 = 1u << 16;
928-
{
929-
DILocation *L = DILocation::get(Context, UINT32_MAX, U16 - 1, N);
930-
EXPECT_EQ(UINT32_MAX, L->getLine());
931-
EXPECT_EQ(U16 - 1, L->getColumn());
932-
}
933-
{
934-
DILocation *L = DILocation::get(Context, UINT32_MAX, U16, N);
935-
EXPECT_EQ(UINT32_MAX, L->getLine());
936-
EXPECT_EQ(0u, L->getColumn());
937-
}
938-
{
939-
DILocation *L = DILocation::get(Context, UINT32_MAX, U16 + 1, N);
940-
EXPECT_EQ(UINT32_MAX, L->getLine());
941-
EXPECT_EQ(0u, L->getColumn());
942-
}
943-
}
944-
945920
TEST_F(DILocationTest, Merge) {
946921
DISubprogram *N = getSubprogram();
947922
DIScope *S = DILexicalBlock::get(Context, N, getFile(), 3, 4);
@@ -961,11 +936,24 @@ TEST_F(DILocationTest, Merge) {
961936
auto *A = DILocation::get(Context, 2, 7, N);
962937
auto *B = DILocation::get(Context, 2, 7, S);
963938
auto *M = DILocation::getMergedLocation(A, B);
964-
EXPECT_EQ(0u, M->getLine()); // FIXME: Should this be 2?
965-
EXPECT_EQ(0u, M->getColumn()); // FIXME: Should this be 7?
939+
EXPECT_EQ(2u, M->getLine());
940+
EXPECT_EQ(7u, M->getColumn());
966941
EXPECT_EQ(N, M->getScope());
967942
}
968943

944+
{
945+
// Same line, different column.
946+
auto *A = DILocation::get(Context, 2, 7, N);
947+
auto *B = DILocation::get(Context, 2, 10, S);
948+
auto *M0 = DILocation::getMergedLocation(A, B);
949+
auto *M1 = DILocation::getMergedLocation(B, A);
950+
for (auto *M : {M0, M1}) {
951+
EXPECT_EQ(2u, M->getLine());
952+
EXPECT_EQ(0u, M->getColumn());
953+
EXPECT_EQ(N, M->getScope());
954+
}
955+
}
956+
969957
{
970958
// Different lines, same scopes.
971959
auto *A = DILocation::get(Context, 1, 6, N);
@@ -998,15 +986,36 @@ TEST_F(DILocationTest, Merge) {
998986

999987
auto *I = DILocation::get(Context, 2, 7, N);
1000988
auto *A = DILocation::get(Context, 1, 6, SP1, I);
1001-
auto *B = DILocation::get(Context, 2, 7, SP2, I);
989+
auto *B = DILocation::get(Context, 3, 8, SP2, I);
1002990
auto *M = DILocation::getMergedLocation(A, B);
1003-
EXPECT_EQ(0u, M->getLine());
991+
EXPECT_EQ(2u, M->getLine());
992+
EXPECT_EQ(7u, M->getColumn());
993+
EXPECT_EQ(N, M->getScope());
994+
EXPECT_EQ(nullptr, M->getInlinedAt());
995+
}
996+
997+
{
998+
// Different function, inlined-at same line, but different column.
999+
auto *F = getFile();
1000+
auto *SP1 = DISubprogram::getDistinct(Context, F, "a", "a", F, 0, nullptr,
1001+
0, nullptr, 0, 0, DINode::FlagZero,
1002+
DISubprogram::SPFlagZero, nullptr);
1003+
auto *SP2 = DISubprogram::getDistinct(Context, F, "b", "b", F, 0, nullptr,
1004+
0, nullptr, 0, 0, DINode::FlagZero,
1005+
DISubprogram::SPFlagZero, nullptr);
1006+
1007+
auto *IA = DILocation::get(Context, 2, 7, N);
1008+
auto *IB = DILocation::get(Context, 2, 8, N);
1009+
auto *A = DILocation::get(Context, 1, 6, SP1, IA);
1010+
auto *B = DILocation::get(Context, 3, 8, SP2, IB);
1011+
auto *M = DILocation::getMergedLocation(A, B);
1012+
EXPECT_EQ(2u, M->getLine());
10041013
EXPECT_EQ(0u, M->getColumn());
1005-
EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
1006-
EXPECT_EQ(I, M->getInlinedAt());
1014+
EXPECT_EQ(N, M->getScope());
1015+
EXPECT_EQ(nullptr, M->getInlinedAt());
10071016
}
10081017

1009-
{
1018+
{
10101019
// Completely different.
10111020
auto *I = DILocation::get(Context, 2, 7, N);
10121021
auto *A = DILocation::get(Context, 1, 6, S, I);
@@ -1018,6 +1027,67 @@ TEST_F(DILocationTest, Merge) {
10181027
EXPECT_EQ(S, M->getScope());
10191028
EXPECT_EQ(nullptr, M->getInlinedAt());
10201029
}
1030+
1031+
// Two locations, same line/column different file, inlined at the same place.
1032+
{
1033+
auto *FA = getFile();
1034+
auto *FB = getFile();
1035+
auto *FI = getFile();
1036+
1037+
auto *SPA = DISubprogram::getDistinct(Context, FA, "a", "a", FA, 0, nullptr,
1038+
0, nullptr, 0, 0, DINode::FlagZero,
1039+
DISubprogram::SPFlagZero, nullptr);
1040+
1041+
auto *SPB = DISubprogram::getDistinct(Context, FB, "b", "b", FB, 0, nullptr,
1042+
0, nullptr, 0, 0, DINode::FlagZero,
1043+
DISubprogram::SPFlagZero, nullptr);
1044+
1045+
auto *SPI = DISubprogram::getDistinct(Context, FI, "i", "i", FI, 0, nullptr,
1046+
0, nullptr, 0, 0, DINode::FlagZero,
1047+
DISubprogram::SPFlagZero, nullptr);
1048+
1049+
auto *I = DILocation::get(Context, 3, 8, SPI);
1050+
auto *A = DILocation::get(Context, 2, 7, SPA, I);
1051+
auto *B = DILocation::get(Context, 2, 7, SPB, I);
1052+
auto *M = DILocation::getMergedLocation(A, B);
1053+
EXPECT_EQ(3u, M->getLine());
1054+
EXPECT_EQ(8u, M->getColumn());
1055+
EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
1056+
EXPECT_EQ(SPI, M->getScope());
1057+
EXPECT_EQ(nullptr, M->getInlinedAt());
1058+
}
1059+
1060+
// Two locations, same line/column different file, one location with 2 scopes,
1061+
// inlined at the same place.
1062+
{
1063+
auto *FA = getFile();
1064+
auto *FB = getFile();
1065+
auto *FI = getFile();
1066+
1067+
auto *SPA = DISubprogram::getDistinct(Context, FA, "a", "a", FA, 0, nullptr,
1068+
0, nullptr, 0, 0, DINode::FlagZero,
1069+
DISubprogram::SPFlagZero, nullptr);
1070+
1071+
auto *SPB = DISubprogram::getDistinct(Context, FB, "b", "b", FB, 0, nullptr,
1072+
0, nullptr, 0, 0, DINode::FlagZero,
1073+
DISubprogram::SPFlagZero, nullptr);
1074+
1075+
auto *SPI = DISubprogram::getDistinct(Context, FI, "i", "i", FI, 0, nullptr,
1076+
0, nullptr, 0, 0, DINode::FlagZero,
1077+
DISubprogram::SPFlagZero, nullptr);
1078+
1079+
auto *SPAScope = DILexicalBlock::getDistinct(Context, SPA, FA, 4, 9);
1080+
1081+
auto *I = DILocation::get(Context, 3, 8, SPI);
1082+
auto *A = DILocation::get(Context, 2, 7, SPAScope, I);
1083+
auto *B = DILocation::get(Context, 2, 7, SPB, I);
1084+
auto *M = DILocation::getMergedLocation(A, B);
1085+
EXPECT_EQ(3u, M->getLine());
1086+
EXPECT_EQ(8u, M->getColumn());
1087+
EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
1088+
EXPECT_EQ(SPI, M->getScope());
1089+
EXPECT_EQ(nullptr, M->getInlinedAt());
1090+
}
10211091
}
10221092

10231093
TEST_F(DILocationTest, getDistinct) {

0 commit comments

Comments
 (0)