diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-08-22 19:00:43 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-13 20:39:49 +0000 |
commit | fe6060f10f634930ff71b7c50291ddc610da2475 (patch) | |
tree | 1483580c790bd4d27b6500a7542b5ee00534d3cc /contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp | |
parent | b61bce17f346d79cecfd8f195a64b10f77be43b1 (diff) | |
parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp b/contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp new file mode 100644 index 000000000000..de6129a912d3 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp @@ -0,0 +1,231 @@ +//===- RemoveRedundantDebugValues.cpp - Remove Redundant Debug Value MIs --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Function.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" + +/// \file RemoveRedundantDebugValues.cpp +/// +/// The RemoveRedundantDebugValues pass removes redundant DBG_VALUEs that +/// appear in MIR after the register allocator. + +#define DEBUG_TYPE "removeredundantdebugvalues" + +using namespace llvm; + +STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)"); +STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)"); + +namespace { + +class RemoveRedundantDebugValues : public MachineFunctionPass { +public: + static char ID; + + RemoveRedundantDebugValues(); + + bool reduceDbgValues(MachineFunction &MF); + + /// Remove redundant debug value MIs for the given machine function. + bool runOnMachineFunction(MachineFunction &MF) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } +}; + +} // namespace + +//===----------------------------------------------------------------------===// +// Implementation +//===----------------------------------------------------------------------===// + +char RemoveRedundantDebugValues::ID = 0; + +char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValues::ID; + +INITIALIZE_PASS(RemoveRedundantDebugValues, DEBUG_TYPE, + "Remove Redundant DEBUG_VALUE analysis", false, false) + +/// Default construct and initialize the pass. +RemoveRedundantDebugValues::RemoveRedundantDebugValues() + : MachineFunctionPass(ID) { + initializeRemoveRedundantDebugValuesPass(*PassRegistry::getPassRegistry()); +} + +// This analysis aims to remove redundant DBG_VALUEs by going forward +// in the basic block by considering the first DBG_VALUE as a valid +// until its first (location) operand is not clobbered/modified. +// For example: +// (1) DBG_VALUE $edi, !"var1", ... +// (2) <block of code that does affect $edi> +// (3) DBG_VALUE $edi, !"var1", ... +// ... +// in this case, we can remove (3). +// TODO: Support DBG_VALUE_LIST and other debug instructions. +static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB) { + LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n"); + + SmallVector<MachineInstr *, 8> DbgValsToBeRemoved; + DenseMap<DebugVariable, std::pair<MachineOperand *, const DIExpression *>> + VariableMap; + const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo(); + + for (auto &MI : MBB) { + if (MI.isDebugValue()) { + DebugVariable Var(MI.getDebugVariable(), NoneType(), + MI.getDebugLoc()->getInlinedAt()); + auto VMI = VariableMap.find(Var); + // Just stop tracking this variable, until we cover DBG_VALUE_LIST. + // 1 DBG_VALUE $rax, "x", DIExpression() + // ... + // 2 DBG_VALUE_LIST "x", DIExpression(...), $rax, $rbx + // ... + // 3 DBG_VALUE $rax, "x", DIExpression() + if (MI.isDebugValueList() && VMI != VariableMap.end()) { + VariableMap.erase(VMI); + continue; + } + + MachineOperand &Loc = MI.getDebugOperand(0); + if (!Loc.isReg()) { + // If it it's not a register, just stop tracking such variable. + if (VMI != VariableMap.end()) + VariableMap.erase(VMI); + continue; + } + + // We have found a new value for a variable. + if (VMI == VariableMap.end() || + VMI->second.first->getReg() != Loc.getReg() || + VMI->second.second != MI.getDebugExpression()) { + VariableMap[Var] = {&Loc, MI.getDebugExpression()}; + continue; + } + + // Found an identical DBG_VALUE, so it can be considered + // for later removal. + DbgValsToBeRemoved.push_back(&MI); + } + + if (MI.isMetaInstruction()) + continue; + + // Stop tracking any location that is clobbered by this instruction. + for (auto &Var : VariableMap) { + auto &LocOp = Var.second.first; + if (MI.modifiesRegister(LocOp->getReg(), TRI)) + VariableMap.erase(Var.first); + } + } + + for (auto &Instr : DbgValsToBeRemoved) { + LLVM_DEBUG(dbgs() << "removing "; Instr->dump()); + Instr->eraseFromParent(); + ++NumRemovedForward; + } + + return !DbgValsToBeRemoved.empty(); +} + +// This analysis aims to remove redundant DBG_VALUEs by going backward +// in the basic block and removing all but the last DBG_VALUE for any +// given variable in a set of consecutive DBG_VALUE instructions. +// For example: +// (1) DBG_VALUE $edi, !"var1", ... +// (2) DBG_VALUE $esi, !"var2", ... +// (3) DBG_VALUE $edi, !"var1", ... +// ... +// in this case, we can remove (1). +static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB) { + LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n"); + SmallVector<MachineInstr *, 8> DbgValsToBeRemoved; + SmallDenseSet<DebugVariable> VariableSet; + + for (MachineBasicBlock::reverse_iterator I = MBB.rbegin(), E = MBB.rend(); + I != E; ++I) { + MachineInstr *MI = &*I; + + if (MI->isDebugValue()) { + DebugVariable Var(MI->getDebugVariable(), MI->getDebugExpression(), + MI->getDebugLoc()->getInlinedAt()); + auto R = VariableSet.insert(Var); + // If it is a DBG_VALUE describing a constant as: + // DBG_VALUE 0, ... + // we just don't consider such instructions as candidates + // for redundant removal. + if (MI->isNonListDebugValue()) { + MachineOperand &Loc = MI->getDebugOperand(0); + if (!Loc.isReg()) { + // If we have already encountered this variable, just stop + // tracking it. + if (!R.second) + VariableSet.erase(Var); + continue; + } + } + + // We have already encountered the value for this variable, + // so this one can be deleted. + if (!R.second) + DbgValsToBeRemoved.push_back(MI); + continue; + } + + // If we encountered a non-DBG_VALUE, try to find the next + // sequence with consecutive DBG_VALUE instructions. + VariableSet.clear(); + } + + for (auto &Instr : DbgValsToBeRemoved) { + LLVM_DEBUG(dbgs() << "removing "; Instr->dump()); + Instr->eraseFromParent(); + ++NumRemovedBackward; + } + + return !DbgValsToBeRemoved.empty(); +} + +bool RemoveRedundantDebugValues::reduceDbgValues(MachineFunction &MF) { + LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n"); + + bool Changed = false; + + for (auto &MBB : MF) { + Changed |= reduceDbgValsBackwardScan(MBB); + Changed |= reduceDbgValsForwardScan(MBB); + } + + return Changed; +} + +bool RemoveRedundantDebugValues::runOnMachineFunction(MachineFunction &MF) { + // Skip functions without debugging information. + if (!MF.getFunction().getSubprogram()) + return false; + + // Skip functions from NoDebug compilation units. + if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() == + DICompileUnit::NoDebug) + return false; + + bool Changed = reduceDbgValues(MF); + return Changed; +} |