xref: /freebsd/contrib/llvm-project/llvm/lib/IR/DroppedVariableStatsIR.cpp (revision 1342eb5a832fa10e689a29faab3acb6054e4778c)
1 ///===- DroppedVariableStatsIR.cpp ----------------------------------------===//
2 ///
3 /// Part of the LLVM Project, under the Apache License v2.0 with LLVM
4 /// Exceptions. See https://llvm.org/LICENSE.txt for license information.
5 /// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 ///
7 ///===---------------------------------------------------------------------===//
8 /// \file
9 /// Dropped Variable Statistics for Debug Information. Reports any number
10 /// of #dbg_value that get dropped due to an optimization pass.
11 ///
12 ///===---------------------------------------------------------------------===//
13 
14 #include "llvm/IR/DroppedVariableStatsIR.h"
15 #include "llvm/IR/DebugInfoMetadata.h"
16 #include "llvm/IR/InstIterator.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/IR/PassInstrumentation.h"
19 
20 using namespace llvm;
21 
22 template <typename IRUnitT>
23 const IRUnitT *DroppedVariableStatsIR::unwrapIR(Any IR) {
24   const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
25   return IRPtr ? *IRPtr : nullptr;
26 }
27 
28 void DroppedVariableStatsIR::runBeforePass(StringRef P, Any IR) {
29   setup();
30   if (const auto *M = unwrapIR<Module>(IR))
31     return this->runOnModule(P, M, true);
32   if (const auto *F = unwrapIR<Function>(IR))
33     return this->runOnFunction(P, F, true);
34 }
35 
36 void DroppedVariableStatsIR::runAfterPass(StringRef P, Any IR) {
37   if (const auto *M = unwrapIR<Module>(IR))
38     runAfterPassModule(P, M);
39   else if (const auto *F = unwrapIR<Function>(IR))
40     runAfterPassFunction(P, F);
41   cleanup();
42 }
43 
44 void DroppedVariableStatsIR::runAfterPassFunction(StringRef PassID,
45                                                   const Function *F) {
46   runOnFunction(PassID, F, false);
47   calculateDroppedVarStatsOnFunction(F, PassID, F->getName().str(), "Function");
48 }
49 
50 void DroppedVariableStatsIR::runAfterPassModule(StringRef PassID,
51                                                 const Module *M) {
52   runOnModule(PassID, M, false);
53   calculateDroppedVarStatsOnModule(M, PassID, M->getName().str(), "Module");
54 }
55 
56 void DroppedVariableStatsIR::runOnFunction(StringRef PassID, const Function *F,
57                                            bool Before) {
58   auto &DebugVariables = DebugVariablesStack.back()[F];
59   auto FuncName = F->getName();
60   Func = F;
61   run(DebugVariables, FuncName, Before);
62 }
63 
64 void DroppedVariableStatsIR::calculateDroppedVarStatsOnFunction(
65     const Function *F, StringRef PassID, StringRef FuncOrModName,
66     StringRef PassLevel) {
67   Func = F;
68   StringRef FuncName = F->getName();
69   DebugVariables &DbgVariables = DebugVariablesStack.back()[F];
70   calculateDroppedStatsAndPrint(DbgVariables, FuncName, PassID, FuncOrModName,
71                                 PassLevel, Func);
72 }
73 
74 void DroppedVariableStatsIR::runOnModule(StringRef PassID, const Module *M,
75                                          bool Before) {
76   for (auto &F : *M) {
77     runOnFunction(PassID, &F, Before);
78   }
79 }
80 
81 void DroppedVariableStatsIR::calculateDroppedVarStatsOnModule(
82     const Module *M, StringRef PassID, StringRef FuncOrModName,
83     StringRef PassLevel) {
84   for (auto &F : *M) {
85     calculateDroppedVarStatsOnFunction(&F, PassID, FuncOrModName, PassLevel);
86   }
87 }
88 
89 void DroppedVariableStatsIR::registerCallbacks(
90     PassInstrumentationCallbacks &PIC) {
91   if (!DroppedVariableStatsEnabled)
92     return;
93 
94   PIC.registerBeforeNonSkippedPassCallback(
95       [this](StringRef P, Any IR) { return runBeforePass(P, IR); });
96   PIC.registerAfterPassCallback(
97       [this](StringRef P, Any IR, const PreservedAnalyses &PA) {
98         return runAfterPass(P, IR);
99       });
100   PIC.registerAfterPassInvalidatedCallback(
101       [this](StringRef P, const PreservedAnalyses &PA) { return cleanup(); });
102 }
103 
104 void DroppedVariableStatsIR::visitEveryInstruction(
105     unsigned &DroppedCount, DenseMap<VarID, DILocation *> &InlinedAtsMap,
106     VarID Var) {
107   const DIScope *DbgValScope = std::get<0>(Var);
108   for (const auto &I : instructions(Func)) {
109     auto *DbgLoc = I.getDebugLoc().get();
110     if (!DbgLoc)
111       continue;
112     if (updateDroppedCount(DbgLoc, DbgLoc->getScope(), DbgValScope,
113                            InlinedAtsMap, Var, DroppedCount))
114       break;
115   }
116 }
117 
118 void DroppedVariableStatsIR::visitEveryDebugRecord(
119     DenseSet<VarID> &VarIDSet,
120     DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
121     StringRef FuncName, bool Before) {
122   for (const auto &I : instructions(Func)) {
123     for (DbgRecord &DR : I.getDbgRecordRange()) {
124       if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) {
125         auto *DbgVar = Dbg->getVariable();
126         auto DbgLoc = DR.getDebugLoc();
127         populateVarIDSetAndInlinedMap(DbgVar, DbgLoc, VarIDSet, InlinedAtsMap,
128                                       FuncName, Before);
129       }
130     }
131   }
132 }
133