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