mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 11:56:08 +00:00

This patch attempts to reland https://github.com/llvm/llvm-project/pull/120780 while addressing the issues that caused the patch to be reverted. Namely: 1. The patch had included code from the llvm/Passes directory in the llvm/CodeGen directory. 2. The patch increased the backend compile time by 2% due to adding a very expensive include in MachineFunctionPass.h The patch has been re-structured so that there is no dependency between the llvm/Passes and llvm/CodeGen directory, by moving the base class, `class DroppedVariableStats` to the llvm/IR directory. The expensive include in MachineFunctionPass.h has been changed to contain forward declarations instead of other header includes which was pulling a ton of code into MachineFunctionPass.h and should resolve any issues when it comes to compile time increase.
133 lines
4.6 KiB
C++
133 lines
4.6 KiB
C++
///===- DroppedVariableStatsIR.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/IR/DroppedVariableStatsIR.h"
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
|
#include "llvm/IR/InstIterator.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/PassInstrumentation.h"
|
|
|
|
using namespace llvm;
|
|
|
|
template <typename IRUnitT>
|
|
const IRUnitT *DroppedVariableStatsIR::unwrapIR(Any IR) {
|
|
const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
|
|
return IRPtr ? *IRPtr : nullptr;
|
|
}
|
|
|
|
void DroppedVariableStatsIR::runBeforePass(StringRef P, Any IR) {
|
|
setup();
|
|
if (const auto *M = unwrapIR<Module>(IR))
|
|
return this->runOnModule(P, M, true);
|
|
if (const auto *F = unwrapIR<Function>(IR))
|
|
return this->runOnFunction(P, F, true);
|
|
}
|
|
|
|
void DroppedVariableStatsIR::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 DroppedVariableStatsIR::runAfterPassFunction(StringRef PassID,
|
|
const Function *F) {
|
|
runOnFunction(PassID, F, false);
|
|
calculateDroppedVarStatsOnFunction(F, PassID, F->getName().str(), "Function");
|
|
}
|
|
|
|
void DroppedVariableStatsIR::runAfterPassModule(StringRef PassID,
|
|
const Module *M) {
|
|
runOnModule(PassID, M, false);
|
|
calculateDroppedVarStatsOnModule(M, PassID, M->getName().str(), "Module");
|
|
}
|
|
|
|
void DroppedVariableStatsIR::runOnFunction(StringRef PassID, 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(StringRef PassID, const Module *M,
|
|
bool Before) {
|
|
for (auto &F : *M) {
|
|
runOnFunction(PassID, &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;
|
|
|
|
PIC.registerBeforeNonSkippedPassCallback(
|
|
[this](StringRef P, Any IR) { return runBeforePass(P, 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(); });
|
|
}
|
|
|
|
void DroppedVariableStatsIR::visitEveryInstruction(
|
|
unsigned &DroppedCount, 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 (updateDroppedCount(DbgLoc, DbgLoc->getScope(), DbgValScope,
|
|
InlinedAtsMap, Var, DroppedCount))
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DroppedVariableStatsIR::visitEveryDebugRecord(
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|