Skip to content

Commit a2b780b

Browse files
committed
[DebugInfo] Use zero linenos for debug intrinsics when promoting dbg.declare
In certain circumstances, optimizations pick line numbers from debug intrinsic instructions as the new location for altered instructions. This is problematic because the line number of a debugging intrinsic is meaningless (it doesn't produce any machine instruction), only the scope information is valid. The result can be the line number of a variable declaration "leaking" into real code from debugging intrinsics, making the line table un-necessarily jumpy, and potentially different with / without variable locations. Fix this by using zero line numbers when promoting dbg.declare intrinsics into dbg.values: this is safe for debug intrinsics as their line numbers are meaningless, and reduces the scope for damage / misleading stepping when optimizations pick locations from the wrong place. Differential Revision: https://reviews.llvm.org/D59272 llvm-svn: 360415
1 parent e357ca8 commit a2b780b

File tree

3 files changed

+142
-9
lines changed

3 files changed

+142
-9
lines changed

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,19 @@ static bool valueCoversEntireFragment(Type *ValTy, DbgVariableIntrinsic *DII) {
12881288
return false;
12891289
}
12901290

1291+
/// Produce a DebugLoc to use for each dbg.declare/inst pair that are promoted
1292+
/// to a dbg.value. Because no machine insts can come from debug intrinsics,
1293+
/// only the scope and inlinedAt is significant. Zero line numbers are used in
1294+
/// case this DebugLoc leaks into any adjacent instructions.
1295+
static DebugLoc getDebugValueLoc(DbgVariableIntrinsic *DII, Instruction *Src) {
1296+
// Original dbg.declare must have a location.
1297+
DebugLoc DeclareLoc = DII->getDebugLoc();
1298+
MDNode *Scope = DeclareLoc.getScope();
1299+
DILocation *InlinedAt = DeclareLoc.getInlinedAt();
1300+
// Produce an unknown location with the correct scope / inlinedAt fields.
1301+
return DebugLoc::get(0, 0, Scope, InlinedAt);
1302+
}
1303+
12911304
/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
12921305
/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
12931306
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
@@ -1298,6 +1311,8 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
12981311
auto *DIExpr = DII->getExpression();
12991312
Value *DV = SI->getValueOperand();
13001313

1314+
DebugLoc NewLoc = getDebugValueLoc(DII, SI);
1315+
13011316
if (!valueCoversEntireFragment(DV->getType(), DII)) {
13021317
// FIXME: If storing to a part of the variable described by the dbg.declare,
13031318
// then we want to insert a dbg.value for the corresponding fragment.
@@ -1308,14 +1323,12 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
13081323
// know nothing about the variable's content.
13091324
DV = UndefValue::get(DV->getType());
13101325
if (!LdStHasDebugValue(DIVar, DIExpr, SI))
1311-
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, DII->getDebugLoc(),
1312-
SI);
1326+
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, SI);
13131327
return;
13141328
}
13151329

13161330
if (!LdStHasDebugValue(DIVar, DIExpr, SI))
1317-
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, DII->getDebugLoc(),
1318-
SI);
1331+
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, SI);
13191332
}
13201333

13211334
/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
@@ -1338,12 +1351,14 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
13381351
return;
13391352
}
13401353

1354+
DebugLoc NewLoc = getDebugValueLoc(DII, nullptr);
1355+
13411356
// We are now tracking the loaded value instead of the address. In the
13421357
// future if multi-location support is added to the IR, it might be
13431358
// preferable to keep tracking both the loaded value and the original
13441359
// address in case the alloca can not be elided.
13451360
Instruction *DbgValue = Builder.insertDbgValueIntrinsic(
1346-
LI, DIVar, DIExpr, DII->getDebugLoc(), (Instruction *)nullptr);
1361+
LI, DIVar, DIExpr, NewLoc, (Instruction *)nullptr);
13471362
DbgValue->insertAfter(LI);
13481363
}
13491364

@@ -1370,12 +1385,13 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
13701385
BasicBlock *BB = APN->getParent();
13711386
auto InsertionPt = BB->getFirstInsertionPt();
13721387

1388+
DebugLoc NewLoc = getDebugValueLoc(DII, nullptr);
1389+
13731390
// The block may be a catchswitch block, which does not have a valid
13741391
// insertion point.
13751392
// FIXME: Insert dbg.value markers in the successors when appropriate.
13761393
if (InsertionPt != BB->end())
1377-
Builder.insertDbgValueIntrinsic(APN, DIVar, DIExpr, DII->getDebugLoc(),
1378-
&*InsertionPt);
1394+
Builder.insertDbgValueIntrinsic(APN, DIVar, DIExpr, NewLoc, &*InsertionPt);
13791395
}
13801396

13811397
/// Determine whether this alloca is either a VLA or an array.
@@ -1430,10 +1446,11 @@ bool llvm::LowerDbgDeclare(Function &F) {
14301446
// This is a call by-value or some other instruction that takes a
14311447
// pointer to the variable. Insert a *value* intrinsic that describes
14321448
// the variable by dereferencing the alloca.
1449+
DebugLoc NewLoc = getDebugValueLoc(DDI, nullptr);
14331450
auto *DerefExpr =
14341451
DIExpression::append(DDI->getExpression(), dwarf::DW_OP_deref);
1435-
DIB.insertDbgValueIntrinsic(AI, DDI->getVariable(), DerefExpr,
1436-
DDI->getDebugLoc(), CI);
1452+
DIB.insertDbgValueIntrinsic(AI, DDI->getVariable(), DerefExpr, NewLoc,
1453+
CI);
14371454
}
14381455
}
14391456
DDI->eraseFromParent();
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
; RUN: opt < %s -S -mem2reg -instcombine | FileCheck %s
2+
3+
; The '%bar' alloca will be promoted to an SSA register by mem2reg: test that
4+
; zero line number are assigned to the dbg.value intrinsics that are inserted
5+
; to represent changes in variable value. No machine instructions are
6+
; generated from these dbg.values so their lines are irrelevant, only the
7+
; scope and inlining information must be correct.
8+
9+
; In the second function here, LowerDbgDeclare will promote various variable
10+
; accesses of a dbg.declare'd alloca into dbg.values. Check that their line
11+
; numbers are sane too. (IR copied from DebugInfo/X86/formal_parameter.ll).
12+
13+
; CHECK-LABEL: define i32 @foo
14+
15+
; CHECK-LABEL: bb1:
16+
; CHECK-NEXT: %bar.0 = phi i32
17+
; CHECK-NEXT: dbg.value(metadata i32 %bar.0,{{.*}}), !dbg ![[UNKNOWN:[0-9]+]]
18+
; CHECK-NEXT: %totest = load
19+
; CHECK-NEXT: %add = add i32 %bar.0
20+
; CHECK-NEXT: dbg.value(metadata i32 %add, {{.*}}), !dbg ![[UNKNOWN]]
21+
; CHECK-NEXT: %cond = icmp ult
22+
; CHECK-NEXT: br i1 %cond, label %bb1, label %bb2
23+
;
24+
; CHECK-LABEL: bb2:
25+
; CHECK-NEXT: %toret = add i32 %bar.0, 3
26+
; CHECK-NEXT: dbg.value(metadata i32 %toret, {{.*}}), !dbg ![[UNKNOWN]]
27+
; CHECK-NEXT: ret i32 %toret
28+
29+
define i32 @foo(i32 *%bees, i32 *%output) {
30+
entry:
31+
%bar = alloca i32
32+
call void @llvm.dbg.declare(metadata i32 *%bar, metadata !7, metadata !DIExpression()), !dbg !6
33+
store i32 0, i32 *%bar
34+
br label %bb1, !dbg !6
35+
36+
bb1:
37+
%totest = load i32, i32 *%bees, !dbg !8
38+
%load1 = load i32, i32 *%bar, !dbg !9
39+
%add = add i32 %load1, 1, !dbg !10
40+
store i32 %add, i32 *%bar, !dbg !11
41+
%toret = add i32 %add, 2, !dbg !12
42+
%cond = icmp ult i32 %totest, %load1, !dbg !13
43+
br i1 %cond, label %bb1, label %bb2, !dbg !14
44+
45+
bb2:
46+
store i32 %toret, i32 *%bar, !dbg !16
47+
ret i32 %toret
48+
}
49+
50+
; In the following, the dbg.value created for the store should get the stores
51+
; line number, the other dbg.values should be unknown.
52+
; CHECK-LABEL: define void @bar
53+
;
54+
; CHECK: dbg.value(metadata i32 %map, metadata ![[MAPVAR:[0-9]+]],{{.*}}),
55+
; CHECK-SAME: !dbg ![[UNKNOWN2:[0-9]+]]
56+
; CHECK-NEXT: store
57+
; CHECK-NEXT: dbg.value(metadata i32* %map.addr, metadata ![[MAPVAR]],
58+
; CHECK-SAME: metadata !DIExpression(DW_OP_deref)),
59+
; CHECK-SAME: !dbg ![[UNKNOWN2]]
60+
; CHECK-NEXT: call
61+
; CHECK-NEXT: load
62+
; CHECK-NEXT: dbg.value(metadata i32 %{{[0-9]+}}, metadata ![[MAPVAR]],
63+
; CHECK-SAME: !dbg ![[UNKNOWN2]]
64+
65+
define void @bar(i32 %map) !dbg !20 {
66+
entry:
67+
%map.addr = alloca i32, align 4
68+
store i32 %map, i32* %map.addr, align 4, !dbg !27
69+
call void @llvm.dbg.declare(metadata i32* %map.addr, metadata !21, metadata !DIExpression()), !dbg !22
70+
%call = call i32 (i32*, ...) bitcast (i32 (...)* @lookup to i32 (i32*, ...)*)(i32* %map.addr), !dbg !23
71+
%0 = load i32, i32* %map.addr, align 4, !dbg !24
72+
%call1 = call i32 (i32, ...) bitcast (i32 (...)* @verify to i32 (i32, ...)*)(i32 %0), !dbg !25
73+
ret void, !dbg !26
74+
}
75+
76+
declare void @llvm.dbg.value(metadata, metadata, metadata)
77+
declare void @llvm.dbg.declare(metadata, metadata, metadata)
78+
declare i32 @verify(...)
79+
declare i32 @lookup(...)
80+
81+
; CHECK: ![[SUBPROG:[0-9]+]] = distinct !DISubprogram(name: "nope",
82+
; CHECK: ![[UNKNOWN]] = !DILocation(line: 0, scope: ![[SUBPROG]])
83+
84+
; CHECK: ![[SUBPROG2:[0-9]+]] = distinct !DISubprogram(name: "thin",
85+
; CHECK: ![[MAPVAR]] = !DILocalVariable(name: "floogie",
86+
; CHECK: ![[UNKNOWN2]] = !DILocation(line: 0
87+
88+
!llvm.module.flags = !{!4}
89+
!llvm.dbg.cu = !{!2}
90+
!1 = !DILocalVariable(name: "bees", scope: !5, type: null)
91+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "beards", isOptimized: true, runtimeVersion: 4, emissionKind: FullDebug)
92+
!3 = !DIFile(filename: "bees.cpp", directory: "")
93+
!4 = !{i32 2, !"Debug Info Version", i32 3}
94+
!5 = distinct !DISubprogram(name: "nope", scope: !3, file: !3, line: 1, unit: !2)
95+
!6 = !DILocation(line: 1, scope: !5)
96+
!7 = !DILocalVariable(name: "flannel", scope: !5, type: null)
97+
!8 = !DILocation(line: 2, scope: !5)
98+
!9 = !DILocation(line: 3, scope: !5)
99+
!10 = !DILocation(line: 4, scope: !5)
100+
!11 = !DILocation(line: 5, scope: !5)
101+
!12 = !DILocation(line: 6, scope: !5)
102+
!13 = !DILocation(line: 7, scope: !5)
103+
!14 = !DILocation(line: 8, scope: !5)
104+
!15 = distinct !DISubprogram(name: "wat", scope: !2, file: !3, line: 10, unit: !2)
105+
!16 = !DILocation(line: 9, scope: !15, inlinedAt: !14)
106+
!20 = distinct !DISubprogram(name: "thin", scope: !3, file: !3, line: 20, unit: !2)
107+
!21 = !DILocalVariable(name: "floogie", scope: !20, type: null)
108+
!22 = !DILocation(line: 21, scope: !20)
109+
!23 = !DILocation(line: 22, scope: !20)
110+
!24 = !DILocation(line: 23, scope: !20)
111+
!25 = !DILocation(line: 24, scope: !20)
112+
!26 = !DILocation(line: 25, scope: !20)
113+
!27 = !DILocation(line: 20, scope: !20)

llvm/test/DebugInfo/X86/formal_parameter.ll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ entry:
4141
ret void, !dbg !22
4242
}
4343

44+
; LOWERING: ![[SCOPE:[0-9]+]] = distinct !DISubprogram(name: "foo",
45+
; LOWERING: ![[LOC]] = !DILocation(line: 0, scope: ![[SCOPE]]
46+
4447
; Function Attrs: nounwind readnone
4548
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
4649

0 commit comments

Comments
 (0)