Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
Line
Count
Source (jump to first uncovered line)
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
54.3k
    : Def(Def) {
26
54.3k
  if (!Def->getMF()->getFunction().getSubprogram())
27
49.5k
    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
4.82k
  if (!Def->getOperand(0).isReg())
33
0
    return;
34
4.82k
  CurrentReg = Def->getOperand(0).getReg();
35
36
4.82k
  for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
37
4.82k
                                   ME = Def->getParent()->end();
38
292k
       MI != ME; ++MI) {
39
    // If another definition appears, stop
40
287k
    if (MI->definesRegister(CurrentReg))
41
65
      break;
42
287k
    if (MI->isDebugValue() && MI->hasDebugOperandForReg(CurrentReg))
43
9
      DbgValues.push_back(&*MI);
44
287k
  }
45
4.82k
}
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
0
static bool isSameScalarConst(const MachineInstr *A, const MachineInstr *B) {
50
0
  if (A->getOpcode() != B->getOpcode() ||
51
0
      !WebAssembly::isScalarConst(A->getOpcode()) ||
52
0
      !WebAssembly::isScalarConst(B->getOpcode()))
53
0
    return false;
54
0
  const MachineOperand &OpA = A->getOperand(1), &OpB = B->getOperand(1);
55
0
  if ((OpA.isImm() && OpB.isImm() && OpA.getImm() == OpB.getImm()) ||
56
0
      (OpA.isFPImm() && OpB.isFPImm() && OpA.getFPImm() == OpB.getFPImm()) ||
57
0
      (OpA.isGlobal() && OpB.isGlobal() && OpA.getGlobal() == OpB.getGlobal()))
58
0
    return true;
59
0
  return false;
60
0
}
61
62
SmallVector<MachineInstr *, 1>
63
WebAssemblyDebugValueManager::getSinkableDebugValues(
64
16.4k
    MachineInstr *Insert) const {
65
16.4k
  if (DbgValues.empty())
66
16.4k
    return {};
67
  // DBG_VALUEs between Def and Insert
68
6
  SmallVector<MachineInstr *, 8> DbgValuesInBetween;
69
70
6
  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
6
    bool DefFirst = false;
74
6
    for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
75
6
                                     ME = Def->getParent()->end();
76
66
         MI != ME; ++MI) {
77
66
      if (&*MI == Insert) {
78
6
        DefFirst = true;
79
6
        break;
80
6
      }
81
60
      if (MI->isDebugValue())
82
3
        DbgValuesInBetween.push_back(&*MI);
83
60
    }
84
6
    if (!DefFirst) // Not a sink
85
0
      return {};
86
87
6
  } 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
0
    if (!Def->getParent()->isSuccessor(Insert->getParent()))
91
0
      return {};
92
93
    // Gather DBG_VALUEs between 'Def~Def BB's end' and
94
    // 'Insert BB's begin~Insert'
95
0
    for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
96
0
                                     ME = Def->getParent()->end();
97
0
         MI != ME; ++MI) {
98
0
      if (MI->isDebugValue())
99
0
        DbgValuesInBetween.push_back(&*MI);
100
0
    }
101
0
    for (MachineBasicBlock::iterator MI = Insert->getParent()->begin(),
102
0
                                     ME = Insert->getIterator();
103
0
         MI != ME; ++MI) {
104
0
      if (MI->isDebugValue())
105
0
        DbgValuesInBetween.push_back(&*MI);
106
0
    }
107
0
  }
108
109
  // Gather DebugVariables that are seen between Def and Insert, excluding our
110
  // own DBG_VALUEs in DbgValues.
111
6
  SmallDenseMap<DebugVariable, SmallVector<MachineInstr *, 2>>
112
6
      SeenDbgVarToDbgValues;
113
6
  for (auto *DV : DbgValuesInBetween) {
114
3
    if (!llvm::is_contained(DbgValues, DV)) {
115
0
      DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
116
0
                        DV->getDebugLoc()->getInlinedAt());
117
0
      SeenDbgVarToDbgValues[Var].push_back(DV);
118
0
    }
119
3
  }
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
6
  SmallVector<MachineInstr *, 1> SinkableDbgValues;
131
6
  MachineRegisterInfo &MRI = Def->getParent()->getParent()->getRegInfo();
132
6
  for (auto *DV : DbgValues) {
133
6
    DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
134
6
                      DV->getDebugLoc()->getInlinedAt());
135
6
    auto It = SeenDbgVarToDbgValues.find(Var);
136
6
    if (It == SeenDbgVarToDbgValues.end()) {
137
6
      SinkableDbgValues.push_back(DV);
138
6
      continue;
139
6
    }
140
0
    if (!WebAssembly::isScalarConst(Def->getOpcode()))
141
0
      continue;
142
0
    auto &OverlappingDbgValues = It->second;
143
0
    bool Sinkable = true;
144
0
    for (auto *OverlappingDV : OverlappingDbgValues) {
145
0
      MachineOperand &DbgOp = OverlappingDV->getDebugOperand(0);
146
0
      if (!DbgOp.isReg()) {
147
0
        Sinkable = false;
148
0
        break;
149
0
      }
150
0
      Register OtherReg = DbgOp.getReg();
151
0
      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,
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
0
      if (!OtherDef || !isSameScalarConst(Def, OtherDef)) {
208
0
        Sinkable = false;
209
0
        break;
210
0
      }
211
0
    }
212
0
    if (Sinkable)
213
0
      SinkableDbgValues.push_back(DV);
214
0
  }
215
6
  return SinkableDbgValues;
216
6
}
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
30.4k
    MachineInstr *Insert) const {
222
30.4k
  if (Def->getParent() != Insert->getParent())
223
0
    return false;
224
30.4k
  for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
225
30.4k
                                   ME = Insert;
226
30.4k
       MI != ME; ++MI) {
227
3.99k
    if (!llvm::is_contained(DbgValues, MI)) {
228
3.99k
      return false;
229
3.99k
    }
230
3.99k
  }
231
26.4k
  return true;
232
30.4k
}
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
5.19k
static bool hasSameDebugLoc(const MachineBasicBlock *MBB, DebugLoc DL) {
237
5.19k
  for (const auto &MI : *MBB)
238
5.19k
    if (MI.getDebugLoc() == DL)
239
5.19k
      return true;
240
0
  return false;
241
5.19k
}
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
30.4k
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
30.4k
  if (isInsertSamePlace(Insert))
269
26.4k
    return;
270
271
3.99k
  MachineBasicBlock *MBB = Insert->getParent();
272
3.99k
  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
3.99k
  SmallVector<MachineInstr *, 1> SinkableDbgValues =
277
3.99k
      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
3.99k
  if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
285
0
      Def->setDebugLoc(DebugLoc());
286
3.99k
  MBB->splice(Insert, Def->getParent(), Def);
287
288
3.99k
  if (DbgValues.empty())
289
3.98k
    return;
290
291
  // Clone sinkable DBG_VALUEs and insert them.
292
3
  SmallVector<MachineInstr *, 1> NewDbgValues;
293
3
  for (MachineInstr *DV : SinkableDbgValues) {
294
3
    MachineInstr *Clone = MF->CloneMachineInstr(DV);
295
3
    MBB->insert(Insert, Clone);
296
3
    NewDbgValues.push_back(Clone);
297
3
  }
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
3
  for (MachineInstr *DV : DbgValues)
339
3
    DV->setDebugValueUndef();
340
341
3
  DbgValues.swap(NewDbgValues);
342
3
}
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
12.4k
                                             bool CloneDef) const {
357
12.4k
  MachineBasicBlock *MBB = Insert->getParent();
358
12.4k
  MachineFunction *MF = MBB->getParent();
359
360
12.4k
  SmallVector<MachineInstr *> SinkableDbgValues =
361
12.4k
      getSinkableDebugValues(Insert);
362
363
  // Clone Def first.
364
12.4k
  if (CloneDef) {
365
7.89k
    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
7.89k
    if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
370
0
      Clone->setDebugLoc(DebugLoc());
371
7.89k
    if (NewReg != CurrentReg && NewReg.isValid())
372
7.89k
      Clone->getOperand(0).setReg(NewReg);
373
7.89k
    MBB->insert(Insert, Clone);
374
7.89k
  }
375
376
12.4k
  if (DbgValues.empty())
377
12.4k
    return;
378
379
  // Clone sinkable DBG_VALUEs and insert them.
380
3
  SmallVector<MachineInstr *, 1> NewDbgValues;
381
3
  for (MachineInstr *DV : SinkableDbgValues) {
382
3
    MachineInstr *Clone = MF->CloneMachineInstr(DV);
383
3
    MBB->insert(Insert, Clone);
384
3
    NewDbgValues.push_back(Clone);
385
3
  }
386
387
3
  if (NewReg != CurrentReg && NewReg.isValid())
388
3
    for (auto *DBI : NewDbgValues)
389
3
      for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
390
3
        MO.setReg(NewReg);
391
3
}
392
393
// Update the register for Def and DBG_VALUEs.
394
4.62k
void WebAssemblyDebugValueManager::updateReg(Register Reg) {
395
4.62k
  if (Reg != CurrentReg && Reg.isValid()) {
396
4.62k
    for (auto *DBI : DbgValues)
397
3
      for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
398
3
        MO.setReg(Reg);
399
4.62k
    CurrentReg = Reg;
400
4.62k
    Def->getOperand(0).setReg(Reg);
401
4.62k
  }
402
4.62k
}
403
404
16.0k
void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) {
405
16.0k
  for (auto *DBI : DbgValues) {
406
3
    auto IndexType = DBI->isIndirectDebugValue()
407
3
                         ? llvm::WebAssembly::TI_LOCAL_INDIRECT
408
3
                         : llvm::WebAssembly::TI_LOCAL;
409
3
    for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
410
3
      MO.ChangeToTargetIndex(IndexType, LocalId);
411
3
  }
412
16.0k
}
413
414
// Remove Def, and set its DBG_VALUEs to undef.
415
2.09k
void WebAssemblyDebugValueManager::removeDef() {
416
2.09k
  Def->removeFromParent();
417
2.09k
  for (MachineInstr *DV : DbgValues)
418
0
    DV->setDebugValueUndef();
419
2.09k
}