[llvm] [NFC] Move DroppedVariableStats to its own file and redesign it to be extensible. (PR #115563)
Shubham Sandeep Rastogi via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 14 11:29:04 PST 2024
https://github.com/rastogishubham updated https://github.com/llvm/llvm-project/pull/115563
>From 6daa027c9947fcde207c91bf86e7575012bb14cd Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Mon, 11 Nov 2024 11:53:00 -0800
Subject: [PATCH 1/2] [NFC] Move DroppedVariableStats to its own file
---
.../llvm/CodeGen/DroppedVariableStats.h | 111 ++++++++++
.../llvm/Passes/StandardInstrumentations.h | 78 +------
llvm/lib/CodeGen/CMakeLists.txt | 1 +
llvm/lib/CodeGen/DroppedVariableStats.cpp | 195 ++++++++++++++++++
llvm/lib/Passes/StandardInstrumentations.cpp | 174 ----------------
5 files changed, 308 insertions(+), 251 deletions(-)
create mode 100644 llvm/include/llvm/CodeGen/DroppedVariableStats.h
create mode 100644 llvm/lib/CodeGen/DroppedVariableStats.cpp
diff --git a/llvm/include/llvm/CodeGen/DroppedVariableStats.h b/llvm/include/llvm/CodeGen/DroppedVariableStats.h
new file mode 100644
index 00000000000000..4ce432cb81c13a
--- /dev/null
+++ b/llvm/include/llvm/CodeGen/DroppedVariableStats.h
@@ -0,0 +1,111 @@
+///===- DroppedVariableStats.h - Opt Diagnostics -*- C++ -*----------------===//
+///
+/// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+/// Exceptions. See https://llvm.org/LICENSE.txt for license information.
+/// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+///
+///===---------------------------------------------------------------------===//
+/// \file
+/// Dropped Variable Statistics for Debug Information. Reports any number
+/// of #dbg_value that get dropped due to an optimization pass.
+///
+///===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_DROPPEDVARIABLESTATS_H
+#define LLVM_CODEGEN_DROPPEDVARIABLESTATS_H
+
+#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassInstrumentation.h"
+
+namespace llvm {
+
+/// A class to collect and print dropped debug information variable statistics.
+/// After every LLVM IR pass is run, it will print how many #dbg_values were
+/// dropped due to that pass.
+class DroppedVariableStats {
+public:
+ DroppedVariableStats(bool DroppedVarStatsEnabled)
+ : DroppedVariableStatsEnabled(DroppedVarStatsEnabled) {
+ if (DroppedVarStatsEnabled)
+ llvm::outs()
+ << "Pass Level, Pass Name, Num of Dropped Variables, Func or "
+ "Module Name\n";
+ };
+ // We intend this to be unique per-compilation, thus no copies.
+ DroppedVariableStats(const DroppedVariableStats &) = delete;
+ void operator=(const DroppedVariableStats &) = delete;
+
+ void registerCallbacks(PassInstrumentationCallbacks &PIC);
+ void runBeforePass(StringRef PassID, Any IR);
+ void runAfterPass(StringRef PassID, Any IR, const PreservedAnalyses &PA);
+ void runAfterPassInvalidated(StringRef PassID, const PreservedAnalyses &PA);
+ bool getPassDroppedVariables() { return PassDroppedVariables; }
+
+private:
+ bool PassDroppedVariables = false;
+ bool DroppedVariableStatsEnabled = false;
+ /// A unique key that represents a #dbg_value.
+ using VarID =
+ std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>;
+
+ struct DebugVariables {
+ /// DenseSet of VarIDs before an optimization pass has run.
+ DenseSet<VarID> DebugVariablesBefore;
+ /// DenseSet of VarIDs after an optimization pass has run.
+ DenseSet<VarID> DebugVariablesAfter;
+ };
+
+ /// A stack of a DenseMap, that maps DebugVariables for every pass to an
+ /// llvm::Function. A stack is used because an optimization pass can call
+ /// other passes.
+ SmallVector<DenseMap<const Function *, DebugVariables>> DebugVariablesStack;
+
+ /// A DenseSet tracking whether a scope was visited before.
+ DenseSet<const DIScope *> VisitedScope;
+ /// A stack of DenseMaps, which map the name of an llvm::Function to a
+ /// DenseMap of VarIDs and their inlinedAt locations before an optimization
+ /// pass has run.
+ SmallVector<DenseMap<StringRef, DenseMap<VarID, DILocation *>>> InlinedAts;
+
+ /// Iterate over all Functions in a Module and report any dropped debug
+ /// information. Will call calculateDroppedVarStatsOnFunction on every
+ /// Function.
+ void calculateDroppedVarStatsOnModule(const Module *M, StringRef PassID,
+ std::string FuncOrModName,
+ std::string PassLevel);
+ /// Iterate over all Instructions in a Function and report any dropped debug
+ /// information.
+ void calculateDroppedVarStatsOnFunction(const Function *F, StringRef PassID,
+ std::string FuncOrModName,
+ std::string PassLevel);
+ /// Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
+ /// after a pass has run to facilitate dropped variable calculation for an
+ /// llvm::Function.
+ void runOnFunction(const Function *F, bool Before);
+ /// Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
+ /// after a pass has run to facilitate dropped variable calculation for an
+ /// llvm::Module. Calls runOnFunction on every Function in the Module.
+ void runOnModule(const Module *M, bool Before);
+ /// Remove a dropped #dbg_value VarID from all Sets in the
+ /// DroppedVariablesBefore stack.
+ void removeVarFromAllSets(VarID Var, const Function *F);
+ /// Return true if \p Scope is the same as \p DbgValScope or a child scope of
+ /// \p DbgValScope, return false otherwise.
+ bool isScopeChildOfOrEqualTo(DIScope *Scope, const DIScope *DbgValScope);
+ /// Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of
+ /// the InlinedAt chain, return false otherwise.
+ bool isInlinedAtChildOfOrEqualTo(const DILocation *InlinedAt,
+ const DILocation *DbgValInlinedAt);
+ template <typename IRUnitT> static const IRUnitT *unwrapIR(Any IR) {
+ const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
+ return IRPtr ? *IRPtr : nullptr;
+ }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index 9301a12c740eec..9a8d09c264f08d 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/CodeGen/DroppedVariableStats.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DebugInfoMetadata.h"
@@ -579,83 +580,6 @@ class PrintCrashIRInstrumentation {
static void SignalHandler(void *);
};
-/// A class to collect and print dropped debug information variable statistics.
-/// After every LLVM IR pass is run, it will print how many #dbg_values were
-/// dropped due to that pass.
-class DroppedVariableStats {
-public:
- DroppedVariableStats(bool DroppedVarStatsEnabled) {
- if (DroppedVarStatsEnabled)
- llvm::outs()
- << "Pass Level, Pass Name, Num of Dropped Variables, Func or "
- "Module Name\n";
- };
- // We intend this to be unique per-compilation, thus no copies.
- DroppedVariableStats(const DroppedVariableStats &) = delete;
- void operator=(const DroppedVariableStats &) = delete;
-
- void registerCallbacks(PassInstrumentationCallbacks &PIC);
- void runBeforePass(StringRef PassID, Any IR);
- void runAfterPass(StringRef PassID, Any IR, const PreservedAnalyses &PA);
- void runAfterPassInvalidated(StringRef PassID, const PreservedAnalyses &PA);
- bool getPassDroppedVariables() { return PassDroppedVariables; }
-
-private:
- bool PassDroppedVariables = false;
- /// A unique key that represents a #dbg_value.
- using VarID =
- std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>;
-
- struct DebugVariables {
- /// DenseSet of VarIDs before an optimization pass has run.
- DenseSet<VarID> DebugVariablesBefore;
- /// DenseSet of VarIDs after an optimization pass has run.
- DenseSet<VarID> DebugVariablesAfter;
- };
-
- /// A stack of a DenseMap, that maps DebugVariables for every pass to an
- /// llvm::Function. A stack is used because an optimization pass can call
- /// other passes.
- SmallVector<DenseMap<const Function *, DebugVariables>> DebugVariablesStack;
-
- /// A DenseSet tracking whether a scope was visited before.
- DenseSet<const DIScope *> VisitedScope;
- /// A stack of DenseMaps, which map the name of an llvm::Function to a
- /// DenseMap of VarIDs and their inlinedAt locations before an optimization
- /// pass has run.
- SmallVector<DenseMap<StringRef, DenseMap<VarID, DILocation *>>> InlinedAts;
-
- /// Iterate over all Functions in a Module and report any dropped debug
- /// information. Will call calculateDroppedVarStatsOnFunction on every
- /// Function.
- void calculateDroppedVarStatsOnModule(const Module *M, StringRef PassID,
- std::string FuncOrModName,
- std::string PassLevel);
- /// Iterate over all Instructions in a Function and report any dropped debug
- /// information.
- void calculateDroppedVarStatsOnFunction(const Function *F, StringRef PassID,
- std::string FuncOrModName,
- std::string PassLevel);
- /// Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
- /// after a pass has run to facilitate dropped variable calculation for an
- /// llvm::Function.
- void runOnFunction(const Function *F, bool Before);
- /// Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
- /// after a pass has run to facilitate dropped variable calculation for an
- /// llvm::Module. Calls runOnFunction on every Function in the Module.
- void runOnModule(const Module *M, bool Before);
- /// Remove a dropped #dbg_value VarID from all Sets in the
- /// DroppedVariablesBefore stack.
- void removeVarFromAllSets(VarID Var, const Function *F);
- /// Return true if \p Scope is the same as \p DbgValScope or a child scope of
- /// \p DbgValScope, return false otherwise.
- bool isScopeChildOfOrEqualTo(DIScope *Scope, const DIScope *DbgValScope);
- /// Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of
- /// the InlinedAt chain, return false otherwise.
- bool isInlinedAtChildOfOrEqualTo(const DILocation *InlinedAt,
- const DILocation *DbgValInlinedAt);
-};
-
/// This class provides an interface to register all the standard pass
/// instrumentations and manages their state (if any).
class StandardInstrumentations {
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index 5a17944db0ae03..3eebeaaf04b3a2 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -50,6 +50,7 @@ add_llvm_component_library(LLVMCodeGen
DeadMachineInstructionElim.cpp
DetectDeadLanes.cpp
DFAPacketizer.cpp
+ DroppedVariableStats.cpp
DwarfEHPrepare.cpp
EarlyIfConversion.cpp
EdgeBundles.cpp
diff --git a/llvm/lib/CodeGen/DroppedVariableStats.cpp b/llvm/lib/CodeGen/DroppedVariableStats.cpp
new file mode 100644
index 00000000000000..a1c6b5fccc139d
--- /dev/null
+++ b/llvm/lib/CodeGen/DroppedVariableStats.cpp
@@ -0,0 +1,195 @@
+///===- DroppedVariableStats.cpp ------------------------------------------===//
+///
+/// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+/// Exceptions. See https://llvm.org/LICENSE.txt for license information.
+/// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+///
+///===---------------------------------------------------------------------===//
+/// \file
+/// Dropped Variable Statistics for Debug Information. Reports any number
+/// of #dbg_value that get dropped due to an optimization pass.
+///
+///===---------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/DroppedVariableStats.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+
+using namespace llvm;
+
+void DroppedVariableStats::registerCallbacks(
+ PassInstrumentationCallbacks &PIC) {
+ if (!DroppedVariableStatsEnabled)
+ return;
+
+ PIC.registerBeforeNonSkippedPassCallback(
+ [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); });
+ PIC.registerAfterPassCallback(
+ [this](StringRef P, Any IR, const PreservedAnalyses &PA) {
+ return this->runAfterPass(P, IR, PA);
+ });
+ PIC.registerAfterPassInvalidatedCallback(
+ [this](StringRef P, const PreservedAnalyses &PA) {
+ return this->runAfterPassInvalidated(P, PA);
+ });
+}
+
+void DroppedVariableStats::runBeforePass(StringRef PassID, Any IR) {
+ DebugVariablesStack.push_back({DenseMap<const Function *, DebugVariables>()});
+ InlinedAts.push_back({DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});
+ if (auto *M = unwrapIR<Module>(IR))
+ return this->runOnModule(M, true);
+ if (auto *F = unwrapIR<Function>(IR))
+ return this->runOnFunction(F, true);
+ return;
+}
+
+void DroppedVariableStats::runOnFunction(const Function *F, bool Before) {
+ auto &DebugVariables = DebugVariablesStack.back()[F];
+ auto &VarIDSet = (Before ? DebugVariables.DebugVariablesBefore
+ : DebugVariables.DebugVariablesAfter);
+ auto &InlinedAtsMap = InlinedAts.back();
+ auto FuncName = F->getName();
+ if (Before)
+ InlinedAtsMap.try_emplace(FuncName, DenseMap<VarID, DILocation *>());
+ VarIDSet = DenseSet<VarID>();
+ for (const auto &I : instructions(F)) {
+ for (DbgRecord &DR : I.getDbgRecordRange()) {
+ if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) {
+ auto *DbgVar = Dbg->getVariable();
+ auto DbgLoc = DR.getDebugLoc();
+ VarID Key{DbgVar->getScope(), DbgLoc->getInlinedAtScope(), DbgVar};
+ VarIDSet.insert(Key);
+ if (Before)
+ InlinedAtsMap[FuncName].try_emplace(Key, DbgLoc.getInlinedAt());
+ }
+ }
+ }
+}
+
+void DroppedVariableStats::runOnModule(const Module *M, bool Before) {
+ for (auto &F : *M)
+ runOnFunction(&F, Before);
+}
+
+void DroppedVariableStats::removeVarFromAllSets(VarID Var, const Function *F) {
+ // Do not remove Var from the last element, it will be popped from the stack.
+ for (auto &DebugVariablesMap : llvm::drop_end(DebugVariablesStack))
+ DebugVariablesMap[F].DebugVariablesBefore.erase(Var);
+}
+
+void DroppedVariableStats::calculateDroppedVarStatsOnModule(
+ const Module *M, StringRef PassID, std::string FuncOrModName,
+ std::string PassLevel) {
+ for (auto &F : *M) {
+ calculateDroppedVarStatsOnFunction(&F, PassID, FuncOrModName, PassLevel);
+ }
+}
+
+void DroppedVariableStats::calculateDroppedVarStatsOnFunction(
+ const Function *F, StringRef PassID, std::string FuncOrModName,
+ std::string PassLevel) {
+ unsigned DroppedCount = 0;
+ StringRef FuncName = F->getName();
+ DebugVariables &DbgVariables = DebugVariablesStack.back()[F];
+ DenseSet<VarID> &DebugVariablesBeforeSet = DbgVariables.DebugVariablesBefore;
+ DenseSet<VarID> &DebugVariablesAfterSet = DbgVariables.DebugVariablesAfter;
+ DenseMap<VarID, DILocation *> &InlinedAtsMap = InlinedAts.back()[FuncName];
+ // Find an Instruction that shares the same scope as the dropped #dbg_value or
+ // has a scope that is the child of the scope of the #dbg_value, and has an
+ // inlinedAt equal to the inlinedAt of the #dbg_value or it's inlinedAt chain
+ // contains the inlinedAt of the #dbg_value, if such an Instruction is found,
+ // debug information is dropped.
+ for (VarID Var : DebugVariablesBeforeSet) {
+ if (DebugVariablesAfterSet.contains(Var))
+ continue;
+ const DIScope *DbgValScope = std::get<0>(Var);
+ for (const auto &I : instructions(F)) {
+ auto *DbgLoc = I.getDebugLoc().get();
+ if (!DbgLoc)
+ continue;
+
+ auto *Scope = DbgLoc->getScope();
+ if (isScopeChildOfOrEqualTo(Scope, DbgValScope)) {
+ if (isInlinedAtChildOfOrEqualTo(DbgLoc->getInlinedAt(),
+ InlinedAtsMap[Var])) {
+ // Found another instruction in the variable's scope, so there exists
+ // a break point at which the variable could be observed. Count it as
+ // dropped.
+ DroppedCount++;
+ break;
+ }
+ }
+ }
+ removeVarFromAllSets(Var, F);
+ }
+ if (DroppedCount > 0) {
+ llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", "
+ << FuncOrModName << "\n";
+ PassDroppedVariables = true;
+ } else
+ PassDroppedVariables = false;
+}
+
+void DroppedVariableStats::runAfterPassInvalidated(
+ StringRef PassID, const PreservedAnalyses &PA) {
+ DebugVariablesStack.pop_back();
+ InlinedAts.pop_back();
+}
+
+void DroppedVariableStats::runAfterPass(StringRef PassID, Any IR,
+ const PreservedAnalyses &PA) {
+ std::string PassLevel;
+ std::string FuncOrModName;
+ if (auto *M = unwrapIR<Module>(IR)) {
+ this->runOnModule(M, false);
+ PassLevel = "Module";
+ FuncOrModName = M->getName();
+ calculateDroppedVarStatsOnModule(M, PassID, FuncOrModName, PassLevel);
+ } else if (auto *F = unwrapIR<Function>(IR)) {
+ this->runOnFunction(F, false);
+ PassLevel = "Function";
+ FuncOrModName = F->getName();
+ calculateDroppedVarStatsOnFunction(F, PassID, FuncOrModName, PassLevel);
+ }
+
+ DebugVariablesStack.pop_back();
+ InlinedAts.pop_back();
+ return;
+}
+
+bool DroppedVariableStats::isScopeChildOfOrEqualTo(DIScope *Scope,
+ const DIScope *DbgValScope) {
+ while (Scope != nullptr) {
+ if (VisitedScope.find(Scope) == VisitedScope.end()) {
+ VisitedScope.insert(Scope);
+ if (Scope == DbgValScope) {
+ VisitedScope.clear();
+ return true;
+ }
+ Scope = Scope->getScope();
+ } else {
+ VisitedScope.clear();
+ return false;
+ }
+ }
+ return false;
+}
+
+bool DroppedVariableStats::isInlinedAtChildOfOrEqualTo(
+ const DILocation *InlinedAt, const DILocation *DbgValInlinedAt) {
+ if (DbgValInlinedAt == InlinedAt)
+ return true;
+ if (!DbgValInlinedAt)
+ return false;
+ if (!InlinedAt)
+ return false;
+ auto *IA = InlinedAt;
+ while (IA) {
+ if (IA == DbgValInlinedAt)
+ return true;
+ IA = IA->getInlinedAt();
+ }
+ return false;
+}
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 6259f8f736c80b..70825bfa91da25 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -2523,180 +2523,6 @@ void PrintCrashIRInstrumentation::registerCallbacks(
});
}
-void DroppedVariableStats::registerCallbacks(
- PassInstrumentationCallbacks &PIC) {
- if (!DroppedVarStats)
- return;
-
- PIC.registerBeforeNonSkippedPassCallback(
- [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); });
- PIC.registerAfterPassCallback(
- [this](StringRef P, Any IR, const PreservedAnalyses &PA) {
- return this->runAfterPass(P, IR, PA);
- });
- PIC.registerAfterPassInvalidatedCallback(
- [this](StringRef P, const PreservedAnalyses &PA) {
- return this->runAfterPassInvalidated(P, PA);
- });
-}
-
-void DroppedVariableStats::runBeforePass(StringRef PassID, Any IR) {
- DebugVariablesStack.push_back({DenseMap<const Function *, DebugVariables>()});
- InlinedAts.push_back({DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});
- if (auto *M = unwrapIR<Module>(IR))
- return this->runOnModule(M, true);
- if (auto *F = unwrapIR<Function>(IR))
- return this->runOnFunction(F, true);
-}
-
-void DroppedVariableStats::runOnFunction(const Function *F, bool Before) {
- auto &DebugVariables = DebugVariablesStack.back()[F];
- auto &VarIDSet = (Before ? DebugVariables.DebugVariablesBefore
- : DebugVariables.DebugVariablesAfter);
- auto &InlinedAtsMap = InlinedAts.back();
- auto FuncName = F->getName();
- if (Before)
- InlinedAtsMap.try_emplace(FuncName, DenseMap<VarID, DILocation *>());
- VarIDSet = DenseSet<VarID>();
- for (const auto &I : instructions(F)) {
- for (DbgRecord &DR : I.getDbgRecordRange()) {
- if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) {
- auto *DbgVar = Dbg->getVariable();
- auto DbgLoc = DR.getDebugLoc();
- VarID Key{DbgVar->getScope(), DbgLoc->getInlinedAtScope(), DbgVar};
- VarIDSet.insert(Key);
- if (Before)
- InlinedAtsMap[FuncName].try_emplace(Key, DbgLoc.getInlinedAt());
- }
- }
- }
-}
-
-void DroppedVariableStats::runOnModule(const Module *M, bool Before) {
- for (auto &F : *M)
- runOnFunction(&F, Before);
-}
-
-void DroppedVariableStats::removeVarFromAllSets(VarID Var, const Function *F) {
- // Do not remove Var from the last element, it will be popped from the stack.
- for (auto &DebugVariablesMap : llvm::drop_end(DebugVariablesStack))
- DebugVariablesMap[F].DebugVariablesBefore.erase(Var);
-}
-
-void DroppedVariableStats::calculateDroppedVarStatsOnModule(
- const Module *M, StringRef PassID, std::string FuncOrModName,
- std::string PassLevel) {
- for (auto &F : *M) {
- calculateDroppedVarStatsOnFunction(&F, PassID, FuncOrModName, PassLevel);
- }
-}
-
-void DroppedVariableStats::calculateDroppedVarStatsOnFunction(
- const Function *F, StringRef PassID, std::string FuncOrModName,
- std::string PassLevel) {
- unsigned DroppedCount = 0;
- StringRef FuncName = F->getName();
- DebugVariables &DbgVariables = DebugVariablesStack.back()[F];
- DenseSet<VarID> &DebugVariablesBeforeSet = DbgVariables.DebugVariablesBefore;
- DenseSet<VarID> &DebugVariablesAfterSet = DbgVariables.DebugVariablesAfter;
- DenseMap<VarID, DILocation *> &InlinedAtsMap = InlinedAts.back()[FuncName];
- // Find an Instruction that shares the same scope as the dropped #dbg_value or
- // has a scope that is the child of the scope of the #dbg_value, and has an
- // inlinedAt equal to the inlinedAt of the #dbg_value or it's inlinedAt chain
- // contains the inlinedAt of the #dbg_value, if such an Instruction is found,
- // debug information is dropped.
- for (VarID Var : DebugVariablesBeforeSet) {
- if (DebugVariablesAfterSet.contains(Var))
- continue;
- const DIScope *DbgValScope = std::get<0>(Var);
- for (const auto &I : instructions(F)) {
- auto *DbgLoc = I.getDebugLoc().get();
- if (!DbgLoc)
- continue;
-
- auto *Scope = DbgLoc->getScope();
- if (isScopeChildOfOrEqualTo(Scope, DbgValScope)) {
- if (isInlinedAtChildOfOrEqualTo(DbgLoc->getInlinedAt(),
- InlinedAtsMap[Var])) {
- // Found another instruction in the variable's scope, so there exists
- // a break point at which the variable could be observed. Count it as
- // dropped.
- DroppedCount++;
- break;
- }
- }
- }
- removeVarFromAllSets(Var, F);
- }
- if (DroppedCount > 0) {
- llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", "
- << FuncOrModName << "\n";
- PassDroppedVariables = true;
- } else
- PassDroppedVariables = false;
-}
-
-void DroppedVariableStats::runAfterPassInvalidated(
- StringRef PassID, const PreservedAnalyses &PA) {
- DebugVariablesStack.pop_back();
- InlinedAts.pop_back();
-}
-
-void DroppedVariableStats::runAfterPass(StringRef PassID, Any IR,
- const PreservedAnalyses &PA) {
- std::string PassLevel;
- std::string FuncOrModName;
- if (auto *M = unwrapIR<Module>(IR)) {
- this->runOnModule(M, false);
- PassLevel = "Module";
- FuncOrModName = M->getName();
- calculateDroppedVarStatsOnModule(M, PassID, FuncOrModName, PassLevel);
- } else if (auto *F = unwrapIR<Function>(IR)) {
- this->runOnFunction(F, false);
- PassLevel = "Function";
- FuncOrModName = F->getName();
- calculateDroppedVarStatsOnFunction(F, PassID, FuncOrModName, PassLevel);
- }
-
- DebugVariablesStack.pop_back();
- InlinedAts.pop_back();
-}
-
-bool DroppedVariableStats::isScopeChildOfOrEqualTo(DIScope *Scope,
- const DIScope *DbgValScope) {
- while (Scope != nullptr) {
- if (VisitedScope.find(Scope) == VisitedScope.end()) {
- VisitedScope.insert(Scope);
- if (Scope == DbgValScope) {
- VisitedScope.clear();
- return true;
- }
- Scope = Scope->getScope();
- } else {
- VisitedScope.clear();
- return false;
- }
- }
- return false;
-}
-
-bool DroppedVariableStats::isInlinedAtChildOfOrEqualTo(
- const DILocation *InlinedAt, const DILocation *DbgValInlinedAt) {
- if (DbgValInlinedAt == InlinedAt)
- return true;
- if (!DbgValInlinedAt)
- return false;
- if (!InlinedAt)
- return false;
- auto *IA = InlinedAt;
- while (IA) {
- if (IA == DbgValInlinedAt)
- return true;
- IA = IA->getInlinedAt();
- }
- return false;
-}
-
void StandardInstrumentations::registerCallbacks(
PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM) {
PrintIR.registerCallbacks(PIC);
>From 0e57047c1e0bc88548f0df4df479fafc788978b8 Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Mon, 11 Nov 2024 12:07:49 -0800
Subject: [PATCH 2/2] Change DroppedVariableStats to be extensible.
Change DroppedVariableStats to have an extensible design so that we can
use it to add dropped statistics to MIR passes and the instruction
selector.
---
.../llvm/CodeGen/DroppedVariableStats.h | 169 +++++++++--
.../llvm/Passes/StandardInstrumentations.h | 2 +-
llvm/lib/CodeGen/DroppedVariableStats.cpp | 273 +++++++++---------
llvm/lib/Passes/StandardInstrumentations.cpp | 4 +-
llvm/unittests/IR/CMakeLists.txt | 2 +-
...est.cpp => DroppedVariableStatsIRTest.cpp} | 73 ++---
6 files changed, 308 insertions(+), 215 deletions(-)
rename llvm/unittests/IR/{DroppedVariableStatsTest.cpp => DroppedVariableStatsIRTest.cpp} (91%)
diff --git a/llvm/include/llvm/CodeGen/DroppedVariableStats.h b/llvm/include/llvm/CodeGen/DroppedVariableStats.h
index 4ce432cb81c13a..63f9de36a5795d 100644
--- a/llvm/include/llvm/CodeGen/DroppedVariableStats.h
+++ b/llvm/include/llvm/CodeGen/DroppedVariableStats.h
@@ -23,9 +23,12 @@
namespace llvm {
-/// A class to collect and print dropped debug information variable statistics.
-/// After every LLVM IR pass is run, it will print how many #dbg_values were
-/// dropped due to that pass.
+/// A unique key that represents a #dbg_value.
+using VarID =
+ std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>;
+
+/// A base class to collect and print dropped debug information variable
+/// statistics.
class DroppedVariableStats {
public:
DroppedVariableStats(bool DroppedVarStatsEnabled)
@@ -35,22 +38,30 @@ class DroppedVariableStats {
<< "Pass Level, Pass Name, Num of Dropped Variables, Func or "
"Module Name\n";
};
+
+ virtual ~DroppedVariableStats() = default;
+
// We intend this to be unique per-compilation, thus no copies.
DroppedVariableStats(const DroppedVariableStats &) = delete;
void operator=(const DroppedVariableStats &) = delete;
- void registerCallbacks(PassInstrumentationCallbacks &PIC);
- void runBeforePass(StringRef PassID, Any IR);
- void runAfterPass(StringRef PassID, Any IR, const PreservedAnalyses &PA);
- void runAfterPassInvalidated(StringRef PassID, const PreservedAnalyses &PA);
bool getPassDroppedVariables() { return PassDroppedVariables; }
-private:
+protected:
+ void setup() {
+ DebugVariablesStack.push_back(
+ {DenseMap<const Function *, DebugVariables>()});
+ InlinedAts.push_back(
+ {DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});
+ }
+
+ void cleanup() {
+ DebugVariablesStack.pop_back();
+ InlinedAts.pop_back();
+ }
+
bool PassDroppedVariables = false;
bool DroppedVariableStatsEnabled = false;
- /// A unique key that represents a #dbg_value.
- using VarID =
- std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>;
struct DebugVariables {
/// DenseSet of VarIDs before an optimization pass has run.
@@ -70,36 +81,130 @@ class DroppedVariableStats {
/// DenseMap of VarIDs and their inlinedAt locations before an optimization
/// pass has run.
SmallVector<DenseMap<StringRef, DenseMap<VarID, DILocation *>>> InlinedAts;
+ /// Remove a dropped #dbg_value VarID from all Sets in the
+ /// DroppedVariablesBefore stack.
+ void removeVarFromAllSets(VarID Var, const Function *F) {
+ // Do not remove Var from the last element, it will be popped from the
+ // stack.
+ for (auto &DebugVariablesMap : llvm::drop_end(DebugVariablesStack))
+ DebugVariablesMap[F].DebugVariablesBefore.erase(Var);
+ }
+ /// Return true if \p Scope is the same as \p DbgValScope or a child scope of
+ /// \p DbgValScope, return false otherwise.
+ bool isScopeChildOfOrEqualTo(const DIScope *Scope,
+ const DIScope *DbgValScope);
+ /// Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of
+ /// the InlinedAt chain, return false otherwise.
+ bool isInlinedAtChildOfOrEqualTo(const DILocation *InlinedAt,
+ const DILocation *DbgValInlinedAt);
- /// Iterate over all Functions in a Module and report any dropped debug
- /// information. Will call calculateDroppedVarStatsOnFunction on every
- /// Function.
- void calculateDroppedVarStatsOnModule(const Module *M, StringRef PassID,
- std::string FuncOrModName,
- std::string PassLevel);
- /// Iterate over all Instructions in a Function and report any dropped debug
- /// information.
- void calculateDroppedVarStatsOnFunction(const Function *F, StringRef PassID,
- std::string FuncOrModName,
- std::string PassLevel);
+ /// Calculate the number of dropped variables in an llvm::Function or
+ /// llvm::MachineFunction and print the relevant information to stdout.
+ void calculateDroppedStatsAndPrint(DebugVariables &DbgVariables,
+ StringRef FuncName, StringRef PassID,
+ StringRef FuncOrModName,
+ StringRef PassLevel, const Function *Func);
+
+ /// Check if a \p Var has been dropped or is a false positive.
+ bool wasDropped(DILocation *DbgLoc, const DIScope *Scope,
+ const DIScope *DbgValScope,
+ DenseMap<VarID, DILocation *> &InlinedAtsMap, VarID Var,
+ unsigned &DroppedCount);
+ /// Run code to populate relevant data structures over an llvm::Function or
+ /// llvm::MachineFunction.
+ void run(DebugVariables &DbgVariables, StringRef FuncName, bool Before);
+ /// Populate the VarIDSet and InlinedAtMap with the relevant information
+ /// needed for before and after pass analysis to determine dropped variable
+ /// status.
+ void populateVarIDSetAndInlinedMap(
+ const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet<VarID> &VarIDSet,
+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
+ StringRef FuncName, bool Before);
+ /// Visit every VarID in the \p DebugVariablesBeforeSet and check if it may
+ /// have been dropped by an optimization pass.
+ virtual void visitEveryDebugVariable(
+ unsigned &DroppedCount, DenseSet<VarID> &DebugVariablesBeforeSet,
+ DenseSet<VarID> &DebugVariablesAfterSet,
+ DenseMap<VarID, DILocation *> &InlinedAtsMap, VarID Var) = 0;
+ /// Visit every debug intrinsic in an llvm::Function or llvm::MachineFunction
+ /// to populate relevant data structures to determine dropped variable status.
+ virtual void visitEveryDebugIntrinsic(
+ DenseSet<VarID> &VarIDSet,
+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
+ StringRef FuncName, bool Before) = 0;
+};
+
+/// A class to collect and print dropped debug information due to LLVM IR
+/// optimization passes. After every LLVM IR pass is run, it will print how many
+/// #dbg_values were dropped due to that pass.
+class DroppedVariableStatsIR : public DroppedVariableStats {
+public:
+ DroppedVariableStatsIR(bool DroppedVarStatsEnabled)
+ : llvm::DroppedVariableStats(DroppedVarStatsEnabled) {}
+
+ virtual ~DroppedVariableStatsIR() = default;
+
+ void runBeforePass(Any IR) {
+ setup();
+ if (const auto *M = unwrapIR<Module>(IR))
+ return this->runOnModule(M, true);
+ if (const auto *F = unwrapIR<Function>(IR))
+ return this->runOnFunction(F, true);
+ }
+
+ void runAfterPass(StringRef P, Any IR) {
+ if (const auto *M = unwrapIR<Module>(IR))
+ runAfterPassModule(P, M);
+ else if (const auto *F = unwrapIR<Function>(IR))
+ runAfterPassFunction(P, F);
+ cleanup();
+ }
+
+ void registerCallbacks(PassInstrumentationCallbacks &PIC);
+
+private:
+ const Function *Func;
+
+ void runAfterPassFunction(StringRef PassID, const Function *F) {
+ runOnFunction(F, false);
+ calculateDroppedVarStatsOnFunction(F, PassID, F->getName().str(),
+ "Function");
+ }
+
+ void runAfterPassModule(StringRef PassID, const Module *M) {
+ runOnModule(M, false);
+ calculateDroppedVarStatsOnModule(M, PassID, M->getName().str(), "Module");
+ }
/// Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
/// after a pass has run to facilitate dropped variable calculation for an
/// llvm::Function.
void runOnFunction(const Function *F, bool Before);
+ /// Iterate over all Instructions in a Function and report any dropped debug
+ /// information.
+ void calculateDroppedVarStatsOnFunction(const Function *F, StringRef PassID,
+ StringRef FuncOrModName,
+ StringRef PassLevel);
/// Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
/// after a pass has run to facilitate dropped variable calculation for an
/// llvm::Module. Calls runOnFunction on every Function in the Module.
void runOnModule(const Module *M, bool Before);
- /// Remove a dropped #dbg_value VarID from all Sets in the
- /// DroppedVariablesBefore stack.
- void removeVarFromAllSets(VarID Var, const Function *F);
- /// Return true if \p Scope is the same as \p DbgValScope or a child scope of
- /// \p DbgValScope, return false otherwise.
- bool isScopeChildOfOrEqualTo(DIScope *Scope, const DIScope *DbgValScope);
- /// Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of
- /// the InlinedAt chain, return false otherwise.
- bool isInlinedAtChildOfOrEqualTo(const DILocation *InlinedAt,
- const DILocation *DbgValInlinedAt);
+ /// Iterate over all Functions in a Module and report any dropped debug
+ /// information. Will call calculateDroppedVarStatsOnFunction on every
+ /// Function.
+ void calculateDroppedVarStatsOnModule(const Module *M, StringRef PassID,
+ StringRef FuncOrModName,
+ StringRef PassLevel);
+ /// Override base class method to run on an llvm::Function specifically.
+ virtual void visitEveryDebugVariable(
+ unsigned &DroppedCount, DenseSet<VarID> &DebugVariablesBeforeSet,
+ DenseSet<VarID> &DebugVariablesAfterSet,
+ DenseMap<VarID, DILocation *> &InlinedAtsMap, VarID Var) override;
+ /// Override base class method to run on #dbg_values specifically.
+ virtual void visitEveryDebugIntrinsic(
+ DenseSet<VarID> &VarIDSet,
+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
+ StringRef FuncName, bool Before) override;
+
template <typename IRUnitT> static const IRUnitT *unwrapIR(Any IR) {
const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
return IRPtr ? *IRPtr : nullptr;
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index 9a8d09c264f08d..12a34c099eaffe 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -597,7 +597,7 @@ class StandardInstrumentations {
PrintCrashIRInstrumentation PrintCrashIR;
IRChangedTester ChangeTester;
VerifyInstrumentation Verify;
- DroppedVariableStats DroppedStats;
+ DroppedVariableStatsIR DroppedStatsIR;
bool VerifyEach;
diff --git a/llvm/lib/CodeGen/DroppedVariableStats.cpp b/llvm/lib/CodeGen/DroppedVariableStats.cpp
index a1c6b5fccc139d..de5e13da4363c9 100644
--- a/llvm/lib/CodeGen/DroppedVariableStats.cpp
+++ b/llvm/lib/CodeGen/DroppedVariableStats.cpp
@@ -18,81 +18,45 @@
using namespace llvm;
-void DroppedVariableStats::registerCallbacks(
- PassInstrumentationCallbacks &PIC) {
- if (!DroppedVariableStatsEnabled)
- return;
-
- PIC.registerBeforeNonSkippedPassCallback(
- [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); });
- PIC.registerAfterPassCallback(
- [this](StringRef P, Any IR, const PreservedAnalyses &PA) {
- return this->runAfterPass(P, IR, PA);
- });
- PIC.registerAfterPassInvalidatedCallback(
- [this](StringRef P, const PreservedAnalyses &PA) {
- return this->runAfterPassInvalidated(P, PA);
- });
-}
-
-void DroppedVariableStats::runBeforePass(StringRef PassID, Any IR) {
- DebugVariablesStack.push_back({DenseMap<const Function *, DebugVariables>()});
- InlinedAts.push_back({DenseMap<StringRef, DenseMap<VarID, DILocation *>>()});
- if (auto *M = unwrapIR<Module>(IR))
- return this->runOnModule(M, true);
- if (auto *F = unwrapIR<Function>(IR))
- return this->runOnFunction(F, true);
- return;
-}
-
-void DroppedVariableStats::runOnFunction(const Function *F, bool Before) {
- auto &DebugVariables = DebugVariablesStack.back()[F];
- auto &VarIDSet = (Before ? DebugVariables.DebugVariablesBefore
- : DebugVariables.DebugVariablesAfter);
- auto &InlinedAtsMap = InlinedAts.back();
- auto FuncName = F->getName();
- if (Before)
- InlinedAtsMap.try_emplace(FuncName, DenseMap<VarID, DILocation *>());
- VarIDSet = DenseSet<VarID>();
- for (const auto &I : instructions(F)) {
- for (DbgRecord &DR : I.getDbgRecordRange()) {
- if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) {
- auto *DbgVar = Dbg->getVariable();
- auto DbgLoc = DR.getDebugLoc();
- VarID Key{DbgVar->getScope(), DbgLoc->getInlinedAtScope(), DbgVar};
- VarIDSet.insert(Key);
- if (Before)
- InlinedAtsMap[FuncName].try_emplace(Key, DbgLoc.getInlinedAt());
+bool DroppedVariableStats::isScopeChildOfOrEqualTo(const DIScope *Scope,
+ const DIScope *DbgValScope) {
+ while (Scope != nullptr) {
+ if (VisitedScope.find(Scope) == VisitedScope.end()) {
+ VisitedScope.insert(Scope);
+ if (Scope == DbgValScope) {
+ VisitedScope.clear();
+ return true;
}
+ Scope = Scope->getScope();
+ } else {
+ VisitedScope.clear();
+ return false;
}
}
+ return false;
}
-void DroppedVariableStats::runOnModule(const Module *M, bool Before) {
- for (auto &F : *M)
- runOnFunction(&F, Before);
-}
-
-void DroppedVariableStats::removeVarFromAllSets(VarID Var, const Function *F) {
- // Do not remove Var from the last element, it will be popped from the stack.
- for (auto &DebugVariablesMap : llvm::drop_end(DebugVariablesStack))
- DebugVariablesMap[F].DebugVariablesBefore.erase(Var);
-}
-
-void DroppedVariableStats::calculateDroppedVarStatsOnModule(
- const Module *M, StringRef PassID, std::string FuncOrModName,
- std::string PassLevel) {
- for (auto &F : *M) {
- calculateDroppedVarStatsOnFunction(&F, PassID, FuncOrModName, PassLevel);
+bool DroppedVariableStats::isInlinedAtChildOfOrEqualTo(
+ const DILocation *InlinedAt, const DILocation *DbgValInlinedAt) {
+ if (DbgValInlinedAt == InlinedAt)
+ return true;
+ if (!DbgValInlinedAt)
+ return false;
+ if (!InlinedAt)
+ return false;
+ auto *IA = InlinedAt;
+ while (IA) {
+ if (IA == DbgValInlinedAt)
+ return true;
+ IA = IA->getInlinedAt();
}
+ return false;
}
-void DroppedVariableStats::calculateDroppedVarStatsOnFunction(
- const Function *F, StringRef PassID, std::string FuncOrModName,
- std::string PassLevel) {
+void DroppedVariableStats::calculateDroppedStatsAndPrint(
+ DebugVariables &DbgVariables, StringRef FuncName, StringRef PassID,
+ StringRef FuncOrModName, StringRef PassLevel, const Function *Func) {
unsigned DroppedCount = 0;
- StringRef FuncName = F->getName();
- DebugVariables &DbgVariables = DebugVariablesStack.back()[F];
DenseSet<VarID> &DebugVariablesBeforeSet = DbgVariables.DebugVariablesBefore;
DenseSet<VarID> &DebugVariablesAfterSet = DbgVariables.DebugVariablesAfter;
DenseMap<VarID, DILocation *> &InlinedAtsMap = InlinedAts.back()[FuncName];
@@ -104,25 +68,9 @@ void DroppedVariableStats::calculateDroppedVarStatsOnFunction(
for (VarID Var : DebugVariablesBeforeSet) {
if (DebugVariablesAfterSet.contains(Var))
continue;
- const DIScope *DbgValScope = std::get<0>(Var);
- for (const auto &I : instructions(F)) {
- auto *DbgLoc = I.getDebugLoc().get();
- if (!DbgLoc)
- continue;
-
- auto *Scope = DbgLoc->getScope();
- if (isScopeChildOfOrEqualTo(Scope, DbgValScope)) {
- if (isInlinedAtChildOfOrEqualTo(DbgLoc->getInlinedAt(),
- InlinedAtsMap[Var])) {
- // Found another instruction in the variable's scope, so there exists
- // a break point at which the variable could be observed. Count it as
- // dropped.
- DroppedCount++;
- break;
- }
- }
- }
- removeVarFromAllSets(Var, F);
+ visitEveryDebugVariable(DroppedCount, DebugVariablesBeforeSet,
+ DebugVariablesAfterSet, InlinedAtsMap, Var);
+ removeVarFromAllSets(Var, Func);
}
if (DroppedCount > 0) {
llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", "
@@ -132,64 +80,119 @@ void DroppedVariableStats::calculateDroppedVarStatsOnFunction(
PassDroppedVariables = false;
}
-void DroppedVariableStats::runAfterPassInvalidated(
- StringRef PassID, const PreservedAnalyses &PA) {
- DebugVariablesStack.pop_back();
- InlinedAts.pop_back();
+bool DroppedVariableStats::wasDropped(
+ DILocation *DbgLoc, const DIScope *Scope, const DIScope *DbgValScope,
+ DenseMap<VarID, DILocation *> &InlinedAtsMap, VarID Var,
+ unsigned &DroppedCount) {
+
+ // If the Scope is a child of, or equal to the DbgValScope and is inlined at
+ // the Var's InlinedAt location, return true to signify that the Var has been
+ // dropped.
+ if (isScopeChildOfOrEqualTo(Scope, DbgValScope))
+ if (isInlinedAtChildOfOrEqualTo(DbgLoc->getInlinedAt(),
+ InlinedAtsMap[Var])) {
+ // Found another instruction in the variable's scope, so there exists a
+ // break point at which the variable could be observed. Count it as
+ // dropped.
+ DroppedCount++;
+ return true;
+ }
+ return false;
}
-void DroppedVariableStats::runAfterPass(StringRef PassID, Any IR,
- const PreservedAnalyses &PA) {
- std::string PassLevel;
- std::string FuncOrModName;
- if (auto *M = unwrapIR<Module>(IR)) {
- this->runOnModule(M, false);
- PassLevel = "Module";
- FuncOrModName = M->getName();
- calculateDroppedVarStatsOnModule(M, PassID, FuncOrModName, PassLevel);
- } else if (auto *F = unwrapIR<Function>(IR)) {
- this->runOnFunction(F, false);
- PassLevel = "Function";
- FuncOrModName = F->getName();
- calculateDroppedVarStatsOnFunction(F, PassID, FuncOrModName, PassLevel);
+void DroppedVariableStats::run(DebugVariables &DbgVariables, StringRef FuncName,
+ bool Before) {
+ auto &VarIDSet = (Before ? DbgVariables.DebugVariablesBefore
+ : DbgVariables.DebugVariablesAfter);
+ auto &InlinedAtsMap = InlinedAts.back();
+ if (Before)
+ InlinedAtsMap.try_emplace(FuncName, DenseMap<VarID, DILocation *>());
+ VarIDSet = DenseSet<VarID>();
+ visitEveryDebugIntrinsic(VarIDSet, InlinedAtsMap, FuncName, Before);
+}
+
+void DroppedVariableStats::populateVarIDSetAndInlinedMap(
+ const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet<VarID> &VarIDSet,
+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
+ StringRef FuncName, bool Before) {
+ VarID Key{DbgVar->getScope(), DbgLoc->getInlinedAtScope(), DbgVar};
+ VarIDSet.insert(Key);
+ if (Before)
+ InlinedAtsMap[FuncName].try_emplace(Key, DbgLoc.getInlinedAt());
+}
+
+void DroppedVariableStatsIR::runOnFunction(const Function *F, bool Before) {
+ auto &DebugVariables = DebugVariablesStack.back()[F];
+ auto FuncName = F->getName();
+ Func = F;
+ run(DebugVariables, FuncName, Before);
+}
+
+void DroppedVariableStatsIR::calculateDroppedVarStatsOnFunction(
+ const Function *F, StringRef PassID, StringRef FuncOrModName,
+ StringRef PassLevel) {
+ Func = F;
+ StringRef FuncName = F->getName();
+ DebugVariables &DbgVariables = DebugVariablesStack.back()[F];
+ calculateDroppedStatsAndPrint(DbgVariables, FuncName, PassID, FuncOrModName,
+ PassLevel, Func);
+}
+
+void DroppedVariableStatsIR::runOnModule(const Module *M, bool Before) {
+ for (auto &F : *M)
+ runOnFunction(&F, Before);
+}
+
+void DroppedVariableStatsIR::calculateDroppedVarStatsOnModule(
+ const Module *M, StringRef PassID, StringRef FuncOrModName,
+ StringRef PassLevel) {
+ for (auto &F : *M) {
+ calculateDroppedVarStatsOnFunction(&F, PassID, FuncOrModName, PassLevel);
}
+}
+
+void DroppedVariableStatsIR::registerCallbacks(
+ PassInstrumentationCallbacks &PIC) {
+ if (!DroppedVariableStatsEnabled)
+ return;
- DebugVariablesStack.pop_back();
- InlinedAts.pop_back();
- return;
+ PIC.registerBeforeNonSkippedPassCallback(
+ [this](StringRef P, Any IR) { return runBeforePass(IR); });
+ PIC.registerAfterPassCallback(
+ [this](StringRef P, Any IR, const PreservedAnalyses &PA) {
+ return runAfterPass(P, IR);
+ });
+ PIC.registerAfterPassInvalidatedCallback(
+ [this](StringRef P, const PreservedAnalyses &PA) { return cleanup(); });
}
-bool DroppedVariableStats::isScopeChildOfOrEqualTo(DIScope *Scope,
- const DIScope *DbgValScope) {
- while (Scope != nullptr) {
- if (VisitedScope.find(Scope) == VisitedScope.end()) {
- VisitedScope.insert(Scope);
- if (Scope == DbgValScope) {
- VisitedScope.clear();
- return true;
- }
- Scope = Scope->getScope();
- } else {
- VisitedScope.clear();
- return false;
- }
+void DroppedVariableStatsIR::visitEveryDebugVariable(
+ unsigned &DroppedCount, DenseSet<VarID> &DebugVariablesBeforeSet,
+ DenseSet<VarID> &DebugVariablesAfterSet,
+ DenseMap<VarID, DILocation *> &InlinedAtsMap, VarID Var) {
+ const DIScope *DbgValScope = std::get<0>(Var);
+ for (const auto &I : instructions(Func)) {
+ auto *DbgLoc = I.getDebugLoc().get();
+ if (!DbgLoc)
+ continue;
+ if (wasDropped(DbgLoc, DbgLoc->getScope(), DbgValScope, InlinedAtsMap, Var,
+ DroppedCount))
+ break;
}
- return false;
}
-bool DroppedVariableStats::isInlinedAtChildOfOrEqualTo(
- const DILocation *InlinedAt, const DILocation *DbgValInlinedAt) {
- if (DbgValInlinedAt == InlinedAt)
- return true;
- if (!DbgValInlinedAt)
- return false;
- if (!InlinedAt)
- return false;
- auto *IA = InlinedAt;
- while (IA) {
- if (IA == DbgValInlinedAt)
- return true;
- IA = IA->getInlinedAt();
+void DroppedVariableStatsIR::visitEveryDebugIntrinsic(
+ DenseSet<VarID> &VarIDSet,
+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
+ StringRef FuncName, bool Before) {
+ for (const auto &I : instructions(Func)) {
+ for (DbgRecord &DR : I.getDbgRecordRange()) {
+ if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) {
+ auto *DbgVar = Dbg->getVariable();
+ auto DbgLoc = DR.getDebugLoc();
+ populateVarIDSetAndInlinedMap(DbgVar, DbgLoc, VarIDSet, InlinedAtsMap,
+ FuncName, Before);
+ }
+ }
}
- return false;
}
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 70825bfa91da25..b766517e68eba5 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -2462,7 +2462,7 @@ StandardInstrumentations::StandardInstrumentations(
PrintChanged == ChangePrinter::ColourDiffVerbose ||
PrintChanged == ChangePrinter::ColourDiffQuiet),
WebsiteChangeReporter(PrintChanged == ChangePrinter::DotCfgVerbose),
- Verify(DebugLogging), DroppedStats(DroppedVarStats),
+ Verify(DebugLogging), DroppedStatsIR(DroppedVarStats),
VerifyEach(VerifyEach) {}
PrintCrashIRInstrumentation *PrintCrashIRInstrumentation::CrashReporter =
@@ -2538,7 +2538,7 @@ void StandardInstrumentations::registerCallbacks(
WebsiteChangeReporter.registerCallbacks(PIC);
ChangeTester.registerCallbacks(PIC);
PrintCrashIR.registerCallbacks(PIC);
- DroppedStats.registerCallbacks(PIC);
+ DroppedStatsIR.registerCallbacks(PIC);
if (MAM)
PreservedCFGChecker.registerCallbacks(PIC, *MAM);
diff --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt
index ed93ee547d2231..ffa989bec269e4 100644
--- a/llvm/unittests/IR/CMakeLists.txt
+++ b/llvm/unittests/IR/CMakeLists.txt
@@ -43,7 +43,7 @@ add_llvm_unittest(IRTests
ShuffleVectorInstTest.cpp
StructuralHashTest.cpp
TimePassesTest.cpp
- DroppedVariableStatsTest.cpp
+ DroppedVariableStatsIRTest.cpp
TypesTest.cpp
UseTest.cpp
UserTest.cpp
diff --git a/llvm/unittests/IR/DroppedVariableStatsTest.cpp b/llvm/unittests/IR/DroppedVariableStatsIRTest.cpp
similarity index 91%
rename from llvm/unittests/IR/DroppedVariableStatsTest.cpp
rename to llvm/unittests/IR/DroppedVariableStatsIRTest.cpp
index 61f3a87bb355e0..34803a9771850a 100644
--- a/llvm/unittests/IR/DroppedVariableStatsTest.cpp
+++ b/llvm/unittests/IR/DroppedVariableStatsIRTest.cpp
@@ -1,5 +1,4 @@
-//===- unittests/IR/DroppedVariableStatsTest.cpp - TimePassesHandler tests
-//----------===//
+//===- unittests/IR/DroppedVariableStatsIRTest.cpp ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -44,7 +43,7 @@ namespace {
// This test ensures that if a #dbg_value and an instruction that exists in the
// same scope as that #dbg_value are both deleted as a result of an optimization
// pass, debug information is considered not dropped.
-TEST(DroppedVariableStats, BothDeleted) {
+TEST(DroppedVariableStatsIR, BothDeleted) {
PassInstrumentationCallbacks PIC;
PassInstrumentation PI(&PIC);
@@ -79,9 +78,8 @@ TEST(DroppedVariableStats, BothDeleted) {
std::unique_ptr<llvm::Module> M = parseIR(C, IR);
ASSERT_TRUE(M);
- DroppedVariableStats Stats(true);
- Stats.runBeforePass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())));
+ DroppedVariableStatsIR Stats(true);
+ Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
// This loop simulates an IR pass that drops debug information.
for (auto &F : *M) {
@@ -92,16 +90,15 @@ TEST(DroppedVariableStats, BothDeleted) {
}
break;
}
- PreservedAnalyses PA;
Stats.runAfterPass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
+ llvm::Any(const_cast<const llvm::Module *>(M.get())));
ASSERT_EQ(Stats.getPassDroppedVariables(), false);
}
// This test ensures that if a #dbg_value is dropped after an optimization pass,
// but an instruction that shares the same scope as the #dbg_value still exists,
// debug information is conisdered dropped.
-TEST(DroppedVariableStats, DbgValLost) {
+TEST(DroppedVariableStatsIR, DbgValLost) {
PassInstrumentationCallbacks PIC;
PassInstrumentation PI(&PIC);
@@ -136,9 +133,8 @@ TEST(DroppedVariableStats, DbgValLost) {
std::unique_ptr<llvm::Module> M = parseIR(C, IR);
ASSERT_TRUE(M);
- DroppedVariableStats Stats(true);
- Stats.runBeforePass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())));
+ DroppedVariableStatsIR Stats(true);
+ Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
// This loop simulates an IR pass that drops debug information.
for (auto &F : *M) {
@@ -148,16 +144,15 @@ TEST(DroppedVariableStats, DbgValLost) {
}
break;
}
- PreservedAnalyses PA;
Stats.runAfterPass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
+ llvm::Any(const_cast<const llvm::Module *>(M.get())));
ASSERT_EQ(Stats.getPassDroppedVariables(), true);
}
// This test ensures that if a #dbg_value is dropped after an optimization pass,
// but an instruction that has an unrelated scope as the #dbg_value still
// exists, debug information is conisdered not dropped.
-TEST(DroppedVariableStats, UnrelatedScopes) {
+TEST(DroppedVariableStatsIR, UnrelatedScopes) {
PassInstrumentationCallbacks PIC;
PassInstrumentation PI(&PIC);
@@ -193,9 +188,8 @@ TEST(DroppedVariableStats, UnrelatedScopes) {
std::unique_ptr<llvm::Module> M = parseIR(C, IR);
ASSERT_TRUE(M);
- DroppedVariableStats Stats(true);
- Stats.runBeforePass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())));
+ DroppedVariableStatsIR Stats(true);
+ Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
// This loop simulates an IR pass that drops debug information.
for (auto &F : *M) {
@@ -205,16 +199,15 @@ TEST(DroppedVariableStats, UnrelatedScopes) {
}
break;
}
- PreservedAnalyses PA;
Stats.runAfterPass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
+ llvm::Any(const_cast<const llvm::Module *>(M.get())));
ASSERT_EQ(Stats.getPassDroppedVariables(), false);
}
// This test ensures that if a #dbg_value is dropped after an optimization pass,
// but an instruction that has a scope which is a child of the #dbg_value scope
// still exists, debug information is conisdered dropped.
-TEST(DroppedVariableStats, ChildScopes) {
+TEST(DroppedVariableStatsIR, ChildScopes) {
PassInstrumentationCallbacks PIC;
PassInstrumentation PI(&PIC);
@@ -250,9 +243,8 @@ TEST(DroppedVariableStats, ChildScopes) {
std::unique_ptr<llvm::Module> M = parseIR(C, IR);
ASSERT_TRUE(M);
- DroppedVariableStats Stats(true);
- Stats.runBeforePass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())));
+ DroppedVariableStatsIR Stats(true);
+ Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
// This loop simulates an IR pass that drops debug information.
for (auto &F : *M) {
@@ -262,9 +254,8 @@ TEST(DroppedVariableStats, ChildScopes) {
}
break;
}
- PreservedAnalyses PA;
Stats.runAfterPass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
+ llvm::Any(const_cast<const llvm::Module *>(M.get())));
ASSERT_EQ(Stats.getPassDroppedVariables(), true);
}
@@ -272,7 +263,7 @@ TEST(DroppedVariableStats, ChildScopes) {
// but an instruction that has a scope which is a child of the #dbg_value scope
// still exists, and the #dbg_value is inlined at another location, debug
// information is conisdered not dropped.
-TEST(DroppedVariableStats, InlinedAt) {
+TEST(DroppedVariableStatsIR, InlinedAt) {
PassInstrumentationCallbacks PIC;
PassInstrumentation PI(&PIC);
@@ -308,9 +299,8 @@ TEST(DroppedVariableStats, InlinedAt) {
std::unique_ptr<llvm::Module> M = parseIR(C, IR);
ASSERT_TRUE(M);
- DroppedVariableStats Stats(true);
- Stats.runBeforePass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())));
+ DroppedVariableStatsIR Stats(true);
+ Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
// This loop simulates an IR pass that drops debug information.
for (auto &F : *M) {
@@ -320,9 +310,8 @@ TEST(DroppedVariableStats, InlinedAt) {
}
break;
}
- PreservedAnalyses PA;
Stats.runAfterPass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
+ llvm::Any(const_cast<const llvm::Module *>(M.get())));
ASSERT_EQ(Stats.getPassDroppedVariables(), false);
}
@@ -330,7 +319,7 @@ TEST(DroppedVariableStats, InlinedAt) {
// but an instruction that has a scope which is a child of the #dbg_value scope
// still exists, and the #dbg_value and the instruction are inlined at another
// location, debug information is conisdered dropped.
-TEST(DroppedVariableStats, InlinedAtShared) {
+TEST(DroppedVariableStatsIR, InlinedAtShared) {
PassInstrumentationCallbacks PIC;
PassInstrumentation PI(&PIC);
@@ -366,9 +355,8 @@ TEST(DroppedVariableStats, InlinedAtShared) {
std::unique_ptr<llvm::Module> M = parseIR(C, IR);
ASSERT_TRUE(M);
- DroppedVariableStats Stats(true);
- Stats.runBeforePass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())));
+ DroppedVariableStatsIR Stats(true);
+ Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
// This loop simulates an IR pass that drops debug information.
for (auto &F : *M) {
@@ -378,9 +366,8 @@ TEST(DroppedVariableStats, InlinedAtShared) {
}
break;
}
- PreservedAnalyses PA;
Stats.runAfterPass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
+ llvm::Any(const_cast<const llvm::Module *>(M.get())));
ASSERT_EQ(Stats.getPassDroppedVariables(), true);
}
@@ -388,7 +375,7 @@ TEST(DroppedVariableStats, InlinedAtShared) {
// but an instruction that has a scope which is a child of the #dbg_value scope
// still exists, and the instruction is inlined at a location that is the
// #dbg_value's inlined at location, debug information is conisdered dropped.
-TEST(DroppedVariableStats, InlinedAtChild) {
+TEST(DroppedVariableStatsIR, InlinedAtChild) {
PassInstrumentationCallbacks PIC;
PassInstrumentation PI(&PIC);
@@ -425,9 +412,8 @@ TEST(DroppedVariableStats, InlinedAtChild) {
std::unique_ptr<llvm::Module> M = parseIR(C, IR);
ASSERT_TRUE(M);
- DroppedVariableStats Stats(true);
- Stats.runBeforePass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())));
+ DroppedVariableStatsIR Stats(true);
+ Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
// This loop simulates an IR pass that drops debug information.
for (auto &F : *M) {
@@ -437,9 +423,8 @@ TEST(DroppedVariableStats, InlinedAtChild) {
}
break;
}
- PreservedAnalyses PA;
Stats.runAfterPass("Test",
- llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
+ llvm::Any(const_cast<const llvm::Module *>(M.get())));
ASSERT_EQ(Stats.getPassDroppedVariables(), true);
}
More information about the llvm-commits
mailing list