xref: /llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp (revision a4e32ae4cd97ce460e8695281f60ddb10cf510b2)
1 //===-- WebAssemblyDebugValueManager.cpp - WebAssembly DebugValue Manager -===//
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 /// \file
10 /// This file implements the manager for MachineInstr DebugValues.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "WebAssemblyDebugValueManager.h"
15 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16 #include "WebAssembly.h"
17 #include "WebAssemblyMachineFunctionInfo.h"
18 #include "llvm/CodeGen/MachineInstr.h"
19 
20 using namespace llvm;
21 
22 WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(MachineInstr *Def)
23     : Def(Def) {
24   // This code differs from MachineInstr::collectDebugValues in that it scans
25   // the whole BB, not just contiguous DBG_VALUEs, until another definition to
26   // the same register is encountered.
27   if (!Def->getOperand(0).isReg())
28     return;
29   CurrentReg = Def->getOperand(0).getReg();
30 
31   for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
32                                    ME = Def->getParent()->end();
33        MI != ME; ++MI) {
34     // If another definition appears, stop
35     if (MI->definesRegister(CurrentReg))
36       break;
37     if (MI->isDebugValue() && MI->hasDebugOperandForReg(CurrentReg))
38       DbgValues.push_back(&*MI);
39   }
40 }
41 
42 // Returns true if both A and B are the same CONST_I32/I64/F32/F64 instructions.
43 // Doesn't include CONST_V128.
44 static bool isSameScalarConst(const MachineInstr *A, const MachineInstr *B) {
45   if (A->getOpcode() != B->getOpcode() ||
46       !WebAssembly::isScalarConst(A->getOpcode()) ||
47       !WebAssembly::isScalarConst(B->getOpcode()))
48     return false;
49   const MachineOperand &OpA = A->getOperand(1), &OpB = B->getOperand(1);
50   if ((OpA.isImm() && OpB.isImm() && OpA.getImm() == OpB.getImm()) ||
51       (OpA.isFPImm() && OpB.isFPImm() && OpA.getFPImm() == OpB.getFPImm()) ||
52       (OpA.isGlobal() && OpB.isGlobal() && OpA.getGlobal() == OpB.getGlobal()))
53     return true;
54   return false;
55 }
56 
57 SmallVector<MachineInstr *>
58 WebAssemblyDebugValueManager::getSinkableDebugValues(
59     MachineInstr *Insert) const {
60   if (DbgValues.empty())
61     return {};
62   // DBG_VALUEs between Def and Insert
63   SmallVector<MachineInstr *, 8> DbgValuesInBetween;
64 
65   if (Def->getParent() == Insert->getParent()) {
66     // When Def and Insert are within the same BB, check if Insert comes after
67     // Def, because we only support sinking.
68     bool DefFirst = false;
69     for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
70                                      ME = Def->getParent()->end();
71          MI != ME; ++MI) {
72       if (&*MI == Insert) {
73         DefFirst = true;
74         break;
75       }
76       if (MI->isDebugValue())
77         DbgValuesInBetween.push_back(&*MI);
78     }
79     if (!DefFirst) // Not a sink
80       return {};
81 
82   } else { // Def and Insert are in different BBs
83     // If Def and Insert are in different BBs, we only handle a simple case in
84     // which Insert's BB is a successor of Def's BB.
85     if (!Def->getParent()->isSuccessor(Insert->getParent()))
86       return {};
87 
88     // Gather DBG_VALUEs between 'Def~Def BB's end' and
89     // 'Insert BB's begin~Insert'
90     for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
91                                      ME = Def->getParent()->end();
92          MI != ME; ++MI) {
93       if (MI->isDebugValue())
94         DbgValuesInBetween.push_back(&*MI);
95     }
96     for (MachineBasicBlock::iterator MI = Insert->getParent()->begin(),
97                                      ME = Insert->getIterator();
98          MI != ME; ++MI) {
99       if (MI->isDebugValue())
100         DbgValuesInBetween.push_back(&*MI);
101     }
102   }
103 
104   // Gather DebugVariables that are seen between Def and Insert, excluding our
105   // own DBG_VALUEs in DbgValues.
106   SmallDenseMap<DebugVariable, SmallVector<MachineInstr *, 2>>
107       SeenDbgVarToDbgValues;
108   for (auto *DV : DbgValuesInBetween) {
109     if (std::find(DbgValues.begin(), DbgValues.end(), DV) == DbgValues.end()) {
110       DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
111                         DV->getDebugLoc()->getInlinedAt());
112       SeenDbgVarToDbgValues[Var].push_back(DV);
113     }
114   }
115 
116   // Gather sinkable DBG_VALUEs. We should not sink a DBG_VALUE if there is
117   // another DBG_VALUE between Def and Insert referring to the same
118   // DebugVariable. For example,
119   //   %0 = someinst
120   //   DBG_VALUE %0, !"a", !DIExpression() // Should not sink with %0
121   //   %1 = anotherinst
122   //   DBG_VALUE %1, !"a", !DIExpression()
123   // Where if %0 were to sink, the DBG_VAUE should not sink with it, as that
124   // would re-order assignments.
125   SmallVector<MachineInstr *, 1> SinkableDbgValues;
126   MachineRegisterInfo &MRI = Def->getParent()->getParent()->getRegInfo();
127   for (auto *DV : DbgValues) {
128     DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
129                       DV->getDebugLoc()->getInlinedAt());
130     auto It = SeenDbgVarToDbgValues.find(Var);
131     if (It == SeenDbgVarToDbgValues.end()) {
132       SinkableDbgValues.push_back(DV);
133       continue;
134     }
135     if (!WebAssembly::isScalarConst(Def->getOpcode()))
136       continue;
137     auto &OverlappingDbgValues = It->second;
138     bool Sinkable = true;
139     for (auto *OverlappingDV : OverlappingDbgValues) {
140       MachineOperand &DbgOp = OverlappingDV->getDebugOperand(0);
141       if (!DbgOp.isReg()) {
142         Sinkable = false;
143         break;
144       }
145       Register OtherReg = DbgOp.getReg();
146       MachineInstr *OtherDef = MRI.getUniqueVRegDef(OtherReg);
147       // We have an exception to allow encoutering other DBG_VALUEs with the
148       // smae DebugVariables, only when they are referring to the same scalar
149       // CONST instruction. For example,
150       //   %0 = CONST_I32 1
151       //   DBG_VALUE %0, !"a", !DIExpression() // Can sink with %0
152       //   %1 = CONST_I32 1
153       //   DBG_VALUE %1, !"a", !DIExpression()
154       // When %0 were to be sunk/cloneed, the DBG_VALUE can be sunk/cloned with
155       // it because even though the second DBG_VALUE refers to the same
156       // DebugVariable, its value in effect is the same CONST instruction.
157       //
158       // This is to allow a case that can happen with RegStackify's
159       // "rematerializeCheapDef". For example, we have this program with two
160       // BBs:
161       // bb0:
162       //   %0 = CONST_I32 1
163       //   DBG_VALUE %0, !"a", ...
164       //   ...
165       //   INST0 ..., $0 ...
166       //  bb1:
167       //   INST1 ..., $0 ...
168       //   INST2 ..., $0 ...
169       //
170       // We process bb0 first. Because %0 is used multiple times, %0 is cloned
171       // before INST0:
172       // bb0:
173       //   %0 = CONST_I32 1
174       //   DBG_VALUE %0, !"a", ...
175       //   ...
176       //   %1 = CONST_I32 1
177       //   DBG_VALUE %1, !"a", ...
178       //   INST0 ..., $1 ...
179       //
180       // And when we process bb1, we clone %0 and its DBG_VALUE again:
181       // bb0:
182       //   %0 = CONST_I32 1
183       //   DBG_VALUE %0, !"a", ...
184       //   ...
185       //   %1 = CONST_I32 1
186       //   DBG_VALUE %1, !"a", ...
187       //   INST0 ..., $1 ...
188       //  bb1:
189       //   %2 = CONST_I32 1
190       //   DBG_VALUE %2, !"a", ... // !!!
191       //   INST1 ..., $2 ...
192       //   %3 = CONST_I32 1
193       //   DBG_VALUE %3, !"a", ... // !!!
194       //   INST2 ..., $3 ...
195       //
196       // But (without this exception) the cloned DBG_VALUEs marked with !!! are
197       // not possible to be cloned, because there is a previously cloned
198       // 'DBG_VALUE %1, !"a"' at the end of bb0 referring to the same
199       // DebugVariable "a". But in this case they are OK to be cloned, because
200       // the interfering DBG_VALUE is pointing to the same 'CONST_I32 1',
201       // because it was cloned from the same instruction.
202       if (!OtherDef || !isSameScalarConst(Def, OtherDef)) {
203         Sinkable = false;
204         break;
205       }
206     }
207     if (Sinkable)
208       SinkableDbgValues.push_back(DV);
209   }
210   return SinkableDbgValues;
211 }
212 
213 // Returns true if the insertion point is the same as the current place.
214 // Following DBG_VALUEs for 'Def' are ignored.
215 bool WebAssemblyDebugValueManager::isInsertSamePlace(
216     MachineInstr *Insert) const {
217   if (Def->getParent() != Insert->getParent())
218     return false;
219   for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
220                                    ME = Insert;
221        MI != ME; ++MI) {
222     if (std::find(DbgValues.begin(), DbgValues.end(), MI) == DbgValues.end()) {
223       return false;
224     }
225   }
226   return true;
227 }
228 
229 // Sink 'Def', and also sink its eligible DBG_VALUEs to the place before
230 // 'Insert'. Convert the original DBG_VALUEs into undefs.
231 //
232 // For DBG_VALUEs to sink properly, if 'Def' and 'Insert' are within the same
233 // BB, 'Insert' should be below 'Def'; if they are in different BBs, 'Insert'
234 // should be in one of 'Def's BBs successors. Def will be sunk regardless of the
235 // location.
236 //
237 // This DebugValueManager's new Def and DbgValues will be updated to the newly
238 // sinked Def + DBG_VALUEs.
239 void WebAssemblyDebugValueManager::sink(MachineInstr *Insert) {
240   // In case Def is requested to be sunk to
241   // the same place, we don't need to do anything. If we actually do the sink,
242   // it will create unnecessary undef DBG_VALUEs. For example, if the original
243   // code is:
244   //   %0 = someinst           // Def
245   //   DBG_VALUE %0, ...
246   //   %1 = anotherinst        // Insert
247   //
248   // If we actually sink %0 and the following DBG_VALUE and setting the original
249   // DBG_VALUE undef, the result will be:
250   //   DBG_VALUE %noreg, ...   // Unnecessary!
251   //   %0 = someinst           // Def
252   //   DBG_VALUE %0, ...
253   //   %1 = anotherinst        // Insert
254   if (isInsertSamePlace(Insert))
255     return;
256 
257   MachineBasicBlock *MBB = Insert->getParent();
258   MachineFunction *MF = MBB->getParent();
259 
260   // Get the list of sinkable DBG_VALUEs. This should be done before sinking
261   // Def, because we need to examine instructions between Def and Insert.
262   SmallVector<MachineInstr *, 1> SinkableDbgValues =
263       getSinkableDebugValues(Insert);
264 
265   // Sink Def first.
266   MBB->splice(Insert, Def->getParent(), Def);
267 
268   if (DbgValues.empty())
269     return;
270 
271   // Clone sinkable DBG_VALUEs and insert them.
272   SmallVector<MachineInstr *, 1> NewDbgValues;
273   for (MachineInstr *DV : SinkableDbgValues) {
274     MachineInstr *Clone = MF->CloneMachineInstr(DV);
275     MBB->insert(Insert, Clone);
276     NewDbgValues.push_back(Clone);
277   }
278 
279   // When sinking a Def and its DBG_VALUEs, we shouldn't just remove the
280   // original DBG_VALUE instructions; we should set them to undef not to create
281   // an impossible combination of variable assignments in the original program.
282   // For example, this is the original program in order:
283   //   %0 = CONST_I32 0
284   //   DBG_VALUE %0, !"a", !DIExpression()  // a = 0, b = ?
285   //   %1 = CONST_I32 1
286   //   DBG_VALUE %1, !"b", !DIExpression()  // a = 0, b = 1
287   //   %2 = CONST_I32 2
288   //   DBG_VALUE %2, !"a", !DIExpression()  // a = 2, b = 1
289   //   %3 = CONST_I32 3
290   //   DBG_VALUE %3, !"b", !DIExpression()  // a = 2, b = 3
291   //
292   // If %2 were to sink below %3, if we just sink DBG_VALUE %1 with it, the
293   // debug info will show the variable "b" is updated to 2, creating the
294   // variable assignment combination of (a = 0, b = 3), which is not possible in
295   // the original program:
296   //   %0 = CONST_I32 0
297   //   DBG_VALUE %0, !"a", !DIExpression()  // a = 0, b = ?
298   //   %1 = CONST_I32 1
299   //   DBG_VALUE %1, !"b", !DIExpression()  // a = 0, b = 1
300   //   %3 = CONST_I32 3
301   //   DBG_VALUE %3, !"b", !DIExpression()  // a = 0, b = 3 (Incorrect!)
302   //   %2 = CONST_I32 2
303   //   DBG_VALUE %2, !"a", !DIExpression()  // a = 2, b = 3
304   //
305   // To fix this,we leave an undef DBG_VALUE in its original place, so that the
306   // result will be
307   //   %0 = CONST_I32 0
308   //   DBG_VALUE %0, !"a", !DIExpression()      // a = 0, b = ?
309   //   %1 = CONST_I32 1
310   //   DBG_VALUE %1, !"b", !DIExpression()      // a = 0, b = 1
311   //   DBG_VALUE $noreg, !"a", !DIExpression()  // a = ?, b = 1
312   //   %3 = CONST_I32 3
313   //   DBG_VALUE %3, !"b", !DIExpression()      // a = ?, b = 3
314   //   %2 = CONST_I32 2
315   //   DBG_VALUE %2, !"a", !DIExpression()      // a = 2, b = 3
316   // Now in the middle "a" will be shown as "optimized out", but it wouldn't
317   // show the impossible combination of (a = 0, b = 3).
318   for (MachineInstr *DV : DbgValues)
319     DV->setDebugValueUndef();
320 
321   DbgValues.swap(NewDbgValues);
322   return;
323 }
324 
325 // Clone 'Def', and also clone its eligible DBG_VALUEs to the place before
326 // 'Insert'.
327 //
328 // For DBG_VALUEs to be cloned properly, if 'Def' and 'Insert' are within the
329 // same BB, 'Insert' should be below 'Def'; if they are in different BBs,
330 // 'Insert' should be in one of 'Def's BBs successors. Def will be cloned
331 // regardless of the location.
332 //
333 // If NewReg is not $noreg, the newly cloned DBG_VALUEs will have the new
334 // register as its operand.
335 void WebAssemblyDebugValueManager::cloneSink(MachineInstr *Insert,
336                                              Register NewReg,
337                                              bool CloneDef) const {
338   MachineBasicBlock *MBB = Insert->getParent();
339   MachineFunction *MF = MBB->getParent();
340 
341   SmallVector<MachineInstr *> SinkableDbgValues =
342       getSinkableDebugValues(Insert);
343 
344   // Clone Def first.
345   if (CloneDef) {
346     MachineInstr *Clone = MF->CloneMachineInstr(Def);
347     if (NewReg != CurrentReg && NewReg.isValid())
348       Clone->getOperand(0).setReg(NewReg);
349     MBB->insert(Insert, Clone);
350   }
351 
352   if (DbgValues.empty())
353     return;
354 
355   // Clone sinkable DBG_VALUEs and insert them.
356   SmallVector<MachineInstr *, 1> NewDbgValues;
357   for (MachineInstr *DV : SinkableDbgValues) {
358     MachineInstr *Clone = MF->CloneMachineInstr(DV);
359     MBB->insert(Insert, Clone);
360     NewDbgValues.push_back(Clone);
361   }
362 
363   if (NewReg != CurrentReg && NewReg.isValid())
364     for (auto *DBI : NewDbgValues)
365       for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
366         MO.setReg(NewReg);
367 }
368 
369 // Update the register for Def and DBG_VALUEs.
370 void WebAssemblyDebugValueManager::updateReg(Register Reg) {
371   if (Reg != CurrentReg && Reg.isValid()) {
372     for (auto *DBI : DbgValues)
373       for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
374         MO.setReg(Reg);
375     CurrentReg = Reg;
376     Def->getOperand(0).setReg(Reg);
377   }
378 }
379 
380 void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) {
381   for (auto *DBI : DbgValues) {
382     auto IndexType = DBI->isIndirectDebugValue()
383                          ? llvm::WebAssembly::TI_LOCAL_INDIRECT
384                          : llvm::WebAssembly::TI_LOCAL;
385     for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
386       MO.ChangeToTargetIndex(IndexType, LocalId);
387   }
388 }
389 
390 // Remove Def, and set its DBG_VALUEs to undef.
391 void WebAssemblyDebugValueManager::removeDef() {
392   Def->removeFromParent();
393   for (MachineInstr *DV : DbgValues)
394     DV->setDebugValueUndef();
395 }
396