2323
2424namespace llvm {
2525
26- // / A class to collect and print dropped debug information variable statistics.
27- // / After every LLVM IR pass is run, it will print how many #dbg_values were
28- // / dropped due to that pass.
26+ // / A unique key that represents a debug variable.
27+ // / First const DIScope *: Represents the scope of the debug variable.
28+ // / Second const DIScope *: Represents the InlinedAt scope of the debug
29+ // / variable. const DILocalVariable *: It is a pointer to the debug variable
30+ // / itself.
31+ using VarID =
32+ std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>;
33+
34+ // / A base class to collect and print dropped debug information variable
35+ // / statistics.
2936class DroppedVariableStats {
3037public:
3138 DroppedVariableStats (bool DroppedVarStatsEnabled)
@@ -35,22 +42,33 @@ class DroppedVariableStats {
3542 << " Pass Level, Pass Name, Num of Dropped Variables, Func or "
3643 " Module Name\n " ;
3744 };
45+
46+ virtual ~DroppedVariableStats () = default ;
47+
3848 // We intend this to be unique per-compilation, thus no copies.
3949 DroppedVariableStats (const DroppedVariableStats &) = delete ;
4050 void operator =(const DroppedVariableStats &) = delete ;
4151
42- void registerCallbacks (PassInstrumentationCallbacks &PIC);
43- void runBeforePass (StringRef PassID, Any IR);
44- void runAfterPass (StringRef PassID, Any IR, const PreservedAnalyses &PA);
45- void runAfterPassInvalidated (StringRef PassID, const PreservedAnalyses &PA);
4652 bool getPassDroppedVariables () { return PassDroppedVariables; }
4753
48- private:
54+ protected:
55+ void setup () {
56+ DebugVariablesStack.push_back (
57+ {DenseMap<const Function *, DebugVariables>()});
58+ InlinedAts.push_back (
59+ {DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});
60+ }
61+
62+ void cleanup () {
63+ assert (!DebugVariablesStack.empty () &&
64+ " DebugVariablesStack shouldn't be empty!" );
65+ assert (!InlinedAts.empty () && " InlinedAts shouldn't be empty!" );
66+ DebugVariablesStack.pop_back ();
67+ InlinedAts.pop_back ();
68+ }
69+
4970 bool PassDroppedVariables = false ;
5071 bool DroppedVariableStatsEnabled = false ;
51- // / A unique key that represents a #dbg_value.
52- using VarID =
53- std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>;
5472
5573 struct DebugVariables {
5674 // / DenseSet of VarIDs before an optimization pass has run.
@@ -70,36 +88,133 @@ class DroppedVariableStats {
7088 // / DenseMap of VarIDs and their inlinedAt locations before an optimization
7189 // / pass has run.
7290 SmallVector<DenseMap<StringRef, DenseMap<VarID, DILocation *>>> InlinedAts;
91+ // / Calculate the number of dropped variables in an llvm::Function or
92+ // / llvm::MachineFunction and print the relevant information to stdout.
93+ void calculateDroppedStatsAndPrint (DebugVariables &DbgVariables,
94+ StringRef FuncName, StringRef PassID,
95+ StringRef FuncOrModName,
96+ StringRef PassLevel, const Function *Func);
7397
74- // / Iterate over all Functions in a Module and report any dropped debug
75- // / information. Will call calculateDroppedVarStatsOnFunction on every
76- // / Function.
77- void calculateDroppedVarStatsOnModule (const Module *M, StringRef PassID,
78- std::string FuncOrModName,
79- std::string PassLevel);
80- // / Iterate over all Instructions in a Function and report any dropped debug
81- // / information.
82- void calculateDroppedVarStatsOnFunction (const Function *F, StringRef PassID,
83- std::string FuncOrModName,
84- std::string PassLevel);
98+ // / Check if a \p Var has been dropped or is a false positive. Also update the
99+ // / \p DroppedCount if a debug variable is dropped.
100+ bool updateDroppedCount (DILocation *DbgLoc, const DIScope *Scope,
101+ const DIScope *DbgValScope,
102+ DenseMap<VarID, DILocation *> &InlinedAtsMap,
103+ VarID Var, unsigned &DroppedCount);
104+ // / Run code to populate relevant data structures over an llvm::Function or
105+ // / llvm::MachineFunction.
106+ void run (DebugVariables &DbgVariables, StringRef FuncName, bool Before);
107+ // / Populate the VarIDSet and InlinedAtMap with the relevant information
108+ // / needed for before and after pass analysis to determine dropped variable
109+ // / status.
110+ void populateVarIDSetAndInlinedMap (
111+ const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet<VarID> &VarIDSet,
112+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
113+ StringRef FuncName, bool Before);
114+ // / Visit every llvm::Instruction or llvm::MachineInstruction and check if the
115+ // / debug variable denoted by its ID \p Var may have been dropped by an
116+ // / optimization pass.
117+ virtual void
118+ visitEveryInstruction (unsigned &DroppedCount,
119+ DenseMap<VarID, DILocation *> &InlinedAtsMap,
120+ VarID Var) = 0 ;
121+ // / Visit every debug record in an llvm::Function or llvm::MachineFunction
122+ // / and call populateVarIDSetAndInlinedMap on it.
123+ virtual void visitEveryDebugRecord (
124+ DenseSet<VarID> &VarIDSet,
125+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
126+ StringRef FuncName, bool Before) = 0;
127+
128+ private:
129+ // / Remove a dropped debug variable's VarID from all Sets in the
130+ // / DroppedVariablesBefore stack.
131+ void removeVarFromAllSets (VarID Var, const Function *F) {
132+ // Do not remove Var from the last element, it will be popped from the
133+ // stack.
134+ for (auto &DebugVariablesMap : llvm::drop_end (DebugVariablesStack))
135+ DebugVariablesMap[F].DebugVariablesBefore .erase (Var);
136+ }
137+ // / Return true if \p Scope is the same as \p DbgValScope or a child scope of
138+ // / \p DbgValScope, return false otherwise.
139+ bool isScopeChildOfOrEqualTo (const DIScope *Scope,
140+ const DIScope *DbgValScope);
141+ // / Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of
142+ // / the InlinedAt chain, return false otherwise.
143+ bool isInlinedAtChildOfOrEqualTo (const DILocation *InlinedAt,
144+ const DILocation *DbgValInlinedAt);
145+ };
146+
147+ // / A class to collect and print dropped debug information due to LLVM IR
148+ // / optimization passes. After every LLVM IR pass is run, it will print how many
149+ // / #dbg_values were dropped due to that pass.
150+ class DroppedVariableStatsIR : public DroppedVariableStats {
151+ public:
152+ DroppedVariableStatsIR (bool DroppedVarStatsEnabled)
153+ : llvm::DroppedVariableStats(DroppedVarStatsEnabled) {}
154+
155+ virtual ~DroppedVariableStatsIR () = default ;
156+
157+ void runBeforePass (Any IR) {
158+ setup ();
159+ if (const auto *M = unwrapIR<Module>(IR))
160+ return this ->runOnModule (M, true );
161+ if (const auto *F = unwrapIR<Function>(IR))
162+ return this ->runOnFunction (F, true );
163+ }
164+
165+ void runAfterPass (StringRef P, Any IR) {
166+ if (const auto *M = unwrapIR<Module>(IR))
167+ runAfterPassModule (P, M);
168+ else if (const auto *F = unwrapIR<Function>(IR))
169+ runAfterPassFunction (P, F);
170+ cleanup ();
171+ }
172+
173+ void registerCallbacks (PassInstrumentationCallbacks &PIC);
174+
175+ private:
176+ const Function *Func;
177+
178+ void runAfterPassFunction (StringRef PassID, const Function *F) {
179+ runOnFunction (F, false );
180+ calculateDroppedVarStatsOnFunction (F, PassID, F->getName ().str (),
181+ " Function" );
182+ }
183+
184+ void runAfterPassModule (StringRef PassID, const Module *M) {
185+ runOnModule (M, false );
186+ calculateDroppedVarStatsOnModule (M, PassID, M->getName ().str (), " Module" );
187+ }
85188 // / Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
86189 // / after a pass has run to facilitate dropped variable calculation for an
87190 // / llvm::Function.
88191 void runOnFunction (const Function *F, bool Before);
192+ // / Iterate over all Instructions in a Function and report any dropped debug
193+ // / information.
194+ void calculateDroppedVarStatsOnFunction (const Function *F, StringRef PassID,
195+ StringRef FuncOrModName,
196+ StringRef PassLevel);
89197 // / Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
90198 // / after a pass has run to facilitate dropped variable calculation for an
91199 // / llvm::Module. Calls runOnFunction on every Function in the Module.
92200 void runOnModule (const Module *M, bool Before);
93- // / Remove a dropped #dbg_value VarID from all Sets in the
94- // / DroppedVariablesBefore stack.
95- void removeVarFromAllSets (VarID Var, const Function *F);
96- // / Return true if \p Scope is the same as \p DbgValScope or a child scope of
97- // / \p DbgValScope, return false otherwise.
98- bool isScopeChildOfOrEqualTo (DIScope *Scope, const DIScope *DbgValScope);
99- // / Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of
100- // / the InlinedAt chain, return false otherwise.
101- bool isInlinedAtChildOfOrEqualTo (const DILocation *InlinedAt,
102- const DILocation *DbgValInlinedAt);
201+ // / Iterate over all Functions in a Module and report any dropped debug
202+ // / information. Will call calculateDroppedVarStatsOnFunction on every
203+ // / Function.
204+ void calculateDroppedVarStatsOnModule (const Module *M, StringRef PassID,
205+ StringRef FuncOrModName,
206+ StringRef PassLevel);
207+ // / Override base class method to run on an llvm::Function specifically.
208+ virtual void
209+ visitEveryInstruction (unsigned &DroppedCount,
210+ DenseMap<VarID, DILocation *> &InlinedAtsMap,
211+ VarID Var) override ;
212+ // / Override base class method to run on #dbg_values specifically.
213+ virtual void visitEveryDebugRecord (
214+ DenseSet<VarID> &VarIDSet,
215+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
216+ StringRef FuncName, bool Before) override ;
217+
103218 template <typename IRUnitT> static const IRUnitT *unwrapIR (Any IR) {
104219 const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
105220 return IRPtr ? *IRPtr : nullptr ;
0 commit comments