| ///===- 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; | |
| void DroppedVariableStatsIR::runBeforePass(StringRef P, IRUnitRef IR) { | |
| setup(); | |
| if (const auto *M = dyn_cast<Module>(IR)) | |
| return this->runOnModule(P, M, true); | |
| if (const auto *F = dyn_cast<Function>(IR)) | |
| return this->runOnFunction(P, F, true); | |
| } | |
| void DroppedVariableStatsIR::runAfterPass(StringRef P, IRUnitRef IR) { | |
| if (const auto *M = dyn_cast<Module>(IR)) | |
| runAfterPassModule(P, M); | |
| else if (const auto *F = dyn_cast<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, IRUnitRef IR) { return runBeforePass(P, IR); }); | |
| PIC.registerAfterPassCallback( | |
| [this](StringRef P, IRUnitRef 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); | |
| } | |
| } | |
| } | |
| } |