Skip to content

Commit 6f029da

Browse files
alokkrsharmaSouraVX
authored andcommitted
[DebugInfo] Avoid generating duplicate llvm.dbg.value
Summary: This is to avoid generating duplicate llvm.dbg.value instrinsic if it already exists after the Instruction. Before inserting llvm.dbg.value instruction, LLVM checks if the same instruction is already present before the instruction to avoid duplicates. Currently it misses to check if it already exists after the instruction. flang generates IR like this. %4 = load i32, i32* %i1_311, align 4, !dbg !42 call void @llvm.dbg.value(metadata i32 %4, metadata !35, metadata !DIExpression()), !dbg !33 When this IR is processed in llvm, it ends up inserting duplicates. %4 = load i32, i32* %i1_311, align 4, !dbg !42 call void @llvm.dbg.value(metadata i32 %4, metadata !35, metadata !DIExpression()), !dbg !33 call void @llvm.dbg.value(metadata i32 %4, metadata !35, metadata !DIExpression()), !dbg !33 We have now updated LdStHasDebugValue to include the cases when instruction is already followed by same dbg.value instruction we intend to insert. Now, Definition and usage of function LdStHasDebugValue are deleted. RemoveRedundantDbgInstrs is called for the cleanup of duplicate dbg.value's Testing: Added unit test for validation check-llvm check-debuginfo (the debug info integration tests) Reviewers: aprantl, probinson, dblaikie, jmorse, jini.susan.george SouraVX, awpandey, dstenb, vsk Reviewed By: aprantl, jmorse, dstenb, vsk Differential Revision: https://reviews.llvm.org/D74030
1 parent 57397eb commit 6f029da

File tree

3 files changed

+201
-27
lines changed

3 files changed

+201
-27
lines changed

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#include "llvm/Support/ErrorHandling.h"
7676
#include "llvm/Support/KnownBits.h"
7777
#include "llvm/Support/raw_ostream.h"
78+
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
7879
#include "llvm/Transforms/Utils/ValueMapper.h"
7980
#include <algorithm>
8081
#include <cassert>
@@ -1230,24 +1231,6 @@ unsigned llvm::getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign,
12301231
/// Dbg Intrinsic utilities
12311232
///
12321233

1233-
/// See if there is a dbg.value intrinsic for DIVar before I.
1234-
static bool LdStHasDebugValue(DILocalVariable *DIVar, DIExpression *DIExpr,
1235-
Instruction *I) {
1236-
// Since we can't guarantee that the original dbg.declare instrinsic
1237-
// is removed by LowerDbgDeclare(), we need to make sure that we are
1238-
// not inserting the same dbg.value intrinsic over and over.
1239-
BasicBlock::InstListType::iterator PrevI(I);
1240-
if (PrevI != I->getParent()->getInstList().begin()) {
1241-
--PrevI;
1242-
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(PrevI))
1243-
if (DVI->getValue() == I->getOperand(0) &&
1244-
DVI->getVariable() == DIVar &&
1245-
DVI->getExpression() == DIExpr)
1246-
return true;
1247-
}
1248-
return false;
1249-
}
1250-
12511234
/// See if there is a dbg.value intrinsic for DIVar for the PHI node.
12521235
static bool PhiHasDebugValue(DILocalVariable *DIVar,
12531236
DIExpression *DIExpr,
@@ -1324,13 +1307,11 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
13241307
// know which part) we insert an dbg.value instrinsic to indicate that we
13251308
// know nothing about the variable's content.
13261309
DV = UndefValue::get(DV->getType());
1327-
if (!LdStHasDebugValue(DIVar, DIExpr, SI))
1328-
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, SI);
1310+
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, SI);
13291311
return;
13301312
}
13311313

1332-
if (!LdStHasDebugValue(DIVar, DIExpr, SI))
1333-
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, SI);
1314+
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, SI);
13341315
}
13351316

13361317
/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
@@ -1341,9 +1322,6 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
13411322
auto *DIExpr = DII->getExpression();
13421323
assert(DIVar && "Missing variable");
13431324

1344-
if (LdStHasDebugValue(DIVar, DIExpr, LI))
1345-
return;
1346-
13471325
if (!valueCoversEntireFragment(LI->getType(), DII)) {
13481326
// FIXME: If only referring to a part of the variable described by the
13491327
// dbg.declare, then we want to insert a dbg.value for the corresponding
@@ -1410,6 +1388,7 @@ static bool isStructure(AllocaInst *AI) {
14101388
/// LowerDbgDeclare - Lowers llvm.dbg.declare intrinsics into appropriate set
14111389
/// of llvm.dbg.value intrinsics.
14121390
bool llvm::LowerDbgDeclare(Function &F) {
1391+
bool Changed = false;
14131392
DIBuilder DIB(*F.getParent(), /*AllowUnresolved*/ false);
14141393
SmallVector<DbgDeclareInst *, 4> Dbgs;
14151394
for (auto &FI : F)
@@ -1418,7 +1397,7 @@ bool llvm::LowerDbgDeclare(Function &F) {
14181397
Dbgs.push_back(DDI);
14191398

14201399
if (Dbgs.empty())
1421-
return false;
1400+
return Changed;
14221401

14231402
for (auto &I : Dbgs) {
14241403
DbgDeclareInst *DDI = I;
@@ -1471,8 +1450,14 @@ bool llvm::LowerDbgDeclare(Function &F) {
14711450
}
14721451
}
14731452
DDI->eraseFromParent();
1453+
Changed = true;
14741454
}
1475-
return true;
1455+
1456+
if (Changed)
1457+
for (BasicBlock &BB : F)
1458+
RemoveRedundantDbgInstrs(&BB);
1459+
1460+
return Changed;
14761461
}
14771462

14781463
/// Propagate dbg.value intrinsics through the newly inserted PHIs.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
; RUN: opt -instcombine -S -o - < %s | FileCheck %s
2+
3+
; CHECK-LABEL: %4 = load i32, i32* %i1_311
4+
; CHECK: call void @llvm.dbg.value(metadata i32 %4
5+
; Next instruction should not be duplicate dbg.value intrinsic.
6+
; CHECK-NEXT: @f90io_sc_i_ldw
7+
8+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9+
;program main
10+
;integer :: res
11+
; res = mfun()
12+
; print *, res
13+
;contains
14+
; function mfun()
15+
; integer :: i1
16+
; i1 = 5
17+
; mfun = fun(i1)
18+
; write (*,*) i1
19+
; end function
20+
; function fun(a)
21+
; integer, intent (in) :: a
22+
; fun = a
23+
; end function
24+
;end program main
25+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26+
27+
; ModuleID = 'duplicate_dbgvalue.ll'
28+
source_filename = "duplicate_dbgvalue.ll"
29+
target datalayout = "e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
30+
target triple = "x86_64-unknown-linux-gnu"
31+
32+
%struct.BSS1 = type <{ [4 x i8] }>
33+
34+
@.BSS1 = internal unnamed_addr global %struct.BSS1 zeroinitializer, align 32, !dbg !0
35+
@.C303_MAIN_ = internal constant i32 6
36+
@.C300_MAIN_ = internal constant [22 x i8] c"duplicate_dbgvalue.f90"
37+
@.C302_MAIN_ = internal constant i32 4
38+
@.C283_MAIN_ = internal constant i32 0
39+
@.C283_main_mfun = internal constant i32 0
40+
@.C302_main_mfun = internal constant i32 6
41+
@.C300_main_mfun = internal constant [22 x i8] c"duplicate_dbgvalue.f90"
42+
@.C313_main_mfun = internal constant i32 10
43+
44+
define void @MAIN_() local_unnamed_addr !dbg !2 {
45+
L.entry:
46+
call void (i8*, ...) bitcast (void (...)* @fort_init to void (i8*, ...)*)(i8* bitcast (i32* @.C283_MAIN_ to i8*)), !dbg !16
47+
%0 = call fastcc i32 @main_mfun(), !dbg !18
48+
store i32 %0, i32* bitcast (%struct.BSS1* @.BSS1 to i32*), align 32, !dbg !18
49+
call void (i8*, i8*, i64, ...) bitcast (void (...)* @f90io_src_info03a to void (i8*, i8*, i64, ...)*)(i8* bitcast (i32* @.C302_MAIN_ to i8*), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.C300_MAIN_, i64 0, i64 0), i64 22), !dbg !23
50+
%1 = call i32 (i8*, i8*, i8*, i8*, ...) bitcast (i32 (...)* @f90io_print_init to i32 (i8*, i8*, i8*, i8*, ...)*)(i8* bitcast (i32* @.C303_MAIN_ to i8*), i8* null, i8* bitcast (i32* @.C283_MAIN_ to i8*), i8* bitcast (i32* @.C283_MAIN_ to i8*)), !dbg !23
51+
call void @llvm.dbg.value(metadata i32 %1, metadata !24, metadata !DIExpression()), !dbg !25
52+
%2 = load i32, i32* bitcast (%struct.BSS1* @.BSS1 to i32*), align 32, !dbg !23
53+
%3 = call i32 (i32, i32, ...) bitcast (i32 (...)* @f90io_sc_i_ldw to i32 (i32, i32, ...)*)(i32 %2, i32 25), !dbg !23
54+
call void @llvm.dbg.value(metadata i32 %3, metadata !24, metadata !DIExpression()), !dbg !25
55+
%4 = call i32 (...) @f90io_ldw_end(), !dbg !23
56+
call void @llvm.dbg.value(metadata i32 %4, metadata !24, metadata !DIExpression()), !dbg !25
57+
ret void, !dbg !26
58+
}
59+
60+
define internal fastcc signext i32 @main_mfun() unnamed_addr !dbg !27 {
61+
L.entry:
62+
%i1_311 = alloca i32, align 4
63+
call void @llvm.dbg.declare(metadata i64* undef, metadata !31, metadata !DIExpression()), !dbg !33
64+
call void @llvm.dbg.declare(metadata i32* %i1_311, metadata !35, metadata !DIExpression()), !dbg !33
65+
store i32 5, i32* %i1_311, align 4, !dbg !36
66+
%0 = bitcast i32* %i1_311 to i64*, !dbg !41
67+
%1 = call fastcc float @main_fun(i64* %0), !dbg !41
68+
%2 = fptosi float %1 to i32, !dbg !41
69+
call void (i8*, i8*, i64, ...) bitcast (void (...)* @f90io_src_info03a to void (i8*, i8*, i64, ...)*)(i8* bitcast (i32* @.C313_main_mfun to i8*), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.C300_main_mfun, i32 0, i32 0), i64 22), !dbg !42
70+
%3 = call i32 (i8*, i8*, i8*, i8*, ...) bitcast (i32 (...)* @f90io_print_init to i32 (i8*, i8*, i8*, i8*, ...)*)(i8* bitcast (i32* @.C302_main_mfun to i8*), i8* null, i8* bitcast (i32* @.C283_main_mfun to i8*), i8* bitcast (i32* @.C283_main_mfun to i8*)), !dbg !42
71+
call void @llvm.dbg.value(metadata i32 %3, metadata !43, metadata !DIExpression()), !dbg !33
72+
%4 = load i32, i32* %i1_311, align 4, !dbg !42
73+
call void @llvm.dbg.value(metadata i32 %4, metadata !35, metadata !DIExpression()), !dbg !33
74+
%5 = call i32 (i32, i32, ...) bitcast (i32 (...)* @f90io_sc_i_ldw to i32 (i32, i32, ...)*)(i32 %4, i32 25), !dbg !42
75+
call void @llvm.dbg.value(metadata i32 %5, metadata !43, metadata !DIExpression()), !dbg !33
76+
%6 = call i32 (...) @f90io_ldw_end(), !dbg !42
77+
call void @llvm.dbg.value(metadata i32 %6, metadata !43, metadata !DIExpression()), !dbg !33
78+
ret i32 %2, !dbg !44
79+
}
80+
81+
define internal fastcc float @main_fun(i64* noalias %a) unnamed_addr !dbg !45 {
82+
L.entry:
83+
call void @llvm.dbg.declare(metadata i64* %a, metadata !50, metadata !DIExpression()), !dbg !51
84+
call void @llvm.dbg.declare(metadata i64* undef, metadata !53, metadata !DIExpression()), !dbg !51
85+
%0 = bitcast i64* %a to i32*, !dbg !54
86+
%1 = load i32, i32* %0, align 4, !dbg !54
87+
%2 = sitofp i32 %1 to float, !dbg !54
88+
ret float %2, !dbg !59
89+
}
90+
91+
declare signext i32 @f90io_ldw_end(...) local_unnamed_addr
92+
93+
declare signext i32 @f90io_sc_i_ldw(...) local_unnamed_addr
94+
95+
; Function Attrs: nounwind readnone speculatable willreturn
96+
declare void @llvm.dbg.declare(metadata, metadata, metadata)
97+
98+
declare signext i32 @f90io_print_init(...) local_unnamed_addr
99+
100+
declare void @f90io_src_info03a(...) local_unnamed_addr
101+
102+
declare void @fort_init(...) local_unnamed_addr
103+
104+
; Function Attrs: nounwind readnone speculatable willreturn
105+
declare void @llvm.dbg.value(metadata, metadata, metadata)
106+
107+
!llvm.module.flags = !{!14, !15}
108+
!llvm.dbg.cu = !{!4}
109+
110+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
111+
!1 = distinct !DIGlobalVariable(name: "res", scope: !2, file: !3, type: !9, isLocal: true, isDefinition: true)
112+
!2 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 1, type: !12, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4)
113+
!3 = !DIFile(filename: "duplicate-dbgvalue.f90", directory: "/dir")
114+
!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5)
115+
!5 = !{}
116+
!6 = !{!0, !7, !10}
117+
!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression())
118+
!8 = distinct !DIGlobalVariable(name: "res", scope: !4, file: !3, type: !9, isLocal: true, isDefinition: true)
119+
!9 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
120+
!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
121+
!11 = distinct !DIGlobalVariable(name: "res", scope: !4, file: !3, type: !9, isLocal: true, isDefinition: true)
122+
!12 = !DISubroutineType(cc: DW_CC_program, types: !13)
123+
!13 = !{null}
124+
!14 = !{i32 2, !"Dwarf Version", i32 4}
125+
!15 = !{i32 2, !"Debug Info Version", i32 3}
126+
!16 = !DILocation(line: 1, column: 1, scope: !17)
127+
!17 = !DILexicalBlock(scope: !2, file: !3, line: 1, column: 1)
128+
!18 = !DILocation(line: 3, column: 1, scope: !17)
129+
!19 = !{!20, !20, i64 0}
130+
!20 = !{!"t1.2", !21, i64 0}
131+
!21 = !{!"unlimited ptr", !22, i64 0}
132+
!22 = !{!"Flang FAA 1"}
133+
!23 = !DILocation(line: 4, column: 1, scope: !17)
134+
!24 = !DILocalVariable(scope: !17, file: !3, type: !9, flags: DIFlagArtificial)
135+
!25 = !DILocation(line: 0, scope: !17)
136+
!26 = !DILocation(line: 5, column: 1, scope: !17)
137+
!27 = distinct !DISubprogram(name: "mfun", scope: !2, file: !3, line: 6, type: !28, scopeLine: 6, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4)
138+
!28 = !DISubroutineType(types: !29)
139+
!29 = !{!30}
140+
!30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, align: 64)
141+
!31 = !DILocalVariable(arg: 1, scope: !27, file: !3, type: !32, flags: DIFlagArtificial)
142+
!32 = !DIBasicType(name: "uinteger*8", size: 64, align: 64, encoding: DW_ATE_unsigned)
143+
!33 = !DILocation(line: 0, scope: !34)
144+
!34 = !DILexicalBlock(scope: !27, file: !3, line: 6, column: 1)
145+
!35 = !DILocalVariable(name: "i1", scope: !34, file: !3, type: !9)
146+
!36 = !DILocation(line: 8, column: 1, scope: !34)
147+
!37 = !{!38, !38, i64 0}
148+
!38 = !{!"t2.2", !39, i64 0}
149+
!39 = !{!"unlimited ptr", !40, i64 0}
150+
!40 = !{!"Flang FAA 2"}
151+
!41 = !DILocation(line: 9, column: 1, scope: !34)
152+
!42 = !DILocation(line: 10, column: 1, scope: !34)
153+
!43 = !DILocalVariable(scope: !34, file: !3, type: !9, flags: DIFlagArtificial)
154+
!44 = !DILocation(line: 11, column: 1, scope: !34)
155+
!45 = distinct !DISubprogram(name: "fun", scope: !2, file: !3, line: 12, type: !46, scopeLine: 12, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4)
156+
!46 = !DISubroutineType(types: !47)
157+
!47 = !{!48, !9}
158+
!48 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !49, size: 64, align: 64)
159+
!49 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float)
160+
!50 = !DILocalVariable(name: "a", arg: 1, scope: !45, file: !3, type: !9)
161+
!51 = !DILocation(line: 0, scope: !52)
162+
!52 = !DILexicalBlock(scope: !45, file: !3, line: 12, column: 1)
163+
!53 = !DILocalVariable(arg: 2, scope: !45, file: !3, type: !32, flags: DIFlagArtificial)
164+
!54 = !DILocation(line: 14, column: 1, scope: !52)
165+
!55 = !{!56, !56, i64 0}
166+
!56 = !{!"t3.2", !57, i64 0}
167+
!57 = !{!"unlimited ptr", !58, i64 0}
168+
!58 = !{!"Flang FAA 3"}
169+
!59 = !DILocation(line: 15, column: 1, scope: !52)

llvm/test/Transforms/Util/dbg-call-bitcast.ll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@ define dso_local void @_Z1fv() {
1010
; CHECK: call void @_Z1gPv
1111
call void @_Z1gPv(i8* nonnull %2)
1212
%3 = bitcast i32* %1 to i8*
13+
; CHECK-NOT: call void @llvm.dbg.value
14+
; CHECK: call void @_Z1gPv
15+
call void @_Z1gPv(i8* nonnull %3)
16+
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %2)
17+
ret void, !dbg !21
18+
}
19+
20+
define dso_local void @_Z2fv() {
21+
%1 = alloca i32, align 4
22+
%2 = bitcast i32* %1 to i8*
23+
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %2)
24+
call void @llvm.dbg.declare(metadata i32* %1, metadata !16, metadata !DIExpression()), !dbg !19
25+
; CHECK: %[[A:.*]] = alloca i32, align 4
26+
; CHECK: call void @llvm.dbg.value(metadata i32* %[[A]], {{.*}}, metadata !DIExpression(DW_OP_deref)
27+
; CHECK: call void @_Z1gPv
28+
call void @_Z1gPv(i8* nonnull %2)
29+
br label %block2
30+
31+
block2:
32+
%3 = bitcast i32* %1 to i8*
1333
; CHECK: call void @llvm.dbg.value(metadata i32* %[[A]], {{.*}}, metadata !DIExpression(DW_OP_deref)
1434
; CHECK: call void @_Z1gPv
1535
call void @_Z1gPv(i8* nonnull %3)

0 commit comments

Comments
 (0)