25
25
#include " llvm/CodeGen/MachineVerifier.h"
26
26
#include " llvm/IR/Constants.h"
27
27
#include " llvm/IR/Function.h"
28
+ #include " llvm/IR/InstIterator.h"
29
+ #include " llvm/IR/IntrinsicInst.h"
28
30
#include " llvm/IR/Module.h"
29
31
#include " llvm/IR/PassInstrumentation.h"
30
32
#include " llvm/IR/PassManager.h"
@@ -138,6 +140,11 @@ static cl::opt<std::string> IRDumpDirectory(
138
140
" files in this directory rather than written to stderr" ),
139
141
cl::Hidden, cl::value_desc(" filename" ));
140
142
143
+ static cl::opt<bool >
144
+ DroppedVarStats (" dropped-variable-stats" , cl::Hidden,
145
+ cl::desc (" Dump dropped debug variables stats" ),
146
+ cl::init(false ));
147
+
141
148
template <typename IRUnitT> static const IRUnitT *unwrapIR (Any IR) {
142
149
const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
143
150
return IRPtr ? *IRPtr : nullptr ;
@@ -2444,16 +2451,16 @@ void DotCfgChangeReporter::registerCallbacks(
2444
2451
StandardInstrumentations::StandardInstrumentations (
2445
2452
LLVMContext &Context, bool DebugLogging, bool VerifyEach,
2446
2453
PrintPassOptions PrintPassOpts)
2447
- : PrintPass(DebugLogging, PrintPassOpts),
2448
- OptNone (DebugLogging),
2454
+ : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2449
2455
OptPassGate (Context),
2450
2456
PrintChangedIR(PrintChanged == ChangePrinter::Verbose),
2451
2457
PrintChangedDiff(PrintChanged == ChangePrinter::DiffVerbose ||
2452
2458
PrintChanged == ChangePrinter::ColourDiffVerbose,
2453
2459
PrintChanged == ChangePrinter::ColourDiffVerbose ||
2454
2460
PrintChanged == ChangePrinter::ColourDiffQuiet),
2455
2461
WebsiteChangeReporter(PrintChanged == ChangePrinter::DotCfgVerbose),
2456
- Verify(DebugLogging), VerifyEach(VerifyEach) {}
2462
+ Verify(DebugLogging), DroppedStats(DroppedVarStats),
2463
+ VerifyEach(VerifyEach) {}
2457
2464
2458
2465
PrintCrashIRInstrumentation *PrintCrashIRInstrumentation::CrashReporter =
2459
2466
nullptr ;
@@ -2513,6 +2520,182 @@ void PrintCrashIRInstrumentation::registerCallbacks(
2513
2520
});
2514
2521
}
2515
2522
2523
+ void DroppedVariableStats::registerCallbacks (
2524
+ PassInstrumentationCallbacks &PIC) {
2525
+ if (!DroppedVarStats)
2526
+ return ;
2527
+
2528
+ PIC.registerBeforeNonSkippedPassCallback (
2529
+ [this ](StringRef P, Any IR) { return this ->runBeforePass (P, IR); });
2530
+ PIC.registerAfterPassCallback (
2531
+ [this ](StringRef P, Any IR, const PreservedAnalyses &PA) {
2532
+ return this ->runAfterPass (P, IR, PA);
2533
+ });
2534
+ PIC.registerAfterPassInvalidatedCallback (
2535
+ [this ](StringRef P, const PreservedAnalyses &PA) {
2536
+ return this ->runAfterPassInvalidated (P, PA);
2537
+ });
2538
+ }
2539
+
2540
+ void DroppedVariableStats::runBeforePass (StringRef PassID, Any IR) {
2541
+ DebugVariablesStack.push_back ({DenseMap<const Function *, DebugVariables>()});
2542
+ InlinedAts.push_back ({DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});
2543
+ if (auto *M = unwrapIR<Module>(IR))
2544
+ return this ->runOnModule (M, true );
2545
+ if (auto *F = unwrapIR<Function>(IR))
2546
+ return this ->runOnFunction (F, true );
2547
+ return ;
2548
+ }
2549
+
2550
+ void DroppedVariableStats::runOnFunction (const Function *F, bool Before) {
2551
+ auto &DebugVariables = DebugVariablesStack.back ()[F];
2552
+ auto &VarIDSet = (Before ? DebugVariables.DebugVariablesBefore
2553
+ : DebugVariables.DebugVariablesAfter );
2554
+ auto &InlinedAtsMap = InlinedAts.back ();
2555
+ auto FuncName = F->getName ();
2556
+ if (Before)
2557
+ InlinedAtsMap.try_emplace (FuncName, DenseMap<VarID, DILocation *>());
2558
+ VarIDSet = DenseSet<VarID>();
2559
+ for (const auto &I : instructions (F)) {
2560
+ for (DbgRecord &DR : I.getDbgRecordRange ()) {
2561
+ if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) {
2562
+ auto *DbgVar = Dbg->getVariable ();
2563
+ auto DbgLoc = DR.getDebugLoc ();
2564
+ VarID Key{DbgVar->getScope (), DbgLoc->getInlinedAtScope (), DbgVar};
2565
+ VarIDSet.insert (Key);
2566
+ if (Before)
2567
+ InlinedAtsMap[FuncName].try_emplace (Key, DbgLoc.getInlinedAt ());
2568
+ }
2569
+ }
2570
+ }
2571
+ }
2572
+
2573
+ void DroppedVariableStats::runOnModule (const Module *M, bool Before) {
2574
+ for (auto &F : *M)
2575
+ runOnFunction (&F, Before);
2576
+ }
2577
+
2578
+ void DroppedVariableStats::removeVarFromAllSets (VarID Var, const Function *F) {
2579
+ // Do not remove Var from the last element, it will be popped from the stack.
2580
+ for (auto &DebugVariablesMap : llvm::drop_end (DebugVariablesStack))
2581
+ DebugVariablesMap[F].DebugVariablesBefore .erase (Var);
2582
+ }
2583
+
2584
+ void DroppedVariableStats::calculateDroppedVarStatsOnModule (
2585
+ const Module *M, StringRef PassID, std::string FuncOrModName,
2586
+ std::string PassLevel) {
2587
+ for (auto &F : *M) {
2588
+ calculateDroppedVarStatsOnFunction (&F, PassID, FuncOrModName, PassLevel);
2589
+ }
2590
+ }
2591
+
2592
+ void DroppedVariableStats::calculateDroppedVarStatsOnFunction (
2593
+ const Function *F, StringRef PassID, std::string FuncOrModName,
2594
+ std::string PassLevel) {
2595
+ unsigned DroppedCount = 0 ;
2596
+ StringRef FuncName = F->getName ();
2597
+ DebugVariables &DbgVariables = DebugVariablesStack.back ()[F];
2598
+ DenseSet<VarID> &DebugVariablesBeforeSet = DbgVariables.DebugVariablesBefore ;
2599
+ DenseSet<VarID> &DebugVariablesAfterSet = DbgVariables.DebugVariablesAfter ;
2600
+ DenseMap<VarID, DILocation *> &InlinedAtsMap = InlinedAts.back ()[FuncName];
2601
+ // Find an Instruction that shares the same scope as the dropped #dbg_value or
2602
+ // has a scope that is the child of the scope of the #dbg_value, and has an
2603
+ // inlinedAt equal to the inlinedAt of the #dbg_value or it's inlinedAt chain
2604
+ // contains the inlinedAt of the #dbg_value, if such an Instruction is found,
2605
+ // debug information is dropped.
2606
+ for (VarID Var : DebugVariablesBeforeSet) {
2607
+ if (DebugVariablesAfterSet.contains (Var))
2608
+ continue ;
2609
+ const DIScope *DbgValScope = std::get<0 >(Var);
2610
+ for (const auto &I : instructions (F)) {
2611
+ auto *DbgLoc = I.getDebugLoc ().get ();
2612
+ if (!DbgLoc)
2613
+ continue ;
2614
+
2615
+ auto *Scope = DbgLoc->getScope ();
2616
+ if (isScopeChildOfOrEqualTo (Scope, DbgValScope)) {
2617
+ if (isInlinedAtChildOfOrEqualTo (DbgLoc->getInlinedAt (),
2618
+ InlinedAtsMap[Var])) {
2619
+ // Found another instruction in the variable's scope, so there exists
2620
+ // a break point at which the variable could be observed. Count it as
2621
+ // dropped.
2622
+ DroppedCount++;
2623
+ break ;
2624
+ }
2625
+ }
2626
+ }
2627
+ removeVarFromAllSets (Var, F);
2628
+ }
2629
+ if (DroppedCount > 0 ) {
2630
+ llvm::outs () << PassLevel << " , " << PassID << " , " << DroppedCount << " , "
2631
+ << FuncOrModName << " \n " ;
2632
+ PassDroppedVariables = true ;
2633
+ } else
2634
+ PassDroppedVariables = false ;
2635
+ }
2636
+
2637
+ void DroppedVariableStats::runAfterPassInvalidated (
2638
+ StringRef PassID, const PreservedAnalyses &PA) {
2639
+ DebugVariablesStack.pop_back ();
2640
+ InlinedAts.pop_back ();
2641
+ }
2642
+
2643
+ void DroppedVariableStats::runAfterPass (StringRef PassID, Any IR,
2644
+ const PreservedAnalyses &PA) {
2645
+ std::string PassLevel;
2646
+ std::string FuncOrModName;
2647
+ if (auto *M = unwrapIR<Module>(IR)) {
2648
+ this ->runOnModule (M, false );
2649
+ PassLevel = " Module" ;
2650
+ FuncOrModName = M->getName ();
2651
+ calculateDroppedVarStatsOnModule (M, PassID, FuncOrModName, PassLevel);
2652
+ } else if (auto *F = unwrapIR<Function>(IR)) {
2653
+ this ->runOnFunction (F, false );
2654
+ PassLevel = " Function" ;
2655
+ FuncOrModName = F->getName ();
2656
+ calculateDroppedVarStatsOnFunction (F, PassID, FuncOrModName, PassLevel);
2657
+ }
2658
+
2659
+ DebugVariablesStack.pop_back ();
2660
+ InlinedAts.pop_back ();
2661
+ return ;
2662
+ }
2663
+
2664
+ bool DroppedVariableStats::isScopeChildOfOrEqualTo (DIScope *Scope,
2665
+ const DIScope *DbgValScope) {
2666
+ while (Scope != nullptr ) {
2667
+ if (VisitedScope.find (Scope) == VisitedScope.end ()) {
2668
+ VisitedScope.insert (Scope);
2669
+ if (Scope == DbgValScope) {
2670
+ VisitedScope.clear ();
2671
+ return true ;
2672
+ }
2673
+ Scope = Scope->getScope ();
2674
+ } else {
2675
+ VisitedScope.clear ();
2676
+ return false ;
2677
+ }
2678
+ }
2679
+ return false ;
2680
+ }
2681
+
2682
+ bool DroppedVariableStats::isInlinedAtChildOfOrEqualTo (
2683
+ const DILocation *InlinedAt, const DILocation *DbgValInlinedAt) {
2684
+ if (DbgValInlinedAt == InlinedAt)
2685
+ return true ;
2686
+ if (!DbgValInlinedAt)
2687
+ return false ;
2688
+ if (!InlinedAt)
2689
+ return false ;
2690
+ auto *IA = InlinedAt;
2691
+ while (IA) {
2692
+ if (IA == DbgValInlinedAt)
2693
+ return true ;
2694
+ IA = IA->getInlinedAt ();
2695
+ }
2696
+ return false ;
2697
+ }
2698
+
2516
2699
void StandardInstrumentations::registerCallbacks (
2517
2700
PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM) {
2518
2701
PrintIR.registerCallbacks (PIC);
@@ -2528,6 +2711,7 @@ void StandardInstrumentations::registerCallbacks(
2528
2711
WebsiteChangeReporter.registerCallbacks (PIC);
2529
2712
ChangeTester.registerCallbacks (PIC);
2530
2713
PrintCrashIR.registerCallbacks (PIC);
2714
+ DroppedStats.registerCallbacks (PIC);
2531
2715
if (MAM)
2532
2716
PreservedCFGChecker.registerCallbacks (PIC, *MAM);
2533
2717
0 commit comments