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