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