LLVM 20.0.0git
DroppedVariableStats.h
Go to the documentation of this file.
1///===- DroppedVariableStats.h - Opt Diagnostics -*- C++ -*----------------===//
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#ifndef LLVM_CODEGEN_DROPPEDVARIABLESTATS_H
15#define LLVM_CODEGEN_DROPPEDVARIABLESTATS_H
16
19#include "llvm/IR/Function.h"
21
22namespace llvm {
23
24/// A unique key that represents a debug variable.
25/// First const DIScope *: Represents the scope of the debug variable.
26/// Second const DIScope *: Represents the InlinedAt scope of the debug
27/// variable. const DILocalVariable *: It is a pointer to the debug variable
28/// itself.
29using VarID =
30 std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>;
31
32/// A base class to collect and print dropped debug information variable
33/// statistics.
35public:
36 DroppedVariableStats(bool DroppedVarStatsEnabled)
37 : DroppedVariableStatsEnabled(DroppedVarStatsEnabled) {
38 if (DroppedVarStatsEnabled)
40 << "Pass Level, Pass Name, Num of Dropped Variables, Func or "
41 "Module Name\n";
42 };
43
45
46 // We intend this to be unique per-compilation, thus no copies.
48 void operator=(const DroppedVariableStats &) = delete;
49
50 bool getPassDroppedVariables() { return PassDroppedVariables; }
51
52protected:
53 void setup() {
54 DebugVariablesStack.push_back(
56 InlinedAts.push_back(
58 }
59
60 void cleanup() {
61 assert(!DebugVariablesStack.empty() &&
62 "DebugVariablesStack shouldn't be empty!");
63 assert(!InlinedAts.empty() && "InlinedAts shouldn't be empty!");
64 DebugVariablesStack.pop_back();
65 InlinedAts.pop_back();
66 }
67
70 /// DenseSet of VarIDs before an optimization pass has run.
72 /// DenseSet of VarIDs after an optimization pass has run.
74 };
75
76protected:
77 /// A stack of a DenseMap, that maps DebugVariables for every pass to an
78 /// llvm::Function. A stack is used because an optimization pass can call
79 /// other passes.
81
82 /// A DenseSet tracking whether a scope was visited before.
84 /// A stack of DenseMaps, which map the name of an llvm::Function to a
85 /// DenseMap of VarIDs and their inlinedAt locations before an optimization
86 /// pass has run.
88 /// Calculate the number of dropped variables in an llvm::Function or
89 /// llvm::MachineFunction and print the relevant information to stdout.
91 StringRef FuncName, StringRef PassID,
92 StringRef FuncOrModName,
93 StringRef PassLevel,
94 const Function *Func) {
95 unsigned DroppedCount = 0;
96 DenseSet<VarID> &DebugVariablesBeforeSet =
97 DbgVariables.DebugVariablesBefore;
98 DenseSet<VarID> &DebugVariablesAfterSet = DbgVariables.DebugVariablesAfter;
99 DenseMap<VarID, DILocation *> &InlinedAtsMap = InlinedAts.back()[FuncName];
100 // Find an Instruction that shares the same scope as the dropped #dbg_value
101 // or has a scope that is the child of the scope of the #dbg_value, and has
102 // an inlinedAt equal to the inlinedAt of the #dbg_value or it's inlinedAt
103 // chain contains the inlinedAt of the #dbg_value, if such an Instruction is
104 // found, debug information is dropped.
105 for (VarID Var : DebugVariablesBeforeSet) {
106 if (DebugVariablesAfterSet.contains(Var))
107 continue;
108 visitEveryInstruction(DroppedCount, InlinedAtsMap, Var);
109 removeVarFromAllSets(Var, Func);
110 }
111 if (DroppedCount > 0) {
112 llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount
113 << ", " << FuncOrModName << "\n";
114 PassDroppedVariables = true;
115 } else
116 PassDroppedVariables = false;
117 }
118
119 /// Check if a \p Var has been dropped or is a false positive. Also update the
120 /// \p DroppedCount if a debug variable is dropped.
121 bool updateDroppedCount(DILocation *DbgLoc, const DIScope *Scope,
122 const DIScope *DbgValScope,
123 DenseMap<VarID, DILocation *> &InlinedAtsMap,
124 VarID Var, unsigned &DroppedCount) {
125 // If the Scope is a child of, or equal to the DbgValScope and is inlined at
126 // the Var's InlinedAt location, return true to signify that the Var has
127 // been dropped.
128 if (isScopeChildOfOrEqualTo(Scope, DbgValScope))
129 if (isInlinedAtChildOfOrEqualTo(DbgLoc->getInlinedAt(),
130 InlinedAtsMap[Var])) {
131 // Found another instruction in the variable's scope, so there exists a
132 // break point at which the variable could be observed. Count it as
133 // dropped.
134 DroppedCount++;
135 return true;
136 }
137 return false;
138 }
139 /// Run code to populate relevant data structures over an llvm::Function or
140 /// llvm::MachineFunction.
141 void run(DebugVariables &DbgVariables, StringRef FuncName, bool Before) {
142 auto &VarIDSet = (Before ? DbgVariables.DebugVariablesBefore
143 : DbgVariables.DebugVariablesAfter);
144 auto &InlinedAtsMap = InlinedAts.back();
145 if (Before)
146 InlinedAtsMap.try_emplace(FuncName, DenseMap<VarID, DILocation *>());
147 VarIDSet = DenseSet<VarID>();
148 visitEveryDebugRecord(VarIDSet, InlinedAtsMap, FuncName, Before);
149 }
150 /// Populate the VarIDSet and InlinedAtMap with the relevant information
151 /// needed for before and after pass analysis to determine dropped variable
152 /// status.
154 const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet<VarID> &VarIDSet,
156 StringRef FuncName, bool Before) {
157 VarID Key{DbgVar->getScope(), DbgLoc->getInlinedAtScope(), DbgVar};
158 VarIDSet.insert(Key);
159 if (Before)
160 InlinedAtsMap[FuncName].try_emplace(Key, DbgLoc.getInlinedAt());
161 }
162 /// Visit every llvm::Instruction or llvm::MachineInstruction and check if the
163 /// debug variable denoted by its ID \p Var may have been dropped by an
164 /// optimization pass.
165 virtual void
166 visitEveryInstruction(unsigned &DroppedCount,
167 DenseMap<VarID, DILocation *> &InlinedAtsMap,
168 VarID Var) = 0;
169 /// Visit every debug record in an llvm::Function or llvm::MachineFunction
170 /// and call populateVarIDSetAndInlinedMap on it.
172 DenseSet<VarID> &VarIDSet,
174 StringRef FuncName, bool Before) = 0;
175
176private:
177 /// Remove a dropped debug variable's VarID from all Sets in the
178 /// DroppedVariablesBefore stack.
179 void removeVarFromAllSets(VarID Var, const Function *F) {
180 // Do not remove Var from the last element, it will be popped from the
181 // stack.
182 for (auto &DebugVariablesMap : llvm::drop_end(DebugVariablesStack))
183 DebugVariablesMap[F].DebugVariablesBefore.erase(Var);
184 }
185 /// Return true if \p Scope is the same as \p DbgValScope or a child scope of
186 /// \p DbgValScope, return false otherwise.
187 bool isScopeChildOfOrEqualTo(const DIScope *Scope,
188 const DIScope *DbgValScope) {
189 while (Scope != nullptr) {
190 if (VisitedScope.find(Scope) == VisitedScope.end()) {
191 VisitedScope.insert(Scope);
192 if (Scope == DbgValScope) {
193 VisitedScope.clear();
194 return true;
195 }
196 Scope = Scope->getScope();
197 } else {
198 VisitedScope.clear();
199 return false;
200 }
201 }
202 return false;
203 }
204 /// Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of
205 /// the InlinedAt chain, return false otherwise.
206 bool isInlinedAtChildOfOrEqualTo(const DILocation *InlinedAt,
207 const DILocation *DbgValInlinedAt) {
208 if (DbgValInlinedAt == InlinedAt)
209 return true;
210 if (!DbgValInlinedAt)
211 return false;
212 auto *IA = InlinedAt;
213 while (IA) {
214 if (IA == DbgValInlinedAt)
215 return true;
216 IA = IA->getInlinedAt();
217 }
218 return false;
219 }
220 bool PassDroppedVariables = false;
221};
222
223} // namespace llvm
224
225#endif
#define F(x, y, z)
Definition: MD5.cpp:55
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
DILocalScope * getScope() const
Get the local scope for this variable.
Debug location.
Base class for scope-like contexts.
A debug info location.
Definition: DebugLoc.h:33
DILocation * getInlinedAt() const
Definition: DebugLoc.cpp:39
Implements a dense probed hash-table based set.
Definition: DenseSet.h:278
A base class to collect and print dropped debug information variable statistics.
void calculateDroppedStatsAndPrint(DebugVariables &DbgVariables, StringRef FuncName, StringRef PassID, StringRef FuncOrModName, StringRef PassLevel, const Function *Func)
Calculate the number of dropped variables in an llvm::Function or llvm::MachineFunction and print the...
DenseSet< const DIScope * > VisitedScope
A DenseSet tracking whether a scope was visited before.
virtual void visitEveryInstruction(unsigned &DroppedCount, DenseMap< VarID, DILocation * > &InlinedAtsMap, VarID Var)=0
Visit every llvm::Instruction or llvm::MachineInstruction and check if the debug variable denoted by ...
SmallVector< DenseMap< StringRef, DenseMap< VarID, DILocation * > > > InlinedAts
A stack of DenseMaps, which map the name of an llvm::Function to a DenseMap of VarIDs and their inlin...
void populateVarIDSetAndInlinedMap(const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet< VarID > &VarIDSet, DenseMap< StringRef, DenseMap< VarID, DILocation * > > &InlinedAtsMap, StringRef FuncName, bool Before)
Populate the VarIDSet and InlinedAtMap with the relevant information needed for before and after pass...
virtual void visitEveryDebugRecord(DenseSet< VarID > &VarIDSet, DenseMap< StringRef, DenseMap< VarID, DILocation * > > &InlinedAtsMap, StringRef FuncName, bool Before)=0
Visit every debug record in an llvm::Function or llvm::MachineFunction and call populateVarIDSetAndIn...
DroppedVariableStats(bool DroppedVarStatsEnabled)
DroppedVariableStats(const DroppedVariableStats &)=delete
bool updateDroppedCount(DILocation *DbgLoc, const DIScope *Scope, const DIScope *DbgValScope, DenseMap< VarID, DILocation * > &InlinedAtsMap, VarID Var, unsigned &DroppedCount)
Check if a Var has been dropped or is a false positive.
void run(DebugVariables &DbgVariables, StringRef FuncName, bool Before)
Run code to populate relevant data structures over an llvm::Function or llvm::MachineFunction.
SmallVector< DenseMap< const Function *, DebugVariables > > DebugVariablesStack
A stack of a DenseMap, that maps DebugVariables for every pass to an llvm::Function.
void operator=(const DroppedVariableStats &)=delete
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:213
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition: DenseSet.h:193
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
std::tuple< const DIScope *, const DIScope *, const DILocalVariable * > VarID
A unique key that represents a debug variable.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
Definition: STLExtras.h:336
DenseSet< VarID > DebugVariablesAfter
DenseSet of VarIDs after an optimization pass has run.
DenseSet< VarID > DebugVariablesBefore
DenseSet of VarIDs before an optimization pass has run.