1 ///===- DroppedVariableStats.h - Opt Diagnostics -*- C++ -*----------------===// 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 #ifndef LLVM_CODEGEN_DROPPEDVARIABLESTATS_H 15 #define LLVM_CODEGEN_DROPPEDVARIABLESTATS_H 16 17 #include "llvm/ADT/DenseSet.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/Support/Compiler.h" 20 #include <tuple> 21 22 namespace llvm { 23 24 class DIScope; 25 class DILocalVariable; 26 class Function; 27 class DILocation; 28 class DebugLoc; 29 class StringRef; 30 31 /// A unique key that represents a debug variable. 32 /// First const DIScope *: Represents the scope of the debug variable. 33 /// Second const DIScope *: Represents the InlinedAt scope of the debug 34 /// variable. const DILocalVariable *: It is a pointer to the debug variable 35 /// itself. 36 using VarID = 37 std::tuple<const DIScope *, const DIScope *, const DILocalVariable *>; 38 39 /// A base class to collect and print dropped debug information variable 40 /// statistics. 41 class DroppedVariableStats { 42 public: 43 LLVM_ABI DroppedVariableStats(bool DroppedVarStatsEnabled); 44 ~DroppedVariableStats()45 virtual ~DroppedVariableStats() {} 46 47 // We intend this to be unique per-compilation, thus no copies. 48 DroppedVariableStats(const DroppedVariableStats &) = delete; 49 void operator=(const DroppedVariableStats &) = delete; 50 getPassDroppedVariables()51 bool getPassDroppedVariables() { return PassDroppedVariables; } 52 53 protected: 54 LLVM_ABI void setup(); 55 56 LLVM_ABI void cleanup(); 57 58 bool DroppedVariableStatsEnabled = false; 59 struct DebugVariables { 60 /// DenseSet of VarIDs before an optimization pass has run. 61 DenseSet<VarID> DebugVariablesBefore; 62 /// DenseSet of VarIDs after an optimization pass has run. 63 DenseSet<VarID> DebugVariablesAfter; 64 }; 65 66 /// A stack of a DenseMap, that maps DebugVariables for every pass to an 67 /// llvm::Function. A stack is used because an optimization pass can call 68 /// other passes. 69 SmallVector<DenseMap<const Function *, DebugVariables>> DebugVariablesStack; 70 71 /// A DenseSet tracking whether a scope was visited before. 72 DenseSet<const DIScope *> VisitedScope; 73 /// A stack of DenseMaps, which map the name of an llvm::Function to a 74 /// DenseMap of VarIDs and their inlinedAt locations before an optimization 75 /// pass has run. 76 SmallVector<DenseMap<StringRef, DenseMap<VarID, DILocation *>>> InlinedAts; 77 /// Calculate the number of dropped variables in an llvm::Function or 78 /// llvm::MachineFunction and print the relevant information to stdout. 79 LLVM_ABI void calculateDroppedStatsAndPrint( 80 DebugVariables &DbgVariables, StringRef FuncName, StringRef PassID, 81 StringRef FuncOrModName, StringRef PassLevel, const Function *Func); 82 83 /// Check if a \p Var has been dropped or is a false positive. Also update the 84 /// \p DroppedCount if a debug variable is dropped. 85 LLVM_ABI bool updateDroppedCount(DILocation *DbgLoc, const DIScope *Scope, 86 const DIScope *DbgValScope, 87 DenseMap<VarID, DILocation *> &InlinedAtsMap, 88 VarID Var, unsigned &DroppedCount); 89 90 /// Run code to populate relevant data structures over an llvm::Function or 91 /// llvm::MachineFunction. 92 LLVM_ABI void run(DebugVariables &DbgVariables, StringRef FuncName, 93 bool Before); 94 95 /// Populate the VarIDSet and InlinedAtMap with the relevant information 96 /// needed for before and after pass analysis to determine dropped variable 97 /// status. 98 LLVM_ABI void populateVarIDSetAndInlinedMap( 99 const DILocalVariable *DbgVar, DebugLoc DbgLoc, DenseSet<VarID> &VarIDSet, 100 DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap, 101 StringRef FuncName, bool Before); 102 103 /// Visit every llvm::Instruction or llvm::MachineInstruction and check if the 104 /// debug variable denoted by its ID \p Var may have been dropped by an 105 /// optimization pass. 106 virtual void 107 visitEveryInstruction(unsigned &DroppedCount, 108 DenseMap<VarID, DILocation *> &InlinedAtsMap, 109 VarID Var) = 0; 110 /// Visit every debug record in an llvm::Function or llvm::MachineFunction 111 /// and call populateVarIDSetAndInlinedMap on it. 112 virtual void visitEveryDebugRecord( 113 DenseSet<VarID> &VarIDSet, 114 DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap, 115 StringRef FuncName, bool Before) = 0; 116 117 private: 118 /// Remove a dropped debug variable's VarID from all Sets in the 119 /// DroppedVariablesBefore stack. 120 void removeVarFromAllSets(VarID Var, const Function *F); 121 122 /// Return true if \p Scope is the same as \p DbgValScope or a child scope of 123 /// \p DbgValScope, return false otherwise. 124 bool isScopeChildOfOrEqualTo(const DIScope *Scope, 125 const DIScope *DbgValScope); 126 127 /// Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of 128 /// the InlinedAt chain, return false otherwise. 129 bool isInlinedAtChildOfOrEqualTo(const DILocation *InlinedAt, 130 const DILocation *DbgValInlinedAt); 131 132 bool PassDroppedVariables = false; 133 }; 134 135 } // namespace llvm 136 137 #endif 138