diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h --- a/llvm/include/llvm/IR/DebugInfo.h +++ b/llvm/include/llvm/IR/DebugInfo.h @@ -212,6 +212,9 @@ return make_range(Value::user_iterator(), Value::user_iterator()); } +/// Delete the llvm.dbg.assign intrinsics linked to \p Inst. +void deleteAssignmentMarkers(const Instruction *Inst); + /// Replace all uses (and attachments) of \p Old with \p New. void RAUW(DIAssignID *Old, DIAssignID *New); diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1661,6 +1661,15 @@ return make_range(IDAsValue->user_begin(), IDAsValue->user_end()); } +void at::deleteAssignmentMarkers(const Instruction *Inst) { + auto Range = getAssignmentMarkers(Inst); + if (Range.empty()) + return; + SmallVector ToDelete(Range.begin(), Range.end()); + for (auto *DAI : ToDelete) + DAI->eraseFromParent(); +} + void at::RAUW(DIAssignID *Old, DIAssignID *New) { // Replace MetadataAsValue uses. if (auto *OldIDAsValue = diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -398,6 +398,13 @@ ret void, !dbg !19 } + define dso_local void @fun3() !dbg !21 { + entry: + %local = alloca i32, align 4, !DIAssignID !24 + call void @llvm.dbg.assign(metadata i32 undef, metadata !22, metadata !DIExpression(), metadata !24, metadata i32* undef, metadata !DIExpression()), !dbg !23 + ret void + } + declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) !llvm.dbg.cu = !{!0} @@ -425,6 +432,10 @@ !18 = !DILocalVariable(name: "local2", scope: !17, file: !1, line: 2, type: !11) !19 = !DILocation(line: 4, column: 1, scope: !17) !20 = distinct !DIAssignID() + !21 = distinct !DISubprogram(name: "fun3", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) + !22 = !DILocalVariable(name: "local4", scope: !21, file: !1, line: 2, type: !11) + !23 = !DILocation(line: 4, column: 1, scope: !21) + !24 = distinct !DIAssignID() )"); // Check the test IR isn't malformed. @@ -483,7 +494,16 @@ ASSERT_TRUE(std::distance(Fun2Insts.begin(), Fun2Insts.end()) == 1); EXPECT_EQ(*Fun2Insts.begin(), &Fun2Alloca); - // 3. Check that deleting works and applies only to the target function. + // 3. Check that deleting dbg.assigns from a specific instruction works. + Instruction &Fun3Alloca = + *M->getFunction("fun3")->getEntryBlock().getFirstNonPHIOrDbg(); + auto Fun3Markers = at::getAssignmentMarkers(&Fun3Alloca); + ASSERT_TRUE(std::distance(Fun3Markers.begin(), Fun3Markers.end()) == 1); + at::deleteAssignmentMarkers(&Fun3Alloca); + Fun3Markers = at::getAssignmentMarkers(&Fun3Alloca); + EXPECT_EQ(Fun3Markers.empty(), true); + + // 4. Check that deleting works and applies only to the target function. at::deleteAll(&Fun1); // There should now only be the alloca and ret in fun1. EXPECT_EQ(Fun1.begin()->size(), 2u);