1; RUN: opt -passes=redundant-dbg-inst-elim -S %s -o - \ 2; RUN: | FileCheck %s --implicit-check-not="call void @llvm.dbg" 3; RUN: opt --try-experimental-debuginfo-iterators -passes=redundant-dbg-inst-elim -S %s -o - \ 4; RUN: | FileCheck %s --implicit-check-not="call void @llvm.dbg" 5 6;; $ cat -n reduce.c 7;; 1 void ext(); 8;; 2 typedef struct { 9;; 3 short *a; 10;; 4 char *b; 11;; 5 } c; 12;; 6 char d; 13;; 7 void f(); 14;; 8 typedef struct { 15;; 9 c decoder; 16;; 10 } e; 17;; 11 void g() { 18;; 12 e a; 19;; 13 (&(&a)->decoder)->b = 0; 20;; 14 (&(&a)->decoder)->a = 0; 21;; 15 ext(); 22;; 16 a.decoder.b = &d; 23;; 17 f(&a); 24;; 18 } 25 26;; clang -O2 -g -Xclang -fexperiemental-assignment-tracking: 27;; 28;; MemCpyOptPass: Aggregate scalar stores from line 13 and 14 into memset. 29;; DSE: Shorten aggregated store because field 'b' is re-assigned later. 30;; Insert an unlinked dbg.assign after the dbg.assign describing 31;; the fragment for field 'b', which is still linked to the memset. 32;; 33;; Check we don't delete that inserted unlinked dbg.assign. 34 35; CHECK: %a = alloca %struct.e, align 8, !DIAssignID ![[ID_0:[0-9]+]] 36; CHECK-NEXT: #dbg_assign({{.*}}, ![[ID_0]],{{.*}}) 37 38;; This dbg.assign is linked to the memset. 39; CHECK: #dbg_assign(ptr null,{{.*}}, !DIExpression(DW_OP_LLVM_fragment, 64, 64), ![[ID_1:[0-9]+]], ptr %b, !DIExpression(), 40 41;; Importantly, check this unlinked dbg.assign which is shadowed by the 42;; dbg.assign above isn't deleted. 43; CHECK-NEXT: #dbg_assign(ptr null,{{.*}}, !DIExpression(DW_OP_LLVM_fragment, 64, 64), ![[ID_2:[0-9]+]], ptr undef, !DIExpression(), 44 45; CHECK: #dbg_assign(ptr null,{{.*}}, !DIExpression(DW_OP_LLVM_fragment, 0, 64), ![[ID_1]], ptr %a2, !DIExpression(), 46 47; CHECK: call void @llvm.memset{{.*}}, !DIAssignID ![[ID_1]] 48 49; CHECK: store ptr @d, ptr %b, align 8,{{.*}}!DIAssignID ![[ID_3:[0-9]+]] 50; CHECK-NEXT: #dbg_assign(ptr @d,{{.*}}, !DIExpression(DW_OP_LLVM_fragment, 64, 64), ![[ID_3]], ptr %b, !DIExpression(), 51 52; CHECK-DAG: ![[ID_0]] = distinct !DIAssignID() 53; CHECK-DAG: ![[ID_1]] = distinct !DIAssignID() 54; CHECK-DAG: ![[ID_2]] = distinct !DIAssignID() 55; CHECK-DAG: ![[ID_3]] = distinct !DIAssignID() 56 57%struct.e = type { %struct.c } 58%struct.c = type { ptr, ptr } 59 60@d = dso_local global i8 0, align 1, !dbg !0 61 62define dso_local void @g() local_unnamed_addr #0 !dbg !12 { 63entry: 64 %a = alloca %struct.e, align 8, !DIAssignID !29 65 call void @llvm.dbg.assign(metadata i1 undef, metadata !16, metadata !DIExpression(), metadata !29, metadata ptr %a, metadata !DIExpression()), !dbg !30 66 call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %a) #5, !dbg !31 67 %b = getelementptr inbounds %struct.e, ptr %a, i64 0, i32 0, i32 1, !dbg !32 68 call void @llvm.dbg.assign(metadata ptr null, metadata !16, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64), metadata !33, metadata ptr %b, metadata !DIExpression()), !dbg !30 69 call void @llvm.dbg.assign(metadata ptr null, metadata !16, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64), metadata !34, metadata ptr undef, metadata !DIExpression()), !dbg !30 70 %a2 = getelementptr inbounds %struct.e, ptr %a, i64 0, i32 0, i32 0, !dbg !35 71 call void @llvm.dbg.assign(metadata ptr null, metadata !16, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64), metadata !33, metadata ptr %a2, metadata !DIExpression()), !dbg !30 72 call void @llvm.memset.p0.i64(ptr align 8 %a2, i8 0, i64 8, i1 false), !dbg !35, !DIAssignID !33 73 tail call void (...) @ext() #5, !dbg !36 74 store ptr @d, ptr %b, align 8, !dbg !37, !DIAssignID !44 75 call void @llvm.dbg.assign(metadata ptr @d, metadata !16, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64), metadata !44, metadata ptr %b, metadata !DIExpression()), !dbg !30 76 call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %a) #5, !dbg !46 77 ret void, !dbg !46 78} 79 80declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1 81declare !dbg !47 dso_local void @ext(...) local_unnamed_addr #2 82declare dso_local void @f(...) local_unnamed_addr #2 83declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1 84declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #3 85declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #4 86 87!llvm.dbg.cu = !{!2} 88!llvm.module.flags = !{!6, !7, !8, !9, !10, !1000} 89!llvm.ident = !{!11} 90 91!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) 92!1 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 6, type: !5, isLocal: false, isDefinition: true) 93!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 16.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) 94!3 = !DIFile(filename: "reduce.c", directory: "/") 95!4 = !{!0} 96!5 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) 97!6 = !{i32 7, !"Dwarf Version", i32 5} 98!7 = !{i32 2, !"Debug Info Version", i32 3} 99!8 = !{i32 1, !"wchar_size", i32 4} 100!9 = !{i32 7, !"uwtable", i32 1} 101!10 = !{i32 7, !"frame-pointer", i32 2} 102!11 = !{!"clang version 14.0.0"} 103!12 = distinct !DISubprogram(name: "g", scope: !3, file: !3, line: 11, type: !13, scopeLine: 11, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !15) 104!13 = !DISubroutineType(types: !14) 105!14 = !{null} 106!15 = !{!16} 107!16 = !DILocalVariable(name: "a", scope: !12, file: !3, line: 12, type: !17) 108!17 = !DIDerivedType(tag: DW_TAG_typedef, name: "e", file: !3, line: 10, baseType: !18) 109!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 8, size: 128, elements: !19) 110!19 = !{!20} 111!20 = !DIDerivedType(tag: DW_TAG_member, name: "decoder", scope: !18, file: !3, line: 9, baseType: !21, size: 128) 112!21 = !DIDerivedType(tag: DW_TAG_typedef, name: "c", file: !3, line: 5, baseType: !22) 113!22 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 2, size: 128, elements: !23) 114!23 = !{!24, !27} 115!24 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !22, file: !3, line: 3, baseType: !25, size: 64) 116!25 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !26, size: 64) 117!26 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed) 118!27 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !22, file: !3, line: 4, baseType: !28, size: 64, offset: 64) 119!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64) 120!29 = distinct !DIAssignID() 121!30 = !DILocation(line: 0, scope: !12) 122!31 = !DILocation(line: 12, scope: !12) 123!32 = !DILocation(line: 13, scope: !12) 124!33 = distinct !DIAssignID() 125!34 = distinct !DIAssignID() 126!35 = !DILocation(line: 14, scope: !12) 127!36 = !DILocation(line: 15, scope: !12) 128!37 = !DILocation(line: 16, scope: !12) 129!44 = distinct !DIAssignID() 130!45 = !DILocation(line: 17, scope: !12) 131!46 = !DILocation(line: 18, scope: !12) 132!47 = !DISubprogram(name: "ext", scope: !3, file: !3, line: 1, type: !13, spFlags: DISPFlagOptimized, retainedNodes: !48) 133!48 = !{} 134!1000 = !{i32 7, !"debug-info-assignment-tracking", i1 true} 135