[RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
This new MIR pass removes redundant DBG_VALUEs.
After the register allocator is done, more precisely, after
the Virtual Register Rewriter, we end up having duplicated
DBG_VALUEs, since some virtual registers are being rewritten
into the same physical register as some of existing DBG_VALUEs.
Each DBG_VALUE should indicate (at least before the LiveDebugValues)
variables assignment, but it is being clobbered for function
parameters during the SelectionDAG since it generates new DBG_VALUEs
after COPY instructions, even though the parameter has no assignment.
For example, if we had a DBG_VALUE $regX as an entry debug value
representing the parameter, and a COPY and after the COPY,
DBG_VALUE $virt_reg, and after the virtregrewrite the $virt_reg gets
rewritten into $regX, we'd end up having redundant DBG_VALUE.
This breaks the definition of the DBG_VALUE since some analysis passes
might be built on top of that premise..., and this patch tries to fix
the MIR with the respect to that.
This first patch performs bacward scan, by trying to detect a sequence of
consecutive DBG_VALUEs, and to remove all DBG_VALUEs describing one
variable but the last one:
For example:
(1) DBG_VALUE $edi, !"var1", ...
(2) DBG_VALUE $esi, !"var2", ...
(3) DBG_VALUE $edi, !"var1", ...
...
in this case, we can remove (1).
By combining the forward scan that will be introduced in the next patch
(from this stack), by inspecting the statistics, the RemoveRedundantDebugValues
removes 15032 instructions by using gdb-7.11 as a testbed.
Differential Revision: https://reviews.llvm.org/D105279
2021-06-28 14:15:31 +02:00
|
|
|
//===- 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2021-07-15 08:45:19 +02:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
[RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
This new MIR pass removes redundant DBG_VALUEs.
After the register allocator is done, more precisely, after
the Virtual Register Rewriter, we end up having duplicated
DBG_VALUEs, since some virtual registers are being rewritten
into the same physical register as some of existing DBG_VALUEs.
Each DBG_VALUE should indicate (at least before the LiveDebugValues)
variables assignment, but it is being clobbered for function
parameters during the SelectionDAG since it generates new DBG_VALUEs
after COPY instructions, even though the parameter has no assignment.
For example, if we had a DBG_VALUE $regX as an entry debug value
representing the parameter, and a COPY and after the COPY,
DBG_VALUE $virt_reg, and after the virtregrewrite the $virt_reg gets
rewritten into $regX, we'd end up having redundant DBG_VALUE.
This breaks the definition of the DBG_VALUE since some analysis passes
might be built on top of that premise..., and this patch tries to fix
the MIR with the respect to that.
This first patch performs bacward scan, by trying to detect a sequence of
consecutive DBG_VALUEs, and to remove all DBG_VALUEs describing one
variable but the last one:
For example:
(1) DBG_VALUE $edi, !"var1", ...
(2) DBG_VALUE $esi, !"var2", ...
(3) DBG_VALUE $edi, !"var1", ...
...
in this case, we can remove (1).
By combining the forward scan that will be introduced in the next patch
(from this stack), by inspecting the statistics, the RemoveRedundantDebugValues
removes 15032 instructions by using gdb-7.11 as a testbed.
Differential Revision: https://reviews.llvm.org/D105279
2021-06-28 14:15:31 +02:00
|
|
|
#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"
|
2021-07-15 08:45:19 +02:00
|
|
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
[RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
This new MIR pass removes redundant DBG_VALUEs.
After the register allocator is done, more precisely, after
the Virtual Register Rewriter, we end up having duplicated
DBG_VALUEs, since some virtual registers are being rewritten
into the same physical register as some of existing DBG_VALUEs.
Each DBG_VALUE should indicate (at least before the LiveDebugValues)
variables assignment, but it is being clobbered for function
parameters during the SelectionDAG since it generates new DBG_VALUEs
after COPY instructions, even though the parameter has no assignment.
For example, if we had a DBG_VALUE $regX as an entry debug value
representing the parameter, and a COPY and after the COPY,
DBG_VALUE $virt_reg, and after the virtregrewrite the $virt_reg gets
rewritten into $regX, we'd end up having redundant DBG_VALUE.
This breaks the definition of the DBG_VALUE since some analysis passes
might be built on top of that premise..., and this patch tries to fix
the MIR with the respect to that.
This first patch performs bacward scan, by trying to detect a sequence of
consecutive DBG_VALUEs, and to remove all DBG_VALUEs describing one
variable but the last one:
For example:
(1) DBG_VALUE $edi, !"var1", ...
(2) DBG_VALUE $esi, !"var2", ...
(3) DBG_VALUE $edi, !"var1", ...
...
in this case, we can remove (1).
By combining the forward scan that will be introduced in the next patch
(from this stack), by inspecting the statistics, the RemoveRedundantDebugValues
removes 15032 instructions by using gdb-7.11 as a testbed.
Differential Revision: https://reviews.llvm.org/D105279
2021-06-28 14:15:31 +02:00
|
|
|
#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)");
|
2021-07-15 08:45:19 +02:00
|
|
|
STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)");
|
[RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
This new MIR pass removes redundant DBG_VALUEs.
After the register allocator is done, more precisely, after
the Virtual Register Rewriter, we end up having duplicated
DBG_VALUEs, since some virtual registers are being rewritten
into the same physical register as some of existing DBG_VALUEs.
Each DBG_VALUE should indicate (at least before the LiveDebugValues)
variables assignment, but it is being clobbered for function
parameters during the SelectionDAG since it generates new DBG_VALUEs
after COPY instructions, even though the parameter has no assignment.
For example, if we had a DBG_VALUE $regX as an entry debug value
representing the parameter, and a COPY and after the COPY,
DBG_VALUE $virt_reg, and after the virtregrewrite the $virt_reg gets
rewritten into $regX, we'd end up having redundant DBG_VALUE.
This breaks the definition of the DBG_VALUE since some analysis passes
might be built on top of that premise..., and this patch tries to fix
the MIR with the respect to that.
This first patch performs bacward scan, by trying to detect a sequence of
consecutive DBG_VALUEs, and to remove all DBG_VALUEs describing one
variable but the last one:
For example:
(1) DBG_VALUE $edi, !"var1", ...
(2) DBG_VALUE $esi, !"var2", ...
(3) DBG_VALUE $edi, !"var1", ...
...
in this case, we can remove (1).
By combining the forward scan that will be introduced in the next patch
(from this stack), by inspecting the statistics, the RemoveRedundantDebugValues
removes 15032 instructions by using gdb-7.11 as a testbed.
Differential Revision: https://reviews.llvm.org/D105279
2021-06-28 14:15:31 +02:00
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2021-07-15 08:45:19 +02:00
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
|
[RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
This new MIR pass removes redundant DBG_VALUEs.
After the register allocator is done, more precisely, after
the Virtual Register Rewriter, we end up having duplicated
DBG_VALUEs, since some virtual registers are being rewritten
into the same physical register as some of existing DBG_VALUEs.
Each DBG_VALUE should indicate (at least before the LiveDebugValues)
variables assignment, but it is being clobbered for function
parameters during the SelectionDAG since it generates new DBG_VALUEs
after COPY instructions, even though the parameter has no assignment.
For example, if we had a DBG_VALUE $regX as an entry debug value
representing the parameter, and a COPY and after the COPY,
DBG_VALUE $virt_reg, and after the virtregrewrite the $virt_reg gets
rewritten into $regX, we'd end up having redundant DBG_VALUE.
This breaks the definition of the DBG_VALUE since some analysis passes
might be built on top of that premise..., and this patch tries to fix
the MIR with the respect to that.
This first patch performs bacward scan, by trying to detect a sequence of
consecutive DBG_VALUEs, and to remove all DBG_VALUEs describing one
variable but the last one:
For example:
(1) DBG_VALUE $edi, !"var1", ...
(2) DBG_VALUE $esi, !"var2", ...
(3) DBG_VALUE $edi, !"var1", ...
...
in this case, we can remove (1).
By combining the forward scan that will be introduced in the next patch
(from this stack), by inspecting the statistics, the RemoveRedundantDebugValues
removes 15032 instructions by using gdb-7.11 as a testbed.
Differential Revision: https://reviews.llvm.org/D105279
2021-06-28 14:15:31 +02:00
|
|
|
// 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;
|
|
|
|
|
2021-07-15 08:45:19 +02:00
|
|
|
for (auto &MBB : MF) {
|
[RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
This new MIR pass removes redundant DBG_VALUEs.
After the register allocator is done, more precisely, after
the Virtual Register Rewriter, we end up having duplicated
DBG_VALUEs, since some virtual registers are being rewritten
into the same physical register as some of existing DBG_VALUEs.
Each DBG_VALUE should indicate (at least before the LiveDebugValues)
variables assignment, but it is being clobbered for function
parameters during the SelectionDAG since it generates new DBG_VALUEs
after COPY instructions, even though the parameter has no assignment.
For example, if we had a DBG_VALUE $regX as an entry debug value
representing the parameter, and a COPY and after the COPY,
DBG_VALUE $virt_reg, and after the virtregrewrite the $virt_reg gets
rewritten into $regX, we'd end up having redundant DBG_VALUE.
This breaks the definition of the DBG_VALUE since some analysis passes
might be built on top of that premise..., and this patch tries to fix
the MIR with the respect to that.
This first patch performs bacward scan, by trying to detect a sequence of
consecutive DBG_VALUEs, and to remove all DBG_VALUEs describing one
variable but the last one:
For example:
(1) DBG_VALUE $edi, !"var1", ...
(2) DBG_VALUE $esi, !"var2", ...
(3) DBG_VALUE $edi, !"var1", ...
...
in this case, we can remove (1).
By combining the forward scan that will be introduced in the next patch
(from this stack), by inspecting the statistics, the RemoveRedundantDebugValues
removes 15032 instructions by using gdb-7.11 as a testbed.
Differential Revision: https://reviews.llvm.org/D105279
2021-06-28 14:15:31 +02:00
|
|
|
Changed |= reduceDbgValsBackwardScan(MBB);
|
2021-07-15 08:45:19 +02:00
|
|
|
Changed |= reduceDbgValsForwardScan(MBB);
|
|
|
|
}
|
[RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
This new MIR pass removes redundant DBG_VALUEs.
After the register allocator is done, more precisely, after
the Virtual Register Rewriter, we end up having duplicated
DBG_VALUEs, since some virtual registers are being rewritten
into the same physical register as some of existing DBG_VALUEs.
Each DBG_VALUE should indicate (at least before the LiveDebugValues)
variables assignment, but it is being clobbered for function
parameters during the SelectionDAG since it generates new DBG_VALUEs
after COPY instructions, even though the parameter has no assignment.
For example, if we had a DBG_VALUE $regX as an entry debug value
representing the parameter, and a COPY and after the COPY,
DBG_VALUE $virt_reg, and after the virtregrewrite the $virt_reg gets
rewritten into $regX, we'd end up having redundant DBG_VALUE.
This breaks the definition of the DBG_VALUE since some analysis passes
might be built on top of that premise..., and this patch tries to fix
the MIR with the respect to that.
This first patch performs bacward scan, by trying to detect a sequence of
consecutive DBG_VALUEs, and to remove all DBG_VALUEs describing one
variable but the last one:
For example:
(1) DBG_VALUE $edi, !"var1", ...
(2) DBG_VALUE $esi, !"var2", ...
(3) DBG_VALUE $edi, !"var1", ...
...
in this case, we can remove (1).
By combining the forward scan that will be introduced in the next patch
(from this stack), by inspecting the statistics, the RemoveRedundantDebugValues
removes 15032 instructions by using gdb-7.11 as a testbed.
Differential Revision: https://reviews.llvm.org/D105279
2021-06-28 14:15:31 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|