summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2017-09-20 21:52:33 +0000
committerReid Kleckner <rnk@google.com>2017-09-20 21:52:33 +0000
commit3f547e87b2cdd148c0429ddda48fdeeb111b527d (patch)
tree8eec0bb5535f40c9328bb90dc12844e56c31e8c2 /llvm/test/Transforms
parent047cbee1e77e545c0f1a32b7a1eae113f87deb71 (diff)
downloadbcm5719-llvm-3f547e87b2cdd148c0429ddda48fdeeb111b527d.tar.gz
bcm5719-llvm-3f547e87b2cdd148c0429ddda48fdeeb111b527d.zip
[IR] Add llvm.dbg.addr, a control-dependent version of llvm.dbg.declare
Summary: This implements the design discussed on llvm-dev for better tracking of variables that live in memory through optimizations: http://lists.llvm.org/pipermail/llvm-dev/2017-September/117222.html This is tracked as PR34136 llvm.dbg.addr is intended to be produced and used in almost precisely the same way as llvm.dbg.declare is today, with the exception that it is control-dependent. That means that dbg.addr should always have a position in the instruction stream, and it will allow passes that optimize memory operations on local variables to insert llvm.dbg.value calls to reflect deleted stores. See SourceLevelDebugging.rst for more details. The main drawback to generating DBG_VALUE machine instrs is that they usually cause LLVM to emit a location list for DW_AT_location. The next step will be to teach DwarfDebug.cpp how to recognize more DBG_VALUE ranges as not needing a location list, and possibly start setting DW_AT_start_offset for variables whose lifetimes begin mid-scope. Reviewers: aprantl, dblaikie, probinson Subscribers: eraman, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D37768 llvm-svn: 313825
Diffstat (limited to 'llvm/test/Transforms')
-rw-r--r--llvm/test/Transforms/Mem2Reg/dbg-addr-inline-dse.ll94
-rw-r--r--llvm/test/Transforms/Mem2Reg/dbg-addr.ll91
-rw-r--r--llvm/test/Transforms/SROA/dbg-addr-diamond.ll127
3 files changed, 312 insertions, 0 deletions
diff --git a/llvm/test/Transforms/Mem2Reg/dbg-addr-inline-dse.ll b/llvm/test/Transforms/Mem2Reg/dbg-addr-inline-dse.ll
new file mode 100644
index 00000000000..8fe2e0ab317
--- /dev/null
+++ b/llvm/test/Transforms/Mem2Reg/dbg-addr-inline-dse.ll
@@ -0,0 +1,94 @@
+; RUN: opt -mem2reg -S < %s | FileCheck %s -implicit-check-not="call void @llvm.dbg.addr"
+
+; This example is intended to simulate this pass pipeline, which may not exist
+; in practice:
+; 1. DSE f from the original C source
+; 2. Inline escape
+; 3. mem2reg
+; This exercises the corner case of multiple llvm.dbg.addr intrinsics.
+
+; C source:
+;
+; void escape(int *px) { ++*px; }
+; extern int global;
+; void f(int x) {
+; escape(&x);
+; x = 1; // DSE should delete and insert dbg.value(i32 1)
+; global = x;
+; x = 2; // DSE should insert dbg.addr
+; escape(&x);
+; }
+
+; ModuleID = 'dse.c'
+source_filename = "dse.c"
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+declare void @llvm.dbg.addr(metadata, metadata, metadata) #2
+declare void @llvm.dbg.value(metadata, metadata, metadata) #2
+
+@global = external global i32, align 4
+
+; Function Attrs: nounwind uwtable
+define void @f(i32 %x) #0 !dbg !8 {
+entry:
+ %x.addr = alloca i32, align 4
+ store i32 %x, i32* %x.addr, align 4
+ call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !18
+ %ld.1 = load i32, i32* %x.addr, align 4, !dbg !19
+ %inc.1 = add nsw i32 %ld.1, 1, !dbg !19
+ store i32 %inc.1, i32* %x.addr, align 4, !dbg !19
+ call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression()), !dbg !20
+ store i32 1, i32* @global, align 4, !dbg !22
+ call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !23
+ store i32 2, i32* %x.addr, align 4, !dbg !23
+ %ld.2 = load i32, i32* %x.addr, align 4, !dbg !19
+ %inc.2 = add nsw i32 %ld.2, 1, !dbg !19
+ store i32 %inc.2, i32* %x.addr, align 4, !dbg !19
+ ret void, !dbg !25
+}
+
+; CHECK-LABEL: define void @f(i32 %x)
+; CHECK: call void @llvm.dbg.value(metadata i32 %x, metadata !13, metadata !DIExpression())
+; CHECK: %inc.1 = add nsw i32 %x, 1
+; CHECK: call void @llvm.dbg.value(metadata i32 %inc.1, metadata !13, metadata !DIExpression())
+; CHECK: call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression())
+; CHECK: store i32 1, i32* @global, align 4
+; CHECK: call void @llvm.dbg.value(metadata i32 2, metadata !13, metadata !DIExpression())
+; CHECK: %inc.2 = add nsw i32 2, 1
+; CHECK: call void @llvm.dbg.value(metadata i32 %inc.2, metadata !13, metadata !DIExpression())
+; CHECK: ret void
+
+attributes #0 = { nounwind uwtable }
+attributes #2 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "dse.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 2}
+!6 = !{i32 7, !"PIC Level", i32 2}
+!7 = !{!"clang version 6.0.0 "}
+!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
+!9 = !DISubroutineType(types: !10)
+!10 = !{null, !11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !{!13}
+!13 = !DILocalVariable(name: "x", arg: 1, scope: !8, file: !1, line: 3, type: !11)
+!14 = !{!15, !15, i64 0}
+!15 = !{!"int", !16, i64 0}
+!16 = !{!"omnipotent char", !17, i64 0}
+!17 = !{!"Simple C/C++ TBAA"}
+!18 = !DILocation(line: 3, column: 12, scope: !8)
+!19 = !DILocation(line: 4, column: 3, scope: !8)
+!20 = !DILocation(line: 5, column: 5, scope: !8)
+!21 = !DILocation(line: 6, column: 12, scope: !8)
+!22 = !DILocation(line: 6, column: 10, scope: !8)
+!23 = !DILocation(line: 7, column: 5, scope: !8)
+!24 = !DILocation(line: 8, column: 3, scope: !8)
+!25 = !DILocation(line: 9, column: 1, scope: !8)
diff --git a/llvm/test/Transforms/Mem2Reg/dbg-addr.ll b/llvm/test/Transforms/Mem2Reg/dbg-addr.ll
new file mode 100644
index 00000000000..8c97f791a08
--- /dev/null
+++ b/llvm/test/Transforms/Mem2Reg/dbg-addr.ll
@@ -0,0 +1,91 @@
+; RUN: opt -mem2reg -S < %s | FileCheck %s
+
+; ModuleID = 'newvars.c'
+source_filename = "newvars.c"
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+; Function Attrs: nounwind uwtable
+define i32 @if_else(i32 %cond, i32 %a, i32 %b) !dbg !8 {
+entry:
+ %x = alloca i32, align 4
+ call void @llvm.dbg.addr(metadata i32* %x, metadata !16, metadata !DIExpression()), !dbg !26
+ store i32 %a, i32* %x, align 4, !dbg !26, !tbaa !17
+ %tobool = icmp ne i32 %cond, 0, !dbg !28
+ br i1 %tobool, label %if.then, label %if.else, !dbg !30
+
+if.then: ; preds = %entry
+ store i32 0, i32* %x, align 4, !dbg !31, !tbaa !17
+ br label %if.end, !dbg !33
+
+if.else: ; preds = %entry
+ store i32 %b, i32* %x, align 4, !dbg !36, !tbaa !17
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %rv = load i32, i32* %x, align 4, !dbg !37, !tbaa !17
+ ret i32 %rv, !dbg !39
+}
+
+; CHECK-LABEL: define i32 @if_else({{.*}})
+; CHECK: entry:
+; CHECK-NOT: alloca i32
+; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[X_LOCAL:[0-9]+]], metadata !DIExpression())
+; CHECK: if.then: ; preds = %entry
+; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[X_LOCAL]], metadata !DIExpression())
+; CHECK: if.else: ; preds = %entry
+; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[X_LOCAL]], metadata !DIExpression())
+; CHECK: if.end: ; preds = %if.else, %if.then
+; CHECK: %[[PHI:[^ ]*]] = phi i32 [ 0, %if.then ], [ %b, %if.else ]
+; CHECK: call void @llvm.dbg.value(metadata i32 %[[PHI]], metadata ![[X_LOCAL]], metadata !DIExpression())
+; CHECK: ret i32
+
+; CHECK: ![[X_LOCAL]] = !DILocalVariable(name: "x", {{.*}})
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+declare void @llvm.dbg.addr(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "newvars.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 2}
+!6 = !{i32 7, !"PIC Level", i32 2}
+!7 = !{!"clang version 6.0.0 "}
+!8 = distinct !DISubprogram(name: "if_else", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11, !11, !11, !11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !{!13, !14, !15, !16}
+!13 = !DILocalVariable(name: "b", arg: 3, scope: !8, file: !1, line: 1, type: !11)
+!14 = !DILocalVariable(name: "a", arg: 2, scope: !8, file: !1, line: 1, type: !11)
+!15 = !DILocalVariable(name: "cond", arg: 1, scope: !8, file: !1, line: 1, type: !11)
+!16 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !11)
+!17 = !{!18, !18, i64 0}
+!18 = !{!"int", !19, i64 0}
+!19 = !{!"omnipotent char", !20, i64 0}
+!20 = !{!"Simple C/C++ TBAA"}
+!22 = !DILocation(line: 1, column: 34, scope: !8)
+!23 = !DILocation(line: 1, column: 27, scope: !8)
+!24 = !DILocation(line: 1, column: 17, scope: !8)
+!25 = !DILocation(line: 2, column: 3, scope: !8)
+!26 = !DILocation(line: 2, column: 7, scope: !8)
+!27 = !DILocation(line: 2, column: 11, scope: !8)
+!28 = !DILocation(line: 3, column: 7, scope: !29)
+!29 = distinct !DILexicalBlock(scope: !8, file: !1, line: 3, column: 7)
+!30 = !DILocation(line: 3, column: 7, scope: !8)
+!31 = !DILocation(line: 4, column: 7, scope: !32)
+!32 = distinct !DILexicalBlock(scope: !29, file: !1, line: 3, column: 13)
+!33 = !DILocation(line: 5, column: 3, scope: !32)
+!34 = !DILocation(line: 6, column: 9, scope: !35)
+!35 = distinct !DILexicalBlock(scope: !29, file: !1, line: 5, column: 10)
+!36 = !DILocation(line: 6, column: 7, scope: !35)
+!37 = !DILocation(line: 8, column: 10, scope: !8)
+!38 = !DILocation(line: 9, column: 1, scope: !8)
+!39 = !DILocation(line: 8, column: 3, scope: !8)
diff --git a/llvm/test/Transforms/SROA/dbg-addr-diamond.ll b/llvm/test/Transforms/SROA/dbg-addr-diamond.ll
new file mode 100644
index 00000000000..132da991464
--- /dev/null
+++ b/llvm/test/Transforms/SROA/dbg-addr-diamond.ll
@@ -0,0 +1,127 @@
+; RUN: opt -use-dbg-addr -sroa -S < %s | FileCheck %s
+
+; ModuleID = '<stdin>'
+source_filename = "newvars.c"
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+%struct.Pair = type { i32, i32 }
+
+@pair = internal global %struct.Pair zeroinitializer
+
+; Function Attrs: nounwind uwtable
+define void @if_else(i32 %cond, i32 %a, i32 %b) !dbg !8 {
+entry:
+ %p = alloca %struct.Pair, align 4
+ %0 = bitcast %struct.Pair* %p to i8*, !dbg !25
+ call void @llvm.dbg.addr(metadata %struct.Pair* %p, metadata !20, metadata !DIExpression()), !dbg !26
+ %x = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !27
+ store i32 %a, i32* %x, align 4, !dbg !28
+ %y = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !34
+ store i32 %b, i32* %y, align 4, !dbg !35
+ %tobool = icmp ne i32 %cond, 0, !dbg !37
+ br i1 %tobool, label %if.then, label %if.else, !dbg !39
+
+if.then: ; preds = %entry
+ %x1 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !40
+ store i32 0, i32* %x1, align 4, !dbg !42
+ %y2 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !43
+ store i32 %a, i32* %y2, align 4, !dbg !44
+ br label %if.end, !dbg !45
+
+if.else: ; preds = %entry
+ %x3 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !46
+ store i32 %b, i32* %x3, align 4, !dbg !48
+ %y4 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !49
+ store i32 0, i32* %y4, align 4, !dbg !50
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %1 = bitcast %struct.Pair* %p to i8*, !dbg !51
+ %2 = bitcast %struct.Pair* @pair to i8*, !dbg !51
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %1, i64 8, i32 4, i1 false), !dbg !51
+ ret void
+}
+
+; CHECK-LABEL: define void @if_else(i32 %cond, i32 %a, i32 %b)
+; CHECK: entry:
+; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[PVAR:[0-9]+]], metadata ![[XFRAG:DIExpression\(DW_OP_LLVM_fragment, 0, 32\)]])
+; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[PVAR]], metadata ![[YFRAG:DIExpression\(DW_OP_LLVM_fragment, 32, 32\)]])
+; CHECK: if.then:
+; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[PVAR]], metadata ![[XFRAG]])
+; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[PVAR]], metadata ![[YFRAG]])
+; CHECK: if.else:
+; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[PVAR]], metadata ![[XFRAG]])
+; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[PVAR]], metadata ![[YFRAG]])
+; CHECK: if.end:
+; CHECK: %p.sroa.4.0 = phi i32 [ %a, %if.then ], [ 0, %if.else ]
+; CHECK: %p.sroa.0.0 = phi i32 [ 0, %if.then ], [ %b, %if.else ]
+; CHECK: call void @llvm.dbg.value(metadata i32 %p.sroa.0.0, metadata ![[PVAR]], metadata ![[XFRAG]])
+; CHECK: call void @llvm.dbg.value(metadata i32 %p.sroa.4.0, metadata ![[PVAR]], metadata ![[YFRAG]])
+
+; CHECK: ![[PVAR]] = !DILocalVariable(name: "p", {{.*}})
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #2
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.addr(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "newvars.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 2}
+!6 = !{i32 7, !"PIC Level", i32 2}
+!7 = !{!"clang version 6.0.0 "}
+!8 = distinct !DISubprogram(name: "if_else", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !16)
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11, !14, !14, !14}
+!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Pair", file: !1, line: 1, size: 64, elements: !12)
+!12 = !{!13, !15}
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 1, baseType: !14, size: 32)
+!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !11, file: !1, line: 1, baseType: !14, size: 32, offset: 32)
+!16 = !{!17, !18, !19, !20}
+!17 = !DILocalVariable(name: "b", arg: 3, scope: !8, file: !1, line: 2, type: !14)
+!18 = !DILocalVariable(name: "a", arg: 2, scope: !8, file: !1, line: 2, type: !14)
+!19 = !DILocalVariable(name: "cond", arg: 1, scope: !8, file: !1, line: 2, type: !14)
+!20 = !DILocalVariable(name: "p", scope: !8, file: !1, line: 3, type: !11)
+!22 = !DILocation(line: 2, column: 42, scope: !8)
+!23 = !DILocation(line: 2, column: 35, scope: !8)
+!24 = !DILocation(line: 2, column: 25, scope: !8)
+!25 = !DILocation(line: 3, column: 3, scope: !8)
+!26 = !DILocation(line: 3, column: 15, scope: !8)
+!27 = !DILocation(line: 4, column: 5, scope: !8)
+!28 = !DILocation(line: 4, column: 7, scope: !8)
+!29 = !{!30, !31, i64 0}
+!30 = !{!"Pair", !31, i64 0, !31, i64 4}
+!31 = !{!"int", !32, i64 0}
+!32 = !{!"omnipotent char", !33, i64 0}
+!33 = !{!"Simple C/C++ TBAA"}
+!34 = !DILocation(line: 5, column: 5, scope: !8)
+!35 = !DILocation(line: 5, column: 7, scope: !8)
+!36 = !{!30, !31, i64 4}
+!37 = !DILocation(line: 6, column: 7, scope: !38)
+!38 = distinct !DILexicalBlock(scope: !8, file: !1, line: 6, column: 7)
+!39 = !DILocation(line: 6, column: 7, scope: !8)
+!40 = !DILocation(line: 7, column: 7, scope: !41)
+!41 = distinct !DILexicalBlock(scope: !38, file: !1, line: 6, column: 13)
+!42 = !DILocation(line: 7, column: 9, scope: !41)
+!43 = !DILocation(line: 8, column: 7, scope: !41)
+!44 = !DILocation(line: 8, column: 9, scope: !41)
+!45 = !DILocation(line: 9, column: 3, scope: !41)
+!46 = !DILocation(line: 10, column: 7, scope: !47)
+!47 = distinct !DILexicalBlock(scope: !38, file: !1, line: 9, column: 10)
+!48 = !DILocation(line: 10, column: 9, scope: !47)
+!49 = !DILocation(line: 11, column: 7, scope: !47)
+!50 = !DILocation(line: 11, column: 9, scope: !47)
+!51 = !DILocation(line: 13, column: 10, scope: !8)
+!52 = !{i64 0, i64 4, !53, i64 4, i64 4, !53}
+!53 = !{!31, !31, i64 0}
+!54 = !DILocation(line: 14, column: 1, scope: !8)
OpenPOWER on IntegriCloud