Skip to content

Commit 6b1c6c1

Browse files
committed
[Debuginfo][Instcombiner] Do not clone dbg.declare.
TryToSinkInstruction() has a bug: While updating debug info for sunk instruction, it could clone dbg.declare intrinsic. That is wrong. There could be only one dbg.declare. The fix is to not clone dbg.declare intrinsic and to update it`s arguments, to not to point to sunk instruction. Differential Revision: https://reviews.llvm.org/D67217 llvm-svn: 371587
1 parent 9ca1b94 commit 6b1c6c1

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3164,6 +3164,21 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
31643164
findDbgUsers(DbgUsers, I);
31653165
for (auto *DII : reverse(DbgUsers)) {
31663166
if (DII->getParent() == SrcBlock) {
3167+
if (isa<DbgDeclareInst>(DII)) {
3168+
// A dbg.declare instruction should not be cloned, since there can only be
3169+
// one per variable fragment. It should be left in the original place since
3170+
// sunk instruction is not an alloca(otherwise we could not be here).
3171+
// But we need to update arguments of dbg.declare instruction, so that it
3172+
// would not point into sunk instruction.
3173+
if (!isa<CastInst>(I))
3174+
continue; // dbg.declare points at something it shouldn't
3175+
3176+
DII->setOperand(
3177+
0, MetadataAsValue::get(I->getContext(),
3178+
ValueAsMetadata::get(I->getOperand(0))));
3179+
continue;
3180+
}
3181+
31673182
// dbg.value is in the same basic block as the sunk inst, see if we can
31683183
// salvage it. Clone a new copy of the instruction: on success we need
31693184
// both salvaged and unsalvaged copies.
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
2+
; RUN: opt %s -instcombine -verify -S -o - | FileCheck %s
3+
4+
; Hand-reduced from this example.
5+
; -g -O -mllvm -disable-llvm-optzns -gno-column-info
6+
; plus opt -sroa -instcombine -inline
7+
8+
; #include <stdio.h>
9+
;
10+
; struct S1 {
11+
; int p1;
12+
; int p2;
13+
;
14+
; bool IsNull ( ) {
15+
; return p1 == 0;
16+
; }
17+
; };
18+
;
19+
; S1 foo ( void );
20+
;
21+
; int bar ( ) {
22+
;
23+
; S1 result = foo();
24+
;
25+
; if ( result.IsNull() )
26+
; return 0;
27+
;
28+
; result.p1 = 2;
29+
; result.p2 = 3;
30+
;
31+
; int* ptr = &result.p1;
32+
;
33+
; printf("%d", *ptr);
34+
; printf("%d", *(ptr+1));
35+
;
36+
; return result.p1 + 1;
37+
; }
38+
39+
; CHECK: _Z3barv
40+
; CHECK: llvm.dbg.declare(metadata i64* %{{.*}}, metadata [[METADATA_IDX1:![0-9]+]]
41+
; CHECK-NOT: llvm.dbg.declare(metadata %struct.S1* %{{.*}}, metadata [[METADATA_IDX1]]
42+
; CHECK: ret
43+
; CHECK: DICompileUnit
44+
; CHECK: [[METADATA_IDX1]] = !DILocalVariable(name: "result"
45+
46+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
47+
target triple = "x86_64-unknown-linux-gnu"
48+
49+
%struct.S1 = type { i32, i32 }
50+
51+
@.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1
52+
53+
define dso_local i32 @_Z3barv() !dbg !7 {
54+
entry:
55+
%result = alloca i64, align 8
56+
%tmpcast = bitcast i64* %result to %struct.S1*
57+
%0 = bitcast i64* %result to i8*, !dbg !24
58+
call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0) #4, !dbg !24
59+
call void @llvm.dbg.declare(metadata %struct.S1* %tmpcast, metadata !12, metadata !DIExpression()), !dbg !24
60+
%call = call i64 @_Z3foov(), !dbg !24
61+
store i64 %call, i64* %result, align 8, !dbg !24
62+
call void @llvm.dbg.value(metadata %struct.S1* %tmpcast, metadata !25, metadata !DIExpression()), !dbg !29
63+
%p1.i = getelementptr inbounds %struct.S1, %struct.S1* %tmpcast, i64 0, i32 0, !dbg !32
64+
%1 = load i32, i32* %p1.i, align 4, !dbg !32
65+
%cmp.i = icmp eq i32 %1, 0, !dbg !32
66+
br i1 %cmp.i, label %if.then, label %if.end, !dbg !38
67+
68+
if.then: ; preds = %entry
69+
br label %cleanup, !dbg !38
70+
71+
if.end: ; preds = %entry
72+
73+
%p1 = bitcast i64* %result to i32*, !dbg !38
74+
store i32 2, i32* %p1, align 8, !dbg !38
75+
%p2 = getelementptr inbounds %struct.S1, %struct.S1* %tmpcast, i64 0, i32 1, !dbg !38
76+
store i32 3, i32* %p2, align 4, !dbg !38
77+
%p12 = bitcast i64* %result to i32*, !dbg !38
78+
call void @llvm.dbg.value(metadata i32* %p12, metadata !22, metadata !DIExpression()), !dbg !38
79+
%call3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i32 2), !dbg !38
80+
%add.ptr = getelementptr inbounds i32, i32* %p12, i64 1, !dbg !38
81+
%2 = load i32, i32* %add.ptr, align 4, !dbg !38
82+
%call4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i32 %2), !dbg !38
83+
%p15 = bitcast i64* %result to i32*, !dbg !38
84+
%3 = load i32, i32* %p15, align 8, !dbg !38
85+
%add = add nsw i32 %3, 1, !dbg !38
86+
br label %cleanup
87+
88+
cleanup: ; preds = %if.end, %if.then
89+
%retval.0 = phi i32 [ 0, %if.then ], [ %add, %if.end ], !dbg !38
90+
%4 = bitcast i64* %result to i8*, !dbg !38
91+
call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %4) #4, !dbg !38
92+
ret i32 %retval.0, !dbg !38
93+
}
94+
95+
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
96+
97+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
98+
99+
declare dso_local i64 @_Z3foov() #3
100+
101+
declare dso_local i32 @printf(i8*, ...) #3
102+
103+
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
104+
105+
declare void @llvm.dbg.value(metadata, metadata, metadata) #2
106+
107+
!llvm.dbg.cu = !{!0}
108+
!llvm.module.flags = !{!3, !4, !5}
109+
!llvm.ident = !{!6}
110+
111+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
112+
!1 = !DIFile(filename: "test.cpp", directory: "")
113+
!2 = !{}
114+
!3 = !{i32 2, !"Dwarf Version", i32 4}
115+
!4 = !{i32 2, !"Debug Info Version", i32 3}
116+
!5 = !{i32 1, !"wchar_size", i32 4}
117+
!6 = !{!"clang"}
118+
!7 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 15, type: !8, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
119+
!8 = !DISubroutineType(types: !9)
120+
!9 = !{!10}
121+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
122+
!11 = !{!12, !22}
123+
!12 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 17, type: !13)
124+
!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S1", file: !1, line: 4, size: 64, flags: DIFlagTypePassByValue, elements: !14, identifier: "_ZTS2S1")
125+
!14 = !{!15, !16, !17}
126+
!15 = !DIDerivedType(tag: DW_TAG_member, name: "p1", scope: !13, file: !1, line: 5, baseType: !10, size: 32)
127+
!16 = !DIDerivedType(tag: DW_TAG_member, name: "p2", scope: !13, file: !1, line: 6, baseType: !10, size: 32, offset: 32)
128+
!17 = !DISubprogram(name: "IsNull", linkageName: "_ZN2S16IsNullEv", scope: !13, file: !1, line: 8, type: !18, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
129+
!18 = !DISubroutineType(types: !19)
130+
!19 = !{!20, !21}
131+
!20 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
132+
!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
133+
!22 = !DILocalVariable(name: "ptr", scope: !7, file: !1, line: 25, type: !23)
134+
!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
135+
!24 = !DILocation(line: 17, scope: !7)
136+
!25 = !DILocalVariable(name: "this", arg: 1, scope: !26, type: !28, flags: DIFlagArtificial | DIFlagObjectPointer)
137+
!26 = distinct !DISubprogram(name: "IsNull", linkageName: "_ZN2S16IsNullEv", scope: !13, file: !1, line: 8, type: !18, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !17, retainedNodes: !27)
138+
!27 = !{!25}
139+
!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
140+
!29 = !DILocation(line: 0, scope: !26, inlinedAt: !30)
141+
!30 = distinct !DILocation(line: 19, scope: !31)
142+
!31 = distinct !DILexicalBlock(scope: !7, file: !1, line: 19)
143+
!32 = !DILocation(line: 9, scope: !26, inlinedAt: !30)
144+
!38 = !DILocation(line: 0, scope: !7)

0 commit comments

Comments
 (0)