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/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.cpp
24///
25/// The RemoveRedundantDebugValues pass removes redundant DBG_VALUEs that
26/// 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} // namespace
56
57//===----------------------------------------------------------------------===//
58// Implementation
59//===----------------------------------------------------------------------===//
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
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.
82static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB) {
83 LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n");
84
85 SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
86 DenseMap<DebugVariable, std::pair<MachineOperand *, const DIExpression *>>
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(Val: 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(I: VMI);
103 continue;
104 }
105
106 MachineOperand &Loc = MI.getDebugOperand(Index: 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(I: 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(Elt: &MI);
125 }
126
127 if (MI.isMetaInstruction())
128 continue;
129
130 // Stop tracking any location that is clobbered by this instruction.
131 VariableMap.remove_if(Pred: [&](const auto &Var) {
132 return MI.modifiesRegister(Reg: Var.second.first->getReg(), TRI);
133 });
134 }
135
136 for (auto &Instr : DbgValsToBeRemoved) {
137 LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
138 Instr->eraseFromParent();
139 ++NumRemovedForward;
140 }
141
142 return !DbgValsToBeRemoved.empty();
143}
144
145// This analysis aims to remove redundant DBG_VALUEs by going backward
146// in the basic block and removing all but the last DBG_VALUE for any
147// given variable in a set of consecutive DBG_VALUE instructions.
148// For example:
149// (1) DBG_VALUE $edi, !"var1", ...
150// (2) DBG_VALUE $esi, !"var2", ...
151// (3) DBG_VALUE $edi, !"var1", ...
152// ...
153// in this case, we can remove (1).
154static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB) {
155 LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n");
156 SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
157 SmallDenseSet<DebugVariable> VariableSet;
158
159 for (MachineInstr &MI : llvm::reverse(C&: MBB)) {
160 if (MI.isDebugValue()) {
161 DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
162 MI.getDebugLoc()->getInlinedAt());
163 auto R = VariableSet.insert(V: Var);
164 // If it is a DBG_VALUE describing a constant as:
165 // DBG_VALUE 0, ...
166 // we just don't consider such instructions as candidates
167 // for redundant removal.
168 if (MI.isNonListDebugValue()) {
169 MachineOperand &Loc = MI.getDebugOperand(Index: 0);
170 if (!Loc.isReg()) {
171 // If we have already encountered this variable, just stop
172 // tracking it.
173 if (!R.second)
174 VariableSet.erase(V: Var);
175 continue;
176 }
177 }
178
179 // We have already encountered the value for this variable,
180 // so this one can be deleted.
181 if (!R.second)
182 DbgValsToBeRemoved.push_back(Elt: &MI);
183 continue;
184 }
185
186 // If we encountered a non-DBG_VALUE, try to find the next
187 // sequence with consecutive DBG_VALUE instructions.
188 VariableSet.clear();
189 }
190
191 for (auto &Instr : DbgValsToBeRemoved) {
192 LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
193 Instr->eraseFromParent();
194 ++NumRemovedBackward;
195 }
196
197 return !DbgValsToBeRemoved.empty();
198}
199
200bool RemoveRedundantDebugValuesImpl::reduceDbgValues(MachineFunction &MF) {
201 LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n");
202
203 bool Changed = false;
204
205 for (auto &MBB : MF) {
206 Changed |= reduceDbgValsBackwardScan(MBB);
207 Changed |= reduceDbgValsForwardScan(MBB);
208 }
209
210 return Changed;
211}
212
213bool RemoveRedundantDebugValuesLegacy::runOnMachineFunction(
214 MachineFunction &MF) {
215 // Skip functions without debugging information or functions from NoDebug
216 // compilation units.
217 if (!MF.getFunction().getSubprogram() ||
218 (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
219 DICompileUnit::NoDebug))
220 return false;
221
222 return RemoveRedundantDebugValuesImpl().reduceDbgValues(MF);
223}
224
225PreservedAnalyses
226RemoveRedundantDebugValuesPass::run(MachineFunction &MF,
227 MachineFunctionAnalysisManager &MFAM) {
228 // Skip functions without debugging information or functions from NoDebug
229 // compilation units.
230 if (!MF.getFunction().getSubprogram() ||
231 (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
232 DICompileUnit::NoDebug))
233 return PreservedAnalyses::all();
234
235 if (!RemoveRedundantDebugValuesImpl().reduceDbgValues(MF))
236 return PreservedAnalyses::all();
237
238 auto PA = getMachineFunctionPassPreservedAnalyses();
239 PA.preserveSet<CFGAnalyses>();
240 return PA;
241}
242