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