Skip to content

Commit 4259198

Browse files
committed
[DebugInfo][RemoveDIs] Support finding DPValues like dbg.values (#71952)
This patch extends findDbgValue and friends to optionally fill out a vector of DPValue pointers, containing DPValues that refer to the sought Value. This will allow us to incrementally add instrumentation to other optimisation passes one-at-a-time, while un-instrumented passes will not (yet) update DPValues. Unit tests to check this behaves in the same way as dbg.values.
1 parent 89b0f1e commit 4259198

File tree

5 files changed

+167
-10
lines changed

5 files changed

+167
-10
lines changed

llvm/include/llvm/IR/DebugInfo.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace llvm {
3434
class DbgDeclareInst;
3535
class DbgValueInst;
3636
class DbgVariableIntrinsic;
37+
class DPValue;
3738
class Instruction;
3839
class Module;
3940

@@ -42,10 +43,12 @@ class Module;
4243
TinyPtrVector<DbgDeclareInst *> FindDbgDeclareUses(Value *V);
4344

4445
/// Finds the llvm.dbg.value intrinsics describing a value.
45-
void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V);
46+
void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues,
47+
Value *V, SmallVectorImpl<DPValue *> *DPValues = nullptr);
4648

4749
/// Finds the debug info intrinsics describing a value.
48-
void findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgInsts, Value *V);
50+
void findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgInsts,
51+
Value *V, SmallVectorImpl<DPValue *> *DPValues = nullptr);
4952

5053
/// Find subprogram that is enclosing this scope.
5154
DISubprogram *getDISubprogram(const MDNode *Scope);

llvm/lib/IR/DebugInfo.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/IR/DebugInfo.h"
2626
#include "llvm/IR/DebugInfoMetadata.h"
2727
#include "llvm/IR/DebugLoc.h"
28+
#include "llvm/IR/DebugProgramInstruction.h"
2829
#include "llvm/IR/Function.h"
2930
#include "llvm/IR/GVMaterializer.h"
3031
#include "llvm/IR/Instruction.h"
@@ -65,7 +66,8 @@ TinyPtrVector<DbgDeclareInst *> llvm::FindDbgDeclareUses(Value *V) {
6566
}
6667

6768
template <typename IntrinsicT>
68-
static void findDbgIntrinsics(SmallVectorImpl<IntrinsicT *> &Result, Value *V) {
69+
static void findDbgIntrinsics(SmallVectorImpl<IntrinsicT *> &Result,
70+
Value *V, SmallVectorImpl<DPValue *> *DPValues) {
6971
// This function is hot. Check whether the value has any metadata to avoid a
7072
// DenseMap lookup.
7173
if (!V->isUsedByMetadata())
@@ -78,31 +80,51 @@ static void findDbgIntrinsics(SmallVectorImpl<IntrinsicT *> &Result, Value *V) {
7880
// V will also appear twice in a dbg.assign if its used in the both the value
7981
// and address components.
8082
SmallPtrSet<IntrinsicT *, 4> EncounteredIntrinsics;
83+
SmallPtrSet<DPValue *, 4> EncounteredDPValues;
8184

8285
/// Append IntrinsicT users of MetadataAsValue(MD).
83-
auto AppendUsers = [&Ctx, &EncounteredIntrinsics, &Result](Metadata *MD) {
86+
auto AppendUsers = [&Ctx, &EncounteredIntrinsics, &Result,
87+
DPValues](Metadata *MD) {
8488
if (auto *MDV = MetadataAsValue::getIfExists(Ctx, MD)) {
8589
for (User *U : MDV->users())
8690
if (IntrinsicT *DVI = dyn_cast<IntrinsicT>(U))
8791
if (EncounteredIntrinsics.insert(DVI).second)
8892
Result.push_back(DVI);
8993
}
94+
if (!DPValues)
95+
return;
96+
// Get DPValues that use this as a single value.
97+
if (LocalAsMetadata *L = dyn_cast<LocalAsMetadata>(MD)) {
98+
for (DPValue *DPV : L->getAllDPValueUsers()) {
99+
if (DPV->getType() == DPValue::LocationType::Value)
100+
DPValues->push_back(DPV);
101+
}
102+
}
90103
};
91104

92105
if (auto *L = LocalAsMetadata::getIfExists(V)) {
93106
AppendUsers(L);
94-
for (Metadata *AL : L->getAllArgListUsers())
107+
for (Metadata *AL : L->getAllArgListUsers()) {
95108
AppendUsers(AL);
109+
if (!DPValues)
110+
continue;
111+
DIArgList *DI = cast<DIArgList>(AL);
112+
for (DPValue *DPV : DI->getAllDPValueUsers())
113+
if (DPV->getType() == DPValue::LocationType::Value)
114+
if (EncounteredDPValues.insert(DPV).second)
115+
DPValues->push_back(DPV);
116+
}
96117
}
97118
}
98119

99-
void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V) {
100-
findDbgIntrinsics<DbgValueInst>(DbgValues, V);
120+
void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues,
121+
Value *V, SmallVectorImpl<DPValue *> *DPValues) {
122+
findDbgIntrinsics<DbgValueInst>(DbgValues, V, DPValues);
101123
}
102124

103125
void llvm::findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers,
104-
Value *V) {
105-
findDbgIntrinsics<DbgVariableIntrinsic>(DbgUsers, V);
126+
Value *V, SmallVectorImpl<DPValue *> *DPValues) {
127+
findDbgIntrinsics<DbgVariableIntrinsic>(DbgUsers, V, DPValues);
106128
}
107129

108130
DISubprogram *llvm::getDISubprogram(const MDNode *Scope) {

llvm/lib/IR/Value.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,11 +574,17 @@ void Value::replaceUsesWithIf(Value *New,
574574
/// with New.
575575
static void replaceDbgUsesOutsideBlock(Value *V, Value *New, BasicBlock *BB) {
576576
SmallVector<DbgVariableIntrinsic *> DbgUsers;
577-
findDbgUsers(DbgUsers, V);
577+
SmallVector<DPValue *> DPUsers;
578+
findDbgUsers(DbgUsers, V, &DPUsers);
578579
for (auto *DVI : DbgUsers) {
579580
if (DVI->getParent() != BB)
580581
DVI->replaceVariableLocationOp(V, New);
581582
}
583+
for (auto *DPV : DPUsers) {
584+
DPMarker *Marker = DPV->getMarker();
585+
if (Marker->getParent() != BB)
586+
DPV->replaceVariableLocationOp(V, New);
587+
}
582588
}
583589

584590
// Like replaceAllUsesWith except it does not handle constants or basic blocks.

llvm/unittests/IR/DebugInfoTest.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,56 @@ TEST(DbgVariableIntrinsic, EmptyMDIsKillLocation) {
234234
EXPECT_TRUE(DbgDeclare->isKillLocation());
235235
}
236236

237+
// Duplicate of above test, but in DPValue representation.
238+
TEST(MetadataTest, DeleteInstUsedByDPValue) {
239+
LLVMContext C;
240+
std::unique_ptr<Module> M = parseIR(C, R"(
241+
define i16 @f(i16 %a) !dbg !6 {
242+
%b = add i16 %a, 1, !dbg !11
243+
call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
244+
call void @llvm.dbg.value(metadata !DIArgList(i16 %a, i16 %b), metadata !9, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)), !dbg !11
245+
ret i16 0, !dbg !11
246+
}
247+
declare void @llvm.dbg.value(metadata, metadata, metadata) #0
248+
attributes #0 = { nounwind readnone speculatable willreturn }
249+
250+
!llvm.dbg.cu = !{!0}
251+
!llvm.module.flags = !{!5}
252+
253+
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
254+
!1 = !DIFile(filename: "t.ll", directory: "/")
255+
!2 = !{}
256+
!5 = !{i32 2, !"Debug Info Version", i32 3}
257+
!6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
258+
!7 = !DISubroutineType(types: !2)
259+
!8 = !{!9}
260+
!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
261+
!10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
262+
!11 = !DILocation(line: 1, column: 1, scope: !6)
263+
)");
264+
265+
bool OldDbgValueMode = UseNewDbgInfoFormat;
266+
UseNewDbgInfoFormat = true;
267+
Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI();
268+
M->convertToNewDbgValues();
269+
270+
// Find the DPValues using %b.
271+
SmallVector<DbgValueInst *, 2> DVIs;
272+
SmallVector<DPValue *, 2> DPVs;
273+
findDbgValues(DVIs, &I, &DPVs);
274+
ASSERT_EQ(DPVs.size(), 2u);
275+
276+
// Delete %b. The DPValue should now point to undef.
277+
I.eraseFromParent();
278+
EXPECT_EQ(DPVs[0]->getNumVariableLocationOps(), 1u);
279+
EXPECT_TRUE(isa<UndefValue>(DPVs[0]->getVariableLocationOp(0)));
280+
EXPECT_TRUE(DPVs[0]->isKillLocation());
281+
EXPECT_EQ(DPVs[1]->getNumVariableLocationOps(), 2u);
282+
EXPECT_TRUE(isa<UndefValue>(DPVs[1]->getVariableLocationOp(1)));
283+
EXPECT_TRUE(DPVs[1]->isKillLocation());
284+
UseNewDbgInfoFormat = OldDbgValueMode;
285+
}
286+
237287
TEST(DIBuiler, CreateFile) {
238288
LLVMContext Ctx;
239289
std::unique_ptr<Module> M(new Module("MyModule", Ctx));

llvm/unittests/IR/ValueTest.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "gtest/gtest.h"
1818
using namespace llvm;
1919

20+
extern cl::opt<bool> UseNewDbgInfoFormat;
21+
2022
namespace {
2123

2224
TEST(ValueTest, UsedInBasicBlock) {
@@ -314,4 +316,78 @@ TEST(ValueTest, replaceUsesOutsideBlock) {
314316
ASSERT_TRUE(ExitDbg->getValue(0) == cast<Value>(B));
315317
ASSERT_TRUE(Ret->getOperand(0) == cast<Value>(B));
316318
}
319+
320+
TEST(ValueTest, replaceUsesOutsideBlockDPValue) {
321+
// Check that Value::replaceUsesOutsideBlock(New, BB) replaces uses outside
322+
// BB, including DPValues.
323+
const auto *IR = R"(
324+
define i32 @f() !dbg !6 {
325+
entry:
326+
%a = add i32 0, 1, !dbg !15
327+
%b = add i32 0, 2, !dbg !15
328+
%c = add i32 %a, 2, !dbg !15
329+
call void @llvm.dbg.value(metadata i32 %a, metadata !9, metadata !DIExpression()), !dbg !15
330+
br label %exit, !dbg !15
331+
332+
exit:
333+
call void @llvm.dbg.value(metadata i32 %a, metadata !11, metadata !DIExpression()), !dbg !16
334+
ret i32 %a, !dbg !16
335+
}
336+
337+
declare void @llvm.dbg.value(metadata, metadata, metadata)
338+
339+
!llvm.dbg.cu = !{!0}
340+
!llvm.module.flags = !{!5}
341+
342+
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
343+
!1 = !DIFile(filename: "test.ll", directory: "/")
344+
!2 = !{}
345+
!5 = !{i32 2, !"Debug Info Version", i32 3}
346+
!6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)
347+
!7 = !DISubroutineType(types: !2)
348+
!8 = !{!9, !11}
349+
!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
350+
!10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_signed)
351+
!11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 2, type: !12)
352+
!12 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_signed)
353+
!15 = !DILocation(line: 1, column: 1, scope: !6)
354+
!16 = !DILocation(line: 5, column: 1, scope: !6)
355+
)";
356+
LLVMContext Ctx;
357+
SMDiagnostic Err;
358+
std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Ctx);
359+
if (!M)
360+
Err.print("ValueTest", errs());
361+
362+
bool OldDbgValueMode = UseNewDbgInfoFormat;
363+
UseNewDbgInfoFormat = true;
364+
M->convertToNewDbgValues();
365+
366+
auto GetNext = [](auto *I) { return &*++I->getIterator(); };
367+
368+
Function *F = M->getFunction("f");
369+
// Entry.
370+
BasicBlock *Entry = &F->front();
371+
Instruction *A = &Entry->front();
372+
Instruction *B = GetNext(A);
373+
Instruction *C = GetNext(B);
374+
Instruction *Branch = GetNext(C);
375+
// Exit.
376+
BasicBlock *Exit = GetNext(Entry);
377+
Instruction *Ret = &Exit->front();
378+
379+
EXPECT_TRUE(Branch->hasDbgValues());
380+
EXPECT_TRUE(Ret->hasDbgValues());
381+
382+
DPValue *DPV1 = &*Branch->getDbgValueRange().begin();
383+
DPValue *DPV2 = &*Ret->getDbgValueRange().begin();
384+
385+
A->replaceUsesOutsideBlock(B, Entry);
386+
// These users are in Entry so shouldn't be changed.
387+
EXPECT_TRUE(DPV1->getVariableLocationOp(0) == cast<Value>(A));
388+
// These users are outside Entry so should be changed.
389+
EXPECT_TRUE(DPV2->getVariableLocationOp(0) == cast<Value>(B));
390+
UseNewDbgInfoFormat = OldDbgValueMode;
391+
}
392+
317393
} // end anonymous namespace

0 commit comments

Comments
 (0)