Index: llvm/test/DebugInfo/assignment-tracking/X86/dbg-phi-produces-undef.ll =================================================================== --- llvm/test/DebugInfo/assignment-tracking/X86/dbg-phi-produces-undef.ll +++ llvm/test/DebugInfo/assignment-tracking/X86/dbg-phi-produces-undef.ll @@ -16,11 +16,11 @@ ;; ;; exit: ;; ; <-- Dbg=!1, Stack=!1, Loc=Mem -;; memddef 1, !2 ; <-- Dbg=!1, Stack=!2, Loc=Val(undef) XXX +;; memddef 1, !2 ; <-- Dbg=!1, Stack=!2, Loc=Val(undef) @HERE ;; call ;; dbgdef !2 ;; -;; Check that the dbg.value inserted at XXX is undef because there's no +;; Check that the dbg.value inserted at @HERE is undef because there's no ;; appropriate alternative value to choose. ; CHECK: bb.0.entry: @@ -34,7 +34,7 @@ ; CHECK: bb.2.exit: ; CHECK-NEXT: MOV8mi %stack.0.c, 1, $noreg, 0, $noreg, 1 -;; XXX +;; @HERE ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[var]], !DIExpression() ; CHECK: CALL64pcrel32 @d ; CHECK-NEXT: ADJCALLSTACKUP64 Index: llvm/test/DebugInfo/assignment-tracking/X86/loop-sink.ll =================================================================== --- llvm/test/DebugInfo/assignment-tracking/X86/loop-sink.ll +++ llvm/test/DebugInfo/assignment-tracking/X86/loop-sink.ll @@ -1,14 +1,16 @@ ; RUN: llc %s -stop-after=finalize-isel -o - -experimental-assignment-tracking \ -; RUN: | FileCheck %s --implicit-check-not=DBG_VALUE +; RUN: | FileCheck %s --implicit-check-not=DBG ;; Tiny loop with a store sunk out of it: ;; void e(); ;; void es(int*); ;; int *g; +;; int getInt(); ;; int f(int a, int b) { +;; int z = getInt(); ;; while (g) { ;; e(); -;; a = b; +;; a = z; ;; } ;; es(&a); ;; return a; @@ -22,14 +24,13 @@ ; CHECK-LABEL: bb.0.entry: ; CHECK: DBG_VALUE $edi, $noreg, ![[A]], !DIExpression() +; CHECK: CALL64pcrel32 @getInt{{.*}}debug-instr-number 1 ; CHECK-LABEL: bb.2.while.body: -;; It's unfortunate that we see $noreg here -- the vreg use gets lost at some -;; point by SelectionDAG. -; CHECK: DBG_VALUE $noreg, $noreg, ![[A]], !DIExpression() +; CHECK: DBG_INSTR_REF 1, 6, ![[A]], !DIExpression() ; CHECK-LABEL: bb.3.while.end: -; CHECK: MOV32mr %stack.0.a.addr, 1, $noreg, 0, $noreg, %0 +; CHECK: MOV32mr %stack.0.a.addr, 1, $noreg, 0, $noreg, %1 ; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[A]], !DIExpression(DW_OP_deref) target triple = "x86_64-unknown-linux-gnu" @@ -42,13 +43,14 @@ %a.addr = alloca i32, align 4, !DIAssignID !18 call void @llvm.dbg.assign(metadata i1 undef, metadata !16, metadata !DIExpression(), metadata !18, metadata ptr %a.addr, metadata !DIExpression()), !dbg !19 call void @llvm.dbg.assign(metadata i32 %a, metadata !16, metadata !DIExpression(), metadata !20, metadata ptr %a.addr, metadata !DIExpression()), !dbg !19 + %z = call i32 @getInt() %0 = load ptr, ptr @g, align 8, !dbg !22 %tobool.not1 = icmp eq ptr %0, null, !dbg !22 br i1 %tobool.not1, label %while.end, label %while.body, !dbg !27 while.body: ; preds = %entry, %while.body tail call void @_Z1ev(), !dbg !28 - call void @llvm.dbg.assign(metadata i32 %b, metadata !16, metadata !DIExpression(), metadata !20, metadata ptr %a.addr, metadata !DIExpression()), !dbg !19 + call void @llvm.dbg.assign(metadata i32 %z, metadata !16, metadata !DIExpression(), metadata !20, metadata ptr %a.addr, metadata !DIExpression()), !dbg !19 %1 = load ptr, ptr @g, align 8, !dbg !22 %tobool.not = icmp eq ptr %1, null, !dbg !22 br i1 %tobool.not, label %while.end, label %while.body, !dbg !27, !llvm.loop !30 @@ -58,12 +60,14 @@ store i32 %storemerge.lcssa, ptr %a.addr, align 4, !DIAssignID !20 call void @_Z2esPi(ptr noundef nonnull %a.addr), !dbg !35 %2 = load i32, ptr %a.addr, align 4, !dbg !36 - ret i32 %2, !dbg !37 + %r = add i32 %2, %z + ret i32 %r, !dbg !37 } declare !dbg !38 dso_local void @_Z1ev() local_unnamed_addr #1 declare !dbg !42 dso_local void @_Z2esPi(ptr noundef) local_unnamed_addr #1 declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #2 +declare dso_local i32 @getInt() !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!7, !8, !9, !10} Index: llvm/test/DebugInfo/assignment-tracking/X86/mem-loc-frag-fill.ll =================================================================== --- llvm/test/DebugInfo/assignment-tracking/X86/mem-loc-frag-fill.ll +++ llvm/test/DebugInfo/assignment-tracking/X86/mem-loc-frag-fill.ll @@ -45,7 +45,7 @@ ; CHECK: MOV64mr %stack.0.nums, 1, $noreg, 0, $noreg, killed %0 call void @llvm.dbg.assign(metadata i1 undef, metadata !12, metadata !DIExpression(), metadata !22, metadata ptr %nums, metadata !DIExpression()), !dbg !19 call void @llvm.dbg.assign(metadata i1 undef, metadata !12, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 32), metadata !22, metadata ptr undef, metadata !DIExpression()), !dbg !19 -; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[nums]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 64, 32) +; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[nums]], !DIExpression(DW_OP_LLVM_fragment, 64, 32) ; CHECK-NEXT: DBG_VALUE %stack.0.nums, $noreg, ![[nums]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 64) tail call void @_Z4stepv(), !dbg !23 %c = getelementptr inbounds %struct.Nums, ptr %nums, i64 0, i32 2, !dbg !24 Index: llvm/test/DebugInfo/assignment-tracking/X86/nested-loop.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/assignment-tracking/X86/nested-loop.ll @@ -0,0 +1,367 @@ +; RUN: llc %s -stop-after=finalize-isel -o - -experimental-assignment-tracking \ +; RUN: | FileCheck %s --implicit-check-not=DBG + +;; Test a variety of block inputs and lattice configurations for the assignment +;; tracking analysis (debug-ata). + +;; The CFG looks like this: +;; entry +;; | +;; v +;; do.body <-----+ +;; | | +;; V | +;; do.body1 <--+ | +;; / \ | | +;; / \ | | +;; / \ | | +;; v v | | +;; if.then if.else | | +;; \ / | | +;; \ / | | +;; \ / | | +;; do.cond ----+ | +;; | | +;; v | +;; do.cond4 -----+ +;; | +;; v +;; do.end6 + +;; Key +;; ╔═════════════════════╦═══════════════════════════════════════════════════════════════════╗ +;; ║ thing ║ meaning ║ +;; ╠═════════════════════╬═══════════════════════════════════════════════════════════════════╣ +;; ║ mem= ║ assignment of !n or phi to memory ║ +;; ║ dbg= ║ assignment of !n or phi to source variable ║ +;; ║ phi ║ phi of assignments (operands not traked)* ║ +;; ║ loc= ║ location to use is value (implicit location), stack home, or none ║ +;; ╚═════════════════════╩═══════════════════════════════════════════════════════════════════╝ +;; (*) A phi in the def column represents an assignment made by an untagged store. +;; +;; Variable 'a' (!21) +;; Check initial dbg and mem assignment values are propagated through all blocks. +;; ╔═════════════╦══════════════════════════╦═════════════════╦══════════════════════════╗ +;; ║ block ║ in ║ def ║ out ║ +;; ╠═════════════╬══════════════════════════╬═════════════════╬══════════════════════════╣ +;; ║ entry ║ ║ mem=!63 dbg=!70 ║ mem=!63 dbg=!70 loc=val ║ +;; ║ do.end6 ║ mem=!63 dbg=!70 loc=val ║ mem=!63 ║ mem=!63 dbg=!63 loc=mem ║ +;; ╚═════════════╩══════════════════════════╩═════════════════╩══════════════════════════╝ +;; +;; Variable 'b' (!22) +;; Check mem=dbg assignment on branch in nested loop causes a mem=phi (tested by looking +;; for value-based DBG_VALUE in do.end6). +;; ╔═════════════╦══════════════════════════╦═════════════════╦══════════════════════════╗ +;; ║ block ║ in ║ def ║ out ║ +;; ╠═════════════╬══════════════════════════╬═════════════════╬══════════════════════════╣ +;; ║ entry ║ ║ mem=!65 dbg=!71 ║ mem=!65 dbg=!71 loc=val ║ +;; ║ if.then ║ mem=phi dbg=phi loc=none ║ mem=!66 dbg=!66 ║ mem=!66 dbg=!66 loc=mem ║ +;; ║ do.end6 ║ mem=phi dbg=phi loc=none ║ mem=!65 ║ mem=phi dbg=!65 loc=val ║ +;; ╚═════════════╩══════════════════════════╩═════════════════╩══════════════════════════╝ +;; +;; Variable 'c' (!67) +;; Check initial dbg and mem assignment values are propagated through all blocks, with +;; dbg defs with the inital assignment ID put in do.cond and do.end6 (variable is always +;; in memory). +;; ╔═════════════╦══════════════════════════╦═════════════════╦══════════════════════════╗ +;; ║ block ║ in ║ def ║ out ║ +;; ╠═════════════╬══════════════════════════╬═════════════════╬══════════════════════════╣ +;; ║ entry ║ ║ mem=!69 dbg=!69 ║ mem=!69 dbg=!69 loc=mem ║ +;; ║ do.cond ║ mem=!69 dbg=!69 loc=mem ║ dbg=!69 ║ mem=!69 dbg=!69 loc=mem ║ +;; ║ do.end6 ║ mem=!69 dbg=!69 loc=mem ║ dbg=!69 ║ mem=!69 dbg=!69 loc=mem ║ +;; ╚═════════════╩══════════════════════════╩═════════════════╩══════════════════════════╝ +;; +;; Variable 'd' (!72) +;; Same as above, except the "if.then" dbg def has been swapped for a dbg=mem def (with +;; the initial assignment ID) has been placed in if.else. +;; ╔═════════════╦══════════════════════════╦═════════════════╦══════════════════════════╗ +;; ║ block ║ in ║ def ║ out ║ +;; ╠═════════════╬══════════════════════════╬═════════════════╬══════════════════════════╣ +;; ║ entry ║ ║ mem=!74 dbg=!74 ║ mem=!74 dbg=!74 loc=mem ║ +;; ║ if.else ║ mem=!74 dbg=!74 loc=mem ║ mem=!74 dbg=!74 ║ mem=!74 dbg=!74 loc=mem ║ +;; ║ do.end6 ║ mem=!74 dbg=!74 loc=mem ║ dbg=!74 ║ mem=!74 dbg=!74 loc=mem ║ +;; ╚═════════════╩══════════════════════════╩═════════════════╩══════════════════════════╝ +;; +;; Variable 'e' (!75) +;; mem defs in entry, if.then and if.else with same ID (!77). Check these join correct +;; (tested using the dbg defs of the same ID - the memory location is valid at each of +;; these with that ID). +;; ╔═════════════╦══════════════════════════╦═════════════════╦══════════════════════════╗ +;; ║ block ║ in ║ def ║ out ║ +;; ╠═════════════╬══════════════════════════╬═════════════════╬══════════════════════════╣ +;; ║ entry ║ ║ mem=!77 dbg=!78 ║ mem=!77 dbg=!78 loc=val ║ +;; ║ do.body ║ mem=!77 dbg=phi loc=none ║ dbg=!77 ║ mem=!77 dbg=!77 loc=mem ║ +;; ║ do.body1 ║ mem=!77 dbg=!77 loc=mem ║ dbg=!77 ║ mem=!77 dbg=!77 loc=mem ║ +;; ║ if.then ║ mem=!77 dbg=!77 loc=mem ║ mem=!77 ║ mem=!77 dbg=!77 loc=mem ║ +;; ║ if.else ║ mem=!77 dbg=!77 loc=mem ║ mem=!77 ║ mem=!77 dbg=!77 loc=mem ║ +;; ╚═════════════╩══════════════════════════╩═════════════════╩══════════════════════════╝ +;; +;; Variable 'f' (!79) +;; mem def in entry and an untagged store in if.else (results in mem=phi, dbg=phi defs). +;; Use dbg defs in do.body, do.body1, do.cond and do.end6 to check the phi-ness +;; has been propagated (the memory loc at each is not a valid location). Check the memory +;; loc is used in if.else after the untagged store. +;; ╔═════════════╦══════════════════════════╦═════════════════╦══════════════════════════╗ +;; ║ block ║ in ║ def ║ out ║ +;; ╠═════════════╬══════════════════════════╬═════════════════╬══════════════════════════╣ +;; ║ entry ║ ║ mem=!81 dbg=!81 ║ mem=!81 dbg=!81 loc=mem ║ +;; ║ do.body ║ mem=phi dbg=phi loc=none ║ dbg=!81 ║ mem=phi dbg=!81 loc=val ║ +;; ║ do.body1 ║ mem=phi dbg=phi loc=none ║ dbg=!81 ║ mem=phi dbg=!81 loc=val ║ +;; ║ if.else ║ mem=phi dbg=phi loc=none ║ mem=phi dbg=phi ║ mem=phi dbg=phi loc=mem ║ +;; ║ do.cond ║ mem=phi dbg=phi loc=none ║ dbg=!81 ║ mem=phi dbg=!81 loc=val ║ +;; ║ do.end6 ║ mem=phi dbg=!81 loc=val ║ dbg=!81 ║ mem=!69 dbg=!81 loc=val ║ +;; ╚═════════════╩══════════════════════════╩═════════════════╩══════════════════════════╝ + +; CHECK-DAG: ![[a:[0-9]+]] = !DILocalVariable(name: "a", +; CHECK-DAG: ![[b:[0-9]+]] = !DILocalVariable(name: "b", +; CHECK-DAG: ![[c:[0-9]+]] = !DILocalVariable(name: "c", +; CHECK-DAG: ![[d:[0-9]+]] = !DILocalVariable(name: "d", +; CHECK-DAG: ![[e:[0-9]+]] = !DILocalVariable(name: "e", +; CHECK-DAG: ![[f:[0-9]+]] = !DILocalVariable(name: "f", + +;; Variables 'c' (!67) and 'd' (!72) are always stack-homed. +; CHECK: - { id: 2, name: c.addr, type: default, offset: 0, size: 4, alignment: 4, +; CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true, +; CHECK-NEXT: debug-info-variable: '![[c]]', debug-info-expression: '!DIExpression()', +; CHECK: - { id: 3, name: d.addr, type: default, offset: 0, size: 4, alignment: 4, +; CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true, +; CHECK-NEXT: debug-info-variable: '![[d]]', debug-info-expression: '!DIExpression()', + +source_filename = "test.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@g_a = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 +@g_b = dso_local local_unnamed_addr global i32 0, align 4, !dbg !5 +@g_c = dso_local local_unnamed_addr global i32 0, align 4, !dbg !8 + +define dso_local noundef i32 @_Z3funii(i32 noundef %a, i32 noundef %b) local_unnamed_addr #0 !dbg !17 { +entry: + %a.addr = alloca i32, align 4, !DIAssignID !58 ; VAR:a + call void @llvm.dbg.assign(metadata i1 undef, metadata !21, metadata !DIExpression(), metadata !58, metadata ptr %a.addr, metadata !DIExpression()), !dbg !27 ; VAR:a + %b.addr = alloca i32, align 4, !DIAssignID !64 ; VAR:b + call void @llvm.dbg.assign(metadata i1 undef, metadata !22, metadata !DIExpression(), metadata !64, metadata ptr %b.addr, metadata !DIExpression()), !dbg !27 ; VAR:b + %c.addr = alloca i32, align 4, !DIAssignID !68 ; VAR:c + call void @llvm.dbg.assign(metadata i1 undef, metadata !67, metadata !DIExpression(), metadata !68, metadata ptr %c.addr, metadata !DIExpression()), !dbg !27 ; VAR:c + %d.addr = alloca i32, align 4, !DIAssignID !73 ; VAR:d + call void @llvm.dbg.assign(metadata i1 undef, metadata !72, metadata !DIExpression(), metadata !73, metadata ptr %d.addr, metadata !DIExpression()), !dbg !27 ; VAR:d + %e.addr = alloca i32, align 4, !DIAssignID !76 ; VAR:e + call void @llvm.dbg.assign(metadata i1 undef, metadata !75, metadata !DIExpression(), metadata !76, metadata ptr %e.addr, metadata !DIExpression()), !dbg !27 ; VAR:e + %f.addr = alloca i32, align 4, !DIAssignID !80 ; VAR:f + call void @llvm.dbg.assign(metadata i1 undef, metadata !79, metadata !DIExpression(), metadata !80, metadata ptr %f.addr, metadata !DIExpression()), !dbg !27 ; VAR:f + store i32 1, ptr %a.addr, !DIAssignID !70 ; VAR:a + call void @llvm.dbg.assign(metadata i32 1, metadata !21, metadata !DIExpression(), metadata !70, metadata ptr %a.addr, metadata !DIExpression()), !dbg !27 ; VAR:a + store i32 2, ptr %b.addr, !DIAssignID !71 ; VAR:b + call void @llvm.dbg.assign(metadata i32 2, metadata !22, metadata !DIExpression(), metadata !71, metadata ptr %b.addr, metadata !DIExpression()), !dbg !27 ; VAR:b + store i32 9, ptr %e.addr, !DIAssignID !78 ; VAR:e + call void @llvm.dbg.assign(metadata i32 9, metadata !75, metadata !DIExpression(), metadata !78, metadata ptr %e.addr, metadata !DIExpression()), !dbg !27 ; VAR:c + store i32 3, ptr %a.addr, !DIAssignID !63 ; VAR:a + store i32 4, ptr %b.addr, !DIAssignID !65 ; VAR:b + store i32 5, ptr %c.addr, !DIAssignID !69 ; VAR:c + call void @llvm.dbg.assign(metadata i32 5, metadata !67, metadata !DIExpression(), metadata !69, metadata ptr %c.addr, metadata !DIExpression()), !dbg !27 ; VAR:c + store i32 6, ptr %d.addr, !DIAssignID !74 ; VAR:d + call void @llvm.dbg.assign(metadata i32 6, metadata !72, metadata !DIExpression(), metadata !74, metadata ptr %d.addr, metadata !DIExpression()), !dbg !27 ; VAR:d + store i32 8, ptr %e.addr, !DIAssignID !77 ; VAR:e + store i32 11, ptr %f.addr, !DIAssignID !81 ; VAR:f + call void @llvm.dbg.assign(metadata i32 11, metadata !79, metadata !DIExpression(), metadata !81, metadata ptr %f.addr, metadata !DIExpression()), !dbg !27 ; VAR:f + br label %do.body, !dbg !24 +; CHECK-LABEL: bb.0.entry: +; CHECK-NEXT: successors +; CHECK-NEXT: {{^ *$}} +; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[a]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: DBG_VALUE %stack.1.b.addr, $noreg, ![[b]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: DBG_VALUE %stack.4.e.addr, $noreg, ![[e]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: DBG_VALUE %stack.5.f.addr, $noreg, ![[f]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: MOV32mi %stack.0.a.addr, 1, $noreg, 0, $noreg, 3 +; CHECK-NEXT: DBG_VALUE 1, $noreg, ![[a]], !DIExpression() +; CHECK-NEXT: MOV32mi %stack.1.b.addr, 1, $noreg, 0, $noreg, 4 +; CHECK-NEXT: DBG_VALUE 2, $noreg, ![[b]], !DIExpression() +; CHECK-NEXT: MOV32mi %stack.2.c.addr, 1, $noreg, 0, $noreg, 5 +; CHECK-NEXT: MOV32mi %stack.3.d.addr, 1, $noreg, 0, $noreg, 6 +; CHECK-NEXT: MOV32mi %stack.4.e.addr, 1, $noreg, 0, $noreg, 8 +; CHECK-NEXT: DBG_VALUE 9, $noreg, ![[e]], !DIExpression() +; CHECK-NEXT: MOV32mi %stack.5.f.addr, 1, $noreg, 0, $noreg, 11 +; CHECK-NEXT: {{^ *$}} + +do.body: ; preds = %do.cond4, %entry + call void @llvm.dbg.assign(metadata i32 8, metadata !75, metadata !DIExpression(), metadata !77, metadata ptr %e.addr, metadata !DIExpression()), !dbg !27 ; VAR:e + call void @llvm.dbg.assign(metadata i32 11, metadata !79, metadata !DIExpression(), metadata !81, metadata ptr %f.addr, metadata !DIExpression()), !dbg !27 ; VAR:f + %.pre10 = load i32, ptr @g_a, align 4, !dbg !27 + br label %do.body1, !dbg !34 +; CHECK-LABEL: bb.1.do.body: +; CHECK-NEXT: successors +; CHECK-NEXT: {{^ *$}} +; CHECK-NEXT: DBG_VALUE %stack.4.e.addr, $noreg, ![[e]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: DBG_VALUE 11, $noreg, ![[f]], !DIExpression() +; CHECK-NEXT: %0:gr32 = MOV32rm $rip, 1, $noreg, @g_a, $noreg +; CHECK-NEXT: {{^ *$}} + +do.body1: ; preds = %do.cond, %do.body + %0 = phi i32 [ %.pre10, %do.body ], [ %1, %do.cond ], !dbg !27 + call void @llvm.dbg.assign(metadata i32 8, metadata !75, metadata !DIExpression(), metadata !77, metadata ptr %e.addr, metadata !DIExpression()), !dbg !27 ; VAR:e + call void @llvm.dbg.assign(metadata i32 11, metadata !79, metadata !DIExpression(), metadata !81, metadata ptr %f.addr, metadata !DIExpression()), !dbg !27 ; VAR:f + %tobool.not = icmp eq i32 %0, 0, !dbg !27 + br i1 %tobool.not, label %if.else, label %if.then, !dbg !35 +; CHECK-LABEL: bb.2.do.body1: +; CHECK-NEXT: successors +; CHECK-NEXT: {{^ *$}} +; CHECK: DBG_VALUE %stack.4.e.addr, $noreg, ![[e]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: DBG_VALUE 11, $noreg, ![[f]], !DIExpression() +; CHECK: JMP_1 +; CHECK-NEXT: {{^ *$}} + +if.then: ; preds = %do.body1 + %.pre = load i32, ptr @g_a, align 4, !dbg !27 + store i32 %.pre, ptr %b.addr, !DIAssignID !66 ; VAR:b + call void @llvm.dbg.assign(metadata i32 %.pre, metadata !22, metadata !DIExpression(), metadata !66, metadata ptr %b.addr, metadata !DIExpression()), !dbg !27 ; VAR:b + store i32 8, ptr %e.addr, !DIAssignID !77 ; VAR:e + br label %do.cond, !dbg !39 +; CHECK-LABEL: bb.3.if.then: +; CHECK-NEXT: successors +; CHECK-NEXT: {{^ *$}} +; CHECK-NEXT: %5:gr32 = MOV32rm +; CHECK-NEXT: MOV32mr %stack.1.b.addr, 1, $noreg, 0, $noreg, killed %5 +; CHECK-NEXT: DBG_VALUE %stack.1.b.addr, $noreg, ![[b]], !DIExpression(DW_OP_deref +; CHECK-NEXT: MOV32mi %stack.4.e.addr, 1, $noreg, 0, $noreg, 8 +; CHECK-NEXT: DBG_VALUE %stack.4.e.addr, $noreg, ![[e]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: JMP_1 %bb.5 +; CHECK-NEXT: {{^ *$}} + +if.else: ; preds = %do.body1 + store i32 6, ptr %d.addr, !DIAssignID !74 ; VAR:d + call void @llvm.dbg.assign(metadata i32 6, metadata !72, metadata !DIExpression(), metadata !74, metadata ptr %d.addr, metadata !DIExpression()), !dbg !27 ; VAR:d + store i32 8, ptr %e.addr, !DIAssignID !77 ; VAR:e + store i32 10, ptr %f.addr ; VAR:f + br label %do.cond +; CHECK-LABEL: bb.4.if.else: +; CHECK-NEXT: successors +; CHECK-NEXT: {{^ *$}} +; CHECK-NEXT: MOV32mi %stack.3.d.addr, 1, $noreg, 0, $noreg, 6 +; CHECK-NEXT: MOV32mi %stack.4.e.addr, 1, $noreg, 0, $noreg, 8 +; CHECK-NEXT: DBG_VALUE %stack.4.e.addr, $noreg, ![[e]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: MOV32mi %stack.5.f.addr, 1, $noreg, 0, $noreg, 10 +; CHECK-NEXT: DBG_VALUE %stack.5.f.addr, $noreg, !36, !DIExpression(DW_OP_deref) +; CHECK-NEXT: {{^ *$}} + +do.cond: ; preds = %if.then, %if.else + call void @llvm.dbg.assign(metadata i1 undef, metadata !67, metadata !DIExpression(), metadata !69, metadata ptr %c.addr, metadata !DIExpression()), !dbg !27 ; VAR:c + call void @llvm.dbg.assign(metadata i32 11, metadata !79, metadata !DIExpression(), metadata !81, metadata ptr %f.addr, metadata !DIExpression()), !dbg !27 ; VAR:f + %1 = load i32, ptr @g_b, align 4, !dbg !43 + %tobool3.not = icmp eq i32 %1, 0, !dbg !43 + br i1 %tobool3.not, label %do.cond4, label %do.body1, !dbg !44, !llvm.loop !45 +; CHECK-LABEL: bb.5.do.cond: +; CHECK-NEXT: successors +; CHECK-NEXT: {{^ *$}} +; CHECK-NEXT: DBG_VALUE 11, $noreg, ![[f]], !DIExpression() +; CHECK: {{^ *$}} + +do.cond4: ; preds = %do.cond + %2 = load i32, ptr @g_c, align 4, !dbg !48 + %tobool5.not = icmp eq i32 %2, 0, !dbg !48 + br i1 %tobool5.not, label %do.end6, label %do.body, !dbg !49, !llvm.loop !50 +; CHECK-LABEL: bb.6.do.cond4: +; CHECK-NEXT: successors +; CHECK-NEXT: {{^ *$}} +; CHECK-NOT: DBG +; CHECK: {{^ *$}} + +do.end6: ; preds = %do.cond4 + call void @llvm.dbg.assign(metadata i32 3, metadata !21, metadata !DIExpression(), metadata !63, metadata ptr %a.addr, metadata !DIExpression()), !dbg !27; VAR:a + call void @llvm.dbg.assign(metadata i32 4, metadata !22, metadata !DIExpression(), metadata !65, metadata ptr %b.addr, metadata !DIExpression()), !dbg !27 ; VAR:b + call void @llvm.dbg.assign(metadata i1 undef, metadata !67, metadata !DIExpression(), metadata !69, metadata ptr %c.addr, metadata !DIExpression()), !dbg !27 ; VAR:c + call void @llvm.dbg.assign(metadata i32 6, metadata !72, metadata !DIExpression(), metadata !74, metadata ptr %d.addr, metadata !DIExpression()), !dbg !27 ; VAR:d + call void @llvm.dbg.assign(metadata i32 11, metadata !79, metadata !DIExpression(), metadata !81, metadata ptr %f.addr, metadata !DIExpression()), !dbg !27 ; VAR:f + ret i32 0, !dbg !53 +; CHECK-LABEL: bb.7.do.end6: +; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[a]], !DIExpression(DW_OP_deref) +; CHECK-NEXT: DBG_VALUE 4, $noreg, ![[b]], !DIExpression() +; CHECK-NEXT: DBG_VALUE 11, $noreg, ![[f]], !DIExpression() +} + +declare !dbg !54 void @_Z4calli(i32 noundef) local_unnamed_addr #1 +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @llvm.dbg.value(metadata, metadata, metadata) +declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12, !13, !14, !15} +!llvm.ident = !{!16} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g_a", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 16.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.cpp", directory: "/") +!4 = !{!0, !5, !8} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "g_b", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression()) +!9 = distinct !DIGlobalVariable(name: "g_c", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!10 = !{i32 7, !"Dwarf Version", i32 5} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{i32 8, !"PIC Level", i32 2} +!14 = !{i32 7, !"PIE Level", i32 2} +!15 = !{i32 7, !"uwtable", i32 2} +!16 = !{!"clang version 16.0.0"} +!17 = distinct !DISubprogram(name: "fun", linkageName: "_Z3funii", scope: !3, file: !3, line: 3, type: !18, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !20) +!18 = !DISubroutineType(types: !19) +!19 = !{!7, !7, !7} +!20 = !{!21, !22} +!21 = !DILocalVariable(name: "a", arg: 1, scope: !17, file: !3, line: 3, type: !7) +!22 = !DILocalVariable(name: "b", arg: 2, scope: !17, file: !3, line: 3, type: !7) +!23 = !DILocation(line: 0, scope: !17) +!24 = !DILocation(line: 4, column: 3, scope: !17) +!25 = !DILocation(line: 5, column: 5, scope: !26) +!26 = distinct !DILexicalBlock(scope: !17, file: !3, line: 4, column: 6) +!27 = !DILocation(line: 7, column: 11, scope: !28) +!28 = distinct !DILexicalBlock(scope: !29, file: !3, line: 7, column: 11) +!29 = distinct !DILexicalBlock(scope: !26, file: !3, line: 6, column: 8) +!34 = !DILocation(line: 6, column: 5, scope: !26) +!35 = !DILocation(line: 7, column: 11, scope: !29) +!36 = !DILocation(line: 8, column: 11, scope: !37) +!37 = distinct !DILexicalBlock(scope: !28, file: !3, line: 7, column: 16) +!38 = !DILocation(line: 9, column: 9, scope: !37) +!39 = !DILocation(line: 10, column: 7, scope: !37) +!40 = !DILocation(line: 11, column: 11, scope: !41) +!41 = distinct !DILexicalBlock(scope: !28, file: !3, line: 10, column: 14) +!42 = !DILocation(line: 0, scope: !28) +!43 = !DILocation(line: 13, column: 14, scope: !26) +!44 = !DILocation(line: 13, column: 5, scope: !29) +!45 = distinct !{!45, !34, !46, !47} +!46 = !DILocation(line: 13, column: 17, scope: !26) +!47 = !{!"llvm.loop.mustprogress"} +!48 = !DILocation(line: 14, column: 12, scope: !17) +!49 = !DILocation(line: 14, column: 3, scope: !26) +!50 = distinct !{!50, !24, !51, !47} +!51 = !DILocation(line: 14, column: 15, scope: !17) +!52 = !DILocation(line: 15, column: 12, scope: !17) +!53 = !DILocation(line: 15, column: 3, scope: !17) +!54 = !DISubprogram(name: "call", linkageName: "_Z4calli", scope: !3, file: !3, line: 2, type: !55, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !57) +!55 = !DISubroutineType(types: !56) +!56 = !{null, !7} +!57 = !{} +!58 = distinct !DIAssignID() +!59 = !DILocalVariable(name: "Arr", scope: !17, file: !3, line: 4, type: !60) +!60 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 96, elements: !61) +!61 = !{!62} +!62 = !DISubrange(count: 3) +!63 = distinct !DIAssignID() +!64 = distinct !DIAssignID() +!65 = distinct !DIAssignID() +!66 = distinct !DIAssignID() +!67 = !DILocalVariable(name: "c", scope: !17, file: !3, line: 3, type: !7) +!68 = distinct !DIAssignID() +!69 = distinct !DIAssignID() +!70 = distinct !DIAssignID() +!71 = distinct !DIAssignID() +!72 = !DILocalVariable(name: "d", scope: !17, file: !3, line: 3, type: !7) +!73 = distinct !DIAssignID() +!74 = distinct !DIAssignID() +!75 = !DILocalVariable(name: "e", scope: !17, file: !3, line: 3, type: !7) +!76 = distinct !DIAssignID() +!77 = distinct !DIAssignID() +!78 = distinct !DIAssignID() +!79 = !DILocalVariable(name: "f", scope: !17, file: !3, line: 3, type: !7) +!80 = distinct !DIAssignID() +!81 = distinct !DIAssignID() Index: llvm/test/DebugInfo/assignment-tracking/X86/order-of-defs.ll =================================================================== --- llvm/test/DebugInfo/assignment-tracking/X86/order-of-defs.ll +++ llvm/test/DebugInfo/assignment-tracking/X86/order-of-defs.ll @@ -8,10 +8,10 @@ ; CHECK-DAG: ![[B:[0-9]+]] = !DILocalVariable(name: "b", ; CHECK-DAG: ![[C:[0-9]+]] = !DILocalVariable(name: "c", -; CHECK: DBG_VALUE $esi, $noreg, ![[B]], !DIExpression(), debug-location !20 -; CHECK-NEXT: DBG_VALUE $edx, $noreg, ![[C]], !DIExpression(), debug-location !20 -; CHECK-NEXT: DBG_VALUE $esi, $noreg, ![[A]], !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !20 -; CHECK-NEXT: DBG_VALUE $edx, $noreg, ![[A]], !DIExpression(DW_OP_LLVM_fragment, 32, 32), debug-location !20 +; CHECK: DBG_VALUE $esi, $noreg, ![[B]], !DIExpression() +; CHECK-NEXT: DBG_VALUE $edx, $noreg, ![[C]], !DIExpression() +; CHECK-NEXT: DBG_VALUE $esi, $noreg, ![[A]], !DIExpression(DW_OP_LLVM_fragment, 0, 32) +; CHECK-NEXT: DBG_VALUE $edx, $noreg, ![[A]], !DIExpression(DW_OP_LLVM_fragment, 32, 32) target triple = "x86_64-unknown-linux-gnu" Index: llvm/test/DebugInfo/assignment-tracking/X86/remove-redundant-defs-to-prevent-reordering.ll =================================================================== --- llvm/test/DebugInfo/assignment-tracking/X86/remove-redundant-defs-to-prevent-reordering.ll +++ llvm/test/DebugInfo/assignment-tracking/X86/remove-redundant-defs-to-prevent-reordering.ll @@ -17,7 +17,7 @@ ;; a += b; ;; return a; ;; } -;; An `dbg.assign(undef, ...)` has been added by hand in if.end. +;; A `dbg.assign(undef, ...)` has been added by hand in if.end. ;; For some variable we generate: ;; %inc = add nuw nsw i32 %i.0128, 1 Index: llvm/test/DebugInfo/assignment-tracking/X86/remove-undef-fragment.ll =================================================================== --- llvm/test/DebugInfo/assignment-tracking/X86/remove-undef-fragment.ll +++ llvm/test/DebugInfo/assignment-tracking/X86/remove-undef-fragment.ll @@ -67,9 +67,9 @@ define void @_Z1kv({ <2 x float>, <2 x float> } %call, <2 x float> %0, float %n.sroa.6.8.vec.extract) !dbg !7 { entry: - %call1 = tail call { <2 x float>, <2 x float> } undef(), !dbg !13 + %call1 = tail call { <2 x float>, <2 x float> } poison(), !dbg !13 %1 = extractvalue { <2 x float>, <2 x float> } %call, 1 - %add.i = fadd float undef, 0.000000e+00 + %add.i = fadd float poison, 0.000000e+00 call void @llvm.dbg.assign(metadata float %add.i, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !14, metadata ptr undef, metadata !DIExpression()), !dbg !15 %n.sroa.6.8.vec.extract2 = extractelement <2 x float> %0, i64 0 %add4.i = fadd float %n.sroa.6.8.vec.extract, 0.000000e+00 @@ -77,7 +77,7 @@ call void @llvm.dbg.assign(metadata float %add4.i, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 32), metadata !16, metadata ptr undef, metadata !DIExpression()), !dbg !15 %add.i23 = fadd float 0.000000e+00, 0.000000e+00 %ah.sroa.0.0.vec.insert = insertelement <2 x float> zeroinitializer, float %add4.i, i64 0 - tail call void undef(<2 x float> zeroinitializer, <2 x float> zeroinitializer, <2 x float> %ah.sroa.0.0.vec.insert, <2 x float> zeroinitializer) + tail call void poison(<2 x float> zeroinitializer, <2 x float> zeroinitializer, <2 x float> %ah.sroa.0.0.vec.insert, <2 x float> zeroinitializer) ret void } Index: llvm/test/DebugInfo/assignment-tracking/X86/untagged-store-frag.ll =================================================================== --- llvm/test/DebugInfo/assignment-tracking/X86/untagged-store-frag.ll +++ llvm/test/DebugInfo/assignment-tracking/X86/untagged-store-frag.ll @@ -34,6 +34,10 @@ ; CHECK-NEXT: MOV32mr %stack.0.a.addr, 1, $noreg, 4, $noreg, %1 :: (store (s32) into %ir.add.ptr, align 8) ; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[A]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 32, 32) +;; NOTE: The second and third DBG_VALUE combined make the first redundant. If +;; removeRedundantDbgInstrs gets smarter, add an instruction between the first +;; dbg.assign and the subsequent dbg.value. + target triple = "x86_64-unknown-linux-gnu" define dso_local noundef i64 @_Z1fl(i64 noundef %a, i32 %b) #0 !dbg !8 { Index: llvm/test/DebugInfo/assignment-tracking/X86/use-known-value-at-early-mem-def.ll =================================================================== --- llvm/test/DebugInfo/assignment-tracking/X86/use-known-value-at-early-mem-def.ll +++ llvm/test/DebugInfo/assignment-tracking/X86/use-known-value-at-early-mem-def.ll @@ -2,7 +2,7 @@ ; RUN: -experimental-assignment-tracking \ ; RUN: | FileCheck %s --implicit-check-not=DBG_VALUE -;; Check that sandwitching instructions between a linked store and dbg.assign +;; Check that sandwiching instructions between a linked store and dbg.assign ;; results in a dbg.value(prev_value) being inserted at the store, and a ;; dbg.value(deref) at the dbg.assign.