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" 15*fe013be4SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 16480093f4SDimitry Andric #include "WebAssembly.h" 170b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 19*fe013be4SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric using namespace llvm; 220b57cec5SDimitry Andric 23*fe013be4SDimitry Andric WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(MachineInstr *Def) 24*fe013be4SDimitry Andric : Def(Def) { 25e8d8bef9SDimitry Andric // This code differs from MachineInstr::collectDebugValues in that it scans 26*fe013be4SDimitry Andric // the whole BB, not just contiguous DBG_VALUEs, until another definition to 27*fe013be4SDimitry Andric // the same register is encountered. 28*fe013be4SDimitry Andric if (!Def->getOperand(0).isReg()) 29e8d8bef9SDimitry Andric return; 30*fe013be4SDimitry Andric CurrentReg = Def->getOperand(0).getReg(); 31e8d8bef9SDimitry Andric 32*fe013be4SDimitry Andric for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()), 33*fe013be4SDimitry Andric ME = Def->getParent()->end(); 34*fe013be4SDimitry Andric MI != ME; ++MI) { 35*fe013be4SDimitry Andric // If another definition appears, stop 36*fe013be4SDimitry Andric if (MI->definesRegister(CurrentReg)) 37*fe013be4SDimitry Andric break; 38*fe013be4SDimitry Andric if (MI->isDebugValue() && MI->hasDebugOperandForReg(CurrentReg)) 39*fe013be4SDimitry Andric DbgValues.push_back(&*MI); 40e8d8bef9SDimitry Andric } 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 43*fe013be4SDimitry Andric // Returns true if both A and B are the same CONST_I32/I64/F32/F64 instructions. 44*fe013be4SDimitry Andric // Doesn't include CONST_V128. 45*fe013be4SDimitry Andric static bool isSameScalarConst(const MachineInstr *A, const MachineInstr *B) { 46*fe013be4SDimitry Andric if (A->getOpcode() != B->getOpcode() || 47*fe013be4SDimitry Andric !WebAssembly::isScalarConst(A->getOpcode()) || 48*fe013be4SDimitry Andric !WebAssembly::isScalarConst(B->getOpcode())) 49*fe013be4SDimitry Andric return false; 50*fe013be4SDimitry Andric const MachineOperand &OpA = A->getOperand(1), &OpB = B->getOperand(1); 51*fe013be4SDimitry Andric if ((OpA.isImm() && OpB.isImm() && OpA.getImm() == OpB.getImm()) || 52*fe013be4SDimitry Andric (OpA.isFPImm() && OpB.isFPImm() && OpA.getFPImm() == OpB.getFPImm()) || 53*fe013be4SDimitry Andric (OpA.isGlobal() && OpB.isGlobal() && OpA.getGlobal() == OpB.getGlobal())) 54*fe013be4SDimitry Andric return true; 55*fe013be4SDimitry Andric return false; 56*fe013be4SDimitry Andric } 57*fe013be4SDimitry Andric 58*fe013be4SDimitry Andric SmallVector<MachineInstr *, 1> 59*fe013be4SDimitry Andric WebAssemblyDebugValueManager::getSinkableDebugValues( 60*fe013be4SDimitry Andric MachineInstr *Insert) const { 61*fe013be4SDimitry Andric if (DbgValues.empty()) 62*fe013be4SDimitry Andric return {}; 63*fe013be4SDimitry Andric // DBG_VALUEs between Def and Insert 64*fe013be4SDimitry Andric SmallVector<MachineInstr *, 8> DbgValuesInBetween; 65*fe013be4SDimitry Andric 66*fe013be4SDimitry Andric if (Def->getParent() == Insert->getParent()) { 67*fe013be4SDimitry Andric // When Def and Insert are within the same BB, check if Insert comes after 68*fe013be4SDimitry Andric // Def, because we only support sinking. 69*fe013be4SDimitry Andric bool DefFirst = false; 70*fe013be4SDimitry Andric for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()), 71*fe013be4SDimitry Andric ME = Def->getParent()->end(); 72*fe013be4SDimitry Andric MI != ME; ++MI) { 73*fe013be4SDimitry Andric if (&*MI == Insert) { 74*fe013be4SDimitry Andric DefFirst = true; 75*fe013be4SDimitry Andric break; 76*fe013be4SDimitry Andric } 77*fe013be4SDimitry Andric if (MI->isDebugValue()) 78*fe013be4SDimitry Andric DbgValuesInBetween.push_back(&*MI); 79*fe013be4SDimitry Andric } 80*fe013be4SDimitry Andric if (!DefFirst) // Not a sink 81*fe013be4SDimitry Andric return {}; 82*fe013be4SDimitry Andric 83*fe013be4SDimitry Andric } else { // Def and Insert are in different BBs 84*fe013be4SDimitry Andric // If Def and Insert are in different BBs, we only handle a simple case in 85*fe013be4SDimitry Andric // which Insert's BB is a successor of Def's BB. 86*fe013be4SDimitry Andric if (!Def->getParent()->isSuccessor(Insert->getParent())) 87*fe013be4SDimitry Andric return {}; 88*fe013be4SDimitry Andric 89*fe013be4SDimitry Andric // Gather DBG_VALUEs between 'Def~Def BB's end' and 90*fe013be4SDimitry Andric // 'Insert BB's begin~Insert' 91*fe013be4SDimitry Andric for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()), 92*fe013be4SDimitry Andric ME = Def->getParent()->end(); 93*fe013be4SDimitry Andric MI != ME; ++MI) { 94*fe013be4SDimitry Andric if (MI->isDebugValue()) 95*fe013be4SDimitry Andric DbgValuesInBetween.push_back(&*MI); 96*fe013be4SDimitry Andric } 97*fe013be4SDimitry Andric for (MachineBasicBlock::iterator MI = Insert->getParent()->begin(), 98*fe013be4SDimitry Andric ME = Insert->getIterator(); 99*fe013be4SDimitry Andric MI != ME; ++MI) { 100*fe013be4SDimitry Andric if (MI->isDebugValue()) 101*fe013be4SDimitry Andric DbgValuesInBetween.push_back(&*MI); 102*fe013be4SDimitry Andric } 103*fe013be4SDimitry Andric } 104*fe013be4SDimitry Andric 105*fe013be4SDimitry Andric // Gather DebugVariables that are seen between Def and Insert, excluding our 106*fe013be4SDimitry Andric // own DBG_VALUEs in DbgValues. 107*fe013be4SDimitry Andric SmallDenseMap<DebugVariable, SmallVector<MachineInstr *, 2>> 108*fe013be4SDimitry Andric SeenDbgVarToDbgValues; 109*fe013be4SDimitry Andric for (auto *DV : DbgValuesInBetween) { 110*fe013be4SDimitry Andric if (!llvm::is_contained(DbgValues, DV)) { 111*fe013be4SDimitry Andric DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(), 112*fe013be4SDimitry Andric DV->getDebugLoc()->getInlinedAt()); 113*fe013be4SDimitry Andric SeenDbgVarToDbgValues[Var].push_back(DV); 114*fe013be4SDimitry Andric } 115*fe013be4SDimitry Andric } 116*fe013be4SDimitry Andric 117*fe013be4SDimitry Andric // Gather sinkable DBG_VALUEs. We should not sink a DBG_VALUE if there is 118*fe013be4SDimitry Andric // another DBG_VALUE between Def and Insert referring to the same 119*fe013be4SDimitry Andric // DebugVariable. For example, 120*fe013be4SDimitry Andric // %0 = someinst 121*fe013be4SDimitry Andric // DBG_VALUE %0, !"a", !DIExpression() // Should not sink with %0 122*fe013be4SDimitry Andric // %1 = anotherinst 123*fe013be4SDimitry Andric // DBG_VALUE %1, !"a", !DIExpression() 124*fe013be4SDimitry Andric // Where if %0 were to sink, the DBG_VAUE should not sink with it, as that 125*fe013be4SDimitry Andric // would re-order assignments. 126*fe013be4SDimitry Andric SmallVector<MachineInstr *, 1> SinkableDbgValues; 127*fe013be4SDimitry Andric MachineRegisterInfo &MRI = Def->getParent()->getParent()->getRegInfo(); 128*fe013be4SDimitry Andric for (auto *DV : DbgValues) { 129*fe013be4SDimitry Andric DebugVariable Var(DV->getDebugVariable(), DV->getDebugExpression(), 130*fe013be4SDimitry Andric DV->getDebugLoc()->getInlinedAt()); 131*fe013be4SDimitry Andric auto It = SeenDbgVarToDbgValues.find(Var); 132*fe013be4SDimitry Andric if (It == SeenDbgVarToDbgValues.end()) { 133*fe013be4SDimitry Andric SinkableDbgValues.push_back(DV); 134*fe013be4SDimitry Andric continue; 135*fe013be4SDimitry Andric } 136*fe013be4SDimitry Andric if (!WebAssembly::isScalarConst(Def->getOpcode())) 137*fe013be4SDimitry Andric continue; 138*fe013be4SDimitry Andric auto &OverlappingDbgValues = It->second; 139*fe013be4SDimitry Andric bool Sinkable = true; 140*fe013be4SDimitry Andric for (auto *OverlappingDV : OverlappingDbgValues) { 141*fe013be4SDimitry Andric MachineOperand &DbgOp = OverlappingDV->getDebugOperand(0); 142*fe013be4SDimitry Andric if (!DbgOp.isReg()) { 143*fe013be4SDimitry Andric Sinkable = false; 144*fe013be4SDimitry Andric break; 145*fe013be4SDimitry Andric } 146*fe013be4SDimitry Andric Register OtherReg = DbgOp.getReg(); 147*fe013be4SDimitry Andric MachineInstr *OtherDef = MRI.getUniqueVRegDef(OtherReg); 148*fe013be4SDimitry Andric // We have an exception to allow encoutering other DBG_VALUEs with the 149*fe013be4SDimitry Andric // smae DebugVariables, only when they are referring to the same scalar 150*fe013be4SDimitry Andric // CONST instruction. For example, 151*fe013be4SDimitry Andric // %0 = CONST_I32 1 152*fe013be4SDimitry Andric // DBG_VALUE %0, !"a", !DIExpression() // Can sink with %0 153*fe013be4SDimitry Andric // %1 = CONST_I32 1 154*fe013be4SDimitry Andric // DBG_VALUE %1, !"a", !DIExpression() 155*fe013be4SDimitry Andric // When %0 were to be sunk/cloneed, the DBG_VALUE can be sunk/cloned with 156*fe013be4SDimitry Andric // it because even though the second DBG_VALUE refers to the same 157*fe013be4SDimitry Andric // DebugVariable, its value in effect is the same CONST instruction. 158*fe013be4SDimitry Andric // 159*fe013be4SDimitry Andric // This is to allow a case that can happen with RegStackify's 160*fe013be4SDimitry Andric // "rematerializeCheapDef". For example, we have this program with two 161*fe013be4SDimitry Andric // BBs: 162*fe013be4SDimitry Andric // bb0: 163*fe013be4SDimitry Andric // %0 = CONST_I32 1 164*fe013be4SDimitry Andric // DBG_VALUE %0, !"a", ... 165*fe013be4SDimitry Andric // ... 166*fe013be4SDimitry Andric // INST0 ..., $0 ... 167*fe013be4SDimitry Andric // bb1: 168*fe013be4SDimitry Andric // INST1 ..., $0 ... 169*fe013be4SDimitry Andric // INST2 ..., $0 ... 170*fe013be4SDimitry Andric // 171*fe013be4SDimitry Andric // We process bb0 first. Because %0 is used multiple times, %0 is cloned 172*fe013be4SDimitry Andric // before INST0: 173*fe013be4SDimitry Andric // bb0: 174*fe013be4SDimitry Andric // %0 = CONST_I32 1 175*fe013be4SDimitry Andric // DBG_VALUE %0, !"a", ... 176*fe013be4SDimitry Andric // ... 177*fe013be4SDimitry Andric // %1 = CONST_I32 1 178*fe013be4SDimitry Andric // DBG_VALUE %1, !"a", ... 179*fe013be4SDimitry Andric // INST0 ..., $1 ... 180*fe013be4SDimitry Andric // 181*fe013be4SDimitry Andric // And when we process bb1, we clone %0 and its DBG_VALUE again: 182*fe013be4SDimitry Andric // bb0: 183*fe013be4SDimitry Andric // %0 = CONST_I32 1 184*fe013be4SDimitry Andric // DBG_VALUE %0, !"a", ... 185*fe013be4SDimitry Andric // ... 186*fe013be4SDimitry Andric // %1 = CONST_I32 1 187*fe013be4SDimitry Andric // DBG_VALUE %1, !"a", ... 188*fe013be4SDimitry Andric // INST0 ..., $1 ... 189*fe013be4SDimitry Andric // bb1: 190*fe013be4SDimitry Andric // %2 = CONST_I32 1 191*fe013be4SDimitry Andric // DBG_VALUE %2, !"a", ... // !!! 192*fe013be4SDimitry Andric // INST1 ..., $2 ... 193*fe013be4SDimitry Andric // %3 = CONST_I32 1 194*fe013be4SDimitry Andric // DBG_VALUE %3, !"a", ... // !!! 195*fe013be4SDimitry Andric // INST2 ..., $3 ... 196*fe013be4SDimitry Andric // 197*fe013be4SDimitry Andric // But (without this exception) the cloned DBG_VALUEs marked with !!! are 198*fe013be4SDimitry Andric // not possible to be cloned, because there is a previously cloned 199*fe013be4SDimitry Andric // 'DBG_VALUE %1, !"a"' at the end of bb0 referring to the same 200*fe013be4SDimitry Andric // DebugVariable "a". But in this case they are OK to be cloned, because 201*fe013be4SDimitry Andric // the interfering DBG_VALUE is pointing to the same 'CONST_I32 1', 202*fe013be4SDimitry Andric // because it was cloned from the same instruction. 203*fe013be4SDimitry Andric if (!OtherDef || !isSameScalarConst(Def, OtherDef)) { 204*fe013be4SDimitry Andric Sinkable = false; 205*fe013be4SDimitry Andric break; 206*fe013be4SDimitry Andric } 207*fe013be4SDimitry Andric } 208*fe013be4SDimitry Andric if (Sinkable) 209*fe013be4SDimitry Andric SinkableDbgValues.push_back(DV); 210*fe013be4SDimitry Andric } 211*fe013be4SDimitry Andric return SinkableDbgValues; 212*fe013be4SDimitry Andric } 213*fe013be4SDimitry Andric 214*fe013be4SDimitry Andric // Returns true if the insertion point is the same as the current place. 215*fe013be4SDimitry Andric // Following DBG_VALUEs for 'Def' are ignored. 216*fe013be4SDimitry Andric bool WebAssemblyDebugValueManager::isInsertSamePlace( 217*fe013be4SDimitry Andric MachineInstr *Insert) const { 218*fe013be4SDimitry Andric if (Def->getParent() != Insert->getParent()) 219*fe013be4SDimitry Andric return false; 220*fe013be4SDimitry Andric for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()), 221*fe013be4SDimitry Andric ME = Insert; 222*fe013be4SDimitry Andric MI != ME; ++MI) { 223*fe013be4SDimitry Andric if (!llvm::is_contained(DbgValues, MI)) { 224*fe013be4SDimitry Andric return false; 225*fe013be4SDimitry Andric } 226*fe013be4SDimitry Andric } 227*fe013be4SDimitry Andric return true; 228*fe013be4SDimitry Andric } 229*fe013be4SDimitry Andric 230*fe013be4SDimitry Andric // Returns true if any instruction in MBB has the same debug location as DL. 231*fe013be4SDimitry Andric // Also returns true if DL is an empty location. 232*fe013be4SDimitry Andric static bool hasSameDebugLoc(const MachineBasicBlock *MBB, DebugLoc DL) { 233*fe013be4SDimitry Andric for (const auto &MI : *MBB) 234*fe013be4SDimitry Andric if (MI.getDebugLoc() == DL) 235*fe013be4SDimitry Andric return true; 236*fe013be4SDimitry Andric return false; 237*fe013be4SDimitry Andric } 238*fe013be4SDimitry Andric 239*fe013be4SDimitry Andric // Sink 'Def', and also sink its eligible DBG_VALUEs to the place before 240*fe013be4SDimitry Andric // 'Insert'. Convert the original DBG_VALUEs into undefs. 241*fe013be4SDimitry Andric // 242*fe013be4SDimitry Andric // For DBG_VALUEs to sink properly, if 'Def' and 'Insert' are within the same 243*fe013be4SDimitry Andric // BB, 'Insert' should be below 'Def'; if they are in different BBs, 'Insert' 244*fe013be4SDimitry Andric // should be in one of 'Def's BBs successors. Def will be sunk regardless of the 245*fe013be4SDimitry Andric // location. 246*fe013be4SDimitry Andric // 247*fe013be4SDimitry Andric // This DebugValueManager's new Def and DbgValues will be updated to the newly 248*fe013be4SDimitry Andric // sinked Def + DBG_VALUEs. 249*fe013be4SDimitry Andric void WebAssemblyDebugValueManager::sink(MachineInstr *Insert) { 250*fe013be4SDimitry Andric // In case Def is requested to be sunk to 251*fe013be4SDimitry Andric // the same place, we don't need to do anything. If we actually do the sink, 252*fe013be4SDimitry Andric // it will create unnecessary undef DBG_VALUEs. For example, if the original 253*fe013be4SDimitry Andric // code is: 254*fe013be4SDimitry Andric // %0 = someinst // Def 255*fe013be4SDimitry Andric // DBG_VALUE %0, ... 256*fe013be4SDimitry Andric // %1 = anotherinst // Insert 257*fe013be4SDimitry Andric // 258*fe013be4SDimitry Andric // If we actually sink %0 and the following DBG_VALUE and setting the original 259*fe013be4SDimitry Andric // DBG_VALUE undef, the result will be: 260*fe013be4SDimitry Andric // DBG_VALUE %noreg, ... // Unnecessary! 261*fe013be4SDimitry Andric // %0 = someinst // Def 262*fe013be4SDimitry Andric // DBG_VALUE %0, ... 263*fe013be4SDimitry Andric // %1 = anotherinst // Insert 264*fe013be4SDimitry Andric if (isInsertSamePlace(Insert)) 265*fe013be4SDimitry Andric return; 266*fe013be4SDimitry Andric 2670b57cec5SDimitry Andric MachineBasicBlock *MBB = Insert->getParent(); 268*fe013be4SDimitry Andric MachineFunction *MF = MBB->getParent(); 269*fe013be4SDimitry Andric 270*fe013be4SDimitry Andric // Get the list of sinkable DBG_VALUEs. This should be done before sinking 271*fe013be4SDimitry Andric // Def, because we need to examine instructions between Def and Insert. 272*fe013be4SDimitry Andric SmallVector<MachineInstr *, 1> SinkableDbgValues = 273*fe013be4SDimitry Andric getSinkableDebugValues(Insert); 274*fe013be4SDimitry Andric 275*fe013be4SDimitry Andric // Sink Def first. 276*fe013be4SDimitry Andric // 277*fe013be4SDimitry Andric // When moving to a different BB, we preserve the debug loc only if the 278*fe013be4SDimitry Andric // destination BB contains the same location. See 279*fe013be4SDimitry Andric // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location. 280*fe013be4SDimitry Andric if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc())) 281*fe013be4SDimitry Andric Def->setDebugLoc(DebugLoc()); 282*fe013be4SDimitry Andric MBB->splice(Insert, Def->getParent(), Def); 283*fe013be4SDimitry Andric 284*fe013be4SDimitry Andric if (DbgValues.empty()) 285*fe013be4SDimitry Andric return; 286*fe013be4SDimitry Andric 287*fe013be4SDimitry Andric // Clone sinkable DBG_VALUEs and insert them. 288*fe013be4SDimitry Andric SmallVector<MachineInstr *, 1> NewDbgValues; 289*fe013be4SDimitry Andric for (MachineInstr *DV : SinkableDbgValues) { 290*fe013be4SDimitry Andric MachineInstr *Clone = MF->CloneMachineInstr(DV); 291*fe013be4SDimitry Andric MBB->insert(Insert, Clone); 292*fe013be4SDimitry Andric NewDbgValues.push_back(Clone); 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 295*fe013be4SDimitry Andric // When sinking a Def and its DBG_VALUEs, we shouldn't just remove the 296*fe013be4SDimitry Andric // original DBG_VALUE instructions; we should set them to undef not to create 297*fe013be4SDimitry Andric // an impossible combination of variable assignments in the original program. 298*fe013be4SDimitry Andric // For example, this is the original program in order: 299*fe013be4SDimitry Andric // %0 = CONST_I32 0 300*fe013be4SDimitry Andric // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ? 301*fe013be4SDimitry Andric // %1 = CONST_I32 1 302*fe013be4SDimitry Andric // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1 303*fe013be4SDimitry Andric // %2 = CONST_I32 2 304*fe013be4SDimitry Andric // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 1 305*fe013be4SDimitry Andric // %3 = CONST_I32 3 306*fe013be4SDimitry Andric // DBG_VALUE %3, !"b", !DIExpression() // a = 2, b = 3 307*fe013be4SDimitry Andric // 308*fe013be4SDimitry Andric // If %2 were to sink below %3, if we just sink DBG_VALUE %1 with it, the 309*fe013be4SDimitry Andric // debug info will show the variable "b" is updated to 2, creating the 310*fe013be4SDimitry Andric // variable assignment combination of (a = 0, b = 3), which is not possible in 311*fe013be4SDimitry Andric // the original program: 312*fe013be4SDimitry Andric // %0 = CONST_I32 0 313*fe013be4SDimitry Andric // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ? 314*fe013be4SDimitry Andric // %1 = CONST_I32 1 315*fe013be4SDimitry Andric // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1 316*fe013be4SDimitry Andric // %3 = CONST_I32 3 317*fe013be4SDimitry Andric // DBG_VALUE %3, !"b", !DIExpression() // a = 0, b = 3 (Incorrect!) 318*fe013be4SDimitry Andric // %2 = CONST_I32 2 319*fe013be4SDimitry Andric // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 3 320*fe013be4SDimitry Andric // 321*fe013be4SDimitry Andric // To fix this,we leave an undef DBG_VALUE in its original place, so that the 322*fe013be4SDimitry Andric // result will be 323*fe013be4SDimitry Andric // %0 = CONST_I32 0 324*fe013be4SDimitry Andric // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ? 325*fe013be4SDimitry Andric // %1 = CONST_I32 1 326*fe013be4SDimitry Andric // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1 327*fe013be4SDimitry Andric // DBG_VALUE $noreg, !"a", !DIExpression() // a = ?, b = 1 328*fe013be4SDimitry Andric // %3 = CONST_I32 3 329*fe013be4SDimitry Andric // DBG_VALUE %3, !"b", !DIExpression() // a = ?, b = 3 330*fe013be4SDimitry Andric // %2 = CONST_I32 2 331*fe013be4SDimitry Andric // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 3 332*fe013be4SDimitry Andric // Now in the middle "a" will be shown as "optimized out", but it wouldn't 333*fe013be4SDimitry Andric // show the impossible combination of (a = 0, b = 3). 334*fe013be4SDimitry Andric for (MachineInstr *DV : DbgValues) 335*fe013be4SDimitry Andric DV->setDebugValueUndef(); 336*fe013be4SDimitry Andric 337*fe013be4SDimitry Andric DbgValues.swap(NewDbgValues); 338*fe013be4SDimitry Andric } 339*fe013be4SDimitry Andric 340*fe013be4SDimitry Andric // Clone 'Def', and also clone its eligible DBG_VALUEs to the place before 341*fe013be4SDimitry Andric // 'Insert'. 342*fe013be4SDimitry Andric // 343*fe013be4SDimitry Andric // For DBG_VALUEs to be cloned properly, if 'Def' and 'Insert' are within the 344*fe013be4SDimitry Andric // same BB, 'Insert' should be below 'Def'; if they are in different BBs, 345*fe013be4SDimitry Andric // 'Insert' should be in one of 'Def's BBs successors. Def will be cloned 346*fe013be4SDimitry Andric // regardless of the location. 347*fe013be4SDimitry Andric // 348*fe013be4SDimitry Andric // If NewReg is not $noreg, the newly cloned DBG_VALUEs will have the new 349*fe013be4SDimitry Andric // register as its operand. 350*fe013be4SDimitry Andric void WebAssemblyDebugValueManager::cloneSink(MachineInstr *Insert, 351*fe013be4SDimitry Andric Register NewReg, 352*fe013be4SDimitry Andric bool CloneDef) const { 353*fe013be4SDimitry Andric MachineBasicBlock *MBB = Insert->getParent(); 354*fe013be4SDimitry Andric MachineFunction *MF = MBB->getParent(); 355*fe013be4SDimitry Andric 356*fe013be4SDimitry Andric SmallVector<MachineInstr *> SinkableDbgValues = 357*fe013be4SDimitry Andric getSinkableDebugValues(Insert); 358*fe013be4SDimitry Andric 359*fe013be4SDimitry Andric // Clone Def first. 360*fe013be4SDimitry Andric if (CloneDef) { 361*fe013be4SDimitry Andric MachineInstr *Clone = MF->CloneMachineInstr(Def); 362*fe013be4SDimitry Andric // When cloning to a different BB, we preserve the debug loc only if the 363*fe013be4SDimitry Andric // destination BB contains the same location. See 364*fe013be4SDimitry Andric // https://llvm.org/docs/HowToUpdateDebugInfo.html#when-to-preserve-an-instruction-location. 365*fe013be4SDimitry Andric if (Def->getParent() != MBB && !hasSameDebugLoc(MBB, Def->getDebugLoc())) 366*fe013be4SDimitry Andric Clone->setDebugLoc(DebugLoc()); 367*fe013be4SDimitry Andric if (NewReg != CurrentReg && NewReg.isValid()) 368*fe013be4SDimitry Andric Clone->getOperand(0).setReg(NewReg); 369*fe013be4SDimitry Andric MBB->insert(Insert, Clone); 370*fe013be4SDimitry Andric } 371*fe013be4SDimitry Andric 372*fe013be4SDimitry Andric if (DbgValues.empty()) 373*fe013be4SDimitry Andric return; 374*fe013be4SDimitry Andric 375*fe013be4SDimitry Andric // Clone sinkable DBG_VALUEs and insert them. 376*fe013be4SDimitry Andric SmallVector<MachineInstr *, 1> NewDbgValues; 377*fe013be4SDimitry Andric for (MachineInstr *DV : SinkableDbgValues) { 378*fe013be4SDimitry Andric MachineInstr *Clone = MF->CloneMachineInstr(DV); 379*fe013be4SDimitry Andric MBB->insert(Insert, Clone); 380*fe013be4SDimitry Andric NewDbgValues.push_back(Clone); 381*fe013be4SDimitry Andric } 382*fe013be4SDimitry Andric 383*fe013be4SDimitry Andric if (NewReg != CurrentReg && NewReg.isValid()) 384*fe013be4SDimitry Andric for (auto *DBI : NewDbgValues) 385*fe013be4SDimitry Andric for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg)) 386*fe013be4SDimitry Andric MO.setReg(NewReg); 387*fe013be4SDimitry Andric } 388*fe013be4SDimitry Andric 389*fe013be4SDimitry Andric // Update the register for Def and DBG_VALUEs. 390*fe013be4SDimitry Andric void WebAssemblyDebugValueManager::updateReg(Register Reg) { 391*fe013be4SDimitry Andric if (Reg != CurrentReg && Reg.isValid()) { 3920b57cec5SDimitry Andric for (auto *DBI : DbgValues) 393fe6060f1SDimitry Andric for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg)) 394fe6060f1SDimitry Andric MO.setReg(Reg); 395fe6060f1SDimitry Andric CurrentReg = Reg; 396*fe013be4SDimitry Andric Def->getOperand(0).setReg(Reg); 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric } 399480093f4SDimitry Andric 400480093f4SDimitry Andric void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) { 401480093f4SDimitry Andric for (auto *DBI : DbgValues) { 402fe6060f1SDimitry Andric auto IndexType = DBI->isIndirectDebugValue() 403fe6060f1SDimitry Andric ? llvm::WebAssembly::TI_LOCAL_INDIRECT 404fe6060f1SDimitry Andric : llvm::WebAssembly::TI_LOCAL; 405fe6060f1SDimitry Andric for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg)) 406fe6060f1SDimitry Andric MO.ChangeToTargetIndex(IndexType, LocalId); 407480093f4SDimitry Andric } 408480093f4SDimitry Andric } 409*fe013be4SDimitry Andric 410*fe013be4SDimitry Andric // Remove Def, and set its DBG_VALUEs to undef. 411*fe013be4SDimitry Andric void WebAssemblyDebugValueManager::removeDef() { 412*fe013be4SDimitry Andric Def->removeFromParent(); 413*fe013be4SDimitry Andric for (MachineInstr *DV : DbgValues) 414*fe013be4SDimitry Andric DV->setDebugValueUndef(); 415*fe013be4SDimitry Andric } 416