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
22using namespace llvm;
23
24WebAssemblyDebugValueManager::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(i: 0).isReg())
33 return;
34 CurrentReg = Def->getOperand(i: 0).getReg();
35
36 for (MachineBasicBlock::iterator MI = std::next(x: Def->getIterator()),
37 ME = Def->getParent()->end();
38 MI != ME; ++MI) {
39 // If another definition appears, stop
40 if (MI->definesRegister(Reg: CurrentReg, /*TRI=*/nullptr))
41 break;
42 if (MI->isDebugValue() && MI->hasDebugOperandForReg(Reg: CurrentReg))
43 DbgValues.push_back(Elt: &*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.
49static bool isSameScalarConst(const MachineInstr *A, const MachineInstr *B) {
50 if (A->getOpcode() != B->getOpcode() ||
51 !WebAssembly::isScalarConst(Opc: A->getOpcode()) ||
52 !WebAssembly::isScalarConst(Opc: B->getOpcode()))
53 return false;
54 const MachineOperand &OpA = A->getOperand(i: 1), &OpB = B->getOperand(i: 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
62SmallVector<MachineInstr *, 1>
63WebAssemblyDebugValueManager::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(x: 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(Elt: &*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(MBB: 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(x: Def->getIterator()),
96 ME = Def->getParent()->end();
97 MI != ME; ++MI) {
98 if (MI->isDebugValue())
99 DbgValuesInBetween.push_back(Elt: &*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(Elt: &*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(Range: DbgValues, Element: DV)) {
115 DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
116 DV->getDebugLoc()->getInlinedAt());
117 SeenDbgVarToDbgValues[Var].push_back(Elt: 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(Val: Var);
136 if (It == SeenDbgVarToDbgValues.end()) {
137 SinkableDbgValues.push_back(Elt: DV);
138 continue;
139 }
140 if (!WebAssembly::isScalarConst(Opc: Def->getOpcode()))
141 continue;
142 auto &OverlappingDbgValues = It->second;
143 bool Sinkable = true;
144 for (auto *OverlappingDV : OverlappingDbgValues) {
145 MachineOperand &DbgOp = OverlappingDV->getDebugOperand(Index: 0);
146 if (!DbgOp.isReg()) {
147 Sinkable = false;
148 break;
149 }
150 Register OtherReg = DbgOp.getReg();
151 MachineInstr *OtherDef = MRI.getUniqueVRegDef(Reg: 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(A: Def, B: OtherDef)) {
208 Sinkable = false;
209 break;
210 }
211 }
212 if (Sinkable)
213 SinkableDbgValues.push_back(Elt: 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.
220bool WebAssemblyDebugValueManager::isInsertSamePlace(
221 MachineInstr *Insert) const {
222 if (Def->getParent() != Insert->getParent())
223 return false;
224 for (MachineBasicBlock::iterator MI = std::next(x: Def->getIterator()),
225 ME = Insert;
226 MI != ME; ++MI) {
227 if (!llvm::is_contained(Range: DbgValues, Element: 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.
236static 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.
253void 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, DL: Def->getDebugLoc()))
285 Def->setDebugLoc(DebugLoc());
286 MBB->splice(Where: Insert, Other: Def->getParent(), From: 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(Orig: DV);
295 MBB->insert(I: Insert, MI: Clone);
296 NewDbgValues.push_back(Elt: 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(RHS&: 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.
354void 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(Orig: 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, DL: Def->getDebugLoc()))
370 Clone->setDebugLoc(DebugLoc());
371 if (NewReg != CurrentReg && NewReg.isValid())
372 Clone->getOperand(i: 0).setReg(NewReg);
373 MBB->insert(I: Insert, MI: 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(Orig: DV);
383 MBB->insert(I: Insert, MI: Clone);
384 NewDbgValues.push_back(Elt: Clone);
385 }
386
387 if (NewReg != CurrentReg && NewReg.isValid())
388 for (auto *DBI : NewDbgValues)
389 for (auto &MO : DBI->getDebugOperandsForReg(Reg: CurrentReg))
390 MO.setReg(NewReg);
391}
392
393// Update the register for Def and DBG_VALUEs.
394void WebAssemblyDebugValueManager::updateReg(Register Reg) {
395 if (Reg != CurrentReg && Reg.isValid()) {
396 for (auto *DBI : DbgValues)
397 for (auto &MO : DBI->getDebugOperandsForReg(Reg: CurrentReg))
398 MO.setReg(Reg);
399 CurrentReg = Reg;
400 Def->getOperand(i: 0).setReg(Reg);
401 }
402}
403
404void 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(Reg: CurrentReg))
410 MO.ChangeToTargetIndex(Idx: IndexType, Offset: LocalId);
411 }
412}
413
414// Remove Def, and set its DBG_VALUEs to undef.
415void WebAssemblyDebugValueManager::removeDef() {
416 Def->removeFromParent();
417 for (MachineInstr *DV : DbgValues)
418 DV->setDebugValueUndef();
419}
420