diff options
author | Djordje Todorovic <djordje.todorovic@syrmia.com> | 2021-05-12 01:44:28 -0700 |
---|---|---|
committer | Djordje Todorovic <djtodoro@cisco.com> | 2021-05-20 06:42:02 -0700 |
commit | 76f375f3d9d6902820ffc21200e454926748c678 (patch) | |
tree | 849dbe3bae935dc5b72d60a868b164647591d3e0 /llvm/lib/Transforms/Utils/Debugify.cpp | |
parent | fa6e87cc5a21f885a4f6d0c7a51ad0f40022f5c8 (diff) | |
download | llvm-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.cpp | 101 |
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()) |