LLVM 24.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
10#include "llvm/ADT/DenseMap.h"
11#include "llvm/ADT/DenseSet.h"
13#include "llvm/ADT/Statistic.h"
19#include "llvm/IR/Function.h"
21#include "llvm/Pass.h"
22#include "llvm/PassRegistry.h"
23
24/// \file RemoveRedundantDebugValues.cpp
25///
26/// The RemoveRedundantDebugValues pass removes redundant DBG_VALUEs that
27/// appear in MIR after the register allocator.
28
29#define DEBUG_TYPE "removeredundantdebugvalues"
30
31using namespace llvm;
32
33STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)");
34STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)");
35
36namespace {
37
38struct RemoveRedundantDebugValuesImpl {
39 bool reduceDbgValues(MachineFunction &MF);
40};
41
42class RemoveRedundantDebugValuesLegacy : public MachineFunctionPass {
43public:
44 static char ID;
45
46 RemoveRedundantDebugValuesLegacy();
47 /// Remove redundant debug value MIs for the given machine function.
48 bool runOnMachineFunction(MachineFunction &MF) override;
49
50 void getAnalysisUsage(AnalysisUsage &AU) const override {
51 AU.setPreservesCFG();
53 }
54};
55
56} // namespace
57
58//===----------------------------------------------------------------------===//
59// Implementation
60//===----------------------------------------------------------------------===//
61
62char RemoveRedundantDebugValuesLegacy::ID = 0;
63
64char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValuesLegacy::ID;
65
66INITIALIZE_PASS(RemoveRedundantDebugValuesLegacy, DEBUG_TYPE,
67 "Remove Redundant DEBUG_VALUE analysis", false, false)
68
69/// Default construct and initialize the pass.
70RemoveRedundantDebugValuesLegacy::RemoveRedundantDebugValuesLegacy()
71 : MachineFunctionPass(ID) {}
72
73// This analysis aims to remove redundant DBG_VALUEs by going forward
74// in the basic block by considering the first DBG_VALUE as a valid
75// until its first (location) operand is not clobbered/modified.
76// For example:
77// (1) DBG_VALUE $edi, !"var1", ...
78// (2) <block of code that does affect $edi>
79// (3) DBG_VALUE $edi, !"var1", ...
80// ...
81// in this case, we can remove (3).
82// TODO: Support DBG_VALUE_LIST and other debug instructions.
84 LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n");
85
86 SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
88 VariableMap;
89 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
90
91 for (auto &MI : MBB) {
92 if (MI.isDebugValue()) {
93 DebugVariable Var(MI.getDebugVariable(), std::nullopt,
94 MI.getDebugLoc()->getInlinedAt());
95 auto VMI = VariableMap.find(Var);
96 // Just stop tracking this variable, until we cover DBG_VALUE_LIST.
97 // 1 DBG_VALUE $rax, "x", DIExpression()
98 // ...
99 // 2 DBG_VALUE_LIST "x", DIExpression(...), $rax, $rbx
100 // ...
101 // 3 DBG_VALUE $rax, "x", DIExpression()
102 if (MI.isDebugValueList() && VMI != VariableMap.end()) {
103 VariableMap.erase(VMI);
104 continue;
105 }
106
107 MachineOperand &Loc = MI.getDebugOperand(0);
108 if (!Loc.isReg()) {
109 // If it's not a register, just stop tracking such variable.
110 if (VMI != VariableMap.end())
111 VariableMap.erase(VMI);
112 continue;
113 }
114
115 // We have found a new value for a variable.
116 if (VMI == VariableMap.end() ||
117 VMI->second.first->getReg() != Loc.getReg() ||
118 VMI->second.second != MI.getDebugExpression()) {
119 VariableMap[Var] = {&Loc, MI.getDebugExpression()};
120 continue;
121 }
122
123 // Found an identical DBG_VALUE, so it can be considered
124 // for later removal.
125 DbgValsToBeRemoved.push_back(&MI);
126 }
127
128 if (MI.isMetaInstruction())
129 continue;
130
131 // Stop tracking any location that is clobbered by this instruction.
132 VariableMap.remove_if([&](const auto &Var) {
133 return MI.modifiesRegister(Var.second.first->getReg(), TRI);
134 });
135 }
136
137 for (auto &Instr : DbgValsToBeRemoved) {
138 LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
139 Instr->eraseFromParent();
140 ++NumRemovedForward;
141 }
142
143 return !DbgValsToBeRemoved.empty();
144}
145
146// This analysis aims to remove redundant DBG_VALUEs by going backward
147// in the basic block and removing all but the last DBG_VALUE for any
148// given variable in a set of consecutive DBG_VALUE instructions.
149// For example:
150// (1) DBG_VALUE $edi, !"var1", ...
151// (2) DBG_VALUE $esi, !"var2", ...
152// (3) DBG_VALUE $edi, !"var1", ...
153// ...
154// in this case, we can remove (1).
156 LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n");
157 SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
159
160 for (MachineInstr &MI : llvm::reverse(MBB)) {
161 if (MI.isDebugValue()) {
162 DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
163 MI.getDebugLoc()->getInlinedAt());
164 auto R = VariableSet.insert(Var);
165 // If it is a DBG_VALUE describing a constant as:
166 // DBG_VALUE 0, ...
167 // we just don't consider such instructions as candidates
168 // for redundant removal.
169 if (MI.isNonListDebugValue()) {
170 MachineOperand &Loc = MI.getDebugOperand(0);
171 if (!Loc.isReg()) {
172 // If we have already encountered this variable, just stop
173 // tracking it.
174 if (!R.second)
175 VariableSet.erase(Var);
176 continue;
177 }
178 }
179
180 // We have already encountered the value for this variable,
181 // so this one can be deleted.
182 if (!R.second)
183 DbgValsToBeRemoved.push_back(&MI);
184 continue;
185 }
186
187 // If we encountered a non-DBG_VALUE, try to find the next
188 // sequence with consecutive DBG_VALUE instructions.
189 VariableSet.clear();
190 }
191
192 for (auto &Instr : DbgValsToBeRemoved) {
193 LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
194 Instr->eraseFromParent();
195 ++NumRemovedBackward;
196 }
197
198 return !DbgValsToBeRemoved.empty();
199}
200
201bool RemoveRedundantDebugValuesImpl::reduceDbgValues(MachineFunction &MF) {
202 LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n");
203
204 bool Changed = false;
205
206 for (auto &MBB : MF) {
209 }
210
211 return Changed;
212}
213
214bool RemoveRedundantDebugValuesLegacy::runOnMachineFunction(
215 MachineFunction &MF) {
216 // Skip functions without debugging information or functions from NoDebug
217 // compilation units.
218 if (!MF.getFunction().getSubprogram() ||
219 (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
221 return false;
222
223 return RemoveRedundantDebugValuesImpl().reduceDbgValues(MF);
224}
225
226PreservedAnalyses
229 // Skip functions without debugging information or functions from NoDebug
230 // compilation units.
231 if (!MF.getFunction().getSubprogram() ||
232 (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
234 return PreservedAnalyses::all();
235
236 if (!RemoveRedundantDebugValuesImpl().reduceDbgValues(MF))
237 return PreservedAnalyses::all();
238
240 PA.preserveSet<CFGAnalyses>();
241 return PA;
242}
MachineBasicBlock & MBB
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
#define DEBUG_TYPE
IRTranslator LLVM IR MI
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB)
static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB)
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:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:275
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
Identifies a unique instance of a variable.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
bool erase(const KeyT &Val)
Definition DenseMap.h:377
bool remove_if(Predicate Pred)
Remove entries that match the given predicate.
Definition DenseMap.h:393
iterator end()
Definition DenseMap.h:141
DISubprogram * getSubprogram() const
Get the attached subprogram.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:293
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
bool erase(const ValueT &V)
Definition DenseSet.h:97
Changed
This is an optimization pass for GlobalISel generic memory operations.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI char & RemoveRedundantDebugValuesID
RemoveRedundantDebugValues pass.