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 | |
22 | using namespace llvm; |
23 | |
24 | WebAssemblyDebugValueManager::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. |
49 | static 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 | |
62 | SmallVector<MachineInstr *, 1> |
63 | WebAssemblyDebugValueManager::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. |
220 | bool 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. |
236 | static 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. |
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 |
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. |
354 | void 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. |
394 | void 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 | |
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(Reg: CurrentReg)) |
410 | MO.ChangeToTargetIndex(Idx: IndexType, Offset: LocalId); |
411 | } |
412 | } |
413 | |
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(); |
419 | } |
420 | |