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