LLVM 17.0.0git
WebAssemblyDebugValueManager.cpp
Go to the documentation of this file.
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
16#include "WebAssembly.h"
19
20using namespace llvm;
21
23 : Def(Def) {
24 // This code differs from MachineInstr::collectDebugValues in that it scans
25 // the whole BB, not just contiguous DBG_VALUEs, until another definition to
26 // the same register is encountered.
27 if (!Def->getOperand(0).isReg())
28 return;
29 CurrentReg = Def->getOperand(0).getReg();
30
31 for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
32 ME = Def->getParent()->end();
33 MI != ME; ++MI) {
34 // If another definition appears, stop
35 if (MI->definesRegister(CurrentReg))
36 break;
37 if (MI->isDebugValue() && MI->hasDebugOperandForReg(CurrentReg))
38 DbgValues.push_back(&*MI);
39 }
40}
41
42// Returns true if both A and B are the same CONST_I32/I64/F32/F64 instructions.
43// Doesn't include CONST_V128.
44static bool isSameScalarConst(const MachineInstr *A, const MachineInstr *B) {
45 if (A->getOpcode() != B->getOpcode() ||
46 !WebAssembly::isScalarConst(A->getOpcode()) ||
47 !WebAssembly::isScalarConst(B->getOpcode()))
48 return false;
49 const MachineOperand &OpA = A->getOperand(1), &OpB = B->getOperand(1);
50 if ((OpA.isImm() && OpB.isImm() && OpA.getImm() == OpB.getImm()) ||
51 (OpA.isFPImm() && OpB.isFPImm() && OpA.getFPImm() == OpB.getFPImm()) ||
52 (OpA.isGlobal() && OpB.isGlobal() && OpA.getGlobal() == OpB.getGlobal()))
53 return true;
54 return false;
55}
56
58WebAssemblyDebugValueManager::getSinkableDebugValues(
59 MachineInstr *Insert) const {
60 if (DbgValues.empty())
61 return {};
62 // DBG_VALUEs between Def and Insert
63 SmallVector<MachineInstr *, 8> DbgValuesInBetween;
64
65 if (Def->getParent() == Insert->getParent()) {
66 // When Def and Insert are within the same BB, check if Insert comes after
67 // Def, because we only support sinking.
68 bool DefFirst = false;
69 for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
70 ME = Def->getParent()->end();
71 MI != ME; ++MI) {
72 if (&*MI == Insert) {
73 DefFirst = true;
74 break;
75 }
76 if (MI->isDebugValue())
77 DbgValuesInBetween.push_back(&*MI);
78 }
79 if (!DefFirst) // Not a sink
80 return {};
81
82 } else { // Def and Insert are in different BBs
83 // If Def and Insert are in different BBs, we only handle a simple case in
84 // which Insert's BB is a successor of Def's BB.
85 if (!Def->getParent()->isSuccessor(Insert->getParent()))
86 return {};
87
88 // Gather DBG_VALUEs between 'Def~Def BB's end' and
89 // 'Insert BB's begin~Insert'
90 for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
91 ME = Def->getParent()->end();
92 MI != ME; ++MI) {
93 if (MI->isDebugValue())
94 DbgValuesInBetween.push_back(&*MI);
95 }
96 for (MachineBasicBlock::iterator MI = Insert->getParent()->begin(),
97 ME = Insert->getIterator();
98 MI != ME; ++MI) {
99 if (MI->isDebugValue())
100 DbgValuesInBetween.push_back(&*MI);
101 }
102 }
103
104 // Gather DebugVariables that are seen between Def and Insert, excluding our
105 // own DBG_VALUEs in DbgValues.
107 SeenDbgVarToDbgValues;
108 for (auto *DV : DbgValuesInBetween) {
109 if (std::find(DbgValues.begin(), DbgValues.end(), DV) == DbgValues.end()) {
110 DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
111 DV->getDebugLoc()->getInlinedAt());
112 SeenDbgVarToDbgValues[Var].push_back(DV);
113 }
114 }
115
116 // Gather sinkable DBG_VALUEs. We should not sink a DBG_VALUE if there is
117 // another DBG_VALUE between Def and Insert referring to the same
118 // DebugVariable. For example,
119 // %0 = someinst
120 // DBG_VALUE %0, !"a", !DIExpression() // Should not sink with %0
121 // %1 = anotherinst
122 // DBG_VALUE %1, !"a", !DIExpression()
123 // Where if %0 were to sink, the DBG_VAUE should not sink with it, as that
124 // would re-order assignments.
125 SmallVector<MachineInstr *, 1> SinkableDbgValues;
127 for (auto *DV : DbgValues) {
128 DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
129 DV->getDebugLoc()->getInlinedAt());
130 auto It = SeenDbgVarToDbgValues.find(Var);
131 if (It == SeenDbgVarToDbgValues.end()) {
132 SinkableDbgValues.push_back(DV);
133 continue;
134 }
136 continue;
137 auto &OverlappingDbgValues = It->second;
138 bool Sinkable = true;
139 for (auto *OverlappingDV : OverlappingDbgValues) {
140 MachineOperand &DbgOp = OverlappingDV->getDebugOperand(0);
141 if (!DbgOp.isReg()) {
142 Sinkable = false;
143 break;
144 }
145 Register OtherReg = DbgOp.getReg();
146 MachineInstr *OtherDef = MRI.getUniqueVRegDef(OtherReg);
147 // We have an exception to allow encoutering other DBG_VALUEs with the
148 // smae DebugVariables, only when they are referring to the same scalar
149 // CONST instruction. For example,
150 // %0 = CONST_I32 1
151 // DBG_VALUE %0, !"a", !DIExpression() // Can sink with %0
152 // %1 = CONST_I32 1
153 // DBG_VALUE %1, !"a", !DIExpression()
154 // When %0 were to be sunk/cloneed, the DBG_VALUE can be sunk/cloned with
155 // it because even though the second DBG_VALUE refers to the same
156 // DebugVariable, its value in effect is the same CONST instruction.
157 //
158 // This is to allow a case that can happen with RegStackify's
159 // "rematerializeCheapDef". For example, we have this program with two
160 // BBs:
161 // bb0:
162 // %0 = CONST_I32 1
163 // DBG_VALUE %0, !"a", ...
164 // ...
165 // INST0 ..., $0 ...
166 // bb1:
167 // INST1 ..., $0 ...
168 // INST2 ..., $0 ...
169 //
170 // We process bb0 first. Because %0 is used multiple times, %0 is cloned
171 // before INST0:
172 // bb0:
173 // %0 = CONST_I32 1
174 // DBG_VALUE %0, !"a", ...
175 // ...
176 // %1 = CONST_I32 1
177 // DBG_VALUE %1, !"a", ...
178 // INST0 ..., $1 ...
179 //
180 // And when we process bb1, we clone %0 and its DBG_VALUE again:
181 // bb0:
182 // %0 = CONST_I32 1
183 // DBG_VALUE %0, !"a", ...
184 // ...
185 // %1 = CONST_I32 1
186 // DBG_VALUE %1, !"a", ...
187 // INST0 ..., $1 ...
188 // bb1:
189 // %2 = CONST_I32 1
190 // DBG_VALUE %2, !"a", ... // !!!
191 // INST1 ..., $2 ...
192 // %3 = CONST_I32 1
193 // DBG_VALUE %3, !"a", ... // !!!
194 // INST2 ..., $3 ...
195 //
196 // But (without this exception) the cloned DBG_VALUEs marked with !!! are
197 // not possible to be cloned, because there is a previously cloned
198 // 'DBG_VALUE %1, !"a"' at the end of bb0 referring to the same
199 // DebugVariable "a". But in this case they are OK to be cloned, because
200 // the interfering DBG_VALUE is pointing to the same 'CONST_I32 1',
201 // because it was cloned from the same instruction.
202 if (!OtherDef || !isSameScalarConst(Def, OtherDef)) {
203 Sinkable = false;
204 break;
205 }
206 }
207 if (Sinkable)
208 SinkableDbgValues.push_back(DV);
209 }
210 return SinkableDbgValues;
211}
212
213// Returns true if the insertion point is the same as the current place.
214// Following DBG_VALUEs for 'Def' are ignored.
215bool WebAssemblyDebugValueManager::isInsertSamePlace(
216 MachineInstr *Insert) const {
217 if (Def->getParent() != Insert->getParent())
218 return false;
219 for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
220 ME = Insert;
221 MI != ME; ++MI) {
222 if (std::find(DbgValues.begin(), DbgValues.end(), MI) == DbgValues.end()) {
223 return false;
224 }
225 }
226 return true;
227}
228
229// Sink 'Def', and also sink its eligible DBG_VALUEs to the place before
230// 'Insert'. Convert the original DBG_VALUEs into undefs.
231//
232// For DBG_VALUEs to sink properly, if 'Def' and 'Insert' are within the same
233// BB, 'Insert' should be below 'Def'; if they are in different BBs, 'Insert'
234// should be in one of 'Def's BBs successors. Def will be sunk regardless of the
235// location.
236//
237// This DebugValueManager's new Def and DbgValues will be updated to the newly
238// sinked Def + DBG_VALUEs.
240 // In case Def is requested to be sunk to
241 // the same place, we don't need to do anything. If we actually do the sink,
242 // it will create unnecessary undef DBG_VALUEs. For example, if the original
243 // code is:
244 // %0 = someinst // Def
245 // DBG_VALUE %0, ...
246 // %1 = anotherinst // Insert
247 //
248 // If we actually sink %0 and the following DBG_VALUE and setting the original
249 // DBG_VALUE undef, the result will be:
250 // DBG_VALUE %noreg, ... // Unnecessary!
251 // %0 = someinst // Def
252 // DBG_VALUE %0, ...
253 // %1 = anotherinst // Insert
254 if (isInsertSamePlace(Insert))
255 return;
256
257 MachineBasicBlock *MBB = Insert->getParent();
259
260 // Get the list of sinkable DBG_VALUEs. This should be done before sinking
261 // Def, because we need to examine instructions between Def and Insert.
262 SmallVector<MachineInstr *, 1> SinkableDbgValues =
263 getSinkableDebugValues(Insert);
264
265 // Sink Def first.
266 MBB->splice(Insert, Def->getParent(), Def);
267
268 if (DbgValues.empty())
269 return;
270
271 // Clone sinkable DBG_VALUEs and insert them.
273 for (MachineInstr *DV : SinkableDbgValues) {
274 MachineInstr *Clone = MF->CloneMachineInstr(DV);
275 MBB->insert(Insert, Clone);
276 NewDbgValues.push_back(Clone);
277 }
278
279 // When sinking a Def and its DBG_VALUEs, we shouldn't just remove the
280 // original DBG_VALUE instructions; we should set them to undef not to create
281 // an impossible combination of variable assignments in the original program.
282 // For example, this is the original program in order:
283 // %0 = CONST_I32 0
284 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ?
285 // %1 = CONST_I32 1
286 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1
287 // %2 = CONST_I32 2
288 // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 1
289 // %3 = CONST_I32 3
290 // DBG_VALUE %3, !"b", !DIExpression() // a = 2, b = 3
291 //
292 // If %2 were to sink below %3, if we just sink DBG_VALUE %1 with it, the
293 // debug info will show the variable "b" is updated to 2, creating the
294 // variable assignment combination of (a = 0, b = 3), which is not possible in
295 // the original program:
296 // %0 = CONST_I32 0
297 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ?
298 // %1 = CONST_I32 1
299 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1
300 // %3 = CONST_I32 3
301 // DBG_VALUE %3, !"b", !DIExpression() // a = 0, b = 3 (Incorrect!)
302 // %2 = CONST_I32 2
303 // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 3
304 //
305 // To fix this,we leave an undef DBG_VALUE in its original place, so that the
306 // result will be
307 // %0 = CONST_I32 0
308 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ?
309 // %1 = CONST_I32 1
310 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1
311 // DBG_VALUE $noreg, !"a", !DIExpression() // a = ?, b = 1
312 // %3 = CONST_I32 3
313 // DBG_VALUE %3, !"b", !DIExpression() // a = ?, b = 3
314 // %2 = CONST_I32 2
315 // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 3
316 // Now in the middle "a" will be shown as "optimized out", but it wouldn't
317 // show the impossible combination of (a = 0, b = 3).
318 for (MachineInstr *DV : DbgValues)
319 DV->setDebugValueUndef();
320
321 DbgValues.swap(NewDbgValues);
322 return;
323}
324
325// Clone 'Def', and also clone its eligible DBG_VALUEs to the place before
326// 'Insert'.
327//
328// For DBG_VALUEs to be cloned properly, if 'Def' and 'Insert' are within the
329// same BB, 'Insert' should be below 'Def'; if they are in different BBs,
330// 'Insert' should be in one of 'Def's BBs successors. Def will be cloned
331// regardless of the location.
332//
333// If NewReg is not $noreg, the newly cloned DBG_VALUEs will have the new
334// register as its operand.
336 Register NewReg,
337 bool CloneDef) const {
338 MachineBasicBlock *MBB = Insert->getParent();
340
341 SmallVector<MachineInstr *> SinkableDbgValues =
342 getSinkableDebugValues(Insert);
343
344 // Clone Def first.
345 if (CloneDef) {
346 MachineInstr *Clone = MF->CloneMachineInstr(Def);
347 if (NewReg != CurrentReg && NewReg.isValid())
348 Clone->getOperand(0).setReg(NewReg);
349 MBB->insert(Insert, Clone);
350 }
351
352 if (DbgValues.empty())
353 return;
354
355 // Clone sinkable DBG_VALUEs and insert them.
357 for (MachineInstr *DV : SinkableDbgValues) {
358 MachineInstr *Clone = MF->CloneMachineInstr(DV);
359 MBB->insert(Insert, Clone);
360 NewDbgValues.push_back(Clone);
361 }
362
363 if (NewReg != CurrentReg && NewReg.isValid())
364 for (auto *DBI : NewDbgValues)
365 for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
366 MO.setReg(NewReg);
367}
368
369// Update the register for Def and DBG_VALUEs.
371 if (Reg != CurrentReg && Reg.isValid()) {
372 for (auto *DBI : DbgValues)
373 for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
374 MO.setReg(Reg);
375 CurrentReg = Reg;
376 Def->getOperand(0).setReg(Reg);
377 }
378}
379
381 for (auto *DBI : DbgValues) {
382 auto IndexType = DBI->isIndirectDebugValue()
385 for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
386 MO.ChangeToTargetIndex(IndexType, LocalId);
387 }
388}
389
390// Remove Def, and set its DBG_VALUEs to undef.
392 Def->removeFromParent();
393 for (MachineInstr *DV : DbgValues)
394 DV->setDebugValueUndef();
395}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
static bool isSameScalarConst(const MachineInstr *A, const MachineInstr *B)
This file contains the declaration of the WebAssembly-specific manager for DebugValues associated wit...
This file provides WebAssembly-specific target descriptions.
This file declares WebAssembly-specific per-machine-function information.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
Identifies a unique instance of a variable.
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
iterator end()
Definition: DenseMap.h:84
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineInstr * CloneMachineInstr(const MachineInstr *Orig)
Create a new MachineInstr which is a copy of Orig, identical in all ways except the instruction has n...
Representation of each machine instruction.
Definition: MachineInstr.h:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:516
void setDebugValueUndef()
Sets all register debug operands in this debug value instruction to be undef.
MachineInstr * removeFromParent()
Unlink 'this' from the containing basic block, and return it without deleting it.
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:313
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:526
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const ConstantFP * getFPImm() const
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
bool isValid() const
Definition: Register.h:126
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
void cloneSink(MachineInstr *Insert, Register NewReg=Register(), bool CloneDef=true) const
self_iterator getIterator()
Definition: ilist_node.h:82
bool isScalarConst(unsigned Opc)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
TODO: Might pack better if we changed this to a Struct of Arrays, since MachineOperand is width 32,...