1 ///===- DroppedVariableStatsIR.cpp ----------------------------------------===// 2 /// 3 /// Part of the LLVM Project, under the Apache License v2.0 with LLVM 4 /// Exceptions. See https://llvm.org/LICENSE.txt for license information. 5 /// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 /// 7 ///===---------------------------------------------------------------------===// 8 /// \file 9 /// Dropped Variable Statistics for Debug Information. Reports any number 10 /// of #dbg_value that get dropped due to an optimization pass. 11 /// 12 ///===---------------------------------------------------------------------===// 13 14 #include "llvm/IR/DroppedVariableStatsIR.h" 15 #include "llvm/IR/DebugInfoMetadata.h" 16 #include "llvm/IR/InstIterator.h" 17 #include "llvm/IR/Module.h" 18 #include "llvm/IR/PassInstrumentation.h" 19 20 using namespace llvm; 21 22 template <typename IRUnitT> 23 const IRUnitT *DroppedVariableStatsIR::unwrapIR(Any IR) { 24 const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR); 25 return IRPtr ? *IRPtr : nullptr; 26 } 27 28 void DroppedVariableStatsIR::runBeforePass(StringRef P, Any IR) { 29 setup(); 30 if (const auto *M = unwrapIR<Module>(IR)) 31 return this->runOnModule(P, M, true); 32 if (const auto *F = unwrapIR<Function>(IR)) 33 return this->runOnFunction(P, F, true); 34 } 35 36 void DroppedVariableStatsIR::runAfterPass(StringRef P, Any IR) { 37 if (const auto *M = unwrapIR<Module>(IR)) 38 runAfterPassModule(P, M); 39 else if (const auto *F = unwrapIR<Function>(IR)) 40 runAfterPassFunction(P, F); 41 cleanup(); 42 } 43 44 void DroppedVariableStatsIR::runAfterPassFunction(StringRef PassID, 45 const Function *F) { 46 runOnFunction(PassID, F, false); 47 calculateDroppedVarStatsOnFunction(F, PassID, F->getName().str(), "Function"); 48 } 49 50 void DroppedVariableStatsIR::runAfterPassModule(StringRef PassID, 51 const Module *M) { 52 runOnModule(PassID, M, false); 53 calculateDroppedVarStatsOnModule(M, PassID, M->getName().str(), "Module"); 54 } 55 56 void DroppedVariableStatsIR::runOnFunction(StringRef PassID, const Function *F, 57 bool Before) { 58 auto &DebugVariables = DebugVariablesStack.back()[F]; 59 auto FuncName = F->getName(); 60 Func = F; 61 run(DebugVariables, FuncName, Before); 62 } 63 64 void DroppedVariableStatsIR::calculateDroppedVarStatsOnFunction( 65 const Function *F, StringRef PassID, StringRef FuncOrModName, 66 StringRef PassLevel) { 67 Func = F; 68 StringRef FuncName = F->getName(); 69 DebugVariables &DbgVariables = DebugVariablesStack.back()[F]; 70 calculateDroppedStatsAndPrint(DbgVariables, FuncName, PassID, FuncOrModName, 71 PassLevel, Func); 72 } 73 74 void DroppedVariableStatsIR::runOnModule(StringRef PassID, const Module *M, 75 bool Before) { 76 for (auto &F : *M) { 77 runOnFunction(PassID, &F, Before); 78 } 79 } 80 81 void DroppedVariableStatsIR::calculateDroppedVarStatsOnModule( 82 const Module *M, StringRef PassID, StringRef FuncOrModName, 83 StringRef PassLevel) { 84 for (auto &F : *M) { 85 calculateDroppedVarStatsOnFunction(&F, PassID, FuncOrModName, PassLevel); 86 } 87 } 88 89 void DroppedVariableStatsIR::registerCallbacks( 90 PassInstrumentationCallbacks &PIC) { 91 if (!DroppedVariableStatsEnabled) 92 return; 93 94 PIC.registerBeforeNonSkippedPassCallback( 95 [this](StringRef P, Any IR) { return runBeforePass(P, IR); }); 96 PIC.registerAfterPassCallback( 97 [this](StringRef P, Any IR, const PreservedAnalyses &PA) { 98 return runAfterPass(P, IR); 99 }); 100 PIC.registerAfterPassInvalidatedCallback( 101 [this](StringRef P, const PreservedAnalyses &PA) { return cleanup(); }); 102 } 103 104 void DroppedVariableStatsIR::visitEveryInstruction( 105 unsigned &DroppedCount, DenseMap<VarID, DILocation *> &InlinedAtsMap, 106 VarID Var) { 107 const DIScope *DbgValScope = std::get<0>(Var); 108 for (const auto &I : instructions(Func)) { 109 auto *DbgLoc = I.getDebugLoc().get(); 110 if (!DbgLoc) 111 continue; 112 if (updateDroppedCount(DbgLoc, DbgLoc->getScope(), DbgValScope, 113 InlinedAtsMap, Var, DroppedCount)) 114 break; 115 } 116 } 117 118 void DroppedVariableStatsIR::visitEveryDebugRecord( 119 DenseSet<VarID> &VarIDSet, 120 DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap, 121 StringRef FuncName, bool Before) { 122 for (const auto &I : instructions(Func)) { 123 for (DbgRecord &DR : I.getDbgRecordRange()) { 124 if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) { 125 auto *DbgVar = Dbg->getVariable(); 126 auto DbgLoc = DR.getDebugLoc(); 127 populateVarIDSetAndInlinedMap(DbgVar, DbgLoc, VarIDSet, InlinedAtsMap, 128 FuncName, Before); 129 } 130 } 131 } 132 } 133