[llvm] r337787 - [Debugify] Export per-pass debug info loss statistics
Vedant Kumar via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 23 17:41:29 PDT 2018
Author: vedantk
Date: Mon Jul 23 17:41:29 2018
New Revision: 337787
URL: http://llvm.org/viewvc/llvm-project?rev=337787&view=rev
Log:
[Debugify] Export per-pass debug info loss statistics
Add a -debugify-export option to opt. This exports per-pass `debugify`
loss statistics to a file in CSV format.
For some interesting numbers on debug value loss during an -O2 build
of the sqlite3 amalgamation, see the review thread.
Differential Revision: https://reviews.llvm.org/D49003
Added:
llvm/trunk/test/DebugInfo/debugify-export.ll
Modified:
llvm/trunk/tools/opt/Debugify.cpp
llvm/trunk/tools/opt/Debugify.h
llvm/trunk/tools/opt/opt.cpp
Added: llvm/trunk/test/DebugInfo/debugify-export.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/debugify-export.ll?rev=337787&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/debugify-export.ll (added)
+++ llvm/trunk/test/DebugInfo/debugify-export.ll Mon Jul 23 17:41:29 2018
@@ -0,0 +1,14 @@
+; RUN: opt < %s -debugify-each -debugify-quiet -debugify-export - -o /dev/null | FileCheck %s
+
+; CHECK: Pass Name
+; CHECK-SAME: # of missing debug values
+; CHECK-SAME: # of missing locations
+; CHECK-SAME: Missing/Expected value ratio
+; CHECK-SAME: Missing/Expected location ratio
+
+; CHECK: Module Verifier
+; CHECK-SAME: 0,0,0.000000e+00,0.000000e+00
+
+define void @foo() {
+ ret void
+}
Modified: llvm/trunk/tools/opt/Debugify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Debugify.cpp?rev=337787&r1=337786&r2=337787&view=diff
==============================================================================
--- llvm/trunk/tools/opt/Debugify.cpp (original)
+++ llvm/trunk/tools/opt/Debugify.cpp Mon Jul 23 17:41:29 2018
@@ -209,7 +209,7 @@ bool diagnoseMisSizedDbgValue(Module &M,
bool checkDebugifyMetadata(Module &M,
iterator_range<Module::iterator> Functions,
StringRef NameOfWrappedPass, StringRef Banner,
- bool Strip) {
+ bool Strip, DebugifyStatsMap *StatsMap) {
// Skip modules without debugify metadata.
NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
if (!NMD) {
@@ -227,6 +227,11 @@ bool checkDebugifyMetadata(Module &M,
unsigned OriginalNumVars = getDebugifyOperand(1);
bool HasErrors = false;
+ // Track debug info loss statistics if able.
+ DebugifyStatistics *Stats = nullptr;
+ if (StatsMap && !NameOfWrappedPass.empty())
+ Stats = &StatsMap->operator[](NameOfWrappedPass);
+
BitVector MissingLines{OriginalNumLines, true};
BitVector MissingVars{OriginalNumVars, true};
for (Function &F : Functions) {
@@ -276,6 +281,14 @@ bool checkDebugifyMetadata(Module &M,
for (unsigned Idx : MissingVars.set_bits())
dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";
+ // Update DI loss statistics.
+ if (Stats) {
+ Stats->NumDbgLocsExpected += OriginalNumLines;
+ Stats->NumDbgLocsMissing += MissingLines.count();
+ Stats->NumDbgValuesExpected += OriginalNumVars;
+ Stats->NumDbgValuesMissing += MissingVars.count();
+ }
+
dbg() << Banner;
if (!NameOfWrappedPass.empty())
dbg() << " [" << NameOfWrappedPass << "]";
@@ -331,11 +344,13 @@ struct DebugifyFunctionPass : public Fun
struct CheckDebugifyModulePass : public ModulePass {
bool runOnModule(Module &M) override {
return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
- "CheckModuleDebugify", Strip);
+ "CheckModuleDebugify", Strip, StatsMap);
}
- CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "")
- : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
+ CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr)
+ : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
+ StatsMap(StatsMap) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
@@ -346,6 +361,7 @@ struct CheckDebugifyModulePass : public
private:
bool Strip;
StringRef NameOfWrappedPass;
+ DebugifyStatsMap *StatsMap;
};
/// FunctionPass for checking debug info inserted by -debugify-function, used
@@ -356,12 +372,14 @@ struct CheckDebugifyFunctionPass : publi
auto FuncIt = F.getIterator();
return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
NameOfWrappedPass, "CheckFunctionDebugify",
- Strip);
+ Strip, StatsMap);
}
CheckDebugifyFunctionPass(bool Strip = false,
- StringRef NameOfWrappedPass = "")
- : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
+ StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr)
+ : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
+ StatsMap(StatsMap) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
@@ -372,10 +390,32 @@ struct CheckDebugifyFunctionPass : publi
private:
bool Strip;
StringRef NameOfWrappedPass;
+ DebugifyStatsMap *StatsMap;
};
} // end anonymous namespace
+void exportDebugifyStats(llvm::StringRef Path, const DebugifyStatsMap &Map) {
+ std::error_code EC;
+ raw_fd_ostream OS{Path, EC};
+ if (EC) {
+ errs() << "Could not open file: " << EC.message() << ", " << Path << '\n';
+ return;
+ }
+
+ OS << "Pass Name" << ',' << "# of missing debug values" << ','
+ << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
+ << "Missing/Expected location ratio" << '\n';
+ for (const auto &Entry : Map) {
+ StringRef Pass = Entry.first;
+ DebugifyStatistics Stats = Entry.second;
+
+ OS << Pass << ',' << Stats.NumDbgValuesMissing << ','
+ << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ','
+ << Stats.getEmptyLocationRatio() << '\n';
+ }
+}
+
ModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); }
FunctionPass *createDebugifyFunctionPass() {
@@ -388,18 +428,21 @@ PreservedAnalyses NewPMDebugifyPass::run
}
ModulePass *createCheckDebugifyModulePass(bool Strip,
- StringRef NameOfWrappedPass) {
- return new CheckDebugifyModulePass(Strip, NameOfWrappedPass);
+ StringRef NameOfWrappedPass,
+ DebugifyStatsMap *StatsMap) {
+ return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
}
FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
- StringRef NameOfWrappedPass) {
- return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass);
+ StringRef NameOfWrappedPass,
+ DebugifyStatsMap *StatsMap) {
+ return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
}
PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
ModuleAnalysisManager &) {
- checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false);
+ checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false,
+ nullptr);
return PreservedAnalyses::all();
}
Modified: llvm/trunk/tools/opt/Debugify.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Debugify.h?rev=337787&r1=337786&r2=337787&view=diff
==============================================================================
--- llvm/trunk/tools/opt/Debugify.h (original)
+++ llvm/trunk/tools/opt/Debugify.h Mon Jul 23 17:41:29 2018
@@ -14,7 +14,10 @@
#ifndef LLVM_TOOLS_OPT_DEBUGIFY_H
#define LLVM_TOOLS_OPT_DEBUGIFY_H
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/Support/raw_ostream.h"
llvm::ModulePass *createDebugifyModulePass();
llvm::FunctionPass *createDebugifyFunctionPass();
@@ -23,13 +26,46 @@ struct NewPMDebugifyPass : public llvm::
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
};
+/// Track how much `debugify` information has been lost.
+struct DebugifyStatistics {
+ /// Number of missing dbg.values.
+ unsigned NumDbgValuesMissing = 0;
+
+ /// Number of dbg.values expected.
+ unsigned NumDbgValuesExpected = 0;
+
+ /// Number of instructions with empty debug locations.
+ unsigned NumDbgLocsMissing = 0;
+
+ /// Number of instructions expected to have debug locations.
+ unsigned NumDbgLocsExpected = 0;
+
+ /// Get the ratio of missing/expected dbg.values.
+ float getMissingValueRatio() const {
+ return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
+ }
+
+ /// Get the ratio of missing/expected instructions with locations.
+ float getEmptyLocationRatio() const {
+ return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
+ }
+};
+
+/// Map pass names to a per-pass DebugifyStatistics instance.
+using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
+
+/// Export per-pass debugify statistics to the file specified by \p Path.
+void exportDebugifyStats(llvm::StringRef Path, const DebugifyStatsMap &Map);
+
llvm::ModulePass *
createCheckDebugifyModulePass(bool Strip = false,
- llvm::StringRef NameOfWrappedPass = "");
+ llvm::StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr);
llvm::FunctionPass *
createCheckDebugifyFunctionPass(bool Strip = false,
- llvm::StringRef NameOfWrappedPass = "");
+ llvm::StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr);
struct NewPMCheckDebugifyPass
: public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
Modified: llvm/trunk/tools/opt/opt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/opt.cpp?rev=337787&r1=337786&r2=337787&view=diff
==============================================================================
--- llvm/trunk/tools/opt/opt.cpp (original)
+++ llvm/trunk/tools/opt/opt.cpp Mon Jul 23 17:41:29 2018
@@ -217,6 +217,11 @@ static cl::opt<bool> DebugifyEach(
cl::desc(
"Start each pass with debugify and end it with check-debugify"));
+static cl::opt<std::string>
+ DebugifyExport("debugify-export",
+ cl::desc("Export per-pass debugify statistics to this file"),
+ cl::value_desc("filename"), cl::init(""));
+
static cl::opt<bool>
PrintBreakpoints("print-breakpoints-for-testing",
cl::desc("Print select breakpoints location for testing"));
@@ -267,34 +272,45 @@ static cl::opt<std::string>
cl::value_desc("filename"));
class OptCustomPassManager : public legacy::PassManager {
+ DebugifyStatsMap DIStatsMap;
+
public:
using super = legacy::PassManager;
void add(Pass *P) override {
+ // Wrap each pass with (-check)-debugify passes if requested, making
+ // exceptions for passes which shouldn't see -debugify instrumentation.
bool WrapWithDebugify = DebugifyEach && !P->getAsImmutablePass() &&
!isIRPrintingPass(P) && !isBitcodeWriterPass(P);
if (!WrapWithDebugify) {
super::add(P);
return;
}
+
+ // Apply -debugify/-check-debugify before/after each pass and collect
+ // debug info loss statistics.
PassKind Kind = P->getPassKind();
+ StringRef Name = P->getPassName();
+
// TODO: Implement Debugify for BasicBlockPass, LoopPass.
switch (Kind) {
case PT_Function:
super::add(createDebugifyFunctionPass());
super::add(P);
- super::add(createCheckDebugifyFunctionPass(true, P->getPassName()));
+ super::add(createCheckDebugifyFunctionPass(true, Name, &DIStatsMap));
break;
case PT_Module:
super::add(createDebugifyModulePass());
super::add(P);
- super::add(createCheckDebugifyModulePass(true, P->getPassName()));
+ super::add(createCheckDebugifyModulePass(true, Name, &DIStatsMap));
break;
default:
super::add(P);
break;
}
}
+
+ const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; }
};
static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
@@ -839,6 +855,9 @@ int main(int argc, char **argv) {
Out->os() << BOS->str();
}
+ if (DebugifyEach && !DebugifyExport.empty())
+ exportDebugifyStats(DebugifyExport, Passes.getDebugifyStatsMap());
+
// Declare success.
if (!NoOutput || PrintBreakpoints)
Out->keep();
More information about the llvm-commits
mailing list