[llvm] Add a pass to collect dropped variable statistics (PR #102233)
Shubham Sandeep Rastogi via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 6 14:35:28 PDT 2024
https://github.com/rastogishubham created https://github.com/llvm/llvm-project/pull/102233
Add an instrumentation pass to llvm to collect dropped debug information variable statistics for every Function-level and Module-level IR pass.
This patch creates adds the class DroppedVariableStats which iterates over every DbgRecord in a function or module before and after an optimization pass and counts the number of variables who's debug information has been dropped due to that pass, then prints that output to stdout in a csv format.
>From 793249c108df44a78a71f83760187466bfa15c7e Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Mon, 5 Aug 2024 15:12:37 -0700
Subject: [PATCH] Add a pass to collect dropped variable statistics
Add an instrumentation pass to llvm to collect dropped debug information
variable statistics for every Function-level and Module-level IR pass.
---
.../llvm/Passes/StandardInstrumentations.h | 30 +++++++
llvm/lib/Passes/StandardInstrumentations.cpp | 85 +++++++++++++++++++
2 files changed, 115 insertions(+)
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index fa9c744294a66..f3b722e31de60 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -559,6 +559,35 @@ class DotCfgChangeReporter : public ChangeReporter<IRDataT<DCData>> {
std::unique_ptr<raw_fd_ostream> HTML;
};
+class DroppedVariableStats {
+public:
+ DroppedVariableStats() {
+ llvm::outs() << "Pass Level, Pass Name, Num of Dropped Variables, Func or "
+ "Module Name\n";
+ };
+ // We intend this to be unique per-compilation, thus no copies.
+ DroppedVariableStats(const DroppedVariableStats &) = delete;
+ void operator=(const DroppedVariableStats &) = delete;
+
+ void registerCallbacks(PassInstrumentationCallbacks &PIC);
+
+private:
+ using VarID =
+ std::tuple<const DILocalScope *, llvm::StringRef, unsigned, unsigned>;
+
+ SmallVector<std::pair<llvm::DenseSet<VarID>, std::string>>
+ DebugVariablesBefore;
+ SmallVector<std::pair<llvm::DenseSet<VarID>, std::string>>
+ DebugVariablesAfter;
+
+ // Implementation of pass instrumentation callbacks.
+ void runBeforePass(StringRef PassID, Any IR);
+ void runAfterPass(StringRef PassID, Any IR, const PreservedAnalyses &PA);
+
+ void runOnFunction(const Function *F, bool Before);
+ void runOnModule(const Module *M, bool Before);
+};
+
// Print IR on crash.
class PrintCrashIRInstrumentation {
public:
@@ -595,6 +624,7 @@ class StandardInstrumentations {
PrintCrashIRInstrumentation PrintCrashIR;
IRChangedTester ChangeTester;
VerifyInstrumentation Verify;
+ DroppedVariableStats DroppedStats;
bool VerifyEach;
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 8f2461f40cb00..9d8f5a25d5cba 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -25,6 +25,7 @@
#include "llvm/Demangle/Demangle.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/IR/PassManager.h"
@@ -139,6 +140,11 @@ static cl::opt<std::string> IRDumpDirectory(
"files in this directory rather than written to stderr"),
cl::Hidden, cl::value_desc("filename"));
+static cl::opt<bool>
+ DroppedVarStats("dropped-variable-stats", cl::Hidden,
+ cl::desc("Dump dropped debug variables stats"),
+ cl::init(false));
+
template <typename IRUnitT> static const IRUnitT *unwrapIR(Any IR) {
const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
return IRPtr ? *IRPtr : nullptr;
@@ -2441,6 +2447,84 @@ void DotCfgChangeReporter::registerCallbacks(
}
}
+void DroppedVariableStats::registerCallbacks(
+ PassInstrumentationCallbacks &PIC) {
+ if (!DroppedVarStats)
+ return;
+
+ PIC.registerBeforeNonSkippedPassCallback(
+ [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); });
+ PIC.registerAfterPassCallback(
+ [this](StringRef P, Any IR, const PreservedAnalyses &PA) {
+ return this->runAfterPass(P, IR, PA);
+ });
+}
+
+void DroppedVariableStats::runBeforePass(StringRef PassID, Any IR) {
+ DebugVariablesBefore.push_back(
+ std::make_pair(llvm::DenseSet<VarID>(), PassID.str()));
+ DebugVariablesAfter.push_back(
+ std::make_pair(llvm::DenseSet<VarID>(), PassID.str()));
+ if (auto *M = unwrapIR<Module>(IR))
+ return this->runOnModule(M, true);
+ if (auto *F = unwrapIR<Function>(IR))
+ return this->runOnFunction(F, true);
+ return;
+}
+
+void DroppedVariableStats::runOnFunction(const Function *F, bool Before) {
+ auto &DebugVariables = Before ? DebugVariablesBefore : DebugVariablesAfter;
+ for (auto &BB : *F) {
+ for (const Instruction &I : BB) {
+ for (DbgRecord &DR : I.getDbgRecordRange()) {
+ if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) {
+ llvm::StringRef UniqueName = Dbg->getVariable()->getName();
+ auto DbgLoc = DR.getDebugLoc();
+ unsigned Line = DbgLoc.getLine();
+ unsigned Col = DbgLoc->getColumn();
+ VarID Key(cast<DILocalScope>(DbgLoc.getScope()), UniqueName, Line,
+ Col);
+ DebugVariables.back().first.insert(Key);
+ }
+ }
+ }
+ }
+}
+
+void DroppedVariableStats::runOnModule(const Module *M, bool Before) {
+ for (auto &F : *M)
+ runOnFunction(&F, Before);
+}
+
+void DroppedVariableStats::runAfterPass(StringRef PassID, Any IR,
+ const PreservedAnalyses &PA) {
+ assert(DebugVariablesBefore.back().second ==
+ DebugVariablesAfter.back().second);
+ unsigned DroppedCount = 0;
+ std::string PassLevel = "";
+ std::string FuncOrModName = "";
+ if (auto *M = unwrapIR<Module>(IR)) {
+ this->runOnModule(M, false);
+ PassLevel = "Module";
+ FuncOrModName = M->getName();
+ } else if (auto *F = unwrapIR<Function>(IR)) {
+ this->runOnFunction(F, false);
+ PassLevel = "Function";
+ FuncOrModName = F->getName();
+ } else {
+ return;
+ }
+ for (auto Var : DebugVariablesBefore.back().first)
+ if (!DebugVariablesAfter.back().first.contains(Var))
+ DroppedCount++;
+ if (DroppedCount > 0)
+ llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", "
+ << FuncOrModName << "\n";
+ DebugVariablesBefore.pop_back();
+ DebugVariablesAfter.pop_back();
+ return;
+}
+
StandardInstrumentations::StandardInstrumentations(
LLVMContext &Context, bool DebugLogging, bool VerifyEach,
PrintPassOptions PrintPassOpts)
@@ -2528,6 +2612,7 @@ void StandardInstrumentations::registerCallbacks(
WebsiteChangeReporter.registerCallbacks(PIC);
ChangeTester.registerCallbacks(PIC);
PrintCrashIR.registerCallbacks(PIC);
+ DroppedStats.registerCallbacks(PIC);
if (MAM)
PreservedCFGChecker.registerCallbacks(PIC, *MAM);
More information about the llvm-commits
mailing list