1 //===-- WebAssemblyDebugValueManager.cpp - WebAssembly DebugValue Manager -===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements the manager for MachineInstr DebugValues.
12 //===----------------------------------------------------------------------===//
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"
24 WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(MachineInstr
*Def
)
26 if (!Def
->getMF()->getFunction().getSubprogram())
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())
34 CurrentReg
= Def
->getOperand(0).getReg();
36 for (MachineBasicBlock::iterator MI
= std::next(Def
->getIterator()),
37 ME
= Def
->getParent()->end();
39 // If another definition appears, stop
40 if (MI
->definesRegister(CurrentReg
, /*TRI=*/nullptr))
42 if (MI
->isDebugValue() && MI
->hasDebugOperandForReg(CurrentReg
))
43 DbgValues
.push_back(&*MI
);
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()))
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()))
62 SmallVector
<MachineInstr
*, 1>
63 WebAssemblyDebugValueManager::getSinkableDebugValues(
64 MachineInstr
*Insert
) const {
65 if (DbgValues
.empty())
67 // DBG_VALUEs between Def and Insert
68 SmallVector
<MachineInstr
*, 8> DbgValuesInBetween
;
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();
81 if (MI
->isDebugValue())
82 DbgValuesInBetween
.push_back(&*MI
);
84 if (!DefFirst
) // Not a sink
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()))
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();
98 if (MI
->isDebugValue())
99 DbgValuesInBetween
.push_back(&*MI
);
101 for (MachineBasicBlock::iterator MI
= Insert
->getParent()->begin(),
102 ME
= Insert
->getIterator();
104 if (MI
->isDebugValue())
105 DbgValuesInBetween
.push_back(&*MI
);
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
);
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,
125 // DBG_VALUE %0, !"a", !DIExpression() // Should not sink with %0
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
);
140 if (!WebAssembly::isScalarConst(Def
->getOpcode()))
142 auto &OverlappingDbgValues
= It
->second
;
143 bool Sinkable
= true;
144 for (auto *OverlappingDV
: OverlappingDbgValues
) {
145 MachineOperand
&DbgOp
= OverlappingDV
->getDebugOperand(0);
146 if (!DbgOp
.isReg()) {
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,
156 // DBG_VALUE %0, !"a", !DIExpression() // Can sink with %0
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.
163 // This is to allow a case that can happen with RegStackify's
164 // "rematerializeCheapDef". For example, we have this program with two
168 // DBG_VALUE %0, !"a", ...
175 // We process bb0 first. Because %0 is used multiple times, %0 is cloned
179 // DBG_VALUE %0, !"a", ...
182 // DBG_VALUE %1, !"a", ...
185 // And when we process bb1, we clone %0 and its DBG_VALUE again:
188 // DBG_VALUE %0, !"a", ...
191 // DBG_VALUE %1, !"a", ...
195 // DBG_VALUE %2, !"a", ... // !!!
198 // DBG_VALUE %3, !"a", ... // !!!
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
)) {
213 SinkableDbgValues
.push_back(DV
);
215 return SinkableDbgValues
;
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())
224 for (MachineBasicBlock::iterator MI
= std::next(Def
->getIterator()),
227 if (!llvm::is_contained(DbgValues
, MI
)) {
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
)
243 // Sink 'Def', and also sink its eligible DBG_VALUEs to the place before
244 // 'Insert'. Convert the original DBG_VALUEs into undefs.
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
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
258 // %0 = someinst // Def
260 // %1 = anotherinst // Insert
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
267 // %1 = anotherinst // Insert
268 if (isInsertSamePlace(Insert
))
271 MachineBasicBlock
*MBB
= Insert
->getParent();
272 MachineFunction
*MF
= MBB
->getParent();
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
);
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
);
288 if (DbgValues
.empty())
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
);
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:
304 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ?
306 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1
308 // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 1
310 // DBG_VALUE %3, !"b", !DIExpression() // a = 2, b = 3
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:
317 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ?
319 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1
321 // DBG_VALUE %3, !"b", !DIExpression() // a = 0, b = 3 (Incorrect!)
323 // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 3
325 // To fix this,we leave an undef DBG_VALUE in its original place, so that the
328 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ?
330 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1
331 // DBG_VALUE $noreg, !"a", !DIExpression() // a = ?, b = 1
333 // DBG_VALUE %3, !"b", !DIExpression() // a = ?, b = 3
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();
341 DbgValues
.swap(NewDbgValues
);
344 // Clone 'Def', and also clone its eligible DBG_VALUEs to the place before
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.
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
,
356 bool CloneDef
) const {
357 MachineBasicBlock
*MBB
= Insert
->getParent();
358 MachineFunction
*MF
= MBB
->getParent();
360 SmallVector
<MachineInstr
*> SinkableDbgValues
=
361 getSinkableDebugValues(Insert
);
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
);
376 if (DbgValues
.empty())
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
);
387 if (NewReg
!= CurrentReg
&& NewReg
.isValid())
388 for (auto *DBI
: NewDbgValues
)
389 for (auto &MO
: DBI
->getDebugOperandsForReg(CurrentReg
))
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
))
400 Def
->getOperand(0).setReg(Reg
);
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
);
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();