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