148 lines · cpp
1///===- DroppedVariableStats.cpp ----------------------------------------===//2///3/// Part of the LLVM Project, under the Apache License v2.0 with LLVM4/// Exceptions. See https://llvm.org/LICENSE.txt for license information.5/// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6///7///===---------------------------------------------------------------------===//8/// \file9/// Dropped Variable Statistics for Debug Information. Reports any number10/// of #dbg_value that get dropped due to an optimization pass.11///12///===---------------------------------------------------------------------===//13 14#include "llvm/IR/DroppedVariableStats.h"15#include "llvm/IR/DebugInfoMetadata.h"16#include "llvm/IR/DiagnosticInfo.h"17#include "llvm/IR/Function.h"18 19using namespace llvm;20 21DroppedVariableStats::DroppedVariableStats(bool DroppedVarStatsEnabled)22 : DroppedVariableStatsEnabled(DroppedVarStatsEnabled) {23 if (DroppedVarStatsEnabled)24 llvm::outs() << "Pass Level, Pass Name, Num of Dropped Variables, Func or "25 "Module Name\n";26}27 28void DroppedVariableStats::setup() {29 DebugVariablesStack.push_back({DenseMap<const Function *, DebugVariables>()});30 InlinedAts.push_back({DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});31}32 33void DroppedVariableStats::cleanup() {34 assert(!DebugVariablesStack.empty() &&35 "DebugVariablesStack shouldn't be empty!");36 assert(!InlinedAts.empty() && "InlinedAts shouldn't be empty!");37 DebugVariablesStack.pop_back();38 InlinedAts.pop_back();39}40 41void DroppedVariableStats::calculateDroppedStatsAndPrint(42 DebugVariables &DbgVariables, StringRef FuncName, StringRef PassID,43 StringRef FuncOrModName, StringRef PassLevel, const Function *Func) {44 unsigned DroppedCount = 0;45 DenseSet<VarID> &DebugVariablesBeforeSet = DbgVariables.DebugVariablesBefore;46 DenseSet<VarID> &DebugVariablesAfterSet = DbgVariables.DebugVariablesAfter;47 auto It = InlinedAts.back().find(FuncName);48 if (It == InlinedAts.back().end())49 return;50 DenseMap<VarID, DILocation *> &InlinedAtsMap = It->second;51 // Find an Instruction that shares the same scope as the dropped #dbg_value52 // or has a scope that is the child of the scope of the #dbg_value, and has53 // an inlinedAt equal to the inlinedAt of the #dbg_value or it's inlinedAt54 // chain contains the inlinedAt of the #dbg_value, if such an Instruction is55 // found, debug information is dropped.56 for (VarID Var : DebugVariablesBeforeSet) {57 if (DebugVariablesAfterSet.contains(Var))58 continue;59 visitEveryInstruction(DroppedCount, InlinedAtsMap, Var);60 removeVarFromAllSets(Var, Func);61 }62 if (DroppedCount > 0) {63 llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", "64 << FuncOrModName << "\n";65 PassDroppedVariables = true;66 } else67 PassDroppedVariables = false;68}69 70bool DroppedVariableStats::updateDroppedCount(71 DILocation *DbgLoc, const DIScope *Scope, const DIScope *DbgValScope,72 DenseMap<VarID, DILocation *> &InlinedAtsMap, VarID Var,73 unsigned &DroppedCount) {74 // If the Scope is a child of, or equal to the DbgValScope and is inlined at75 // the Var's InlinedAt location, return true to signify that the Var has76 // been dropped.77 if (isScopeChildOfOrEqualTo(Scope, DbgValScope))78 if (isInlinedAtChildOfOrEqualTo(DbgLoc->getInlinedAt(),79 InlinedAtsMap[Var])) {80 // Found another instruction in the variable's scope, so there exists a81 // break point at which the variable could be observed. Count it as82 // dropped.83 DroppedCount++;84 return true;85 }86 return false;87}88 89void DroppedVariableStats::run(DebugVariables &DbgVariables, StringRef FuncName,90 bool Before) {91 auto &VarIDSet = (Before ? DbgVariables.DebugVariablesBefore92 : DbgVariables.DebugVariablesAfter);93 auto &InlinedAtsMap = InlinedAts.back();94 if (Before)95 InlinedAtsMap.try_emplace(FuncName, DenseMap<VarID, DILocation *>());96 VarIDSet = DenseSet<VarID>();97 visitEveryDebugRecord(VarIDSet, InlinedAtsMap, FuncName, Before);98}99 100void DroppedVariableStats::populateVarIDSetAndInlinedMap(101 const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet<VarID> &VarIDSet,102 DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,103 StringRef FuncName, bool Before) {104 VarID Key{DbgVar->getScope(), DbgLoc->getInlinedAtScope(), DbgVar};105 VarIDSet.insert(Key);106 if (Before)107 InlinedAtsMap[FuncName].try_emplace(Key, DbgLoc.getInlinedAt());108}109 110void DroppedVariableStats::removeVarFromAllSets(VarID Var, const Function *F) {111 // Do not remove Var from the last element, it will be popped from the112 // stack.113 for (auto &DebugVariablesMap : llvm::drop_end(DebugVariablesStack))114 DebugVariablesMap[F].DebugVariablesBefore.erase(Var);115}116 117bool DroppedVariableStats::isScopeChildOfOrEqualTo(const DIScope *Scope,118 const DIScope *DbgValScope) {119 while (Scope != nullptr) {120 if (VisitedScope.insert(Scope).second) {121 if (Scope == DbgValScope) {122 VisitedScope.clear();123 return true;124 }125 Scope = Scope->getScope();126 } else {127 VisitedScope.clear();128 return false;129 }130 }131 return false;132}133 134bool DroppedVariableStats::isInlinedAtChildOfOrEqualTo(135 const DILocation *InlinedAt, const DILocation *DbgValInlinedAt) {136 if (DbgValInlinedAt == InlinedAt)137 return true;138 if (!DbgValInlinedAt)139 return false;140 auto *IA = InlinedAt;141 while (IA) {142 if (IA == DbgValInlinedAt)143 return true;144 IA = IA->getInlinedAt();145 }146 return false;147}148