xref: /src/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1d8e91e46SDimitry Andric //===-- WebAssemblyDebugValueManager.cpp - WebAssembly DebugValue Manager -===//
2d8e91e46SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d8e91e46SDimitry Andric //
7d8e91e46SDimitry Andric //===----------------------------------------------------------------------===//
8d8e91e46SDimitry Andric ///
9d8e91e46SDimitry Andric /// \file
10d8e91e46SDimitry Andric /// This file implements the manager for MachineInstr DebugValues.
11d8e91e46SDimitry Andric ///
12d8e91e46SDimitry Andric //===----------------------------------------------------------------------===//
13d8e91e46SDimitry Andric 
14d8e91e46SDimitry Andric #include "WebAssemblyDebugValueManager.h"
157fa27ce4SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16706b4fc4SDimitry Andric #include "WebAssembly.h"
17d8e91e46SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
18d8e91e46SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
197fa27ce4SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
204df029ccSDimitry Andric #include "llvm/IR/Function.h"
21d8e91e46SDimitry Andric 
22d8e91e46SDimitry Andric using namespace llvm;
23d8e91e46SDimitry Andric 
WebAssemblyDebugValueManager(MachineInstr * Def)247fa27ce4SDimitry Andric WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(MachineInstr *Def)
257fa27ce4SDimitry Andric     : Def(Def) {
264df029ccSDimitry Andric   if (!Def->getMF()->getFunction().getSubprogram())
274df029ccSDimitry Andric     return;
284df029ccSDimitry Andric 
29b60736ecSDimitry Andric   // This code differs from MachineInstr::collectDebugValues in that it scans
307fa27ce4SDimitry Andric   // the whole BB, not just contiguous DBG_VALUEs, until another definition to
317fa27ce4SDimitry Andric   // the same register is encountered.
327fa27ce4SDimitry Andric   if (!Def->getOperand(0).isReg())
33b60736ecSDimitry Andric     return;
347fa27ce4SDimitry Andric   CurrentReg = Def->getOperand(0).getReg();
35b60736ecSDimitry Andric 
367fa27ce4SDimitry Andric   for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
377fa27ce4SDimitry Andric                                    ME = Def->getParent()->end();
387fa27ce4SDimitry Andric        MI != ME; ++MI) {
397fa27ce4SDimitry Andric     // If another definition appears, stop
40ac9a064cSDimitry Andric     if (MI->definesRegister(CurrentReg, /*TRI=*/nullptr))
417fa27ce4SDimitry Andric       break;
427fa27ce4SDimitry Andric     if (MI->isDebugValue() && MI->hasDebugOperandForReg(CurrentReg))
437fa27ce4SDimitry Andric       DbgValues.push_back(&*MI);
44b60736ecSDimitry Andric   }
45d8e91e46SDimitry Andric }
46d8e91e46SDimitry Andric 
477fa27ce4SDimitry Andric // Returns true if both A and B are the same CONST_I32/I64/F32/F64 instructions.
487fa27ce4SDimitry Andric // Doesn't include CONST_V128.
isSameScalarConst(const MachineInstr * A,const MachineInstr * B)497fa27ce4SDimitry Andric static bool isSameScalarConst(const MachineInstr *A, const MachineInstr *B) {
507fa27ce4SDimitry Andric   if (A->getOpcode() != B->getOpcode() ||
517fa27ce4SDimitry Andric       !WebAssembly::isScalarConst(A->getOpcode()) ||
527fa27ce4SDimitry Andric       !WebAssembly::isScalarConst(B->getOpcode()))
537fa27ce4SDimitry Andric     return false;
547fa27ce4SDimitry Andric   const MachineOperand &OpA = A->getOperand(1), &OpB = B->getOperand(1);
557fa27ce4SDimitry Andric   if ((OpA.isImm() && OpB.isImm() && OpA.getImm() == OpB.getImm()) ||
567fa27ce4SDimitry Andric       (OpA.isFPImm() && OpB.isFPImm() && OpA.getFPImm() == OpB.getFPImm()) ||
577fa27ce4SDimitry Andric       (OpA.isGlobal() && OpB.isGlobal() && OpA.getGlobal() == OpB.getGlobal()))
587fa27ce4SDimitry Andric     return true;
597fa27ce4SDimitry Andric   return false;
607fa27ce4SDimitry Andric }
617fa27ce4SDimitry Andric 
627fa27ce4SDimitry Andric SmallVector<MachineInstr *, 1>
getSinkableDebugValues(MachineInstr * Insert) const637fa27ce4SDimitry Andric WebAssemblyDebugValueManager::getSinkableDebugValues(
647fa27ce4SDimitry Andric     MachineInstr *Insert) const {
657fa27ce4SDimitry Andric   if (DbgValues.empty())
667fa27ce4SDimitry Andric     return {};
677fa27ce4SDimitry Andric   // DBG_VALUEs between Def and Insert
687fa27ce4SDimitry Andric   SmallVector<MachineInstr *, 8> DbgValuesInBetween;
697fa27ce4SDimitry Andric 
707fa27ce4SDimitry Andric   if (Def->getParent() == Insert->getParent()) {
717fa27ce4SDimitry Andric     // When Def and Insert are within the same BB, check if Insert comes after
727fa27ce4SDimitry Andric     // Def, because we only support sinking.
737fa27ce4SDimitry Andric     bool DefFirst = false;
747fa27ce4SDimitry Andric     for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
757fa27ce4SDimitry Andric                                      ME = Def->getParent()->end();
767fa27ce4SDimitry Andric          MI != ME; ++MI) {
777fa27ce4SDimitry Andric       if (&*MI == Insert) {
787fa27ce4SDimitry Andric         DefFirst = true;
797fa27ce4SDimitry Andric         break;
807fa27ce4SDimitry Andric       }
817fa27ce4SDimitry Andric       if (MI->isDebugValue())
827fa27ce4SDimitry Andric         DbgValuesInBetween.push_back(&*MI);
837fa27ce4SDimitry Andric     }
847fa27ce4SDimitry Andric     if (!DefFirst) // Not a sink
857fa27ce4SDimitry Andric       return {};
867fa27ce4SDimitry Andric 
877fa27ce4SDimitry Andric   } else { // Def and Insert are in different BBs
887fa27ce4SDimitry Andric     // If Def and Insert are in different BBs, we only handle a simple case in
897fa27ce4SDimitry Andric     // which Insert's BB is a successor of Def's BB.
907fa27ce4SDimitry Andric     if (!Def->getParent()->isSuccessor(Insert->getParent()))
917fa27ce4SDimitry Andric       return {};
927fa27ce4SDimitry Andric 
937fa27ce4SDimitry Andric     // Gather DBG_VALUEs between 'Def~Def BB's end' and
947fa27ce4SDimitry Andric     // 'Insert BB's begin~Insert'
957fa27ce4SDimitry Andric     for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
967fa27ce4SDimitry Andric                                      ME = Def->getParent()->end();
977fa27ce4SDimitry Andric          MI != ME; ++MI) {
987fa27ce4SDimitry Andric       if (MI->isDebugValue())
997fa27ce4SDimitry Andric         DbgValuesInBetween.push_back(&*MI);
1007fa27ce4SDimitry Andric     }
1017fa27ce4SDimitry Andric     for (MachineBasicBlock::iterator MI = Insert->getParent()->begin(),
1027fa27ce4SDimitry Andric                                      ME = Insert->getIterator();
1037fa27ce4SDimitry Andric          MI != ME; ++MI) {
1047fa27ce4SDimitry Andric       if (MI->isDebugValue())
1057fa27ce4SDimitry Andric         DbgValuesInBetween.push_back(&*MI);
1067fa27ce4SDimitry Andric     }
1077fa27ce4SDimitry Andric   }
1087fa27ce4SDimitry Andric 
1097fa27ce4SDimitry Andric   // Gather DebugVariables that are seen between Def and Insert, excluding our
1107fa27ce4SDimitry Andric   // own DBG_VALUEs in DbgValues.
1117fa27ce4SDimitry Andric   SmallDenseMap<DebugVariable, SmallVector<MachineInstr *, 2>>
1127fa27ce4SDimitry Andric       SeenDbgVarToDbgValues;
1137fa27ce4SDimitry Andric   for (auto *DV : DbgValuesInBetween) {
1147fa27ce4SDimitry Andric     if (!llvm::is_contained(DbgValues, DV)) {
1157fa27ce4SDimitry Andric       DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
1167fa27ce4SDimitry Andric                         DV->getDebugLoc()->getInlinedAt());
1177fa27ce4SDimitry Andric       SeenDbgVarToDbgValues[Var].push_back(DV);
1187fa27ce4SDimitry Andric     }
1197fa27ce4SDimitry Andric   }
1207fa27ce4SDimitry Andric 
1217fa27ce4SDimitry Andric   // Gather sinkable DBG_VALUEs. We should not sink a DBG_VALUE if there is
1227fa27ce4SDimitry Andric   // another DBG_VALUE between Def and Insert referring to the same
1237fa27ce4SDimitry Andric   // DebugVariable. For example,
1247fa27ce4SDimitry Andric   //   %0 = someinst
1257fa27ce4SDimitry Andric   //   DBG_VALUE %0, !"a", !DIExpression() // Should not sink with %0
1267fa27ce4SDimitry Andric   //   %1 = anotherinst
1277fa27ce4SDimitry Andric   //   DBG_VALUE %1, !"a", !DIExpression()
1287fa27ce4SDimitry Andric   // Where if %0 were to sink, the DBG_VAUE should not sink with it, as that
1297fa27ce4SDimitry Andric   // would re-order assignments.
1307fa27ce4SDimitry Andric   SmallVector<MachineInstr *, 1> SinkableDbgValues;
1317fa27ce4SDimitry Andric   MachineRegisterInfo &MRI = Def->getParent()->getParent()->getRegInfo();
1327fa27ce4SDimitry Andric   for (auto *DV : DbgValues) {
1337fa27ce4SDimitry Andric     DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(),
1347fa27ce4SDimitry Andric                       DV->getDebugLoc()->getInlinedAt());
1357fa27ce4SDimitry Andric     auto It = SeenDbgVarToDbgValues.find(Var);
1367fa27ce4SDimitry Andric     if (It == SeenDbgVarToDbgValues.end()) {
1377fa27ce4SDimitry Andric       SinkableDbgValues.push_back(DV);
1387fa27ce4SDimitry Andric       continue;
1397fa27ce4SDimitry Andric     }
1407fa27ce4SDimitry Andric     if (!WebAssembly::isScalarConst(Def->getOpcode()))
1417fa27ce4SDimitry Andric       continue;
1427fa27ce4SDimitry Andric     auto &OverlappingDbgValues = It->second;
1437fa27ce4SDimitry Andric     bool Sinkable = true;
1447fa27ce4SDimitry Andric     for (auto *OverlappingDV : OverlappingDbgValues) {
1457fa27ce4SDimitry Andric       MachineOperand &DbgOp = OverlappingDV->getDebugOperand(0);
1467fa27ce4SDimitry Andric       if (!DbgOp.isReg()) {
1477fa27ce4SDimitry Andric         Sinkable = false;
1487fa27ce4SDimitry Andric         break;
1497fa27ce4SDimitry Andric       }
1507fa27ce4SDimitry Andric       Register OtherReg = DbgOp.getReg();
1517fa27ce4SDimitry Andric       MachineInstr *OtherDef = MRI.getUniqueVRegDef(OtherReg);
1527fa27ce4SDimitry Andric       // We have an exception to allow encoutering other DBG_VALUEs with the
1537fa27ce4SDimitry Andric       // smae DebugVariables, only when they are referring to the same scalar
1547fa27ce4SDimitry Andric       // CONST instruction. For example,
1557fa27ce4SDimitry Andric       //   %0 = CONST_I32 1
1567fa27ce4SDimitry Andric       //   DBG_VALUE %0, !"a", !DIExpression() // Can sink with %0
1577fa27ce4SDimitry Andric       //   %1 = CONST_I32 1
1587fa27ce4SDimitry Andric       //   DBG_VALUE %1, !"a", !DIExpression()
1597fa27ce4SDimitry Andric       // When %0 were to be sunk/cloneed, the DBG_VALUE can be sunk/cloned with
1607fa27ce4SDimitry Andric       // it because even though the second DBG_VALUE refers to the same
1617fa27ce4SDimitry Andric       // DebugVariable, its value in effect is the same CONST instruction.
1627fa27ce4SDimitry Andric       //
1637fa27ce4SDimitry Andric       // This is to allow a case that can happen with RegStackify's
1647fa27ce4SDimitry Andric       // "rematerializeCheapDef". For example, we have this program with two
1657fa27ce4SDimitry Andric       // BBs:
1667fa27ce4SDimitry Andric       // bb0:
1677fa27ce4SDimitry Andric       //   %0 = CONST_I32 1
1687fa27ce4SDimitry Andric       //   DBG_VALUE %0, !"a", ...
1697fa27ce4SDimitry Andric       //   ...
1707fa27ce4SDimitry Andric       //   INST0 ..., $0 ...
1717fa27ce4SDimitry Andric       //  bb1:
1727fa27ce4SDimitry Andric       //   INST1 ..., $0 ...
1737fa27ce4SDimitry Andric       //   INST2 ..., $0 ...
1747fa27ce4SDimitry Andric       //
1757fa27ce4SDimitry Andric       // We process bb0 first. Because %0 is used multiple times, %0 is cloned
1767fa27ce4SDimitry Andric       // before INST0:
1777fa27ce4SDimitry Andric       // bb0:
1787fa27ce4SDimitry Andric       //   %0 = CONST_I32 1
1797fa27ce4SDimitry Andric       //   DBG_VALUE %0, !"a", ...
1807fa27ce4SDimitry Andric       //   ...
1817fa27ce4SDimitry Andric       //   %1 = CONST_I32 1
1827fa27ce4SDimitry Andric       //   DBG_VALUE %1, !"a", ...
1837fa27ce4SDimitry Andric       //   INST0 ..., $1 ...
1847fa27ce4SDimitry Andric       //
1857fa27ce4SDimitry Andric       // And when we process bb1, we clone %0 and its DBG_VALUE again:
1867fa27ce4SDimitry Andric       // bb0:
1877fa27ce4SDimitry Andric       //   %0 = CONST_I32 1
1887fa27ce4SDimitry Andric       //   DBG_VALUE %0, !"a", ...
1897fa27ce4SDimitry Andric       //   ...
1907fa27ce4SDimitry Andric       //   %1 = CONST_I32 1
1917fa27ce4SDimitry Andric       //   DBG_VALUE %1, !"a", ...
1927fa27ce4SDimitry Andric       //   INST0 ..., $1 ...
1937fa27ce4SDimitry Andric       //  bb1:
1947fa27ce4SDimitry Andric       //   %2 = CONST_I32 1
1957fa27ce4SDimitry Andric       //   DBG_VALUE %2, !"a", ... // !!!
1967fa27ce4SDimitry Andric       //   INST1 ..., $2 ...
1977fa27ce4SDimitry Andric       //   %3 = CONST_I32 1
1987fa27ce4SDimitry Andric       //   DBG_VALUE %3, !"a", ... // !!!
1997fa27ce4SDimitry Andric       //   INST2 ..., $3 ...
2007fa27ce4SDimitry Andric       //
2017fa27ce4SDimitry Andric       // But (without this exception) the cloned DBG_VALUEs marked with !!! are
2027fa27ce4SDimitry Andric       // not possible to be cloned, because there is a previously cloned
2037fa27ce4SDimitry Andric       // 'DBG_VALUE %1, !"a"' at the end of bb0 referring to the same
2047fa27ce4SDimitry Andric       // DebugVariable "a". But in this case they are OK to be cloned, because
2057fa27ce4SDimitry Andric       // the interfering DBG_VALUE is pointing to the same 'CONST_I32 1',
2067fa27ce4SDimitry Andric       // because it was cloned from the same instruction.
2077fa27ce4SDimitry Andric       if (!OtherDef || !isSameScalarConst(Def, OtherDef)) {
2087fa27ce4SDimitry Andric         Sinkable = false;
2097fa27ce4SDimitry Andric         break;
2107fa27ce4SDimitry Andric       }
2117fa27ce4SDimitry Andric     }
2127fa27ce4SDimitry Andric     if (Sinkable)
2137fa27ce4SDimitry Andric       SinkableDbgValues.push_back(DV);
2147fa27ce4SDimitry Andric   }
2157fa27ce4SDimitry Andric   return SinkableDbgValues;
2167fa27ce4SDimitry Andric }
2177fa27ce4SDimitry Andric 
2187fa27ce4SDimitry Andric // Returns true if the insertion point is the same as the current place.
2197fa27ce4SDimitry Andric // Following DBG_VALUEs for 'Def' are ignored.
isInsertSamePlace(MachineInstr * Insert) const2207fa27ce4SDimitry Andric bool WebAssemblyDebugValueManager::isInsertSamePlace(
2217fa27ce4SDimitry Andric     MachineInstr *Insert) const {
2227fa27ce4SDimitry Andric   if (Def->getParent() != Insert->getParent())
2237fa27ce4SDimitry Andric     return false;
2247fa27ce4SDimitry Andric   for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
2257fa27ce4SDimitry Andric                                    ME = Insert;
2267fa27ce4SDimitry Andric        MI != ME; ++MI) {
2277fa27ce4SDimitry Andric     if (!llvm::is_contained(DbgValues, MI)) {
2287fa27ce4SDimitry Andric       return false;
2297fa27ce4SDimitry Andric     }
2307fa27ce4SDimitry Andric   }
2317fa27ce4SDimitry Andric   return true;
2327fa27ce4SDimitry Andric }
2337fa27ce4SDimitry Andric 
2347fa27ce4SDimitry Andric // Returns true if any instruction in MBB has the same debug location as DL.
2357fa27ce4SDimitry Andric // Also returns true if DL is an empty location.
hasSameDebugLoc(const MachineBasicBlock * MBB,DebugLoc DL)2367fa27ce4SDimitry Andric static bool hasSameDebugLoc(const MachineBasicBlock *MBB, DebugLoc DL) {
2377fa27ce4SDimitry Andric   for (const auto &MI : *MBB)
2387fa27ce4SDimitry Andric     if (MI.getDebugLoc() == DL)
2397fa27ce4SDimitry Andric       return true;
2407fa27ce4SDimitry Andric   return false;
2417fa27ce4SDimitry Andric }
2427fa27ce4SDimitry Andric 
2437fa27ce4SDimitry Andric // Sink 'Def', and also sink its eligible DBG_VALUEs to the place before
2447fa27ce4SDimitry Andric // 'Insert'. Convert the original DBG_VALUEs into undefs.
2457fa27ce4SDimitry Andric //
2467fa27ce4SDimitry Andric // For DBG_VALUEs to sink properly, if 'Def' and 'Insert' are within the same
2477fa27ce4SDimitry Andric // BB, 'Insert' should be below 'Def'; if they are in different BBs, 'Insert'
2487fa27ce4SDimitry Andric // should be in one of 'Def's BBs successors. Def will be sunk regardless of the
2497fa27ce4SDimitry Andric // location.
2507fa27ce4SDimitry Andric //
2517fa27ce4SDimitry Andric // This DebugValueManager's new Def and DbgValues will be updated to the newly
2527fa27ce4SDimitry Andric // sinked Def + DBG_VALUEs.
sink(MachineInstr * Insert)2537fa27ce4SDimitry Andric void WebAssemblyDebugValueManager::sink(MachineInstr *Insert) {
2547fa27ce4SDimitry Andric   // In case Def is requested to be sunk to
2557fa27ce4SDimitry Andric   // the same place, we don't need to do anything. If we actually do the sink,
2567fa27ce4SDimitry Andric   // it will create unnecessary undef DBG_VALUEs. For example, if the original
2577fa27ce4SDimitry Andric   // code is:
2587fa27ce4SDimitry Andric   //   %0 = someinst           // Def
2597fa27ce4SDimitry Andric   //   DBG_VALUE %0, ...
2607fa27ce4SDimitry Andric   //   %1 = anotherinst        // Insert
2617fa27ce4SDimitry Andric   //
2627fa27ce4SDimitry Andric   // If we actually sink %0 and the following DBG_VALUE and setting the original
2637fa27ce4SDimitry Andric   // DBG_VALUE undef, the result will be:
2647fa27ce4SDimitry Andric   //   DBG_VALUE %noreg, ...   // Unnecessary!
2657fa27ce4SDimitry Andric   //   %0 = someinst           // Def
2667fa27ce4SDimitry Andric   //   DBG_VALUE %0, ...
2677fa27ce4SDimitry Andric   //   %1 = anotherinst        // Insert
2687fa27ce4SDimitry Andric   if (isInsertSamePlace(Insert))
2697fa27ce4SDimitry Andric     return;
2707fa27ce4SDimitry Andric 
271d8e91e46SDimitry Andric   MachineBasicBlock *MBB = Insert->getParent();
2727fa27ce4SDimitry Andric   MachineFunction *MF = MBB->getParent();
2737fa27ce4SDimitry Andric 
2747fa27ce4SDimitry Andric   // Get the list of sinkable DBG_VALUEs. This should be done before sinking
2757fa27ce4SDimitry Andric   // Def, because we need to examine instructions between Def and Insert.
2767fa27ce4SDimitry Andric   SmallVector<MachineInstr *, 1> SinkableDbgValues =
2777fa27ce4SDimitry Andric       getSinkableDebugValues(Insert);
2787fa27ce4SDimitry Andric 
2797fa27ce4SDimitry Andric   // Sink Def first.
2807fa27ce4SDimitry Andric   //
2817fa27ce4SDimitry Andric   // When moving to a different BB, we preserve the debug loc only if the
2827fa27ce4SDimitry Andric   // destination BB contains the same location. See
2837fa27ce4SDimitry Andric   // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location.
2847fa27ce4SDimitry Andric   if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
2857fa27ce4SDimitry Andric       Def->setDebugLoc(DebugLoc());
2867fa27ce4SDimitry Andric   MBB->splice(Insert, Def->getParent(), Def);
2877fa27ce4SDimitry Andric 
2887fa27ce4SDimitry Andric   if (DbgValues.empty())
2897fa27ce4SDimitry Andric     return;
2907fa27ce4SDimitry Andric 
2917fa27ce4SDimitry Andric   // Clone sinkable DBG_VALUEs and insert them.
2927fa27ce4SDimitry Andric   SmallVector<MachineInstr *, 1> NewDbgValues;
2937fa27ce4SDimitry Andric   for (MachineInstr *DV : SinkableDbgValues) {
2947fa27ce4SDimitry Andric     MachineInstr *Clone = MF->CloneMachineInstr(DV);
2957fa27ce4SDimitry Andric     MBB->insert(Insert, Clone);
2967fa27ce4SDimitry Andric     NewDbgValues.push_back(Clone);
297d8e91e46SDimitry Andric   }
298d8e91e46SDimitry Andric 
2997fa27ce4SDimitry Andric   // When sinking a Def and its DBG_VALUEs, we shouldn't just remove the
3007fa27ce4SDimitry Andric   // original DBG_VALUE instructions; we should set them to undef not to create
3017fa27ce4SDimitry Andric   // an impossible combination of variable assignments in the original program.
3027fa27ce4SDimitry Andric   // For example, this is the original program in order:
3037fa27ce4SDimitry Andric   //   %0 = CONST_I32 0
3047fa27ce4SDimitry Andric   //   DBG_VALUE %0, !"a", !DIExpression()  // a = 0, b = ?
3057fa27ce4SDimitry Andric   //   %1 = CONST_I32 1
3067fa27ce4SDimitry Andric   //   DBG_VALUE %1, !"b", !DIExpression()  // a = 0, b = 1
3077fa27ce4SDimitry Andric   //   %2 = CONST_I32 2
3087fa27ce4SDimitry Andric   //   DBG_VALUE %2, !"a", !DIExpression()  // a = 2, b = 1
3097fa27ce4SDimitry Andric   //   %3 = CONST_I32 3
3107fa27ce4SDimitry Andric   //   DBG_VALUE %3, !"b", !DIExpression()  // a = 2, b = 3
3117fa27ce4SDimitry Andric   //
3127fa27ce4SDimitry Andric   // If %2 were to sink below %3, if we just sink DBG_VALUE %1 with it, the
3137fa27ce4SDimitry Andric   // debug info will show the variable "b" is updated to 2, creating the
3147fa27ce4SDimitry Andric   // variable assignment combination of (a = 0, b = 3), which is not possible in
3157fa27ce4SDimitry Andric   // the original program:
3167fa27ce4SDimitry Andric   //   %0 = CONST_I32 0
3177fa27ce4SDimitry Andric   //   DBG_VALUE %0, !"a", !DIExpression()  // a = 0, b = ?
3187fa27ce4SDimitry Andric   //   %1 = CONST_I32 1
3197fa27ce4SDimitry Andric   //   DBG_VALUE %1, !"b", !DIExpression()  // a = 0, b = 1
3207fa27ce4SDimitry Andric   //   %3 = CONST_I32 3
3217fa27ce4SDimitry Andric   //   DBG_VALUE %3, !"b", !DIExpression()  // a = 0, b = 3 (Incorrect!)
3227fa27ce4SDimitry Andric   //   %2 = CONST_I32 2
3237fa27ce4SDimitry Andric   //   DBG_VALUE %2, !"a", !DIExpression()  // a = 2, b = 3
3247fa27ce4SDimitry Andric   //
3257fa27ce4SDimitry Andric   // To fix this,we leave an undef DBG_VALUE in its original place, so that the
3267fa27ce4SDimitry Andric   // result will be
3277fa27ce4SDimitry Andric   //   %0 = CONST_I32 0
3287fa27ce4SDimitry Andric   //   DBG_VALUE %0, !"a", !DIExpression()      // a = 0, b = ?
3297fa27ce4SDimitry Andric   //   %1 = CONST_I32 1
3307fa27ce4SDimitry Andric   //   DBG_VALUE %1, !"b", !DIExpression()      // a = 0, b = 1
3317fa27ce4SDimitry Andric   //   DBG_VALUE $noreg, !"a", !DIExpression()  // a = ?, b = 1
3327fa27ce4SDimitry Andric   //   %3 = CONST_I32 3
3337fa27ce4SDimitry Andric   //   DBG_VALUE %3, !"b", !DIExpression()      // a = ?, b = 3
3347fa27ce4SDimitry Andric   //   %2 = CONST_I32 2
3357fa27ce4SDimitry Andric   //   DBG_VALUE %2, !"a", !DIExpression()      // a = 2, b = 3
3367fa27ce4SDimitry Andric   // Now in the middle "a" will be shown as "optimized out", but it wouldn't
3377fa27ce4SDimitry Andric   // show the impossible combination of (a = 0, b = 3).
3387fa27ce4SDimitry Andric   for (MachineInstr *DV : DbgValues)
3397fa27ce4SDimitry Andric     DV->setDebugValueUndef();
3407fa27ce4SDimitry Andric 
3417fa27ce4SDimitry Andric   DbgValues.swap(NewDbgValues);
3427fa27ce4SDimitry Andric }
3437fa27ce4SDimitry Andric 
3447fa27ce4SDimitry Andric // Clone 'Def', and also clone its eligible DBG_VALUEs to the place before
3457fa27ce4SDimitry Andric // 'Insert'.
3467fa27ce4SDimitry Andric //
3477fa27ce4SDimitry Andric // For DBG_VALUEs to be cloned properly, if 'Def' and 'Insert' are within the
3487fa27ce4SDimitry Andric // same BB, 'Insert' should be below 'Def'; if they are in different BBs,
3497fa27ce4SDimitry Andric // 'Insert' should be in one of 'Def's BBs successors. Def will be cloned
3507fa27ce4SDimitry Andric // regardless of the location.
3517fa27ce4SDimitry Andric //
3527fa27ce4SDimitry Andric // If NewReg is not $noreg, the newly cloned DBG_VALUEs will have the new
3537fa27ce4SDimitry Andric // register as its operand.
cloneSink(MachineInstr * Insert,Register NewReg,bool CloneDef) const3547fa27ce4SDimitry Andric void WebAssemblyDebugValueManager::cloneSink(MachineInstr *Insert,
3557fa27ce4SDimitry Andric                                              Register NewReg,
3567fa27ce4SDimitry Andric                                              bool CloneDef) const {
3577fa27ce4SDimitry Andric   MachineBasicBlock *MBB = Insert->getParent();
3587fa27ce4SDimitry Andric   MachineFunction *MF = MBB->getParent();
3597fa27ce4SDimitry Andric 
3607fa27ce4SDimitry Andric   SmallVector<MachineInstr *> SinkableDbgValues =
3617fa27ce4SDimitry Andric       getSinkableDebugValues(Insert);
3627fa27ce4SDimitry Andric 
3637fa27ce4SDimitry Andric   // Clone Def first.
3647fa27ce4SDimitry Andric   if (CloneDef) {
3657fa27ce4SDimitry Andric     MachineInstr *Clone = MF->CloneMachineInstr(Def);
3667fa27ce4SDimitry Andric     // When cloning to a different BB, we preserve the debug loc only if the
3677fa27ce4SDimitry Andric     // destination BB contains the same location. See
3687fa27ce4SDimitry Andric     // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location.
3697fa27ce4SDimitry Andric     if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc()))
3707fa27ce4SDimitry Andric       Clone->setDebugLoc(DebugLoc());
3717fa27ce4SDimitry Andric     if (NewReg != CurrentReg && NewReg.isValid())
3727fa27ce4SDimitry Andric       Clone->getOperand(0).setReg(NewReg);
3737fa27ce4SDimitry Andric     MBB->insert(Insert, Clone);
3747fa27ce4SDimitry Andric   }
3757fa27ce4SDimitry Andric 
3767fa27ce4SDimitry Andric   if (DbgValues.empty())
3777fa27ce4SDimitry Andric     return;
3787fa27ce4SDimitry Andric 
3797fa27ce4SDimitry Andric   // Clone sinkable DBG_VALUEs and insert them.
3807fa27ce4SDimitry Andric   SmallVector<MachineInstr *, 1> NewDbgValues;
3817fa27ce4SDimitry Andric   for (MachineInstr *DV : SinkableDbgValues) {
3827fa27ce4SDimitry Andric     MachineInstr *Clone = MF->CloneMachineInstr(DV);
3837fa27ce4SDimitry Andric     MBB->insert(Insert, Clone);
3847fa27ce4SDimitry Andric     NewDbgValues.push_back(Clone);
3857fa27ce4SDimitry Andric   }
3867fa27ce4SDimitry Andric 
3877fa27ce4SDimitry Andric   if (NewReg != CurrentReg && NewReg.isValid())
3887fa27ce4SDimitry Andric     for (auto *DBI : NewDbgValues)
3897fa27ce4SDimitry Andric       for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
3907fa27ce4SDimitry Andric         MO.setReg(NewReg);
3917fa27ce4SDimitry Andric }
3927fa27ce4SDimitry Andric 
3937fa27ce4SDimitry Andric // Update the register for Def and DBG_VALUEs.
updateReg(Register Reg)3947fa27ce4SDimitry Andric void WebAssemblyDebugValueManager::updateReg(Register Reg) {
3957fa27ce4SDimitry Andric   if (Reg != CurrentReg && Reg.isValid()) {
396d8e91e46SDimitry Andric     for (auto *DBI : DbgValues)
397344a3780SDimitry Andric       for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
398344a3780SDimitry Andric         MO.setReg(Reg);
399344a3780SDimitry Andric     CurrentReg = Reg;
4007fa27ce4SDimitry Andric     Def->getOperand(0).setReg(Reg);
401d8e91e46SDimitry Andric   }
402d8e91e46SDimitry Andric }
403706b4fc4SDimitry Andric 
replaceWithLocal(unsigned LocalId)404706b4fc4SDimitry Andric void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) {
405706b4fc4SDimitry Andric   for (auto *DBI : DbgValues) {
406344a3780SDimitry Andric     auto IndexType = DBI->isIndirectDebugValue()
407344a3780SDimitry Andric                          ? llvm::WebAssembly::TI_LOCAL_INDIRECT
408344a3780SDimitry Andric                          : llvm::WebAssembly::TI_LOCAL;
409344a3780SDimitry Andric     for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
410344a3780SDimitry Andric       MO.ChangeToTargetIndex(IndexType, LocalId);
411706b4fc4SDimitry Andric   }
412706b4fc4SDimitry Andric }
4137fa27ce4SDimitry Andric 
4147fa27ce4SDimitry Andric // Remove Def, and set its DBG_VALUEs to undef.
removeDef()4157fa27ce4SDimitry Andric void WebAssemblyDebugValueManager::removeDef() {
4167fa27ce4SDimitry Andric   Def->removeFromParent();
4177fa27ce4SDimitry Andric   for (MachineInstr *DV : DbgValues)
4187fa27ce4SDimitry Andric     DV->setDebugValueUndef();
4197fa27ce4SDimitry Andric }
420