brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · e9ea501 Raw
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