xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp (revision 924226fba12cc9a228c73b956e1b7fa24c60b055)
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 (MachineInstr &MI : llvm::reverse(MBB)) {
163     if (MI.isDebugValue()) {
164       DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
165                         MI.getDebugLoc()->getInlinedAt());
166       auto R = VariableSet.insert(Var);
167       // If it is a DBG_VALUE describing a constant as:
168       //   DBG_VALUE 0, ...
169       // we just don't consider such instructions as candidates
170       // for redundant removal.
171       if (MI.isNonListDebugValue()) {
172         MachineOperand &Loc = MI.getDebugOperand(0);
173         if (!Loc.isReg()) {
174           // If we have already encountered this variable, just stop
175           // tracking it.
176           if (!R.second)
177             VariableSet.erase(Var);
178           continue;
179         }
180       }
181 
182       // We have already encountered the value for this variable,
183       // so this one can be deleted.
184       if (!R.second)
185         DbgValsToBeRemoved.push_back(&MI);
186       continue;
187     }
188 
189     // If we encountered a non-DBG_VALUE, try to find the next
190     // sequence with consecutive DBG_VALUE instructions.
191     VariableSet.clear();
192   }
193 
194   for (auto &Instr : DbgValsToBeRemoved) {
195     LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
196     Instr->eraseFromParent();
197     ++NumRemovedBackward;
198   }
199 
200   return !DbgValsToBeRemoved.empty();
201 }
202 
203 bool RemoveRedundantDebugValues::reduceDbgValues(MachineFunction &MF) {
204   LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n");
205 
206   bool Changed = false;
207 
208   for (auto &MBB : MF) {
209     Changed |= reduceDbgValsBackwardScan(MBB);
210     Changed |= reduceDbgValsForwardScan(MBB);
211   }
212 
213   return Changed;
214 }
215 
216 bool RemoveRedundantDebugValues::runOnMachineFunction(MachineFunction &MF) {
217   // Skip functions without debugging information.
218   if (!MF.getFunction().getSubprogram())
219     return false;
220 
221   // Skip functions from NoDebug compilation units.
222   if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
223       DICompileUnit::NoDebug)
224     return false;
225 
226   bool Changed = reduceDbgValues(MF);
227   return Changed;
228 }
229