xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp (revision 093cf790569775b80662926efea6d9d3464bde94)
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"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/Statistic.h"
13 #include "llvm/CodeGen/MachineBasicBlock.h"
14 #include "llvm/CodeGen/MachineFunctionPass.h"
15 #include "llvm/CodeGen/Passes.h"
16 #include "llvm/CodeGen/TargetRegisterInfo.h"
17 #include "llvm/CodeGen/TargetSubtargetInfo.h"
18 #include "llvm/IR/DebugInfoMetadata.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/InitializePasses.h"
21 #include "llvm/Pass.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 class RemoveRedundantDebugValues : public MachineFunctionPass {
38 public:
39   static char ID;
40 
41   RemoveRedundantDebugValues();
42 
43   bool reduceDbgValues(MachineFunction &MF);
44 
45   /// Remove redundant debug value MIs for the given machine function.
46   bool runOnMachineFunction(MachineFunction &MF) override;
47 
48   void getAnalysisUsage(AnalysisUsage &AU) const override {
49     AU.setPreservesCFG();
50     MachineFunctionPass::getAnalysisUsage(AU);
51   }
52 };
53 
54 } // namespace
55 
56 //===----------------------------------------------------------------------===//
57 //            Implementation
58 //===----------------------------------------------------------------------===//
59 
60 char RemoveRedundantDebugValues::ID = 0;
61 
62 char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValues::ID;
63 
64 INITIALIZE_PASS(RemoveRedundantDebugValues, DEBUG_TYPE,
65                 "Remove Redundant DEBUG_VALUE analysis", false, false)
66 
67 /// Default construct and initialize the pass.
68 RemoveRedundantDebugValues::RemoveRedundantDebugValues()
69     : MachineFunctionPass(ID) {
70   initializeRemoveRedundantDebugValuesPass(*PassRegistry::getPassRegistry());
71 }
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.
83 static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB) {
84   LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n");
85 
86   SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
87   DenseMap<DebugVariable, std::pair<MachineOperand *, const DIExpression *>>
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(), NoneType(),
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 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     for (auto &Var : VariableMap) {
133       auto &LocOp = Var.second.first;
134       if (MI.modifiesRegister(LocOp->getReg(), TRI))
135         VariableMap.erase(Var.first);
136     }
137   }
138 
139   for (auto &Instr : DbgValsToBeRemoved) {
140     LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
141     Instr->eraseFromParent();
142     ++NumRemovedForward;
143   }
144 
145   return !DbgValsToBeRemoved.empty();
146 }
147 
148 // This analysis aims to remove redundant DBG_VALUEs by going backward
149 // in the basic block and removing all but the last DBG_VALUE for any
150 // given variable in a set of consecutive DBG_VALUE instructions.
151 // For example:
152 //   (1) DBG_VALUE $edi, !"var1", ...
153 //   (2) DBG_VALUE $esi, !"var2", ...
154 //   (3) DBG_VALUE $edi, !"var1", ...
155 //   ...
156 // in this case, we can remove (1).
157 static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB) {
158   LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n");
159   SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
160   SmallDenseSet<DebugVariable> VariableSet;
161 
162   for (MachineBasicBlock::reverse_iterator I = MBB.rbegin(), E = MBB.rend();
163        I != E; ++I) {
164     MachineInstr *MI = &*I;
165 
166     if (MI->isDebugValue()) {
167       DebugVariable Var(MI->getDebugVariable(), MI->getDebugExpression(),
168                         MI->getDebugLoc()->getInlinedAt());
169       auto R = VariableSet.insert(Var);
170       // If it is a DBG_VALUE describing a constant as:
171       //   DBG_VALUE 0, ...
172       // we just don't consider such instructions as candidates
173       // for redundant removal.
174       if (MI->isNonListDebugValue()) {
175         MachineOperand &Loc = MI->getDebugOperand(0);
176         if (!Loc.isReg()) {
177           // If we have already encountered this variable, just stop
178           // tracking it.
179           if (!R.second)
180             VariableSet.erase(Var);
181           continue;
182         }
183       }
184 
185       // We have already encountered the value for this variable,
186       // so this one can be deleted.
187       if (!R.second)
188         DbgValsToBeRemoved.push_back(MI);
189       continue;
190     }
191 
192     // If we encountered a non-DBG_VALUE, try to find the next
193     // sequence with consecutive DBG_VALUE instructions.
194     VariableSet.clear();
195   }
196 
197   for (auto &Instr : DbgValsToBeRemoved) {
198     LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
199     Instr->eraseFromParent();
200     ++NumRemovedBackward;
201   }
202 
203   return !DbgValsToBeRemoved.empty();
204 }
205 
206 bool RemoveRedundantDebugValues::reduceDbgValues(MachineFunction &MF) {
207   LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n");
208 
209   bool Changed = false;
210 
211   for (auto &MBB : MF) {
212     Changed |= reduceDbgValsBackwardScan(MBB);
213     Changed |= reduceDbgValsForwardScan(MBB);
214   }
215 
216   return Changed;
217 }
218 
219 bool RemoveRedundantDebugValues::runOnMachineFunction(MachineFunction &MF) {
220   // Skip functions without debugging information.
221   if (!MF.getFunction().getSubprogram())
222     return false;
223 
224   // Skip functions from NoDebug compilation units.
225   if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
226       DICompileUnit::NoDebug)
227     return false;
228 
229   bool Changed = reduceDbgValues(MF);
230   return Changed;
231 }
232