LLVM 20.0.0git
RemoveRedundantDebugValues.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/DenseMap.h"
10#include "llvm/ADT/DenseSet.h"
12#include "llvm/ADT/Statistic.h"
17#include "llvm/IR/Function.h"
19#include "llvm/Pass.h"
20#include "llvm/PassRegistry.h"
21
22/// \file RemoveRedundantDebugValues.cpp
23///
24/// The RemoveRedundantDebugValues pass removes redundant DBG_VALUEs that
25/// appear in MIR after the register allocator.
26
27#define DEBUG_TYPE "removeredundantdebugvalues"
28
29using namespace llvm;
30
31STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)");
32STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)");
33
34namespace {
35
36class RemoveRedundantDebugValues : public MachineFunctionPass {
37public:
38 static char ID;
39
40 RemoveRedundantDebugValues();
41
42 bool reduceDbgValues(MachineFunction &MF);
43
44 /// Remove redundant debug value MIs for the given machine function.
45 bool runOnMachineFunction(MachineFunction &MF) override;
46
47 void getAnalysisUsage(AnalysisUsage &AU) const override {
48 AU.setPreservesCFG();
50 }
51};
52
53} // namespace
54
55//===----------------------------------------------------------------------===//
56// Implementation
57//===----------------------------------------------------------------------===//
58
59char RemoveRedundantDebugValues::ID = 0;
60
61char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValues::ID;
62
63INITIALIZE_PASS(RemoveRedundantDebugValues, DEBUG_TYPE,
64 "Remove Redundant DEBUG_VALUE analysis", false, false)
65
66/// Default construct and initialize the pass.
67RemoveRedundantDebugValues::RemoveRedundantDebugValues()
70}
71
72// This analysis aims to remove redundant DBG_VALUEs by going forward
73// in the basic block by considering the first DBG_VALUE as a valid
74// until its first (location) operand is not clobbered/modified.
75// For example:
76// (1) DBG_VALUE $edi, !"var1", ...
77// (2) <block of code that does affect $edi>
78// (3) DBG_VALUE $edi, !"var1", ...
79// ...
80// in this case, we can remove (3).
81// TODO: Support DBG_VALUE_LIST and other debug instructions.
83 LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n");
84
85 SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
87 VariableMap;
88 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
89
90 for (auto &MI : MBB) {
91 if (MI.isDebugValue()) {
92 DebugVariable Var(MI.getDebugVariable(), std::nullopt,
93 MI.getDebugLoc()->getInlinedAt());
94 auto VMI = VariableMap.find(Var);
95 // Just stop tracking this variable, until we cover DBG_VALUE_LIST.
96 // 1 DBG_VALUE $rax, "x", DIExpression()
97 // ...
98 // 2 DBG_VALUE_LIST "x", DIExpression(...), $rax, $rbx
99 // ...
100 // 3 DBG_VALUE $rax, "x", DIExpression()
101 if (MI.isDebugValueList() && VMI != VariableMap.end()) {
102 VariableMap.erase(VMI);
103 continue;
104 }
105
106 MachineOperand &Loc = MI.getDebugOperand(0);
107 if (!Loc.isReg()) {
108 // If it's not a register, just stop tracking such variable.
109 if (VMI != VariableMap.end())
110 VariableMap.erase(VMI);
111 continue;
112 }
113
114 // We have found a new value for a variable.
115 if (VMI == VariableMap.end() ||
116 VMI->second.first->getReg() != Loc.getReg() ||
117 VMI->second.second != MI.getDebugExpression()) {
118 VariableMap[Var] = {&Loc, MI.getDebugExpression()};
119 continue;
120 }
121
122 // Found an identical DBG_VALUE, so it can be considered
123 // for later removal.
124 DbgValsToBeRemoved.push_back(&MI);
125 }
126
127 if (MI.isMetaInstruction())
128 continue;
129
130 // Stop tracking any location that is clobbered by this instruction.
131 for (auto &Var : VariableMap) {
132 auto &LocOp = Var.second.first;
133 if (MI.modifiesRegister(LocOp->getReg(), TRI))
134 VariableMap.erase(Var.first);
135 }
136 }
137
138 for (auto &Instr : DbgValsToBeRemoved) {
139 LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
140 Instr->eraseFromParent();
141 ++NumRemovedForward;
142 }
143
144 return !DbgValsToBeRemoved.empty();
145}
146
147// This analysis aims to remove redundant DBG_VALUEs by going backward
148// in the basic block and removing all but the last DBG_VALUE for any
149// given variable in a set of consecutive DBG_VALUE instructions.
150// For example:
151// (1) DBG_VALUE $edi, !"var1", ...
152// (2) DBG_VALUE $esi, !"var2", ...
153// (3) DBG_VALUE $edi, !"var1", ...
154// ...
155// in this case, we can remove (1).
157 LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n");
158 SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
160
161 for (MachineInstr &MI : llvm::reverse(MBB)) {
162 if (MI.isDebugValue()) {
163 DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
164 MI.getDebugLoc()->getInlinedAt());
165 auto R = VariableSet.insert(Var);
166 // If it is a DBG_VALUE describing a constant as:
167 // DBG_VALUE 0, ...
168 // we just don't consider such instructions as candidates
169 // for redundant removal.
170 if (MI.isNonListDebugValue()) {
171 MachineOperand &Loc = MI.getDebugOperand(0);
172 if (!Loc.isReg()) {
173 // If we have already encountered this variable, just stop
174 // tracking it.
175 if (!R.second)
176 VariableSet.erase(Var);
177 continue;
178 }
179 }
180
181 // We have already encountered the value for this variable,
182 // so this one can be deleted.
183 if (!R.second)
184 DbgValsToBeRemoved.push_back(&MI);
185 continue;
186 }
187
188 // If we encountered a non-DBG_VALUE, try to find the next
189 // sequence with consecutive DBG_VALUE instructions.
190 VariableSet.clear();
191 }
192
193 for (auto &Instr : DbgValsToBeRemoved) {
194 LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
195 Instr->eraseFromParent();
196 ++NumRemovedBackward;
197 }
198
199 return !DbgValsToBeRemoved.empty();
200}
201
202bool RemoveRedundantDebugValues::reduceDbgValues(MachineFunction &MF) {
203 LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n");
204
205 bool Changed = false;
206
207 for (auto &MBB : MF) {
208 Changed |= reduceDbgValsBackwardScan(MBB);
209 Changed |= reduceDbgValsForwardScan(MBB);
210 }
211
212 return Changed;
213}
214
215bool RemoveRedundantDebugValues::runOnMachineFunction(MachineFunction &MF) {
216 // Skip functions without debugging information.
217 if (!MF.getFunction().getSubprogram())
218 return false;
219
220 // Skip functions from NoDebug compilation units.
221 if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
223 return false;
224
225 bool Changed = reduceDbgValues(MF);
226 return Changed;
227}
MachineBasicBlock & MBB
#define LLVM_DEBUG(...)
Definition: Debug.h:106
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
IRTranslator LLVM IR MI
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB)
static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB)
#define DEBUG_TYPE
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:166
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:256
Identifies a unique instance of a variable.
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:156
bool erase(const KeyT &Val)
Definition: DenseMap.h:321
iterator end()
Definition: DenseMap.h:84
DISubprogram * getSubprogram() const
Get the attached subprogram.
Definition: Metadata.cpp:1874
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition: DenseSet.h:298
bool empty() const
Definition: SmallVector.h:81
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:213
bool erase(const ValueT &V)
Definition: DenseSet.h:97
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:420
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
char & RemoveRedundantDebugValuesID
RemoveRedundantDebugValues pass.
void initializeRemoveRedundantDebugValuesPass(PassRegistry &)