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