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