xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- WebAssemblyDebugValueManager.cpp - WebAssembly DebugValue Manager -===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements the manager for MachineInstr DebugValues.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "WebAssemblyDebugValueManager.h"
1506c3fb27SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16480093f4SDimitry Andric #include "WebAssembly.h"
170b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
1906c3fb27SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
207a6dacacSDimitry Andric #include "llvm/IR/Function.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
2406c3fb27SDimitry Andric WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(MachineInstr *Def)
2506c3fb27SDimitry Andric     : Def(Def) {
267a6dacacSDimitry Andric   if (!Def->getMF()->getFunction().getSubprogram())
277a6dacacSDimitry Andric     return;
287a6dacacSDimitry Andric 
29e8d8bef9SDimitry Andric   // This code differs from MachineInstr::collectDebugValues in that it scans
3006c3fb27SDimitry Andric   // the whole BB, not just contiguous DBG_VALUEs, until another definition to
3106c3fb27SDimitry Andric   // the same register is encountered.
3206c3fb27SDimitry Andric   if (!Def->getOperand(0).isReg())
33e8d8bef9SDimitry Andric     return;
3406c3fb27SDimitry Andric   CurrentReg = Def->getOperand(0).getReg();
35e8d8bef9SDimitry Andric 
3606c3fb27SDimitry Andric   for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
3706c3fb27SDimitry Andric                                    ME = Def->getParent()->end();
3806c3fb27SDimitry Andric        MI != ME; ++MI) {
3906c3fb27SDimitry Andric     // If another definition appears, stop
40*0fca6ea1SDimitry Andric     if (MI->definesRegister(CurrentReg, /*TRI=*/nullptr))
4106c3fb27SDimitry Andric       break;
4206c3fb27SDimitry Andric     if (MI->isDebugValue() && MI->hasDebugOperandForReg(CurrentReg))
4306c3fb27SDimitry Andric       DbgValues.push_back(&*MI);
44e8d8bef9SDimitry Andric   }
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
4706c3fb27SDimitry Andric // Returns true if both A and B are the same CONST_I32/I64/F32/F64 instructions.
4806c3fb27SDimitry Andric // Doesn't include CONST_V128.
4906c3fb27SDimitry Andric static bool isSameScalarConst(const MachineInstr *A, const MachineInstr *B) {
5006c3fb27SDimitry Andric   if (A->getOpcode() != B->getOpcode() ||
5106c3fb27SDimitry Andric       !WebAssembly::isScalarConst(A->getOpcode()) ||
5206c3fb27SDimitry Andric       !WebAssembly::isScalarConst(B->getOpcode()))
5306c3fb27SDimitry Andric     return false;
5406c3fb27SDimitry Andric   const MachineOperand &OpA = A->getOperand(1), &OpB = B->getOperand(1);
5506c3fb27SDimitry Andric   if ((OpA.isImm() && OpB.isImm() && OpA.getImm() == OpB.getImm()) ||
5606c3fb27SDimitry Andric       (OpA.isFPImm() && OpB.isFPImm() && OpA.getFPImm() == OpB.getFPImm()) ||
5706c3fb27SDimitry Andric       (OpA.isGlobal() && OpB.isGlobal() && OpA.getGlobal() == OpB.getGlobal()))
5806c3fb27SDimitry Andric     return true;
5906c3fb27SDimitry Andric   return false;
6006c3fb27SDimitry Andric }
6106c3fb27SDimitry Andric 
6206c3fb27SDimitry Andric SmallVector<MachineInstr *, 1>
6306c3fb27SDimitry Andric WebAssemblyDebugValueManager::getSinkableDebugValues(
6406c3fb27SDimitry Andric     MachineInstr *Insert) const {
6506c3fb27SDimitry Andric   if (DbgValues.empty())
6606c3fb27SDimitry Andric     return {};
6706c3fb27SDimitry Andric   // DBG_VALUEs between Def and Insert
6806c3fb27SDimitry Andric   SmallVector<MachineInstr *, 8> DbgValuesInBetween;
6906c3fb27SDimitry Andric 
7006c3fb27SDimitry Andric   if (Def->getParent() == Insert->getParent()) {
7106c3fb27SDimitry Andric     // When Def and Insert are within the same BB, check if Insert comes after
7206c3fb27SDimitry Andric     // Def, because we only support sinking.
7306c3fb27SDimitry Andric     bool DefFirst = false;
7406c3fb27SDimitry Andric     for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
7506c3fb27SDimitry Andric                                      ME = Def->getParent()->end();
7606c3fb27SDimitry Andric          MI != ME; ++MI) {
7706c3fb27SDimitry Andric       if (&*MI == Insert) {
7806c3fb27SDimitry Andric         DefFirst = true;
7906c3fb27SDimitry Andric         break;
8006c3fb27SDimitry Andric       }
8106c3fb27SDimitry Andric       if (MI->isDebugValue())
8206c3fb27SDimitry Andric         DbgValuesInBetween.push_back(&*MI);
8306c3fb27SDimitry Andric     }
8406c3fb27SDimitry Andric     if (!DefFirst) // Not a sink
8506c3fb27SDimitry Andric       return {};
8606c3fb27SDimitry Andric 
8706c3fb27SDimitry Andric   } else { // Def and Insert are in different BBs
8806c3fb27SDimitry Andric     // If Def and Insert are in different BBs, we only handle a simple case in
8906c3fb27SDimitry Andric     // which Insert's BB is a successor of Def's BB.
9006c3fb27SDimitry Andric     if (!Def->getParent()->isSuccessor(Insert->getParent()))
9106c3fb27SDimitry Andric       return {};
9206c3fb27SDimitry Andric 
9306c3fb27SDimitry Andric     // Gather DBG_VALUEs between 'Def~Def BB's end' and
9406c3fb27SDimitry Andric     // 'Insert BB's begin~Insert'
9506c3fb27SDimitry Andric     for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
9606c3fb27SDimitry Andric                                      ME = Def->getParent()->end();
9706c3fb27SDimitry Andric          MI != ME; ++MI) {
9806c3fb27SDimitry Andric       if (MI->isDebugValue())
9906c3fb27SDimitry Andric         DbgValuesInBetween.push_back(&*MI);
10006c3fb27SDimitry Andric     }
10106c3fb27SDimitry Andric     for (MachineBasicBlock::iterator MI = Insert->getParent()->begin(),
10206c3fb27SDimitry Andric                                      ME = Insert->getIterator();
10306c3fb27SDimitry Andric          MI != ME; ++MI) {
10406c3fb27SDimitry Andric       if (MI->isDebugValue())
10506c3fb27SDimitry Andric         DbgValuesInBetween.push_back(&*MI);
10606c3fb27SDimitry Andric     }
10706c3fb27SDimitry Andric   }
10806c3fb27SDimitry Andric 
10906c3fb27SDimitry Andric   // Gather DebugVariables that are seen between Def and Insert, excluding our
11006c3fb27SDimitry Andric   // own DBG_VALUEs in DbgValues.
11106c3fb27SDimitry Andric   SmallDenseMap<DebugVariable, SmallVector<MachineInstr *, 2>>
11206c3fb27SDimitry Andric       SeenDbgVarToDbgValues;
11306c3fb27SDimitry Andric   for (auto *DV : DbgValuesInBetween) {
11406c3fb27SDimitry Andric     if (!llvm::is_contained(DbgValues, DV)) {
11506c3fb27SDimitry Andric       DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
11606c3fb27SDimitry Andric                         DV->getDebugLoc()->getInlinedAt());
11706c3fb27SDimitry Andric       SeenDbgVarToDbgValues[Var].push_back(DV);
11806c3fb27SDimitry Andric     }
11906c3fb27SDimitry Andric   }
12006c3fb27SDimitry Andric 
12106c3fb27SDimitry Andric   // Gather sinkable DBG_VALUEs. We should not sink a DBG_VALUE if there is
12206c3fb27SDimitry Andric   // another DBG_VALUE between Def and Insert referring to the same
12306c3fb27SDimitry Andric   // DebugVariable. For example,
12406c3fb27SDimitry Andric   //   %0 = someinst
12506c3fb27SDimitry Andric   //   DBG_VALUE %0, !"a", !DIExpression() // Should not sink with %0
12606c3fb27SDimitry Andric   //   %1 = anotherinst
12706c3fb27SDimitry Andric   //   DBG_VALUE %1, !"a", !DIExpression()
12806c3fb27SDimitry Andric   // Where if %0 were to sink, the DBG_VAUE should not sink with it, as that
12906c3fb27SDimitry Andric   // would re-order assignments.
13006c3fb27SDimitry Andric   SmallVector<MachineInstr *, 1> SinkableDbgValues;
13106c3fb27SDimitry Andric   MachineRegisterInfo &MRI = Def->getParent()->getParent()->getRegInfo();
13206c3fb27SDimitry Andric   for (auto *DV : DbgValues) {
13306c3fb27SDimitry Andric     DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
13406c3fb27SDimitry Andric                       DV->getDebugLoc()->getInlinedAt());
13506c3fb27SDimitry Andric     auto It = SeenDbgVarToDbgValues.find(Var);
13606c3fb27SDimitry Andric     if (It == SeenDbgVarToDbgValues.end()) {
13706c3fb27SDimitry Andric       SinkableDbgValues.push_back(DV);
13806c3fb27SDimitry Andric       continue;
13906c3fb27SDimitry Andric     }
14006c3fb27SDimitry Andric     if (!WebAssembly::isScalarConst(Def->getOpcode()))
14106c3fb27SDimitry Andric       continue;
14206c3fb27SDimitry Andric     auto &OverlappingDbgValues = It->second;
14306c3fb27SDimitry Andric     bool Sinkable = true;
14406c3fb27SDimitry Andric     for (auto *OverlappingDV : OverlappingDbgValues) {
14506c3fb27SDimitry Andric       MachineOperand &DbgOp = OverlappingDV->getDebugOperand(0);
14606c3fb27SDimitry Andric       if (!DbgOp.isReg()) {
14706c3fb27SDimitry Andric         Sinkable = false;
14806c3fb27SDimitry Andric         break;
14906c3fb27SDimitry Andric       }
15006c3fb27SDimitry Andric       Register OtherReg = DbgOp.getReg();
15106c3fb27SDimitry Andric       MachineInstr *OtherDef = MRI.getUniqueVRegDef(OtherReg);
15206c3fb27SDimitry Andric       // We have an exception to allow encoutering other DBG_VALUEs with the
15306c3fb27SDimitry Andric       // smae DebugVariables, only when they are referring to the same scalar
15406c3fb27SDimitry Andric       // CONST instruction. For example,
15506c3fb27SDimitry Andric       //   %0 = CONST_I32 1
15606c3fb27SDimitry Andric       //   DBG_VALUE %0, !"a", !DIExpression() // Can sink with %0
15706c3fb27SDimitry Andric       //   %1 = CONST_I32 1
15806c3fb27SDimitry Andric       //   DBG_VALUE %1, !"a", !DIExpression()
15906c3fb27SDimitry Andric       // When %0 were to be sunk/cloneed, the DBG_VALUE can be sunk/cloned with
16006c3fb27SDimitry Andric       // it because even though the second DBG_VALUE refers to the same
16106c3fb27SDimitry Andric       // DebugVariable, its value in effect is the same CONST instruction.
16206c3fb27SDimitry Andric       //
16306c3fb27SDimitry Andric       // This is to allow a case that can happen with RegStackify's
16406c3fb27SDimitry Andric       // "rematerializeCheapDef". For example, we have this program with two
16506c3fb27SDimitry Andric       // BBs:
16606c3fb27SDimitry Andric       // bb0:
16706c3fb27SDimitry Andric       //   %0 = CONST_I32 1
16806c3fb27SDimitry Andric       //   DBG_VALUE %0, !"a", ...
16906c3fb27SDimitry Andric       //   ...
17006c3fb27SDimitry Andric       //   INST0 ..., $0 ...
17106c3fb27SDimitry Andric       //  bb1:
17206c3fb27SDimitry Andric       //   INST1 ..., $0 ...
17306c3fb27SDimitry Andric       //   INST2 ..., $0 ...
17406c3fb27SDimitry Andric       //
17506c3fb27SDimitry Andric       // We process bb0 first. Because %0 is used multiple times, %0 is cloned
17606c3fb27SDimitry Andric       // before INST0:
17706c3fb27SDimitry Andric       // bb0:
17806c3fb27SDimitry Andric       //   %0 = CONST_I32 1
17906c3fb27SDimitry Andric       //   DBG_VALUE %0, !"a", ...
18006c3fb27SDimitry Andric       //   ...
18106c3fb27SDimitry Andric       //   %1 = CONST_I32 1
18206c3fb27SDimitry Andric       //   DBG_VALUE %1, !"a", ...
18306c3fb27SDimitry Andric       //   INST0 ..., $1 ...
18406c3fb27SDimitry Andric       //
18506c3fb27SDimitry Andric       // And when we process bb1, we clone %0 and its DBG_VALUE again:
18606c3fb27SDimitry Andric       // bb0:
18706c3fb27SDimitry Andric       //   %0 = CONST_I32 1
18806c3fb27SDimitry Andric       //   DBG_VALUE %0, !"a", ...
18906c3fb27SDimitry Andric       //   ...
19006c3fb27SDimitry Andric       //   %1 = CONST_I32 1
19106c3fb27SDimitry Andric       //   DBG_VALUE %1, !"a", ...
19206c3fb27SDimitry Andric       //   INST0 ..., $1 ...
19306c3fb27SDimitry Andric       //  bb1:
19406c3fb27SDimitry Andric       //   %2 = CONST_I32 1
19506c3fb27SDimitry Andric       //   DBG_VALUE %2, !"a", ... // !!!
19606c3fb27SDimitry Andric       //   INST1 ..., $2 ...
19706c3fb27SDimitry Andric       //   %3 = CONST_I32 1
19806c3fb27SDimitry Andric       //   DBG_VALUE %3, !"a", ... // !!!
19906c3fb27SDimitry Andric       //   INST2 ..., $3 ...
20006c3fb27SDimitry Andric       //
20106c3fb27SDimitry Andric       // But (without this exception) the cloned DBG_VALUEs marked with !!! are
20206c3fb27SDimitry Andric       // not possible to be cloned, because there is a previously cloned
20306c3fb27SDimitry Andric       // 'DBG_VALUE %1, !"a"' at the end of bb0 referring to the same
20406c3fb27SDimitry Andric       // DebugVariable "a". But in this case they are OK to be cloned, because
20506c3fb27SDimitry Andric       // the interfering DBG_VALUE is pointing to the same 'CONST_I32 1',
20606c3fb27SDimitry Andric       // because it was cloned from the same instruction.
20706c3fb27SDimitry Andric       if (!OtherDef || !isSameScalarConst(Def, OtherDef)) {
20806c3fb27SDimitry Andric         Sinkable = false;
20906c3fb27SDimitry Andric         break;
21006c3fb27SDimitry Andric       }
21106c3fb27SDimitry Andric     }
21206c3fb27SDimitry Andric     if (Sinkable)
21306c3fb27SDimitry Andric       SinkableDbgValues.push_back(DV);
21406c3fb27SDimitry Andric   }
21506c3fb27SDimitry Andric   return SinkableDbgValues;
21606c3fb27SDimitry Andric }
21706c3fb27SDimitry Andric 
21806c3fb27SDimitry Andric // Returns true if the insertion point is the same as the current place.
21906c3fb27SDimitry Andric // Following DBG_VALUEs for 'Def' are ignored.
22006c3fb27SDimitry Andric bool WebAssemblyDebugValueManager::isInsertSamePlace(
22106c3fb27SDimitry Andric     MachineInstr *Insert) const {
22206c3fb27SDimitry Andric   if (Def->getParent() != Insert->getParent())
22306c3fb27SDimitry Andric     return false;
22406c3fb27SDimitry Andric   for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
22506c3fb27SDimitry Andric                                    ME = Insert;
22606c3fb27SDimitry Andric        MI != ME; ++MI) {
22706c3fb27SDimitry Andric     if (!llvm::is_contained(DbgValues, MI)) {
22806c3fb27SDimitry Andric       return false;
22906c3fb27SDimitry Andric     }
23006c3fb27SDimitry Andric   }
23106c3fb27SDimitry Andric   return true;
23206c3fb27SDimitry Andric }
23306c3fb27SDimitry Andric 
23406c3fb27SDimitry Andric // Returns true if any instruction in MBB has the same debug location as DL.
23506c3fb27SDimitry Andric // Also returns true if DL is an empty location.
23606c3fb27SDimitry Andric static bool hasSameDebugLoc(const MachineBasicBlock *MBB, DebugLoc DL) {
23706c3fb27SDimitry Andric   for (const auto &MI : *MBB)
23806c3fb27SDimitry Andric     if (MI.getDebugLoc() == DL)
23906c3fb27SDimitry Andric       return true;
24006c3fb27SDimitry Andric   return false;
24106c3fb27SDimitry Andric }
24206c3fb27SDimitry Andric 
24306c3fb27SDimitry Andric // Sink 'Def', and also sink its eligible DBG_VALUEs to the place before
24406c3fb27SDimitry Andric // 'Insert'. Convert the original DBG_VALUEs into undefs.
24506c3fb27SDimitry Andric //
24606c3fb27SDimitry Andric // For DBG_VALUEs to sink properly, if 'Def' and 'Insert' are within the same
24706c3fb27SDimitry Andric // BB, 'Insert' should be below 'Def'; if they are in different BBs, 'Insert'
24806c3fb27SDimitry Andric // should be in one of 'Def's BBs successors. Def will be sunk regardless of the
24906c3fb27SDimitry Andric // location.
25006c3fb27SDimitry Andric //
25106c3fb27SDimitry Andric // This DebugValueManager's new Def and DbgValues will be updated to the newly
25206c3fb27SDimitry Andric // sinked Def + DBG_VALUEs.
25306c3fb27SDimitry Andric void WebAssemblyDebugValueManager::sink(MachineInstr *Insert) {
25406c3fb27SDimitry Andric   // In case Def is requested to be sunk to
25506c3fb27SDimitry Andric   // the same place, we don't need to do anything. If we actually do the sink,
25606c3fb27SDimitry Andric   // it will create unnecessary undef DBG_VALUEs. For example, if the original
25706c3fb27SDimitry Andric   // code is:
25806c3fb27SDimitry Andric   //   %0 = someinst           // Def
25906c3fb27SDimitry Andric   //   DBG_VALUE %0, ...
26006c3fb27SDimitry Andric   //   %1 = anotherinst        // Insert
26106c3fb27SDimitry Andric   //
26206c3fb27SDimitry Andric   // If we actually sink %0 and the following DBG_VALUE and setting the original
26306c3fb27SDimitry Andric   // DBG_VALUE undef, the result will be:
26406c3fb27SDimitry Andric   //   DBG_VALUE %noreg, ...   // Unnecessary!
26506c3fb27SDimitry Andric   //   %0 = someinst           // Def
26606c3fb27SDimitry Andric   //   DBG_VALUE %0, ...
26706c3fb27SDimitry Andric   //   %1 = anotherinst        // Insert
26806c3fb27SDimitry Andric   if (isInsertSamePlace(Insert))
26906c3fb27SDimitry Andric     return;
27006c3fb27SDimitry Andric 
2710b57cec5SDimitry Andric   MachineBasicBlock *MBB = Insert->getParent();
27206c3fb27SDimitry Andric   MachineFunction *MF = MBB->getParent();
27306c3fb27SDimitry Andric 
27406c3fb27SDimitry Andric   // Get the list of sinkable DBG_VALUEs. This should be done before sinking
27506c3fb27SDimitry Andric   // Def, because we need to examine instructions between Def and Insert.
27606c3fb27SDimitry Andric   SmallVector<MachineInstr *, 1> SinkableDbgValues =
27706c3fb27SDimitry Andric       getSinkableDebugValues(Insert);
27806c3fb27SDimitry Andric 
27906c3fb27SDimitry Andric   // Sink Def first.
28006c3fb27SDimitry Andric   //
28106c3fb27SDimitry Andric   // When moving to a different BB, we preserve the debug loc only if the
28206c3fb27SDimitry Andric   // destination BB contains the same location. See
28306c3fb27SDimitry Andric   // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location.
28406c3fb27SDimitry Andric   if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
28506c3fb27SDimitry Andric       Def->setDebugLoc(DebugLoc());
28606c3fb27SDimitry Andric   MBB->splice(Insert, Def->getParent(), Def);
28706c3fb27SDimitry Andric 
28806c3fb27SDimitry Andric   if (DbgValues.empty())
28906c3fb27SDimitry Andric     return;
29006c3fb27SDimitry Andric 
29106c3fb27SDimitry Andric   // Clone sinkable DBG_VALUEs and insert them.
29206c3fb27SDimitry Andric   SmallVector<MachineInstr *, 1> NewDbgValues;
29306c3fb27SDimitry Andric   for (MachineInstr *DV : SinkableDbgValues) {
29406c3fb27SDimitry Andric     MachineInstr *Clone = MF->CloneMachineInstr(DV);
29506c3fb27SDimitry Andric     MBB->insert(Insert, Clone);
29606c3fb27SDimitry Andric     NewDbgValues.push_back(Clone);
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric 
29906c3fb27SDimitry Andric   // When sinking a Def and its DBG_VALUEs, we shouldn't just remove the
30006c3fb27SDimitry Andric   // original DBG_VALUE instructions; we should set them to undef not to create
30106c3fb27SDimitry Andric   // an impossible combination of variable assignments in the original program.
30206c3fb27SDimitry Andric   // For example, this is the original program in order:
30306c3fb27SDimitry Andric   //   %0 = CONST_I32 0
30406c3fb27SDimitry Andric   //   DBG_VALUE %0, !"a", !DIExpression()  // a = 0, b = ?
30506c3fb27SDimitry Andric   //   %1 = CONST_I32 1
30606c3fb27SDimitry Andric   //   DBG_VALUE %1, !"b", !DIExpression()  // a = 0, b = 1
30706c3fb27SDimitry Andric   //   %2 = CONST_I32 2
30806c3fb27SDimitry Andric   //   DBG_VALUE %2, !"a", !DIExpression()  // a = 2, b = 1
30906c3fb27SDimitry Andric   //   %3 = CONST_I32 3
31006c3fb27SDimitry Andric   //   DBG_VALUE %3, !"b", !DIExpression()  // a = 2, b = 3
31106c3fb27SDimitry Andric   //
31206c3fb27SDimitry Andric   // If %2 were to sink below %3, if we just sink DBG_VALUE %1 with it, the
31306c3fb27SDimitry Andric   // debug info will show the variable "b" is updated to 2, creating the
31406c3fb27SDimitry Andric   // variable assignment combination of (a = 0, b = 3), which is not possible in
31506c3fb27SDimitry Andric   // the original program:
31606c3fb27SDimitry Andric   //   %0 = CONST_I32 0
31706c3fb27SDimitry Andric   //   DBG_VALUE %0, !"a", !DIExpression()  // a = 0, b = ?
31806c3fb27SDimitry Andric   //   %1 = CONST_I32 1
31906c3fb27SDimitry Andric   //   DBG_VALUE %1, !"b", !DIExpression()  // a = 0, b = 1
32006c3fb27SDimitry Andric   //   %3 = CONST_I32 3
32106c3fb27SDimitry Andric   //   DBG_VALUE %3, !"b", !DIExpression()  // a = 0, b = 3 (Incorrect!)
32206c3fb27SDimitry Andric   //   %2 = CONST_I32 2
32306c3fb27SDimitry Andric   //   DBG_VALUE %2, !"a", !DIExpression()  // a = 2, b = 3
32406c3fb27SDimitry Andric   //
32506c3fb27SDimitry Andric   // To fix this,we leave an undef DBG_VALUE in its original place, so that the
32606c3fb27SDimitry Andric   // result will be
32706c3fb27SDimitry Andric   //   %0 = CONST_I32 0
32806c3fb27SDimitry Andric   //   DBG_VALUE %0, !"a", !DIExpression()      // a = 0, b = ?
32906c3fb27SDimitry Andric   //   %1 = CONST_I32 1
33006c3fb27SDimitry Andric   //   DBG_VALUE %1, !"b", !DIExpression()      // a = 0, b = 1
33106c3fb27SDimitry Andric   //   DBG_VALUE $noreg, !"a", !DIExpression()  // a = ?, b = 1
33206c3fb27SDimitry Andric   //   %3 = CONST_I32 3
33306c3fb27SDimitry Andric   //   DBG_VALUE %3, !"b", !DIExpression()      // a = ?, b = 3
33406c3fb27SDimitry Andric   //   %2 = CONST_I32 2
33506c3fb27SDimitry Andric   //   DBG_VALUE %2, !"a", !DIExpression()      // a = 2, b = 3
33606c3fb27SDimitry Andric   // Now in the middle "a" will be shown as "optimized out", but it wouldn't
33706c3fb27SDimitry Andric   // show the impossible combination of (a = 0, b = 3).
33806c3fb27SDimitry Andric   for (MachineInstr *DV : DbgValues)
33906c3fb27SDimitry Andric     DV->setDebugValueUndef();
34006c3fb27SDimitry Andric 
34106c3fb27SDimitry Andric   DbgValues.swap(NewDbgValues);
34206c3fb27SDimitry Andric }
34306c3fb27SDimitry Andric 
34406c3fb27SDimitry Andric // Clone 'Def', and also clone its eligible DBG_VALUEs to the place before
34506c3fb27SDimitry Andric // 'Insert'.
34606c3fb27SDimitry Andric //
34706c3fb27SDimitry Andric // For DBG_VALUEs to be cloned properly, if 'Def' and 'Insert' are within the
34806c3fb27SDimitry Andric // same BB, 'Insert' should be below 'Def'; if they are in different BBs,
34906c3fb27SDimitry Andric // 'Insert' should be in one of 'Def's BBs successors. Def will be cloned
35006c3fb27SDimitry Andric // regardless of the location.
35106c3fb27SDimitry Andric //
35206c3fb27SDimitry Andric // If NewReg is not $noreg, the newly cloned DBG_VALUEs will have the new
35306c3fb27SDimitry Andric // register as its operand.
35406c3fb27SDimitry Andric void WebAssemblyDebugValueManager::cloneSink(MachineInstr *Insert,
35506c3fb27SDimitry Andric                                              Register NewReg,
35606c3fb27SDimitry Andric                                              bool CloneDef) const {
35706c3fb27SDimitry Andric   MachineBasicBlock *MBB = Insert->getParent();
35806c3fb27SDimitry Andric   MachineFunction *MF = MBB->getParent();
35906c3fb27SDimitry Andric 
36006c3fb27SDimitry Andric   SmallVector<MachineInstr *> SinkableDbgValues =
36106c3fb27SDimitry Andric       getSinkableDebugValues(Insert);
36206c3fb27SDimitry Andric 
36306c3fb27SDimitry Andric   // Clone Def first.
36406c3fb27SDimitry Andric   if (CloneDef) {
36506c3fb27SDimitry Andric     MachineInstr *Clone = MF->CloneMachineInstr(Def);
36606c3fb27SDimitry Andric     // When cloning to a different BB, we preserve the debug loc only if the
36706c3fb27SDimitry Andric     // destination BB contains the same location. See
36806c3fb27SDimitry Andric     // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location.
36906c3fb27SDimitry Andric     if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
37006c3fb27SDimitry Andric       Clone->setDebugLoc(DebugLoc());
37106c3fb27SDimitry Andric     if (NewReg != CurrentReg && NewReg.isValid())
37206c3fb27SDimitry Andric       Clone->getOperand(0).setReg(NewReg);
37306c3fb27SDimitry Andric     MBB->insert(Insert, Clone);
37406c3fb27SDimitry Andric   }
37506c3fb27SDimitry Andric 
37606c3fb27SDimitry Andric   if (DbgValues.empty())
37706c3fb27SDimitry Andric     return;
37806c3fb27SDimitry Andric 
37906c3fb27SDimitry Andric   // Clone sinkable DBG_VALUEs and insert them.
38006c3fb27SDimitry Andric   SmallVector<MachineInstr *, 1> NewDbgValues;
38106c3fb27SDimitry Andric   for (MachineInstr *DV : SinkableDbgValues) {
38206c3fb27SDimitry Andric     MachineInstr *Clone = MF->CloneMachineInstr(DV);
38306c3fb27SDimitry Andric     MBB->insert(Insert, Clone);
38406c3fb27SDimitry Andric     NewDbgValues.push_back(Clone);
38506c3fb27SDimitry Andric   }
38606c3fb27SDimitry Andric 
38706c3fb27SDimitry Andric   if (NewReg != CurrentReg && NewReg.isValid())
38806c3fb27SDimitry Andric     for (auto *DBI : NewDbgValues)
38906c3fb27SDimitry Andric       for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
39006c3fb27SDimitry Andric         MO.setReg(NewReg);
39106c3fb27SDimitry Andric }
39206c3fb27SDimitry Andric 
39306c3fb27SDimitry Andric // Update the register for Def and DBG_VALUEs.
39406c3fb27SDimitry Andric void WebAssemblyDebugValueManager::updateReg(Register Reg) {
39506c3fb27SDimitry Andric   if (Reg != CurrentReg && Reg.isValid()) {
3960b57cec5SDimitry Andric     for (auto *DBI : DbgValues)
397fe6060f1SDimitry Andric       for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
398fe6060f1SDimitry Andric         MO.setReg(Reg);
399fe6060f1SDimitry Andric     CurrentReg = Reg;
40006c3fb27SDimitry Andric     Def->getOperand(0).setReg(Reg);
4010b57cec5SDimitry Andric   }
4020b57cec5SDimitry Andric }
403480093f4SDimitry Andric 
404480093f4SDimitry Andric void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) {
405480093f4SDimitry Andric   for (auto *DBI : DbgValues) {
406fe6060f1SDimitry Andric     auto IndexType = DBI->isIndirectDebugValue()
407fe6060f1SDimitry Andric                          ? llvm::WebAssembly::TI_LOCAL_INDIRECT
408fe6060f1SDimitry Andric                          : llvm::WebAssembly::TI_LOCAL;
409fe6060f1SDimitry Andric     for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
410fe6060f1SDimitry Andric       MO.ChangeToTargetIndex(IndexType, LocalId);
411480093f4SDimitry Andric   }
412480093f4SDimitry Andric }
41306c3fb27SDimitry Andric 
41406c3fb27SDimitry Andric // Remove Def, and set its DBG_VALUEs to undef.
41506c3fb27SDimitry Andric void WebAssemblyDebugValueManager::removeDef() {
41606c3fb27SDimitry Andric   Def->removeFromParent();
41706c3fb27SDimitry Andric   for (MachineInstr *DV : DbgValues)
41806c3fb27SDimitry Andric     DV->setDebugValueUndef();
41906c3fb27SDimitry Andric }
420