Skip to content

Commit 34f61cf

Browse files
authored
[DebugInfo][RemoveDIs] Instrument MergeFunctions for DPValues (#80974)
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). Note that this diff is messy, but that's because I'm hoisting some code into lambdas. The actual decision making processes here are identical.
1 parent e71a5f5 commit 34f61cf

File tree

2 files changed

+122
-69
lines changed

2 files changed

+122
-69
lines changed

llvm/lib/Transforms/IPO/MergeFunctions.cpp

Lines changed: 118 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,20 @@ class MergeFunctions {
256256

257257
/// Fill PDIUnrelatedWL with instructions from the entry block that are
258258
/// unrelated to parameter related debug info.
259+
/// \param PDPVUnrelatedWL The equivalent non-intrinsic debug records.
259260
void filterInstsUnrelatedToPDI(BasicBlock *GEntryBlock,
260-
std::vector<Instruction *> &PDIUnrelatedWL);
261+
std::vector<Instruction *> &PDIUnrelatedWL,
262+
std::vector<DPValue *> &PDPVUnrelatedWL);
261263

262264
/// Erase the rest of the CFG (i.e. barring the entry block).
263265
void eraseTail(Function *G);
264266

265267
/// Erase the instructions in PDIUnrelatedWL as they are unrelated to the
266268
/// parameter debug info, from the entry block.
267-
void eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL);
269+
/// \param PDPVUnrelatedWL contains the equivalent set of non-instruction
270+
/// debug-info records.
271+
void eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL,
272+
std::vector<DPValue *> &PDPVUnrelatedWL);
268273

269274
/// Replace G with a simple tail call to bitcast(F). Also (unless
270275
/// MergeFunctionsPDI holds) replace direct uses of G with bitcast(F),
@@ -506,7 +511,8 @@ static Value *createCast(IRBuilder<> &Builder, Value *V, Type *DestTy) {
506511
// Erase the instructions in PDIUnrelatedWL as they are unrelated to the
507512
// parameter debug info, from the entry block.
508513
void MergeFunctions::eraseInstsUnrelatedToPDI(
509-
std::vector<Instruction *> &PDIUnrelatedWL) {
514+
std::vector<Instruction *> &PDIUnrelatedWL,
515+
std::vector<DPValue *> &PDPVUnrelatedWL) {
510516
LLVM_DEBUG(
511517
dbgs() << " Erasing instructions (in reverse order of appearance in "
512518
"entry block) unrelated to parameter debug info from entry "
@@ -519,6 +525,16 @@ void MergeFunctions::eraseInstsUnrelatedToPDI(
519525
I->eraseFromParent();
520526
PDIUnrelatedWL.pop_back();
521527
}
528+
529+
while (!PDPVUnrelatedWL.empty()) {
530+
DPValue *DPV = PDPVUnrelatedWL.back();
531+
LLVM_DEBUG(dbgs() << " Deleting DPValue ");
532+
LLVM_DEBUG(DPV->print(dbgs()));
533+
LLVM_DEBUG(dbgs() << "\n");
534+
DPV->eraseFromParent();
535+
PDPVUnrelatedWL.pop_back();
536+
}
537+
522538
LLVM_DEBUG(dbgs() << " } // Done erasing instructions unrelated to parameter "
523539
"debug info from entry block. \n");
524540
}
@@ -547,75 +563,99 @@ void MergeFunctions::eraseTail(Function *G) {
547563
// The rest are unrelated to debug info for the parameters; fill up
548564
// PDIUnrelatedWL with such instructions.
549565
void MergeFunctions::filterInstsUnrelatedToPDI(
550-
BasicBlock *GEntryBlock, std::vector<Instruction *> &PDIUnrelatedWL) {
566+
BasicBlock *GEntryBlock, std::vector<Instruction *> &PDIUnrelatedWL,
567+
std::vector<DPValue *> &PDPVUnrelatedWL) {
551568
std::set<Instruction *> PDIRelated;
552-
for (BasicBlock::iterator BI = GEntryBlock->begin(), BIE = GEntryBlock->end();
553-
BI != BIE; ++BI) {
554-
if (auto *DVI = dyn_cast<DbgValueInst>(&*BI)) {
555-
LLVM_DEBUG(dbgs() << " Deciding: ");
556-
LLVM_DEBUG(BI->print(dbgs()));
569+
std::set<DPValue *> PDPVRelated;
570+
571+
// Work out whether a dbg.value intrinsic or an equivalent DPValue is a
572+
// parameter to be preserved.
573+
auto ExamineDbgValue = [](auto *DbgVal, auto &Container) {
574+
LLVM_DEBUG(dbgs() << " Deciding: ");
575+
LLVM_DEBUG(DbgVal->print(dbgs()));
576+
LLVM_DEBUG(dbgs() << "\n");
577+
DILocalVariable *DILocVar = DbgVal->getVariable();
578+
if (DILocVar->isParameter()) {
579+
LLVM_DEBUG(dbgs() << " Include (parameter): ");
580+
LLVM_DEBUG(DbgVal->print(dbgs()));
557581
LLVM_DEBUG(dbgs() << "\n");
558-
DILocalVariable *DILocVar = DVI->getVariable();
559-
if (DILocVar->isParameter()) {
560-
LLVM_DEBUG(dbgs() << " Include (parameter): ");
561-
LLVM_DEBUG(BI->print(dbgs()));
562-
LLVM_DEBUG(dbgs() << "\n");
563-
PDIRelated.insert(&*BI);
564-
} else {
565-
LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
566-
LLVM_DEBUG(BI->print(dbgs()));
567-
LLVM_DEBUG(dbgs() << "\n");
568-
}
569-
} else if (auto *DDI = dyn_cast<DbgDeclareInst>(&*BI)) {
570-
LLVM_DEBUG(dbgs() << " Deciding: ");
571-
LLVM_DEBUG(BI->print(dbgs()));
582+
Container.insert(DbgVal);
583+
} else {
584+
LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
585+
LLVM_DEBUG(DbgVal->print(dbgs()));
572586
LLVM_DEBUG(dbgs() << "\n");
573-
DILocalVariable *DILocVar = DDI->getVariable();
574-
if (DILocVar->isParameter()) {
575-
LLVM_DEBUG(dbgs() << " Parameter: ");
576-
LLVM_DEBUG(DILocVar->print(dbgs()));
577-
AllocaInst *AI = dyn_cast_or_null<AllocaInst>(DDI->getAddress());
578-
if (AI) {
579-
LLVM_DEBUG(dbgs() << " Processing alloca users: ");
580-
LLVM_DEBUG(dbgs() << "\n");
581-
for (User *U : AI->users()) {
582-
if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
583-
if (Value *Arg = SI->getValueOperand()) {
584-
if (isa<Argument>(Arg)) {
585-
LLVM_DEBUG(dbgs() << " Include: ");
586-
LLVM_DEBUG(AI->print(dbgs()));
587-
LLVM_DEBUG(dbgs() << "\n");
588-
PDIRelated.insert(AI);
589-
LLVM_DEBUG(dbgs() << " Include (parameter): ");
590-
LLVM_DEBUG(SI->print(dbgs()));
591-
LLVM_DEBUG(dbgs() << "\n");
592-
PDIRelated.insert(SI);
593-
LLVM_DEBUG(dbgs() << " Include: ");
594-
LLVM_DEBUG(BI->print(dbgs()));
595-
LLVM_DEBUG(dbgs() << "\n");
596-
PDIRelated.insert(&*BI);
597-
} else {
598-
LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
599-
LLVM_DEBUG(SI->print(dbgs()));
600-
LLVM_DEBUG(dbgs() << "\n");
601-
}
587+
}
588+
};
589+
590+
auto ExamineDbgDeclare = [&PDIRelated](auto *DbgDecl, auto &Container) {
591+
LLVM_DEBUG(dbgs() << " Deciding: ");
592+
LLVM_DEBUG(DbgDecl->print(dbgs()));
593+
LLVM_DEBUG(dbgs() << "\n");
594+
DILocalVariable *DILocVar = DbgDecl->getVariable();
595+
if (DILocVar->isParameter()) {
596+
LLVM_DEBUG(dbgs() << " Parameter: ");
597+
LLVM_DEBUG(DILocVar->print(dbgs()));
598+
AllocaInst *AI = dyn_cast_or_null<AllocaInst>(DbgDecl->getAddress());
599+
if (AI) {
600+
LLVM_DEBUG(dbgs() << " Processing alloca users: ");
601+
LLVM_DEBUG(dbgs() << "\n");
602+
for (User *U : AI->users()) {
603+
if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
604+
if (Value *Arg = SI->getValueOperand()) {
605+
if (isa<Argument>(Arg)) {
606+
LLVM_DEBUG(dbgs() << " Include: ");
607+
LLVM_DEBUG(AI->print(dbgs()));
608+
LLVM_DEBUG(dbgs() << "\n");
609+
PDIRelated.insert(AI);
610+
LLVM_DEBUG(dbgs() << " Include (parameter): ");
611+
LLVM_DEBUG(SI->print(dbgs()));
612+
LLVM_DEBUG(dbgs() << "\n");
613+
PDIRelated.insert(SI);
614+
LLVM_DEBUG(dbgs() << " Include: ");
615+
LLVM_DEBUG(DbgDecl->print(dbgs()));
616+
LLVM_DEBUG(dbgs() << "\n");
617+
Container.insert(DbgDecl);
618+
} else {
619+
LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
620+
LLVM_DEBUG(SI->print(dbgs()));
621+
LLVM_DEBUG(dbgs() << "\n");
602622
}
603-
} else {
604-
LLVM_DEBUG(dbgs() << " Defer: ");
605-
LLVM_DEBUG(U->print(dbgs()));
606-
LLVM_DEBUG(dbgs() << "\n");
607623
}
624+
} else {
625+
LLVM_DEBUG(dbgs() << " Defer: ");
626+
LLVM_DEBUG(U->print(dbgs()));
627+
LLVM_DEBUG(dbgs() << "\n");
608628
}
609-
} else {
610-
LLVM_DEBUG(dbgs() << " Delete (alloca NULL): ");
611-
LLVM_DEBUG(BI->print(dbgs()));
612-
LLVM_DEBUG(dbgs() << "\n");
613629
}
614630
} else {
615-
LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
616-
LLVM_DEBUG(BI->print(dbgs()));
631+
LLVM_DEBUG(dbgs() << " Delete (alloca NULL): ");
632+
LLVM_DEBUG(DbgDecl->print(dbgs()));
617633
LLVM_DEBUG(dbgs() << "\n");
618634
}
635+
} else {
636+
LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
637+
LLVM_DEBUG(DbgDecl->print(dbgs()));
638+
LLVM_DEBUG(dbgs() << "\n");
639+
}
640+
};
641+
642+
for (BasicBlock::iterator BI = GEntryBlock->begin(), BIE = GEntryBlock->end();
643+
BI != BIE; ++BI) {
644+
// Examine DPValues as they happen "before" the instruction. Are they
645+
// connected to parameters?
646+
for (DPValue &DPV : BI->getDbgValueRange()) {
647+
if (DPV.isDbgValue() || DPV.isDbgAssign()) {
648+
ExamineDbgValue(&DPV, PDPVRelated);
649+
} else {
650+
assert(DPV.isDbgDeclare());
651+
ExamineDbgDeclare(&DPV, PDPVRelated);
652+
}
653+
}
654+
655+
if (auto *DVI = dyn_cast<DbgValueInst>(&*BI)) {
656+
ExamineDbgValue(DVI, PDIRelated);
657+
} else if (auto *DDI = dyn_cast<DbgDeclareInst>(&*BI)) {
658+
ExamineDbgDeclare(DDI, PDIRelated);
619659
} else if (BI->isTerminator() && &*BI == GEntryBlock->getTerminator()) {
620660
LLVM_DEBUG(dbgs() << " Will Include Terminator: ");
621661
LLVM_DEBUG(BI->print(dbgs()));
@@ -630,17 +670,25 @@ void MergeFunctions::filterInstsUnrelatedToPDI(
630670
LLVM_DEBUG(
631671
dbgs()
632672
<< " Report parameter debug info related/related instructions: {\n");
633-
for (Instruction &I : *GEntryBlock) {
634-
if (PDIRelated.find(&I) == PDIRelated.end()) {
673+
674+
auto IsPDIRelated = [](auto *Rec, auto &Container, auto &UnrelatedCont) {
675+
if (Container.find(Rec) == Container.end()) {
635676
LLVM_DEBUG(dbgs() << " !PDIRelated: ");
636-
LLVM_DEBUG(I.print(dbgs()));
677+
LLVM_DEBUG(Rec->print(dbgs()));
637678
LLVM_DEBUG(dbgs() << "\n");
638-
PDIUnrelatedWL.push_back(&I);
679+
UnrelatedCont.push_back(Rec);
639680
} else {
640681
LLVM_DEBUG(dbgs() << " PDIRelated: ");
641-
LLVM_DEBUG(I.print(dbgs()));
682+
LLVM_DEBUG(Rec->print(dbgs()));
642683
LLVM_DEBUG(dbgs() << "\n");
643684
}
685+
};
686+
687+
// Collect the set of unrelated instructions and debug records.
688+
for (Instruction &I : *GEntryBlock) {
689+
for (auto &DPV : I.getDbgValueRange())
690+
IsPDIRelated(&DPV, PDPVRelated, PDPVUnrelatedWL);
691+
IsPDIRelated(&I, PDIRelated, PDIUnrelatedWL);
644692
}
645693
LLVM_DEBUG(dbgs() << " }\n");
646694
}
@@ -680,6 +728,7 @@ static void copyMetadataIfPresent(Function *From, Function *To, StringRef Key) {
680728
void MergeFunctions::writeThunk(Function *F, Function *G) {
681729
BasicBlock *GEntryBlock = nullptr;
682730
std::vector<Instruction *> PDIUnrelatedWL;
731+
std::vector<DPValue *> PDPVUnrelatedWL;
683732
BasicBlock *BB = nullptr;
684733
Function *NewG = nullptr;
685734
if (MergeFunctionsPDI) {
@@ -691,7 +740,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
691740
dbgs() << "writeThunk: (MergeFunctionsPDI) filter parameter related "
692741
"debug info for "
693742
<< G->getName() << "() {\n");
694-
filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL);
743+
filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL, PDPVUnrelatedWL);
695744
GEntryBlock->getTerminator()->eraseFromParent();
696745
BB = GEntryBlock;
697746
} else {
@@ -740,7 +789,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
740789
<< G->getName() << "()\n");
741790
}
742791
eraseTail(G);
743-
eraseInstsUnrelatedToPDI(PDIUnrelatedWL);
792+
eraseInstsUnrelatedToPDI(PDIUnrelatedWL, PDPVUnrelatedWL);
744793
LLVM_DEBUG(
745794
dbgs() << "} // End of parameter related debug info filtering for: "
746795
<< G->getName() << "()\n");

llvm/test/Transforms/MergeFunc/mergefunc-preserve-debug-info.ll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
; RUN: opt -passes='default<O0>,mergefunc' -S -mergefunc-preserve-debug-info < %s | FileCheck %s --check-prefix=OPTIMIZATION_LEVEL_0
33
; RUN: opt -passes='default<O2>,mergefunc' -S -mergefunc-preserve-debug-info < %s | FileCheck %s --check-prefix=OPTIMIZATION_LEVEL_2
44

5+
;; Does this continue to work under non-intrinsic debug-info?
6+
; RUN: opt -passes='default<O0>,mergefunc' -S -mergefunc-preserve-debug-info < %s --try-experimental-debuginfo-iterators | FileCheck %s --check-prefix=OPTIMIZATION_LEVEL_0
7+
; RUN: opt -passes='default<O2>,mergefunc' -S -mergefunc-preserve-debug-info < %s --try-experimental-debuginfo-iterators | FileCheck %s --check-prefix=OPTIMIZATION_LEVEL_2
8+
59
; Preserve debug info in thunks under -passes=mergefunc -mergefunc-preserve-debug-info
610
;
711
; We test that:

0 commit comments

Comments
 (0)