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