1; RUN: opt %s -S -passes=licm -o - | FileCheck %s 2; RUN: opt --try-experimental-debuginfo-iterators %s -S -passes=licm -o - | FileCheck %s 3 4;; $ cat test.c 5;; int b, c, d; 6;; void e(); 7;; void f(int *g) { *g = b; } 8;; void i() { 9;; int h, a; 10;; for (;;) { 11;; e(); 12;; a = 1; 13;; if (h) { 14;; if (d) 15;; continue; 16;; h = c; 17;; } 18;; f(&a); 19;; } 20;; } 21;; Generated by getting the IR before LICM in: 22;; $ clang -c -O2 -g test.c -fno-unroll-loops -fno-vectorize -fno-inline -Xclang -fexperimental-assignment-tracking -o - 23 24;; entry 25;; | 26;; v 27;; *---->for.cond.outer 28;; | | 29;; | v 30;; | +->for.cond-----+ 31;; | | | | 32;; | | v | 33;; | +--if.then | 34;; | | | 35;; | v v 36;; | if.end if.end3.loopexit 37;; | | | 38;; | v | 39;; +-----if.end3 <----+ 40;; 41;; The store in for.cond is sunk into the inner-loop exits if.end and if.end3.loopexit. 42;; 43;; Check that a store sunk into multiple exits retains its (their) dbg.assign, 44;; and that the new stores share the same DIAssignID. 45 46; CHECK-LABEL: for.cond: 47; CHECK: #dbg_assign(i32 1, ![[var:[0-9]+]], !DIExpression(), ![[id:[0-9]+]], ptr %a, !DIExpression(), 48 49; CHECK-LABEL: if.end: 50; CHECK-NEXT: store i32 1, ptr %a, align 1,{{.*}}!DIAssignID ![[id]] 51 52; CHECK-LABEL: if.end3.loopexit: 53; CHECK-NEXT: store i32 1, ptr %a, align 1,{{.*}}!DIAssignID ![[id]] 54 55; CHECK-DAG: ![[var]] = !DILocalVariable(name: "a", 56 57@b = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 58@d = dso_local local_unnamed_addr global i32 0, align 4, !dbg !9 59@c = dso_local local_unnamed_addr global i32 0, align 4, !dbg !6 60 61define dso_local void @f(ptr nocapture %g) local_unnamed_addr #0 !dbg !15 { 62entry: 63 call void @llvm.dbg.assign(metadata i1 undef, metadata !20, metadata !DIExpression(), metadata !21, metadata ptr undef, metadata !DIExpression()), !dbg !22 64 call void @llvm.dbg.assign(metadata ptr %g, metadata !20, metadata !DIExpression(), metadata !23, metadata ptr undef, metadata !DIExpression()), !dbg !22 65 %0 = load i32, ptr @b, align 4, !dbg !24 66 store i32 %0, ptr %g, align 4, !dbg !29 67 ret void, !dbg !30 68} 69 70define dso_local void @i() local_unnamed_addr #2 !dbg !31 { 71entry: 72 call void @llvm.dbg.assign(metadata i1 undef, metadata !35, metadata !DIExpression(), metadata !37, metadata ptr undef, metadata !DIExpression()), !dbg !38 73 %a = alloca i32, align 4, !DIAssignID !39 74 call void @llvm.dbg.assign(metadata i1 undef, metadata !36, metadata !DIExpression(), metadata !39, metadata ptr %a, metadata !DIExpression()), !dbg !38 75 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %a) #5, !dbg !40 76 br label %for.cond.outer, !dbg !41 77 78for.cond.outer: ; preds = %if.end3, %entry 79 %h.0.ph = phi i32 [ %h.1, %if.end3 ], [ undef, %entry ] 80 br label %for.cond, !dbg !42 81 82for.cond: ; preds = %for.cond.outer, %if.then 83 call void @llvm.dbg.value(metadata i32 %h.0.ph, metadata !35, metadata !DIExpression()), !dbg !38 84 tail call void (...) @e() #5, !dbg !44 85 store i32 1, ptr %a, align 4, !dbg !47, !DIAssignID !48 86 call void @llvm.dbg.assign(metadata i32 1, metadata !36, metadata !DIExpression(), metadata !48, metadata ptr %a, metadata !DIExpression()), !dbg !38 87 %tobool.not = icmp eq i32 %h.0.ph, 0, !dbg !49 88 br i1 %tobool.not, label %if.end3.loopexit, label %if.then, !dbg !51 89 90if.then: ; preds = %for.cond 91 %0 = load i32, ptr @d, align 4, !dbg !52 92 %tobool1.not = icmp eq i32 %0, 0, !dbg !52 93 br i1 %tobool1.not, label %if.end, label %for.cond, !dbg !55, !llvm.loop !56 94 95if.end: ; preds = %if.then 96 %1 = load i32, ptr @c, align 4, !dbg !59 97 call void @llvm.dbg.assign(metadata i32 %1, metadata !35, metadata !DIExpression(), metadata !60, metadata ptr undef, metadata !DIExpression()), !dbg !38 98 br label %if.end3, !dbg !61 99 100if.end3.loopexit: ; preds = %for.cond 101 br label %if.end3, !dbg !62 102 103if.end3: ; preds = %if.end3.loopexit, %if.end 104 %h.1 = phi i32 [ %1, %if.end ], [ 0, %if.end3.loopexit ] 105 call void @llvm.dbg.value(metadata i32 %h.1, metadata !35, metadata !DIExpression()), !dbg !38 106 call void @f(ptr nonnull %a), !dbg !62 107 br label %for.cond.outer, !dbg !63, !llvm.loop !56 108} 109 110declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #1 111declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3 112declare !dbg !64 dso_local void @e(...) local_unnamed_addr #4 113declare void @llvm.dbg.value(metadata, metadata, metadata) #1 114 115!llvm.dbg.cu = !{!2} 116!llvm.module.flags = !{!11, !12, !13, !1000} 117!llvm.ident = !{!14} 118 119!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) 120!1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 1, type: !8, isLocal: false, isDefinition: true) 121!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) 122!3 = !DIFile(filename: "test.c", directory: "/") 123!4 = !{} 124!5 = !{!0, !6, !9} 125!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) 126!7 = distinct !DIGlobalVariable(name: "c", scope: !2, file: !3, line: 1, type: !8, isLocal: false, isDefinition: true) 127!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 128!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression()) 129!10 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 1, type: !8, isLocal: false, isDefinition: true) 130!11 = !{i32 7, !"Dwarf Version", i32 4} 131!12 = !{i32 2, !"Debug Info Version", i32 3} 132!13 = !{i32 1, !"wchar_size", i32 4} 133!14 = !{!"clang version 12.0.0"} 134!15 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 3, type: !16, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !19) 135!16 = !DISubroutineType(types: !17) 136!17 = !{null, !18} 137!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) 138!19 = !{!20} 139!20 = !DILocalVariable(name: "g", arg: 1, scope: !15, file: !3, line: 3, type: !18) 140!21 = distinct !DIAssignID() 141!22 = !DILocation(line: 0, scope: !15) 142!23 = distinct !DIAssignID() 143!24 = !DILocation(line: 3, column: 23, scope: !15) 144!29 = !DILocation(line: 3, column: 21, scope: !15) 145!30 = !DILocation(line: 3, column: 26, scope: !15) 146!31 = distinct !DISubprogram(name: "i", scope: !3, file: !3, line: 4, type: !32, scopeLine: 4, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !34) 147!32 = !DISubroutineType(types: !33) 148!33 = !{null} 149!34 = !{!35, !36} 150!35 = !DILocalVariable(name: "h", scope: !31, file: !3, line: 5, type: !8) 151!36 = !DILocalVariable(name: "a", scope: !31, file: !3, line: 5, type: !8) 152!37 = distinct !DIAssignID() 153!38 = !DILocation(line: 0, scope: !31) 154!39 = distinct !DIAssignID() 155!40 = !DILocation(line: 5, column: 3, scope: !31) 156!41 = !DILocation(line: 6, column: 3, scope: !31) 157!42 = !DILocation(line: 6, column: 3, scope: !43) 158!43 = distinct !DILexicalBlock(scope: !31, file: !3, line: 6, column: 3) 159!44 = !DILocation(line: 7, column: 5, scope: !45) 160!45 = distinct !DILexicalBlock(scope: !46, file: !3, line: 6, column: 12) 161!46 = distinct !DILexicalBlock(scope: !43, file: !3, line: 6, column: 3) 162!47 = !DILocation(line: 8, column: 7, scope: !45) 163!48 = distinct !DIAssignID() 164!49 = !DILocation(line: 9, column: 9, scope: !50) 165!50 = distinct !DILexicalBlock(scope: !45, file: !3, line: 9, column: 9) 166!51 = !DILocation(line: 9, column: 9, scope: !45) 167!52 = !DILocation(line: 10, column: 11, scope: !53) 168!53 = distinct !DILexicalBlock(scope: !54, file: !3, line: 10, column: 11) 169!54 = distinct !DILexicalBlock(scope: !50, file: !3, line: 9, column: 12) 170!55 = !DILocation(line: 10, column: 11, scope: !54) 171!56 = distinct !{!56, !42, !57, !58} 172!57 = !DILocation(line: 15, column: 3, scope: !43) 173!58 = !{!"llvm.loop.unroll.disable"} 174!59 = !DILocation(line: 12, column: 11, scope: !54) 175!60 = distinct !DIAssignID() 176!61 = !DILocation(line: 13, column: 5, scope: !54) 177!62 = !DILocation(line: 14, column: 5, scope: !45) 178!63 = !DILocation(line: 6, column: 3, scope: !46) 179!64 = !DISubprogram(name: "e", scope: !3, file: !3, line: 2, type: !65, spFlags: DISPFlagOptimized, retainedNodes: !4) 180!65 = !DISubroutineType(types: !66) 181!66 = !{null, null} 182!1000 = !{i32 7, !"debug-info-assignment-tracking", i1 true} 183