File indexing completed on 2026-05-10 08:44:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CODEGEN_DROPPEDVARIABLESTATS_H
0015 #define LLVM_CODEGEN_DROPPEDVARIABLESTATS_H
0016
0017 #include "llvm/IR/DebugInfoMetadata.h"
0018 #include "llvm/IR/DiagnosticInfo.h"
0019 #include "llvm/IR/Function.h"
0020 #include "llvm/IR/PassInstrumentation.h"
0021
0022 namespace llvm {
0023
0024
0025
0026
0027
0028
0029 using VarID =
0030 std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>;
0031
0032
0033
0034 class DroppedVariableStats {
0035 public:
0036 DroppedVariableStats(bool DroppedVarStatsEnabled)
0037 : DroppedVariableStatsEnabled(DroppedVarStatsEnabled) {
0038 if (DroppedVarStatsEnabled)
0039 llvm::outs()
0040 << "Pass Level, Pass Name, Num of Dropped Variables, Func or "
0041 "Module Name\n";
0042 };
0043
0044 virtual ~DroppedVariableStats() {}
0045
0046
0047 DroppedVariableStats(const DroppedVariableStats &) = delete;
0048 void operator=(const DroppedVariableStats &) = delete;
0049
0050 bool getPassDroppedVariables() { return PassDroppedVariables; }
0051
0052 protected:
0053 void setup() {
0054 DebugVariablesStack.push_back(
0055 {DenseMap<const Function *, DebugVariables>()});
0056 InlinedAts.push_back(
0057 {DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});
0058 }
0059
0060 void cleanup() {
0061 assert(!DebugVariablesStack.empty() &&
0062 "DebugVariablesStack shouldn't be empty!");
0063 assert(!InlinedAts.empty() && "InlinedAts shouldn't be empty!");
0064 DebugVariablesStack.pop_back();
0065 InlinedAts.pop_back();
0066 }
0067
0068 bool DroppedVariableStatsEnabled = false;
0069 struct DebugVariables {
0070
0071 DenseSet<VarID> DebugVariablesBefore;
0072
0073 DenseSet<VarID> DebugVariablesAfter;
0074 };
0075
0076 protected:
0077
0078
0079
0080 SmallVector<DenseMap<const Function *, DebugVariables>> DebugVariablesStack;
0081
0082
0083 DenseSet<const DIScope *> VisitedScope;
0084
0085
0086
0087 SmallVector<DenseMap<StringRef, DenseMap<VarID, DILocation *>>> InlinedAts;
0088
0089
0090 void calculateDroppedStatsAndPrint(DebugVariables &DbgVariables,
0091 StringRef FuncName, StringRef PassID,
0092 StringRef FuncOrModName,
0093 StringRef PassLevel,
0094 const Function *Func) {
0095 unsigned DroppedCount = 0;
0096 DenseSet<VarID> &DebugVariablesBeforeSet =
0097 DbgVariables.DebugVariablesBefore;
0098 DenseSet<VarID> &DebugVariablesAfterSet = DbgVariables.DebugVariablesAfter;
0099 DenseMap<VarID, DILocation *> &InlinedAtsMap = InlinedAts.back()[FuncName];
0100
0101
0102
0103
0104
0105 for (VarID Var : DebugVariablesBeforeSet) {
0106 if (DebugVariablesAfterSet.contains(Var))
0107 continue;
0108 visitEveryInstruction(DroppedCount, InlinedAtsMap, Var);
0109 removeVarFromAllSets(Var, Func);
0110 }
0111 if (DroppedCount > 0) {
0112 llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount
0113 << ", " << FuncOrModName << "\n";
0114 PassDroppedVariables = true;
0115 } else
0116 PassDroppedVariables = false;
0117 }
0118
0119
0120
0121 bool updateDroppedCount(DILocation *DbgLoc, const DIScope *Scope,
0122 const DIScope *DbgValScope,
0123 DenseMap<VarID, DILocation *> &InlinedAtsMap,
0124 VarID Var, unsigned &DroppedCount) {
0125
0126
0127
0128 if (isScopeChildOfOrEqualTo(Scope, DbgValScope))
0129 if (isInlinedAtChildOfOrEqualTo(DbgLoc->getInlinedAt(),
0130 InlinedAtsMap[Var])) {
0131
0132
0133
0134 DroppedCount++;
0135 return true;
0136 }
0137 return false;
0138 }
0139
0140
0141 void run(DebugVariables &DbgVariables, StringRef FuncName, bool Before) {
0142 auto &VarIDSet = (Before ? DbgVariables.DebugVariablesBefore
0143 : DbgVariables.DebugVariablesAfter);
0144 auto &InlinedAtsMap = InlinedAts.back();
0145 if (Before)
0146 InlinedAtsMap.try_emplace(FuncName, DenseMap<VarID, DILocation *>());
0147 VarIDSet = DenseSet<VarID>();
0148 visitEveryDebugRecord(VarIDSet, InlinedAtsMap, FuncName, Before);
0149 }
0150
0151
0152
0153 void populateVarIDSetAndInlinedMap(
0154 const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet<VarID> &VarIDSet,
0155 DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
0156 StringRef FuncName, bool Before) {
0157 VarID Key{DbgVar->getScope(), DbgLoc->getInlinedAtScope(), DbgVar};
0158 VarIDSet.insert(Key);
0159 if (Before)
0160 InlinedAtsMap[FuncName].try_emplace(Key, DbgLoc.getInlinedAt());
0161 }
0162
0163
0164
0165 virtual void
0166 visitEveryInstruction(unsigned &DroppedCount,
0167 DenseMap<VarID, DILocation *> &InlinedAtsMap,
0168 VarID Var) = 0;
0169
0170
0171 virtual void visitEveryDebugRecord(
0172 DenseSet<VarID> &VarIDSet,
0173 DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
0174 StringRef FuncName, bool Before) = 0;
0175
0176 private:
0177
0178
0179 void removeVarFromAllSets(VarID Var, const Function *F) {
0180
0181
0182 for (auto &DebugVariablesMap : llvm::drop_end(DebugVariablesStack))
0183 DebugVariablesMap[F].DebugVariablesBefore.erase(Var);
0184 }
0185
0186
0187 bool isScopeChildOfOrEqualTo(const DIScope *Scope,
0188 const DIScope *DbgValScope) {
0189 while (Scope != nullptr) {
0190 if (VisitedScope.find(Scope) == VisitedScope.end()) {
0191 VisitedScope.insert(Scope);
0192 if (Scope == DbgValScope) {
0193 VisitedScope.clear();
0194 return true;
0195 }
0196 Scope = Scope->getScope();
0197 } else {
0198 VisitedScope.clear();
0199 return false;
0200 }
0201 }
0202 return false;
0203 }
0204
0205
0206 bool isInlinedAtChildOfOrEqualTo(const DILocation *InlinedAt,
0207 const DILocation *DbgValInlinedAt) {
0208 if (DbgValInlinedAt == InlinedAt)
0209 return true;
0210 if (!DbgValInlinedAt)
0211 return false;
0212 auto *IA = InlinedAt;
0213 while (IA) {
0214 if (IA == DbgValInlinedAt)
0215 return true;
0216 IA = IA->getInlinedAt();
0217 }
0218 return false;
0219 }
0220 bool PassDroppedVariables = false;
0221 };
0222
0223 }
0224
0225 #endif