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