xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
30 using namespace llvm;
31 
32 STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)");
33 STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)");
34 
35 namespace {
36 
37 struct RemoveRedundantDebugValuesImpl {
38   bool reduceDbgValues(MachineFunction &MF);
39 };
40 
41 class RemoveRedundantDebugValuesLegacy : public MachineFunctionPass {
42 public:
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 
61 char RemoveRedundantDebugValuesLegacy::ID = 0;
62 
63 char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValuesLegacy::ID;
64 
65 INITIALIZE_PASS(RemoveRedundantDebugValuesLegacy, DEBUG_TYPE,
66                 "Remove Redundant DEBUG_VALUE analysis", false, false)
67 
68 /// Default construct and initialize the pass.
69 RemoveRedundantDebugValuesLegacy::RemoveRedundantDebugValuesLegacy()
70     : MachineFunctionPass(ID) {
71   initializeRemoveRedundantDebugValuesLegacyPass(
72       *PassRegistry::getPassRegistry());
73 }
74 
75 // This analysis aims to remove redundant DBG_VALUEs by going forward
76 // in the basic block by considering the first DBG_VALUE as a valid
77 // until its first (location) operand is not clobbered/modified.
78 // For example:
79 //   (1) DBG_VALUE $edi, !"var1", ...
80 //   (2) <block of code that does affect $edi>
81 //   (3) DBG_VALUE $edi, !"var1", ...
82 //   ...
83 // in this case, we can remove (3).
84 // TODO: Support DBG_VALUE_LIST and other debug instructions.
85 static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB) {
86   LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n");
87 
88   SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
89   DenseMap<DebugVariable, std::pair<MachineOperand *, const DIExpression *>>
90       VariableMap;
91   const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
92 
93   for (auto &MI : MBB) {
94     if (MI.isDebugValue()) {
95       DebugVariable Var(MI.getDebugVariable(), std::nullopt,
96                         MI.getDebugLoc()->getInlinedAt());
97       auto VMI = VariableMap.find(Var);
98       // Just stop tracking this variable, until we cover DBG_VALUE_LIST.
99       // 1  DBG_VALUE $rax, "x", DIExpression()
100       // ...
101       // 2  DBG_VALUE_LIST "x", DIExpression(...), $rax, $rbx
102       // ...
103       // 3  DBG_VALUE $rax, "x", DIExpression()
104       if (MI.isDebugValueList() && VMI != VariableMap.end()) {
105         VariableMap.erase(VMI);
106         continue;
107       }
108 
109       MachineOperand &Loc = MI.getDebugOperand(0);
110       if (!Loc.isReg()) {
111         // If it's not a register, just stop tracking such variable.
112         if (VMI != VariableMap.end())
113           VariableMap.erase(VMI);
114         continue;
115       }
116 
117       // We have found a new value for a variable.
118       if (VMI == VariableMap.end() ||
119           VMI->second.first->getReg() != Loc.getReg() ||
120           VMI->second.second != MI.getDebugExpression()) {
121         VariableMap[Var] = {&Loc, MI.getDebugExpression()};
122         continue;
123       }
124 
125       // Found an identical DBG_VALUE, so it can be considered
126       // for later removal.
127       DbgValsToBeRemoved.push_back(&MI);
128     }
129 
130     if (MI.isMetaInstruction())
131       continue;
132 
133     // Stop tracking any location that is clobbered by this instruction.
134     for (auto &Var : VariableMap) {
135       auto &LocOp = Var.second.first;
136       if (MI.modifiesRegister(LocOp->getReg(), TRI))
137         VariableMap.erase(Var.first);
138     }
139   }
140 
141   for (auto &Instr : DbgValsToBeRemoved) {
142     LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
143     Instr->eraseFromParent();
144     ++NumRemovedForward;
145   }
146 
147   return !DbgValsToBeRemoved.empty();
148 }
149 
150 // This analysis aims to remove redundant DBG_VALUEs by going backward
151 // in the basic block and removing all but the last DBG_VALUE for any
152 // given variable in a set of consecutive DBG_VALUE instructions.
153 // For example:
154 //   (1) DBG_VALUE $edi, !"var1", ...
155 //   (2) DBG_VALUE $esi, !"var2", ...
156 //   (3) DBG_VALUE $edi, !"var1", ...
157 //   ...
158 // in this case, we can remove (1).
159 static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB) {
160   LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n");
161   SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
162   SmallDenseSet<DebugVariable> VariableSet;
163 
164   for (MachineInstr &MI : llvm::reverse(MBB)) {
165     if (MI.isDebugValue()) {
166       DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
167                         MI.getDebugLoc()->getInlinedAt());
168       auto R = VariableSet.insert(Var);
169       // If it is a DBG_VALUE describing a constant as:
170       //   DBG_VALUE 0, ...
171       // we just don't consider such instructions as candidates
172       // for redundant removal.
173       if (MI.isNonListDebugValue()) {
174         MachineOperand &Loc = MI.getDebugOperand(0);
175         if (!Loc.isReg()) {
176           // If we have already encountered this variable, just stop
177           // tracking it.
178           if (!R.second)
179             VariableSet.erase(Var);
180           continue;
181         }
182       }
183 
184       // We have already encountered the value for this variable,
185       // so this one can be deleted.
186       if (!R.second)
187         DbgValsToBeRemoved.push_back(&MI);
188       continue;
189     }
190 
191     // If we encountered a non-DBG_VALUE, try to find the next
192     // sequence with consecutive DBG_VALUE instructions.
193     VariableSet.clear();
194   }
195 
196   for (auto &Instr : DbgValsToBeRemoved) {
197     LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
198     Instr->eraseFromParent();
199     ++NumRemovedBackward;
200   }
201 
202   return !DbgValsToBeRemoved.empty();
203 }
204 
205 bool RemoveRedundantDebugValuesImpl::reduceDbgValues(MachineFunction &MF) {
206   LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n");
207 
208   bool Changed = false;
209 
210   for (auto &MBB : MF) {
211     Changed |= reduceDbgValsBackwardScan(MBB);
212     Changed |= reduceDbgValsForwardScan(MBB);
213   }
214 
215   return Changed;
216 }
217 
218 bool RemoveRedundantDebugValuesLegacy::runOnMachineFunction(
219     MachineFunction &MF) {
220   // Skip functions without debugging information or functions from NoDebug
221   // compilation units.
222   if (!MF.getFunction().getSubprogram() ||
223       (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
224        DICompileUnit::NoDebug))
225     return false;
226 
227   return RemoveRedundantDebugValuesImpl().reduceDbgValues(MF);
228 }
229 
230 PreservedAnalyses
231 RemoveRedundantDebugValuesPass::run(MachineFunction &MF,
232                                     MachineFunctionAnalysisManager &MFAM) {
233   // Skip functions without debugging information or functions from NoDebug
234   // compilation units.
235   if (!MF.getFunction().getSubprogram() ||
236       (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
237        DICompileUnit::NoDebug))
238     return PreservedAnalyses::all();
239 
240   if (!RemoveRedundantDebugValuesImpl().reduceDbgValues(MF))
241     return PreservedAnalyses::all();
242 
243   auto PA = getMachineFunctionPassPreservedAnalyses();
244   PA.preserveSet<CFGAnalyses>();
245   return PA;
246 }
247