247 lines · cpp
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-exception6//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.cpp24///25/// The RemoveRedundantDebugValues pass removes redundant DBG_VALUEs that26/// appear in MIR after the register allocator.27 28#define DEBUG_TYPE "removeredundantdebugvalues"29 30using namespace llvm;31 32STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)");33STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)");34 35namespace {36 37struct RemoveRedundantDebugValuesImpl {38 bool reduceDbgValues(MachineFunction &MF);39};40 41class RemoveRedundantDebugValuesLegacy : public MachineFunctionPass {42public: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} // namespace56 57//===----------------------------------------------------------------------===//58// Implementation59//===----------------------------------------------------------------------===//60 61char RemoveRedundantDebugValuesLegacy::ID = 0;62 63char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValuesLegacy::ID;64 65INITIALIZE_PASS(RemoveRedundantDebugValuesLegacy, DEBUG_TYPE,66 "Remove Redundant DEBUG_VALUE analysis", false, false)67 68/// Default construct and initialize the pass.69RemoveRedundantDebugValuesLegacy::RemoveRedundantDebugValuesLegacy()70 : MachineFunctionPass(ID) {71 initializeRemoveRedundantDebugValuesLegacyPass(72 *PassRegistry::getPassRegistry());73}74 75// This analysis aims to remove redundant DBG_VALUEs by going forward76// in the basic block by considering the first DBG_VALUE as a valid77// 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.85static 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, $rbx102 // ...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 considered126 // 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 backward151// in the basic block and removing all but the last DBG_VALUE for any152// 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).159static 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 candidates172 // 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 stop177 // 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 next192 // 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 205bool 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 218bool RemoveRedundantDebugValuesLegacy::runOnMachineFunction(219 MachineFunction &MF) {220 // Skip functions without debugging information or functions from NoDebug221 // 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 230PreservedAnalyses231RemoveRedundantDebugValuesPass::run(MachineFunction &MF,232 MachineFunctionAnalysisManager &MFAM) {233 // Skip functions without debugging information or functions from NoDebug234 // 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