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