1 //===- RemoveRedundantDebugValues.cpp - Remove Redundant Debug Value MIs --===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/CodeGen/RemoveRedundantDebugValues.h" 10 #include "llvm/ADT/DenseMap.h" 11 #include "llvm/ADT/DenseSet.h" 12 #include "llvm/ADT/SmallVector.h" 13 #include "llvm/ADT/Statistic.h" 14 #include "llvm/CodeGen/MachineBasicBlock.h" 15 #include "llvm/CodeGen/MachineFunctionPass.h" 16 #include "llvm/CodeGen/TargetSubtargetInfo.h" 17 #include "llvm/IR/DebugInfoMetadata.h" 18 #include "llvm/IR/Function.h" 19 #include "llvm/InitializePasses.h" 20 #include "llvm/Pass.h" 21 #include "llvm/PassRegistry.h" 22 23 /// \file RemoveRedundantDebugValues.cpp 24 /// 25 /// The RemoveRedundantDebugValues pass removes redundant DBG_VALUEs that 26 /// appear in MIR after the register allocator. 27 28 #define DEBUG_TYPE "removeredundantdebugvalues" 29 30 using namespace llvm; 31 32 STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)"); 33 STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)"); 34 35 namespace { 36 37 struct RemoveRedundantDebugValuesImpl { 38 bool reduceDbgValues(MachineFunction &MF); 39 }; 40 41 class RemoveRedundantDebugValuesLegacy : public MachineFunctionPass { 42 public: 43 static char ID; 44 45 RemoveRedundantDebugValuesLegacy(); 46 /// Remove redundant debug value MIs for the given machine function. 47 bool runOnMachineFunction(MachineFunction &MF) override; 48 49 void getAnalysisUsage(AnalysisUsage &AU) const override { 50 AU.setPreservesCFG(); 51 MachineFunctionPass::getAnalysisUsage(AU); 52 } 53 }; 54 55 } // namespace 56 57 //===----------------------------------------------------------------------===// 58 // Implementation 59 //===----------------------------------------------------------------------===// 60 61 char RemoveRedundantDebugValuesLegacy::ID = 0; 62 63 char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValuesLegacy::ID; 64 65 INITIALIZE_PASS(RemoveRedundantDebugValuesLegacy, DEBUG_TYPE, 66 "Remove Redundant DEBUG_VALUE analysis", false, false) 67 68 /// Default construct and initialize the pass. 69 RemoveRedundantDebugValuesLegacy::RemoveRedundantDebugValuesLegacy() 70 : MachineFunctionPass(ID) { 71 initializeRemoveRedundantDebugValuesLegacyPass( 72 *PassRegistry::getPassRegistry()); 73 } 74 75 // This analysis aims to remove redundant DBG_VALUEs by going forward 76 // in the basic block by considering the first DBG_VALUE as a valid 77 // until its first (location) operand is not clobbered/modified. 78 // For example: 79 // (1) DBG_VALUE $edi, !"var1", ... 80 // (2) <block of code that does affect $edi> 81 // (3) DBG_VALUE $edi, !"var1", ... 82 // ... 83 // in this case, we can remove (3). 84 // TODO: Support DBG_VALUE_LIST and other debug instructions. 85 static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB) { 86 LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n"); 87 88 SmallVector<MachineInstr *, 8> DbgValsToBeRemoved; 89 DenseMap<DebugVariable, std::pair<MachineOperand *, const DIExpression *>> 90 VariableMap; 91 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo(); 92 93 for (auto &MI : MBB) { 94 if (MI.isDebugValue()) { 95 DebugVariable Var(MI.getDebugVariable(), std::nullopt, 96 MI.getDebugLoc()->getInlinedAt()); 97 auto VMI = VariableMap.find(Var); 98 // Just stop tracking this variable, until we cover DBG_VALUE_LIST. 99 // 1 DBG_VALUE $rax, "x", DIExpression() 100 // ... 101 // 2 DBG_VALUE_LIST "x", DIExpression(...), $rax, $rbx 102 // ... 103 // 3 DBG_VALUE $rax, "x", DIExpression() 104 if (MI.isDebugValueList() && VMI != VariableMap.end()) { 105 VariableMap.erase(VMI); 106 continue; 107 } 108 109 MachineOperand &Loc = MI.getDebugOperand(0); 110 if (!Loc.isReg()) { 111 // If it's not a register, just stop tracking such variable. 112 if (VMI != VariableMap.end()) 113 VariableMap.erase(VMI); 114 continue; 115 } 116 117 // We have found a new value for a variable. 118 if (VMI == VariableMap.end() || 119 VMI->second.first->getReg() != Loc.getReg() || 120 VMI->second.second != MI.getDebugExpression()) { 121 VariableMap[Var] = {&Loc, MI.getDebugExpression()}; 122 continue; 123 } 124 125 // Found an identical DBG_VALUE, so it can be considered 126 // for later removal. 127 DbgValsToBeRemoved.push_back(&MI); 128 } 129 130 if (MI.isMetaInstruction()) 131 continue; 132 133 // Stop tracking any location that is clobbered by this instruction. 134 for (auto &Var : VariableMap) { 135 auto &LocOp = Var.second.first; 136 if (MI.modifiesRegister(LocOp->getReg(), TRI)) 137 VariableMap.erase(Var.first); 138 } 139 } 140 141 for (auto &Instr : DbgValsToBeRemoved) { 142 LLVM_DEBUG(dbgs() << "removing "; Instr->dump()); 143 Instr->eraseFromParent(); 144 ++NumRemovedForward; 145 } 146 147 return !DbgValsToBeRemoved.empty(); 148 } 149 150 // This analysis aims to remove redundant DBG_VALUEs by going backward 151 // in the basic block and removing all but the last DBG_VALUE for any 152 // given variable in a set of consecutive DBG_VALUE instructions. 153 // For example: 154 // (1) DBG_VALUE $edi, !"var1", ... 155 // (2) DBG_VALUE $esi, !"var2", ... 156 // (3) DBG_VALUE $edi, !"var1", ... 157 // ... 158 // in this case, we can remove (1). 159 static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB) { 160 LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n"); 161 SmallVector<MachineInstr *, 8> DbgValsToBeRemoved; 162 SmallDenseSet<DebugVariable> VariableSet; 163 164 for (MachineInstr &MI : llvm::reverse(MBB)) { 165 if (MI.isDebugValue()) { 166 DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), 167 MI.getDebugLoc()->getInlinedAt()); 168 auto R = VariableSet.insert(Var); 169 // If it is a DBG_VALUE describing a constant as: 170 // DBG_VALUE 0, ... 171 // we just don't consider such instructions as candidates 172 // for redundant removal. 173 if (MI.isNonListDebugValue()) { 174 MachineOperand &Loc = MI.getDebugOperand(0); 175 if (!Loc.isReg()) { 176 // If we have already encountered this variable, just stop 177 // tracking it. 178 if (!R.second) 179 VariableSet.erase(Var); 180 continue; 181 } 182 } 183 184 // We have already encountered the value for this variable, 185 // so this one can be deleted. 186 if (!R.second) 187 DbgValsToBeRemoved.push_back(&MI); 188 continue; 189 } 190 191 // If we encountered a non-DBG_VALUE, try to find the next 192 // sequence with consecutive DBG_VALUE instructions. 193 VariableSet.clear(); 194 } 195 196 for (auto &Instr : DbgValsToBeRemoved) { 197 LLVM_DEBUG(dbgs() << "removing "; Instr->dump()); 198 Instr->eraseFromParent(); 199 ++NumRemovedBackward; 200 } 201 202 return !DbgValsToBeRemoved.empty(); 203 } 204 205 bool RemoveRedundantDebugValuesImpl::reduceDbgValues(MachineFunction &MF) { 206 LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n"); 207 208 bool Changed = false; 209 210 for (auto &MBB : MF) { 211 Changed |= reduceDbgValsBackwardScan(MBB); 212 Changed |= reduceDbgValsForwardScan(MBB); 213 } 214 215 return Changed; 216 } 217 218 bool RemoveRedundantDebugValuesLegacy::runOnMachineFunction( 219 MachineFunction &MF) { 220 // Skip functions without debugging information or functions from NoDebug 221 // compilation units. 222 if (!MF.getFunction().getSubprogram() || 223 (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() == 224 DICompileUnit::NoDebug)) 225 return false; 226 227 return RemoveRedundantDebugValuesImpl().reduceDbgValues(MF); 228 } 229 230 PreservedAnalyses 231 RemoveRedundantDebugValuesPass::run(MachineFunction &MF, 232 MachineFunctionAnalysisManager &MFAM) { 233 // Skip functions without debugging information or functions from NoDebug 234 // compilation units. 235 if (!MF.getFunction().getSubprogram() || 236 (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() == 237 DICompileUnit::NoDebug)) 238 return PreservedAnalyses::all(); 239 240 if (!RemoveRedundantDebugValuesImpl().reduceDbgValues(MF)) 241 return PreservedAnalyses::all(); 242 243 auto PA = getMachineFunctionPassPreservedAnalyses(); 244 PA.preserveSet<CFGAnalyses>(); 245 return PA; 246 } 247