llvm.org GIT mirror llvm / 5b3b7ed
[InstCombine] Add a flag to disable LowerDbgDeclare Summary: This should improve optimized debug info for address-taken variables at the cost of inaccurate debug info in some situations. We patched this into clang and deployed this change to Chromium developers, and this significantly improved debuggability of optimized code. The long-term solution to PR34136 seems more and more like it's going to take a while, so I would like to commit this change under a flag so that it can be used as a stop-gap measure. This flag should really help so for C++ aggregates like std::string and std::vector, which are typically address-taken, even after inlining, and cannot be SROA-ed. Reviewers: aprantl, dblaikie, probinson, dberlin Subscribers: hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D36596 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313108 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 2 years ago
4 changed file(s) with 132 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
5151 #include "llvm/Analysis/TargetLibraryInfo.h"
5252 #include "llvm/Analysis/ValueTracking.h"
5353 #include "llvm/IR/CFG.h"
54 #include "llvm/IR/DIBuilder.h"
5455 #include "llvm/IR/DataLayout.h"
5556 #include "llvm/IR/Dominators.h"
5657 #include "llvm/IR/GetElementPtrTypeIterator.h"
8990 static cl::opt
9091 MaxArraySize("instcombine-maxarray-size", cl::init(1024),
9192 cl::desc("Maximum array size considered when doing a combine"));
93
94 // FIXME: Remove this flag when it is no longer necessary to convert
95 // llvm.dbg.declare to avoid inaccurate debug info. Setting this to false
96 // increases variable availability at the cost of accuracy. Variables that
97 // cannot be promoted by mem2reg or SROA will be described as living in memory
98 // for their entire lifetime. However, passes like DSE and instcombine can
99 // delete stores to the alloca, leading to misleading and inaccurate debug
100 // information. This flag can be removed when those passes are fixed.
101 static cl::opt ShouldLowerDbgDeclare("instcombine-lower-dbg-declare",
102 cl::Hidden, cl::init(true));
92103
93104 Value *InstCombiner::EmitGEPOffset(User *GEP) {
94105 return llvm::EmitGEPOffset(&Builder, DL, GEP);
20912102 // to null and free calls, delete the calls and replace the comparisons with
20922103 // true or false as appropriate.
20932104 SmallVector Users;
2105
2106 // If we are removing an alloca with a dbg.declare, insert dbg.value calls
2107 // before each store.
2108 DbgDeclareInst *DDI = nullptr;
2109 std::unique_ptr DIB;
2110 if (isa(MI)) {
2111 DDI = FindAllocaDbgDeclare(&MI);
2112 DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false));
2113 }
2114
20942115 if (isAllocSiteRemovable(&MI, Users, &TLI)) {
20952116 for (unsigned i = 0, e = Users.size(); i != e; ++i) {
20962117 // Lowering all @llvm.objectsize calls first because they may
21232144 } else if (isa(I) || isa(I) ||
21242145 isa(I)) {
21252146 replaceInstUsesWith(*I, UndefValue::get(I->getType()));
2147 } else if (DDI && isa(I)) {
2148 ConvertDebugDeclareToDebugValue(DDI, cast(I), *DIB);
21262149 }
21272150 eraseInstFromFunction(*I);
21282151 }
21342157 InvokeInst::Create(F, II->getNormalDest(), II->getUnwindDest(),
21352158 None, "", II->getParent());
21362159 }
2160
2161 if (DDI)
2162 eraseInstFromFunction(*DDI);
2163
21372164 return eraseInstFromFunction(MI);
21382165 }
21392166 return nullptr;
31873214
31883215 // Lower dbg.declare intrinsics otherwise their value may be clobbered
31893216 // by instcombiner.
3190 bool MadeIRChange = LowerDbgDeclare(F);
3217 bool MadeIRChange = false;
3218 if (ShouldLowerDbgDeclare)
3219 MadeIRChange = LowerDbgDeclare(F);
31913220
31923221 // Iterate while there is work to do.
31933222 int Iteration = 0;
None ; RUN: opt < %s -instcombine -debug -S -o %t 2>&1 | FileCheck %s
1 ; RUN: cat %t | FileCheck %s --check-prefix=CHECK-IR
2 ; REQUIRES: asserts
3
4 ; Debug output from InstCombine should not have any @llvm.dbg.* instructions visited
5 ; CHECK-NOT: call void @llvm.dbg.
6
7 ; The resulting IR should still have them
8 ; CHECK-IR: call void @llvm.dbg.
0 ; RUN: opt -instcombine-lower-dbg-declare=0 < %s -instcombine -S | FileCheck %s
1 ; RUN: opt -instcombine-lower-dbg-declare=1 < %s -instcombine -S | FileCheck %s
92
103 define i32 @foo(i32 %j) #0 !dbg !7 {
114 entry:
169 %0 = load i32, i32* %j.addr, align 4, !dbg !14
1710 ret i32 %0, !dbg !15
1811 }
12
13 ; Instcombine can remove the alloca and forward the load to store, but it
14 ; should convert the declare to dbg value.
15 ; CHECK-LABEL: define i32 @foo(i32 %j)
16 ; CHECK-NOT: alloca
17 ; CHECK: call void @llvm.dbg.value(metadata i32 %j, {{.*}})
18 ; CHECK: call void @llvm.dbg.value(metadata i32 10, {{.*}})
19 ; CHECK: ret i32 %j
1920
2021 declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
2122 declare void @llvm.dbg.value(metadata, metadata, metadata) #1
None ; RUN: opt < %s -instcombine -S | FileCheck %s
0 ; RUN: opt < %s -instcombine -instcombine-lower-dbg-declare=0 -S \
1 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=NOLOWER
2 ; RUN: opt < %s -instcombine -instcombine-lower-dbg-declare=1 -S | FileCheck %s
3
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64--linux"
6
7 %struct.TwoRegs = type { i64, i64 }
18
29 declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
310
411 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readnone
512
6 declare i8* @foo(i8*, i32, i64, i64) nounwind
13 declare i8* @passthru_callee(i8*, i32, i64, i64)
714
8 define hidden i8* @foobar(i8* %__dest, i32 %__val, i64 %__len) nounwind inlinehint ssp !dbg !1 {
15 define i8* @passthru(i8* %a, i32 %b, i64 %c) !dbg !1 {
916 entry:
10 %__dest.addr = alloca i8*, align 8
11 %__val.addr = alloca i32, align 4
12 %__len.addr = alloca i64, align 8
13 store i8* %__dest, i8** %__dest.addr, align 8
14 ; CHECK-NOT: call void @llvm.dbg.declare
15 ; CHECK: call void @llvm.dbg.value
16 call void @llvm.dbg.declare(metadata i8** %__dest.addr, metadata !0, metadata !DIExpression()), !dbg !16
17 store i32 %__val, i32* %__val.addr, align 4
18 call void @llvm.dbg.declare(metadata i32* %__val.addr, metadata !7, metadata !DIExpression()), !dbg !18
19 store i64 %__len, i64* %__len.addr, align 8
20 call void @llvm.dbg.declare(metadata i64* %__len.addr, metadata !9, metadata !DIExpression()), !dbg !20
21 %tmp = load i8*, i8** %__dest.addr, align 8, !dbg !21
22 %tmp1 = load i32, i32* %__val.addr, align 4, !dbg !21
23 %tmp2 = load i64, i64* %__len.addr, align 8, !dbg !21
24 %tmp3 = load i8*, i8** %__dest.addr, align 8, !dbg !21
17 %a.addr = alloca i8*, align 8
18 %b.addr = alloca i32, align 4
19 %c.addr = alloca i64, align 8
20 store i8* %a, i8** %a.addr, align 8
21 call void @llvm.dbg.declare(metadata i8** %a.addr, metadata !0, metadata !DIExpression()), !dbg !16
22 store i32 %b, i32* %b.addr, align 4
23 call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !7, metadata !DIExpression()), !dbg !18
24 store i64 %c, i64* %c.addr, align 8
25 call void @llvm.dbg.declare(metadata i64* %c.addr, metadata !9, metadata !DIExpression()), !dbg !20
26 %tmp = load i8*, i8** %a.addr, align 8, !dbg !21
27 %tmp1 = load i32, i32* %b.addr, align 4, !dbg !21
28 %tmp2 = load i64, i64* %c.addr, align 8, !dbg !21
29 %tmp3 = load i8*, i8** %a.addr, align 8, !dbg !21
2530 %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp3, i1 false), !dbg !21
26 %call = call i8* @foo(i8* %tmp, i32 %tmp1, i64 %tmp2, i64 %0), !dbg !21
31 %call = call i8* @passthru_callee(i8* %tmp, i32 %tmp1, i64 %tmp2, i64 %0), !dbg !21
2732 ret i8* %call, !dbg !21
2833 }
34
35 ; CHECK-LABEL: define i8* @passthru(i8* %a, i32 %b, i64 %c)
36 ; CHECK-NOT: alloca
37 ; CHECK-NOT: store
38 ; CHECK-NOT: call void @llvm.dbg.declare
39 ; CHECK: call void @llvm.dbg.value(metadata i8* %a, {{.*}})
40 ; CHECK-NOT: store
41 ; CHECK: call void @llvm.dbg.value(metadata i32 %b, {{.*}})
42 ; CHECK-NOT: store
43 ; CHECK: call void @llvm.dbg.value(metadata i64 %c, {{.*}})
44 ; CHECK-NOT: store
45 ; CHECK: call i8* @passthru_callee(i8* %a, i32 %b, i64 %c, i64 %{{.*}})
46
47 declare void @tworegs_callee(i64, i64)
48
49 ; Lowering dbg.declare in instcombine doesn't handle this case very well.
50
51 define void @tworegs(i64 %o.coerce0, i64 %o.coerce1) !dbg !31 {
52 entry:
53 %o = alloca %struct.TwoRegs, align 8
54 %0 = bitcast %struct.TwoRegs* %o to { i64, i64 }*
55 %1 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %0, i32 0, i32 0
56 store i64 %o.coerce0, i64* %1, align 8
57 %2 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %0, i32 0, i32 1
58 store i64 %o.coerce1, i64* %2, align 8
59 call void @llvm.dbg.declare(metadata %struct.TwoRegs* %o, metadata !35, metadata !DIExpression()), !dbg !32
60 %3 = bitcast %struct.TwoRegs* %o to { i64, i64 }*, !dbg !33
61 %4 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %3, i32 0, i32 0, !dbg !33
62 %5 = load i64, i64* %4, align 8, !dbg !33
63 %6 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %3, i32 0, i32 1, !dbg !33
64 %7 = load i64, i64* %6, align 8, !dbg !33
65 call void @tworegs_callee(i64 %5, i64 %7), !dbg !33
66 ret void, !dbg !33
67 }
68
69 ; NOLOWER-LABEL: define void @tworegs(i64 %o.coerce0, i64 %o.coerce1)
70 ; NOLOWER-NOT: alloca
71 ; NOLOWER-NOT: store
72 ; NOLOWER-NOT: call void @llvm.dbg.declare
73 ; NOLOWER: call void @llvm.dbg.value(metadata i64 %o.coerce0, {{.*}})
74 ; NOLOWER-NOT: store
75 ; NOLOWER: call void @llvm.dbg.value(metadata i64 %o.coerce1, {{.*}})
76 ; NOLOWER-NOT: store
77 ; NOLOWER: call void @tworegs_callee(i64 %o.coerce0, i64 %o.coerce1)
78
2979
3080 !llvm.dbg.cu = !{!3}
3181 !llvm.module.flags = !{!30}
3282
33 !0 = !DILocalVariable(name: "__dest", line: 78, arg: 1, scope: !1, file: !2, type: !6)
34 !1 = distinct !DISubprogram(name: "foobar", line: 79, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !3, scopeLine: 79, file: !27, scope: !2, type: !4, variables: !25)
83 !0 = !DILocalVariable(name: "a", line: 78, arg: 1, scope: !1, file: !2, type: !6)
84 !1 = distinct !DISubprogram(name: "passthru", line: 79, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !3, scopeLine: 79, file: !27, scope: !2, type: !4, variables: !25)
3585 !2 = !DIFile(filename: "string.h", directory: "Game")
3686 !3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.0 (trunk 127710)", isOptimized: true, emissionKind: FullDebug, file: !28, enums: !29, retainedTypes: !29)
3787 !4 = !DISubroutineType(types: !5)
3888 !5 = !{!6}
3989 !6 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, scope: !3, baseType: null)
40 !7 = !DILocalVariable(name: "__val", line: 78, arg: 2, scope: !1, file: !2, type: !8)
90 !7 = !DILocalVariable(name: "b", line: 78, arg: 2, scope: !1, file: !2, type: !8)
4191 !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
42 !9 = !DILocalVariable(name: "__len", line: 78, arg: 3, scope: !1, file: !2, type: !10)
43 !10 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", line: 80, file: !27, scope: !3, baseType: !11)
44 !11 = !DIDerivedType(tag: DW_TAG_typedef, name: "__darwin_size_t", line: 90, file: !27, scope: !3, baseType: !12)
92 !9 = !DILocalVariable(name: "c", line: 78, arg: 3, scope: !1, file: !2, type: !12)
4593 !12 = !DIBasicType(tag: DW_TAG_base_type, name: "long unsigned int", size: 64, align: 64, encoding: DW_ATE_unsigned)
4694 !16 = !DILocation(line: 78, column: 28, scope: !1)
4795 !18 = !DILocation(line: 78, column: 40, scope: !1)
5098 !22 = distinct !DILexicalBlock(line: 80, column: 3, file: !27, scope: !23)
5199 !23 = distinct !DILexicalBlock(line: 79, column: 1, file: !27, scope: !1)
52100 !25 = !{!0, !7, !9}
53 !26 = !DIFile(filename: "bits.c", directory: "Game")
54101 !27 = !DIFile(filename: "string.h", directory: "Game")
55102 !28 = !DIFile(filename: "bits.c", directory: "Game")
56103 !29 = !{}
57104 !30 = !{i32 1, !"Debug Info Version", i32 3}
105
106 !31 = distinct !DISubprogram(name: "tworegs", scope: !28, file: !28, line: 4, type: !4, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: true, unit: !3, variables: !34)
107 !32 = !DILocation(line: 4, column: 23, scope: !31)
108 !33 = !DILocation(line: 5, column: 3, scope: !31)
109 !34 = !{!35}
110 !35 = !DILocalVariable(name: "o", arg: 1, scope: !31, file: !28, line: 4, type: !36)
111 !36 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TwoRegs", file: !28, line: 1, size: 128, elements: !37)
112 !37 = !{!38, !39}
113 !38 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !36, file: !28, line: 1, baseType: !12, size: 64)
114 !39 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !36, file: !28, line: 1, baseType: !12, size: 64)
115 !40 = !DISubroutineType(types: !41)
116 !41 = !{!36}
None ; RUN: opt -instcombine -S < %s | FileCheck %s
0 ; RUN: opt -instcombine -instcombine-lower-dbg-declare=1 -S < %s | FileCheck %s
1 ; RUN: opt -instcombine -instcombine-lower-dbg-declare=0 -S < %s | FileCheck %s --check-prefix=DECLARE
12 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
23 target triple = "x86_64-pc-linux-gnu"
34
2526 ret void
2627 }
2728
29 ; Keep the declare if we keep the alloca.
30 ; DECLARE-LABEL: define void @julia_fastshortest_6256()
31 ; DECLARE: %cp = alloca %foo, align 8
32 ; DECLARE: call void @llvm.dbg.declare(metadata %foo* %cp,
33
2834 attributes #0 = { nounwind readnone }
2935 attributes #1 = { sspreq }
3036