Skip to content

Commit 4bff433

Browse files
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.
1 parent 1fb1a5d commit 4bff433

File tree

3 files changed

+151
-3
lines changed

3 files changed

+151
-3
lines changed

llvm/include/llvm/Passes/StandardInstrumentations.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,37 @@ class DotCfgChangeReporter : public ChangeReporter<IRDataT<DCData>> {
559559
std::unique_ptr<raw_fd_ostream> HTML;
560560
};
561561

562+
class DroppedVariableStats {
563+
public:
564+
DroppedVariableStats(bool DroppedVarStatsEnabled) {
565+
if (DroppedVarStatsEnabled)
566+
llvm::outs()
567+
<< "Pass Level, Pass Name, Num of Dropped Variables, Func or "
568+
"Module Name\n";
569+
};
570+
// We intend this to be unique per-compilation, thus no copies.
571+
DroppedVariableStats(const DroppedVariableStats &) = delete;
572+
void operator=(const DroppedVariableStats &) = delete;
573+
574+
void registerCallbacks(PassInstrumentationCallbacks &PIC);
575+
576+
private:
577+
using VarID = std::tuple<const DILocalScope *, const DILocalScope *,
578+
StringRef, unsigned>;
579+
580+
SmallVector<llvm::DenseSet<VarID>> DebugVariablesBefore;
581+
SmallVector<llvm::DenseSet<VarID>> DebugVariablesAfter;
582+
583+
// Implementation of pass instrumentation callbacks.
584+
void runBeforePass(StringRef PassID, Any IR);
585+
void runAfterPass(StringRef PassID, Any IR, const PreservedAnalyses &PA);
586+
587+
void runOnFunction(const Function *F, bool Before);
588+
void runOnModule(const Module *M, bool Before);
589+
590+
void removeVarFromAllSets(VarID Var);
591+
};
592+
562593
// Print IR on crash.
563594
class PrintCrashIRInstrumentation {
564595
public:
@@ -595,6 +626,7 @@ class StandardInstrumentations {
595626
PrintCrashIRInstrumentation PrintCrashIR;
596627
IRChangedTester ChangeTester;
597628
VerifyInstrumentation Verify;
629+
DroppedVariableStats DroppedStats;
598630

599631
bool VerifyEach;
600632

llvm/lib/Passes/StandardInstrumentations.cpp

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "llvm/Demangle/Demangle.h"
2626
#include "llvm/IR/Constants.h"
2727
#include "llvm/IR/Function.h"
28+
#include "llvm/IR/InstIterator.h"
29+
#include "llvm/IR/IntrinsicInst.h"
2830
#include "llvm/IR/Module.h"
2931
#include "llvm/IR/PassInstrumentation.h"
3032
#include "llvm/IR/PassManager.h"
@@ -139,6 +141,11 @@ static cl::opt<std::string> IRDumpDirectory(
139141
"files in this directory rather than written to stderr"),
140142
cl::Hidden, cl::value_desc("filename"));
141143

144+
static cl::opt<bool>
145+
DroppedVarStats("dropped-variable-stats", cl::Hidden,
146+
cl::desc("Dump dropped debug variables stats"),
147+
cl::init(false));
148+
142149
template <typename IRUnitT> static const IRUnitT *unwrapIR(Any IR) {
143150
const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
144151
return IRPtr ? *IRPtr : nullptr;
@@ -2441,19 +2448,101 @@ void DotCfgChangeReporter::registerCallbacks(
24412448
}
24422449
}
24432450

2451+
void DroppedVariableStats::registerCallbacks(
2452+
PassInstrumentationCallbacks &PIC) {
2453+
if (!DroppedVarStats)
2454+
return;
2455+
2456+
PIC.registerBeforeNonSkippedPassCallback(
2457+
[this](StringRef P, Any IR) { return this->runBeforePass(P, IR); });
2458+
PIC.registerAfterPassCallback(
2459+
[this](StringRef P, Any IR, const PreservedAnalyses &PA) {
2460+
return this->runAfterPass(P, IR, PA);
2461+
});
2462+
}
2463+
2464+
void DroppedVariableStats::runBeforePass(StringRef PassID, Any IR) {
2465+
DebugVariablesBefore.push_back(llvm::DenseSet<VarID>());
2466+
DebugVariablesAfter.push_back(llvm::DenseSet<VarID>());
2467+
if (auto *M = unwrapIR<Module>(IR))
2468+
return this->runOnModule(M, true);
2469+
if (auto *F = unwrapIR<Function>(IR))
2470+
return this->runOnFunction(F, true);
2471+
return;
2472+
}
2473+
2474+
void DroppedVariableStats::runOnFunction(const Function *F, bool Before) {
2475+
auto &VarIDs = (Before ? DebugVariablesBefore : DebugVariablesAfter).back();
2476+
for (const auto &I : instructions(F)) {
2477+
for (DbgRecord &DR : I.getDbgRecordRange()) {
2478+
if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) {
2479+
auto *DbgVar = Dbg->getVariable();
2480+
StringRef UniqueName = DbgVar->getName();
2481+
auto DbgLoc = DR.getDebugLoc();
2482+
unsigned Line = DbgVar->getLine();
2483+
VarID Key{cast<DILocalScope>(DbgVar->getScope()),
2484+
DbgLoc->getInlinedAtScope(), UniqueName, Line};
2485+
VarIDs.insert(Key);
2486+
}
2487+
}
2488+
}
2489+
}
2490+
2491+
void DroppedVariableStats::runOnModule(const Module *M, bool Before) {
2492+
for (auto &F : *M)
2493+
runOnFunction(&F, Before);
2494+
}
2495+
2496+
void DroppedVariableStats::removeVarFromAllSets(VarID Var) {
2497+
// Do not remove Var from the last element, it will be popped from the stack
2498+
// anyway.
2499+
for (auto *It = DebugVariablesBefore.begin();
2500+
It != DebugVariablesBefore.end() - 1; It++)
2501+
It->erase(Var);
2502+
}
2503+
2504+
void DroppedVariableStats::runAfterPass(StringRef PassID, Any IR,
2505+
const PreservedAnalyses &PA) {
2506+
unsigned DroppedCount = 0;
2507+
std::string PassLevel;
2508+
std::string FuncOrModName;
2509+
if (auto *M = unwrapIR<Module>(IR)) {
2510+
this->runOnModule(M, false);
2511+
PassLevel = "Module";
2512+
FuncOrModName = M->getName();
2513+
} else if (auto *F = unwrapIR<Function>(IR)) {
2514+
this->runOnFunction(F, false);
2515+
PassLevel = "Function";
2516+
FuncOrModName = F->getName();
2517+
} else {
2518+
return;
2519+
}
2520+
for (auto Var : DebugVariablesBefore.back())
2521+
if (!DebugVariablesAfter.back().contains(Var)) {
2522+
DroppedCount++;
2523+
removeVarFromAllSets(Var);
2524+
}
2525+
if (DroppedCount > 0)
2526+
llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", "
2527+
<< FuncOrModName << "\n";
2528+
DebugVariablesBefore.pop_back();
2529+
DebugVariablesAfter.pop_back();
2530+
return;
2531+
}
2532+
24442533
StandardInstrumentations::StandardInstrumentations(
24452534
LLVMContext &Context, bool DebugLogging, bool VerifyEach,
24462535
PrintPassOptions PrintPassOpts)
2447-
: PrintPass(DebugLogging, PrintPassOpts),
2448-
OptNone(DebugLogging),
2536+
: PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
24492537
OptPassGate(Context),
24502538
PrintChangedIR(PrintChanged == ChangePrinter::Verbose),
24512539
PrintChangedDiff(PrintChanged == ChangePrinter::DiffVerbose ||
24522540
PrintChanged == ChangePrinter::ColourDiffVerbose,
24532541
PrintChanged == ChangePrinter::ColourDiffVerbose ||
24542542
PrintChanged == ChangePrinter::ColourDiffQuiet),
24552543
WebsiteChangeReporter(PrintChanged == ChangePrinter::DotCfgVerbose),
2456-
Verify(DebugLogging), VerifyEach(VerifyEach) {}
2544+
Verify(DebugLogging), DroppedStats(DroppedVarStats),
2545+
VerifyEach(VerifyEach) {}
24572546

24582547
PrintCrashIRInstrumentation *PrintCrashIRInstrumentation::CrashReporter =
24592548
nullptr;
@@ -2528,6 +2617,7 @@ void StandardInstrumentations::registerCallbacks(
25282617
WebsiteChangeReporter.registerCallbacks(PIC);
25292618
ChangeTester.registerCallbacks(PIC);
25302619
PrintCrashIR.registerCallbacks(PIC);
2620+
DroppedStats.registerCallbacks(PIC);
25312621
if (MAM)
25322622
PreservedCFGChecker.registerCallbacks(PIC, *MAM);
25332623

llvm/test/Other/dropped-var-stats.ll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: opt -dropped-variable-stats %s -passes='adce' -S | FileCheck %s
2+
3+
; CHECK: Pass Level, Pass Name, Num of Dropped Variables, Func or Module Name
4+
; CHECK-NEXT: Function, ADCEPass, 1, _Z3bari
5+
6+
; ModuleID = '/tmp/dropped.cpp'
7+
define noundef range(i32 -2147483646, -2147483648) i32 @_Z3bari(i32 noundef %y) local_unnamed_addr #1 !dbg !19 {
8+
#dbg_value(i32 %y, !15, !DIExpression(), !23)
9+
%add = add nsw i32 %y, 2,!dbg !25
10+
ret i32 %add,!dbg !26
11+
}
12+
!llvm.module.flags = !{ !3, !7}
13+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, sysroot: "/")
14+
!1 = !DIFile(filename: "/tmp/dropped.cpp", directory: "/Users/shubham/Development/llvm-project")
15+
!3 = !{i32 2, !"Debug Info Version", i32 3}
16+
!7 = !{i32 7, !"frame-pointer", i32 1}
17+
!9 = distinct !DISubprogram( unit: !0, retainedNodes: !14)
18+
!13 = !DIBasicType()
19+
!14 = !{}
20+
!15 = !DILocalVariable( scope: !9, type: !13)
21+
!19 = distinct !DISubprogram( unit: !0, retainedNodes: !20)
22+
!20 = !{}
23+
!23 = !DILocation( scope: !9, inlinedAt: !24)
24+
!24 = distinct !DILocation( scope: !19)
25+
!25 = !DILocation( scope: !19)
26+
!26 = !DILocation( scope: !19)

0 commit comments

Comments
 (0)