[llvm] [DebugInfo][RemoveDIs] Instrument MergeFunctions for DPValues (PR #80974)
Jeremy Morse via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 7 04:40:09 PST 2024
https://github.com/jmorse updated https://github.com/llvm/llvm-project/pull/80974
>From 7cb1cbab1526c5097c87e1941d6dd4ceb9e14272 Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Wed, 7 Feb 2024 11:15:51 +0000
Subject: [PATCH 1/2] [DebugInfo][RemoveDIs] Instrument MergeFunctions for
DPValues
The MergeFunctions pass has a "preserve some debug-info" mode that tries to
preserve parameter values. This patch generalises its decision-making so
that it applies to both debug-info stored in intrinsics, and debug-info
stored in DPValue objects. For the most part this involves using a generic
lambda and applying it to each type of object.
(Normally we avoid debug-info affecting the code generated, but this is
hidden behind a command line switch, so won't usually be encountered by
users).
---
llvm/lib/Transforms/IPO/MergeFunctions.cpp | 188 +++++++++++++--------
1 file changed, 119 insertions(+), 69 deletions(-)
diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index c8c011d94e4a3..e5138ccd3d359 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -256,15 +256,20 @@ class MergeFunctions {
/// Fill PDIUnrelatedWL with instructions from the entry block that are
/// unrelated to parameter related debug info.
+ /// \param PDPVUnrelatedWL The equivalent non-intrinsic debug records.
void filterInstsUnrelatedToPDI(BasicBlock *GEntryBlock,
- std::vector<Instruction *> &PDIUnrelatedWL);
+ std::vector<Instruction *> &PDIUnrelatedWL,
+ std::vector<DPValue *> &PDPVUnrelatedWL);
/// Erase the rest of the CFG (i.e. barring the entry block).
void eraseTail(Function *G);
/// Erase the instructions in PDIUnrelatedWL as they are unrelated to the
/// parameter debug info, from the entry block.
- void eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL);
+ /// \param PDPVUnrelatedWL contains the equivalent set of non-instruction
+ /// debug-info records.
+ void eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL,
+ std::vector<DPValue *> &PDPVUnrelatedWL);
/// Replace G with a simple tail call to bitcast(F). Also (unless
/// MergeFunctionsPDI holds) replace direct uses of G with bitcast(F),
@@ -506,7 +511,8 @@ static Value *createCast(IRBuilder<> &Builder, Value *V, Type *DestTy) {
// Erase the instructions in PDIUnrelatedWL as they are unrelated to the
// parameter debug info, from the entry block.
void MergeFunctions::eraseInstsUnrelatedToPDI(
- std::vector<Instruction *> &PDIUnrelatedWL) {
+ std::vector<Instruction *> &PDIUnrelatedWL,
+ std::vector<DPValue *> &PDPVUnrelatedWL) {
LLVM_DEBUG(
dbgs() << " Erasing instructions (in reverse order of appearance in "
"entry block) unrelated to parameter debug info from entry "
@@ -519,6 +525,16 @@ void MergeFunctions::eraseInstsUnrelatedToPDI(
I->eraseFromParent();
PDIUnrelatedWL.pop_back();
}
+
+ while (!PDPVUnrelatedWL.empty()) {
+ DPValue *DPV = PDPVUnrelatedWL.back();
+ LLVM_DEBUG(dbgs() << " Deleting DPValue ");
+ LLVM_DEBUG(DPV->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
+ DPV->eraseFromParent();
+ PDPVUnrelatedWL.pop_back();
+ }
+
LLVM_DEBUG(dbgs() << " } // Done erasing instructions unrelated to parameter "
"debug info from entry block. \n");
}
@@ -547,75 +563,99 @@ void MergeFunctions::eraseTail(Function *G) {
// The rest are unrelated to debug info for the parameters; fill up
// PDIUnrelatedWL with such instructions.
void MergeFunctions::filterInstsUnrelatedToPDI(
- BasicBlock *GEntryBlock, std::vector<Instruction *> &PDIUnrelatedWL) {
+ BasicBlock *GEntryBlock, std::vector<Instruction *> &PDIUnrelatedWL,
+ std::vector<DPValue *> &PDPVUnrelatedWL) {
std::set<Instruction *> PDIRelated;
- for (BasicBlock::iterator BI = GEntryBlock->begin(), BIE = GEntryBlock->end();
- BI != BIE; ++BI) {
- if (auto *DVI = dyn_cast<DbgValueInst>(&*BI)) {
- LLVM_DEBUG(dbgs() << " Deciding: ");
- LLVM_DEBUG(BI->print(dbgs()));
+ std::set<DPValue *> PDPVRelated;
+
+ // Work out whether a dbg.value intrinsic or an equivalent DPValue is a
+ // parameter to be preserved.
+ auto ExamineDbgValue = [](auto *DbgVal, auto &Container) {
+ LLVM_DEBUG(dbgs() << " Deciding: ");
+ LLVM_DEBUG(DbgVal->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
+ DILocalVariable *DILocVar = DbgVal->getVariable();
+ if (DILocVar->isParameter()) {
+ LLVM_DEBUG(dbgs() << " Include (parameter): ");
+ LLVM_DEBUG(DbgVal->print(dbgs()));
LLVM_DEBUG(dbgs() << "\n");
- DILocalVariable *DILocVar = DVI->getVariable();
- if (DILocVar->isParameter()) {
- LLVM_DEBUG(dbgs() << " Include (parameter): ");
- LLVM_DEBUG(BI->print(dbgs()));
- LLVM_DEBUG(dbgs() << "\n");
- PDIRelated.insert(&*BI);
- } else {
- LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
- LLVM_DEBUG(BI->print(dbgs()));
- LLVM_DEBUG(dbgs() << "\n");
- }
- } else if (auto *DDI = dyn_cast<DbgDeclareInst>(&*BI)) {
- LLVM_DEBUG(dbgs() << " Deciding: ");
- LLVM_DEBUG(BI->print(dbgs()));
+ Container.insert(DbgVal);
+ } else {
+ LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
+ LLVM_DEBUG(DbgVal->print(dbgs()));
LLVM_DEBUG(dbgs() << "\n");
- DILocalVariable *DILocVar = DDI->getVariable();
- if (DILocVar->isParameter()) {
- LLVM_DEBUG(dbgs() << " Parameter: ");
- LLVM_DEBUG(DILocVar->print(dbgs()));
- AllocaInst *AI = dyn_cast_or_null<AllocaInst>(DDI->getAddress());
- if (AI) {
- LLVM_DEBUG(dbgs() << " Processing alloca users: ");
- LLVM_DEBUG(dbgs() << "\n");
- for (User *U : AI->users()) {
- if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
- if (Value *Arg = SI->getValueOperand()) {
- if (isa<Argument>(Arg)) {
- LLVM_DEBUG(dbgs() << " Include: ");
- LLVM_DEBUG(AI->print(dbgs()));
- LLVM_DEBUG(dbgs() << "\n");
- PDIRelated.insert(AI);
- LLVM_DEBUG(dbgs() << " Include (parameter): ");
- LLVM_DEBUG(SI->print(dbgs()));
- LLVM_DEBUG(dbgs() << "\n");
- PDIRelated.insert(SI);
- LLVM_DEBUG(dbgs() << " Include: ");
- LLVM_DEBUG(BI->print(dbgs()));
- LLVM_DEBUG(dbgs() << "\n");
- PDIRelated.insert(&*BI);
- } else {
- LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
- LLVM_DEBUG(SI->print(dbgs()));
- LLVM_DEBUG(dbgs() << "\n");
- }
+ }
+ };
+
+ auto ExamineDbgDeclare = [&PDIRelated](auto *DbgDecl, auto &Container) {
+ LLVM_DEBUG(dbgs() << " Deciding: ");
+ LLVM_DEBUG(DbgDecl->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
+ DILocalVariable *DILocVar = DbgDecl->getVariable();
+ if (DILocVar->isParameter()) {
+ LLVM_DEBUG(dbgs() << " Parameter: ");
+ LLVM_DEBUG(DILocVar->print(dbgs()));
+ AllocaInst *AI = dyn_cast_or_null<AllocaInst>(DbgDecl->getAddress());
+ if (AI) {
+ LLVM_DEBUG(dbgs() << " Processing alloca users: ");
+ LLVM_DEBUG(dbgs() << "\n");
+ for (User *U : AI->users()) {
+ if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
+ if (Value *Arg = SI->getValueOperand()) {
+ if (isa<Argument>(Arg)) {
+ LLVM_DEBUG(dbgs() << " Include: ");
+ LLVM_DEBUG(AI->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
+ PDIRelated.insert(AI);
+ LLVM_DEBUG(dbgs() << " Include (parameter): ");
+ LLVM_DEBUG(SI->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
+ PDIRelated.insert(SI);
+ LLVM_DEBUG(dbgs() << " Include: ");
+ LLVM_DEBUG(DbgDecl->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
+ Container.insert(DbgDecl);
+ } else {
+ LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
+ LLVM_DEBUG(SI->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
}
- } else {
- LLVM_DEBUG(dbgs() << " Defer: ");
- LLVM_DEBUG(U->print(dbgs()));
- LLVM_DEBUG(dbgs() << "\n");
}
+ } else {
+ LLVM_DEBUG(dbgs() << " Defer: ");
+ LLVM_DEBUG(U->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
}
- } else {
- LLVM_DEBUG(dbgs() << " Delete (alloca NULL): ");
- LLVM_DEBUG(BI->print(dbgs()));
- LLVM_DEBUG(dbgs() << "\n");
}
} else {
- LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
- LLVM_DEBUG(BI->print(dbgs()));
+ LLVM_DEBUG(dbgs() << " Delete (alloca NULL): ");
+ LLVM_DEBUG(DbgDecl->print(dbgs()));
LLVM_DEBUG(dbgs() << "\n");
}
+ } else {
+ LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
+ LLVM_DEBUG(DbgDecl->print(dbgs()));
+ LLVM_DEBUG(dbgs() << "\n");
+ }
+ };
+
+ for (BasicBlock::iterator BI = GEntryBlock->begin(), BIE = GEntryBlock->end();
+ BI != BIE; ++BI) {
+ // Examine DPValues as they happen "before" the instruction. Are they
+ // connected to parameters?
+ for (DPValue &DPV : BI->getDbgValueRange()) {
+ if (DPV.isDbgValue() || DPV.isDbgAssign()) {
+ ExamineDbgValue(&DPV, PDPVRelated);
+ } else {
+ assert(DPV.isDbgDeclare());
+ ExamineDbgDeclare(&DPV, PDPVRelated);
+ }
+ }
+
+ if (auto *DVI = dyn_cast<DbgValueInst>(&*BI)) {
+ ExamineDbgValue(DVI, PDIRelated);
+ } else if (auto *DDI = dyn_cast<DbgDeclareInst>(&*BI)) {
+ ExamineDbgDeclare(DDI, PDIRelated);
} else if (BI->isTerminator() && &*BI == GEntryBlock->getTerminator()) {
LLVM_DEBUG(dbgs() << " Will Include Terminator: ");
LLVM_DEBUG(BI->print(dbgs()));
@@ -630,17 +670,26 @@ void MergeFunctions::filterInstsUnrelatedToPDI(
LLVM_DEBUG(
dbgs()
<< " Report parameter debug info related/related instructions: {\n");
- for (Instruction &I : *GEntryBlock) {
- if (PDIRelated.find(&I) == PDIRelated.end()) {
+
+ auto IsPDIRelated = [](auto *Rec, auto &Container, auto &UnrelatedCont) {
+ if (Container.find(Rec) == Container.end()) {
LLVM_DEBUG(dbgs() << " !PDIRelated: ");
- LLVM_DEBUG(I.print(dbgs()));
+ LLVM_DEBUG(Rec->print(dbgs()));
LLVM_DEBUG(dbgs() << "\n");
- PDIUnrelatedWL.push_back(&I);
+ UnrelatedCont.push_back(Rec);
} else {
LLVM_DEBUG(dbgs() << " PDIRelated: ");
- LLVM_DEBUG(I.print(dbgs()));
+ LLVM_DEBUG(Rec->print(dbgs()));
LLVM_DEBUG(dbgs() << "\n");
}
+ };
+
+ // Collect the set of unrelated instructions and debug records.
+ for (Instruction &I : *GEntryBlock) {
+ for (auto &DPV : I.getDbgValueRange()) {
+ IsPDIRelated(&DPV, PDPVRelated, PDPVUnrelatedWL);
+ }
+ IsPDIRelated(&I, PDIRelated, PDIUnrelatedWL);
}
LLVM_DEBUG(dbgs() << " }\n");
}
@@ -680,6 +729,7 @@ static void copyMetadataIfPresent(Function *From, Function *To, StringRef Key) {
void MergeFunctions::writeThunk(Function *F, Function *G) {
BasicBlock *GEntryBlock = nullptr;
std::vector<Instruction *> PDIUnrelatedWL;
+ std::vector<DPValue *> PDPVUnrelatedWL;
BasicBlock *BB = nullptr;
Function *NewG = nullptr;
if (MergeFunctionsPDI) {
@@ -691,7 +741,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
dbgs() << "writeThunk: (MergeFunctionsPDI) filter parameter related "
"debug info for "
<< G->getName() << "() {\n");
- filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL);
+ filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL, PDPVUnrelatedWL);
GEntryBlock->getTerminator()->eraseFromParent();
BB = GEntryBlock;
} else {
@@ -740,7 +790,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
<< G->getName() << "()\n");
}
eraseTail(G);
- eraseInstsUnrelatedToPDI(PDIUnrelatedWL);
+ eraseInstsUnrelatedToPDI(PDIUnrelatedWL, PDPVUnrelatedWL);
LLVM_DEBUG(
dbgs() << "} // End of parameter related debug info filtering for: "
<< G->getName() << "()\n");
>From e1086fa4bba8f4722a2dd4547f7eb7cfa21edc1c Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Wed, 7 Feb 2024 12:39:28 +0000
Subject: [PATCH 2/2] Remember to add some test coverage
---
.../Transforms/MergeFunc/mergefunc-preserve-debug-info.ll | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/llvm/test/Transforms/MergeFunc/mergefunc-preserve-debug-info.ll b/llvm/test/Transforms/MergeFunc/mergefunc-preserve-debug-info.ll
index 72aa647ae0b2b..9208476a27429 100644
--- a/llvm/test/Transforms/MergeFunc/mergefunc-preserve-debug-info.ll
+++ b/llvm/test/Transforms/MergeFunc/mergefunc-preserve-debug-info.ll
@@ -2,6 +2,10 @@
; RUN: opt -passes='default<O0>,mergefunc' -S -mergefunc-preserve-debug-info < %s | FileCheck %s --check-prefix=OPTIMIZATION_LEVEL_0
; RUN: opt -passes='default<O2>,mergefunc' -S -mergefunc-preserve-debug-info < %s | FileCheck %s --check-prefix=OPTIMIZATION_LEVEL_2
+;; Does this continue to work under non-intrinsic debug-info?
+; RUN: opt -passes='default<O0>,mergefunc' -S -mergefunc-preserve-debug-info < %s --try-experimental-debuginfo-iterators | FileCheck %s --check-prefix=OPTIMIZATION_LEVEL_0
+; RUN: opt -passes='default<O2>,mergefunc' -S -mergefunc-preserve-debug-info < %s --try-experimental-debuginfo-iterators | FileCheck %s --check-prefix=OPTIMIZATION_LEVEL_2
+
; Preserve debug info in thunks under -passes=mergefunc -mergefunc-preserve-debug-info
;
; We test that:
More information about the llvm-commits
mailing list