aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/Debugify.cpp
diff options
context:
space:
mode:
authorDjordje Todorovic <djordje.todorovic@syrmia.com>2021-05-12 01:44:28 -0700
committerDjordje Todorovic <djtodoro@cisco.com>2021-05-20 06:42:02 -0700
commit76f375f3d9d6902820ffc21200e454926748c678 (patch)
tree849dbe3bae935dc5b72d60a868b164647591d3e0 /llvm/lib/Transforms/Utils/Debugify.cpp
parentfa6e87cc5a21f885a4f6d0c7a51ad0f40022f5c8 (diff)
downloadllvm-76f375f3d9d6902820ffc21200e454926748c678.zip
llvm-76f375f3d9d6902820ffc21200e454926748c678.tar.gz
llvm-76f375f3d9d6902820ffc21200e454926748c678.tar.bz2
[Debugify][Original DI] Test dbg var loc preservation
This is an improvement of [0]. This adds checking of original llvm.dbg.values()/declares() instructions in optimizations. We have picked a real issue that has been found with this (actually, picked one variable location missing from [1] and resolved the issue), and the result is the fix for that -- D100844. Before applying the D100844, using the options from [0] (but with this patch applied) on the compilation of GDB 7.11, the final HTML report for the debug-info issues can be found at [1] (please scroll down, and look for "Summary of Variable Location Bugs"). After applying the D100844, the numbers has improved a bit -- please take a look into [2]. [0] https://llvm.org/docs/HowToUpdateDebugInfo.html\ [1] https://djolertrk.github.io/di-check-before-adce-fix/ [2] https://djolertrk.github.io/di-check-after-adce-fix/ Differential Revision: https://reviews.llvm.org/D100845
Diffstat (limited to 'llvm/lib/Transforms/Utils/Debugify.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/Debugify.cpp101
1 files changed, 92 insertions, 9 deletions
diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp
index cbea4077..30c3fa5 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -304,18 +304,39 @@ bool llvm::collectDebugInfoMetadata(Module &M,
// Collect the DISubprogram.
auto *SP = F.getSubprogram();
DIPreservationMap[NameOfWrappedPass].DIFunctions.insert({F.getName(), SP});
- if (SP)
+ if (SP) {
LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');
+ for (const DINode *DN : SP->getRetainedNodes()) {
+ if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
+ DIPreservationMap[NameOfWrappedPass].DIVariables[DV] = 0;
+ }
+ }
+ }
for (BasicBlock &BB : F) {
- // Collect debug locations (!dbg).
- // TODO: Collect dbg.values.
+ // Collect debug locations (!dbg) and debug variable intrinsics.
for (Instruction &I : BB) {
// Skip PHIs.
if (isa<PHINode>(I))
continue;
- // Skip debug instructions.
+ // Collect dbg.values and dbg.declares.
+ if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) {
+ if (!SP)
+ continue;
+ // Skip inlined variables.
+ if (I.getDebugLoc().getInlinedAt())
+ continue;
+ // Skip undef values.
+ if (DVI->isUndef())
+ continue;
+
+ auto *Var = DVI->getVariable();
+ DIPreservationMap[NameOfWrappedPass].DIVariables[Var]++;
+ continue;
+ }
+
+ // Skip debug instructions other than dbg.value and dbg.declare.
if (isa<DbgInfoIntrinsic>(&I))
continue;
@@ -435,6 +456,39 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
return Preserved;
}
+// This checks the preservation of original debug variable intrinsics.
+static bool checkVars(const DebugVarMap &DIFunctionsBefore,
+ const DebugVarMap &DIFunctionsAfter,
+ StringRef NameOfWrappedPass, StringRef FileNameFromCU,
+ bool ShouldWriteIntoJSON, llvm::json::Array &Bugs) {
+ bool Preserved = true;
+ for (const auto &V : DIFunctionsBefore) {
+ auto VarIt = DIFunctionsAfter.find(V.first);
+ if (VarIt == DIFunctionsAfter.end())
+ continue;
+
+ unsigned NumOfDbgValsAfter = VarIt->second;
+
+ if (V.second > NumOfDbgValsAfter) {
+ if (ShouldWriteIntoJSON)
+ Bugs.push_back(llvm::json::Object(
+ {{"metadata", "dbg-var-intrinsic"},
+ {"name", V.first->getName()},
+ {"fn-name", V.first->getScope()->getSubprogram()->getName()},
+ {"action", "drop"}}));
+ else
+ dbg() << "WARNING: " << NameOfWrappedPass
+ << " drops dbg.value()/dbg.declare() for " << V.first->getName()
+ << " from "
+ << "function " << V.first->getScope()->getSubprogram()->getName()
+ << " (file " << FileNameFromCU << ")\n";
+ Preserved = false;
+ }
+ }
+
+ return Preserved;
+}
+
// Write the json data into the specifed file.
static void writeJSON(StringRef OrigDIVerifyBugsReportFilePath,
StringRef FileNameFromCU, StringRef NameOfWrappedPass,
@@ -484,18 +538,40 @@ bool llvm::checkDebugInfoMetadata(Module &M,
auto *SP = F.getSubprogram();
DIPreservationAfter[NameOfWrappedPass].DIFunctions.insert(
{F.getName(), SP});
- if (SP)
+
+ if (SP) {
LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');
+ for (const DINode *DN : SP->getRetainedNodes()) {
+ if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
+ DIPreservationAfter[NameOfWrappedPass].DIVariables[DV] = 0;
+ }
+ }
+ }
for (BasicBlock &BB : F) {
- // Collect debug locations (!dbg attachments).
- // TODO: Collect dbg.values.
+ // Collect debug locations (!dbg) and debug variable intrinsics.
for (Instruction &I : BB) {
// Skip PHIs.
if (isa<PHINode>(I))
continue;
- // Skip debug instructions.
+ // Collect dbg.values and dbg.declares.
+ if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) {
+ if (!SP)
+ continue;
+ // Skip inlined variables.
+ if (I.getDebugLoc().getInlinedAt())
+ continue;
+ // Skip undef values.
+ if (DVI->isUndef())
+ continue;
+
+ auto *Var = DVI->getVariable();
+ DIPreservationAfter[NameOfWrappedPass].DIVariables[Var]++;
+ continue;
+ }
+
+ // Skip debug instructions other than dbg.value and dbg.declare.
if (isa<DbgInfoIntrinsic>(&I))
continue;
@@ -522,6 +598,9 @@ bool llvm::checkDebugInfoMetadata(Module &M,
auto InstToDelete = DIPreservationAfter[NameOfWrappedPass].InstToDelete;
+ auto DIVarsBefore = DIPreservationMap[NameOfWrappedPass].DIVariables;
+ auto DIVarsAfter = DIPreservationAfter[NameOfWrappedPass].DIVariables;
+
bool ShouldWriteIntoJSON = !OrigDIVerifyBugsReportFilePath.empty();
llvm::json::Array Bugs;
@@ -531,7 +610,11 @@ bool llvm::checkDebugInfoMetadata(Module &M,
bool ResultForInsts = checkInstructions(
DILocsBefore, DILocsAfter, InstToDelete, NameOfWrappedPass,
FileNameFromCU, ShouldWriteIntoJSON, Bugs);
- bool Result = ResultForFunc && ResultForInsts;
+
+ bool ResultForVars = checkVars(DIVarsBefore, DIVarsAfter, NameOfWrappedPass,
+ FileNameFromCU, ShouldWriteIntoJSON, Bugs);
+
+ bool Result = ResultForFunc && ResultForInsts && ResultForVars;
StringRef ResultBanner = NameOfWrappedPass != "" ? NameOfWrappedPass : Banner;
if (ShouldWriteIntoJSON && !Bugs.empty())