xref: /llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp (revision b7fb2a3fec7c187d58a6d338ab512d9173bca987)
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 *, 1>
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 // Returns true if any instruction in MBB has the same debug location as DL.
230 // Also returns true if DL is an empty location.
231 static bool hasSameDebugLoc(const MachineBasicBlock *MBB, DebugLoc DL) {
232   for (const auto &MI : *MBB)
233     if (MI.getDebugLoc() == DL)
234       return true;
235   return false;
236 }
237 
238 // Sink 'Def', and also sink its eligible DBG_VALUEs to the place before
239 // 'Insert'. Convert the original DBG_VALUEs into undefs.
240 //
241 // For DBG_VALUEs to sink properly, if 'Def' and 'Insert' are within the same
242 // BB, 'Insert' should be below 'Def'; if they are in different BBs, 'Insert'
243 // should be in one of 'Def's BBs successors. Def will be sunk regardless of the
244 // location.
245 //
246 // This DebugValueManager's new Def and DbgValues will be updated to the newly
247 // sinked Def + DBG_VALUEs.
248 void WebAssemblyDebugValueManager::sink(MachineInstr *Insert) {
249   // In case Def is requested to be sunk to
250   // the same place, we don't need to do anything. If we actually do the sink,
251   // it will create unnecessary undef DBG_VALUEs. For example, if the original
252   // code is:
253   //   %0 = someinst           // Def
254   //   DBG_VALUE %0, ...
255   //   %1 = anotherinst        // Insert
256   //
257   // If we actually sink %0 and the following DBG_VALUE and setting the original
258   // DBG_VALUE undef, the result will be:
259   //   DBG_VALUE %noreg, ...   // Unnecessary!
260   //   %0 = someinst           // Def
261   //   DBG_VALUE %0, ...
262   //   %1 = anotherinst        // Insert
263   if (isInsertSamePlace(Insert))
264     return;
265 
266   MachineBasicBlock *MBB = Insert->getParent();
267   MachineFunction *MF = MBB->getParent();
268 
269   // Get the list of sinkable DBG_VALUEs. This should be done before sinking
270   // Def, because we need to examine instructions between Def and Insert.
271   SmallVector<MachineInstr *, 1> SinkableDbgValues =
272       getSinkableDebugValues(Insert);
273 
274   // Sink Def first.
275   //
276   // When moving to a different BB, we preserve the debug loc only if the
277   // destination BB contains the same location. See
278   // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location.
279   if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
280       Def->setDebugLoc(DebugLoc());
281   MBB->splice(Insert, Def->getParent(), Def);
282 
283   if (DbgValues.empty())
284     return;
285 
286   // Clone sinkable DBG_VALUEs and insert them.
287   SmallVector<MachineInstr *, 1> NewDbgValues;
288   for (MachineInstr *DV : SinkableDbgValues) {
289     MachineInstr *Clone = MF->CloneMachineInstr(DV);
290     MBB->insert(Insert, Clone);
291     NewDbgValues.push_back(Clone);
292   }
293 
294   // When sinking a Def and its DBG_VALUEs, we shouldn't just remove the
295   // original DBG_VALUE instructions; we should set them to undef not to create
296   // an impossible combination of variable assignments in the original program.
297   // For example, this is the original program in order:
298   //   %0 = CONST_I32 0
299   //   DBG_VALUE %0, !"a", !DIExpression()  // a = 0, b = ?
300   //   %1 = CONST_I32 1
301   //   DBG_VALUE %1, !"b", !DIExpression()  // a = 0, b = 1
302   //   %2 = CONST_I32 2
303   //   DBG_VALUE %2, !"a", !DIExpression()  // a = 2, b = 1
304   //   %3 = CONST_I32 3
305   //   DBG_VALUE %3, !"b", !DIExpression()  // a = 2, b = 3
306   //
307   // If %2 were to sink below %3, if we just sink DBG_VALUE %1 with it, the
308   // debug info will show the variable "b" is updated to 2, creating the
309   // variable assignment combination of (a = 0, b = 3), which is not possible in
310   // the original program:
311   //   %0 = CONST_I32 0
312   //   DBG_VALUE %0, !"a", !DIExpression()  // a = 0, b = ?
313   //   %1 = CONST_I32 1
314   //   DBG_VALUE %1, !"b", !DIExpression()  // a = 0, b = 1
315   //   %3 = CONST_I32 3
316   //   DBG_VALUE %3, !"b", !DIExpression()  // a = 0, b = 3 (Incorrect!)
317   //   %2 = CONST_I32 2
318   //   DBG_VALUE %2, !"a", !DIExpression()  // a = 2, b = 3
319   //
320   // To fix this,we leave an undef DBG_VALUE in its original place, so that the
321   // result will be
322   //   %0 = CONST_I32 0
323   //   DBG_VALUE %0, !"a", !DIExpression()      // a = 0, b = ?
324   //   %1 = CONST_I32 1
325   //   DBG_VALUE %1, !"b", !DIExpression()      // a = 0, b = 1
326   //   DBG_VALUE $noreg, !"a", !DIExpression()  // a = ?, b = 1
327   //   %3 = CONST_I32 3
328   //   DBG_VALUE %3, !"b", !DIExpression()      // a = ?, b = 3
329   //   %2 = CONST_I32 2
330   //   DBG_VALUE %2, !"a", !DIExpression()      // a = 2, b = 3
331   // Now in the middle "a" will be shown as "optimized out", but it wouldn't
332   // show the impossible combination of (a = 0, b = 3).
333   for (MachineInstr *DV : DbgValues)
334     DV->setDebugValueUndef();
335 
336   DbgValues.swap(NewDbgValues);
337 }
338 
339 // Clone 'Def', and also clone its eligible DBG_VALUEs to the place before
340 // 'Insert'.
341 //
342 // For DBG_VALUEs to be cloned properly, if 'Def' and 'Insert' are within the
343 // same BB, 'Insert' should be below 'Def'; if they are in different BBs,
344 // 'Insert' should be in one of 'Def's BBs successors. Def will be cloned
345 // regardless of the location.
346 //
347 // If NewReg is not $noreg, the newly cloned DBG_VALUEs will have the new
348 // register as its operand.
349 void WebAssemblyDebugValueManager::cloneSink(MachineInstr *Insert,
350                                              Register NewReg,
351                                              bool CloneDef) const {
352   MachineBasicBlock *MBB = Insert->getParent();
353   MachineFunction *MF = MBB->getParent();
354 
355   SmallVector<MachineInstr *> SinkableDbgValues =
356       getSinkableDebugValues(Insert);
357 
358   // Clone Def first.
359   if (CloneDef) {
360     MachineInstr *Clone = MF->CloneMachineInstr(Def);
361     // When cloning to a different BB, we preserve the debug loc only if the
362     // destination BB contains the same location. See
363     // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location.
364     if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
365       Clone->setDebugLoc(DebugLoc());
366     if (NewReg != CurrentReg && NewReg.isValid())
367       Clone->getOperand(0).setReg(NewReg);
368     MBB->insert(Insert, Clone);
369   }
370 
371   if (DbgValues.empty())
372     return;
373 
374   // Clone sinkable DBG_VALUEs and insert them.
375   SmallVector<MachineInstr *, 1> NewDbgValues;
376   for (MachineInstr *DV : SinkableDbgValues) {
377     MachineInstr *Clone = MF->CloneMachineInstr(DV);
378     MBB->insert(Insert, Clone);
379     NewDbgValues.push_back(Clone);
380   }
381 
382   if (NewReg != CurrentReg && NewReg.isValid())
383     for (auto *DBI : NewDbgValues)
384       for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
385         MO.setReg(NewReg);
386 }
387 
388 // Update the register for Def and DBG_VALUEs.
389 void WebAssemblyDebugValueManager::updateReg(Register Reg) {
390   if (Reg != CurrentReg && Reg.isValid()) {
391     for (auto *DBI : DbgValues)
392       for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
393         MO.setReg(Reg);
394     CurrentReg = Reg;
395     Def->getOperand(0).setReg(Reg);
396   }
397 }
398 
399 void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) {
400   for (auto *DBI : DbgValues) {
401     auto IndexType = DBI->isIndirectDebugValue()
402                          ? llvm::WebAssembly::TI_LOCAL_INDIRECT
403                          : llvm::WebAssembly::TI_LOCAL;
404     for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
405       MO.ChangeToTargetIndex(IndexType, LocalId);
406   }
407 }
408 
409 // Remove Def, and set its DBG_VALUEs to undef.
410 void WebAssemblyDebugValueManager::removeDef() {
411   Def->removeFromParent();
412   for (MachineInstr *DV : DbgValues)
413     DV->setDebugValueUndef();
414 }
415