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 *> 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 // Sink 'Def', and also sink its eligible DBG_VALUEs to the place before 230 // 'Insert'. Convert the original DBG_VALUEs into undefs. 231 // 232 // For DBG_VALUEs to sink properly, if 'Def' and 'Insert' are within the same 233 // BB, 'Insert' should be below 'Def'; if they are in different BBs, 'Insert' 234 // should be in one of 'Def's BBs successors. Def will be sunk regardless of the 235 // location. 236 // 237 // This DebugValueManager's new Def and DbgValues will be updated to the newly 238 // sinked Def + DBG_VALUEs. 239 void WebAssemblyDebugValueManager::sink(MachineInstr *Insert) { 240 // In case Def is requested to be sunk to 241 // the same place, we don't need to do anything. If we actually do the sink, 242 // it will create unnecessary undef DBG_VALUEs. For example, if the original 243 // code is: 244 // %0 = someinst // Def 245 // DBG_VALUE %0, ... 246 // %1 = anotherinst // Insert 247 // 248 // If we actually sink %0 and the following DBG_VALUE and setting the original 249 // DBG_VALUE undef, the result will be: 250 // DBG_VALUE %noreg, ... // Unnecessary! 251 // %0 = someinst // Def 252 // DBG_VALUE %0, ... 253 // %1 = anotherinst // Insert 254 if (isInsertSamePlace(Insert)) 255 return; 256 257 MachineBasicBlock *MBB = Insert->getParent(); 258 MachineFunction *MF = MBB->getParent(); 259 260 // Get the list of sinkable DBG_VALUEs. This should be done before sinking 261 // Def, because we need to examine instructions between Def and Insert. 262 SmallVector<MachineInstr *, 1> SinkableDbgValues = 263 getSinkableDebugValues(Insert); 264 265 // Sink Def first. 266 MBB->splice(Insert, Def->getParent(), Def); 267 268 if (DbgValues.empty()) 269 return; 270 271 // Clone sinkable DBG_VALUEs and insert them. 272 SmallVector<MachineInstr *, 1> NewDbgValues; 273 for (MachineInstr *DV : SinkableDbgValues) { 274 MachineInstr *Clone = MF->CloneMachineInstr(DV); 275 MBB->insert(Insert, Clone); 276 NewDbgValues.push_back(Clone); 277 } 278 279 // When sinking a Def and its DBG_VALUEs, we shouldn't just remove the 280 // original DBG_VALUE instructions; we should set them to undef not to create 281 // an impossible combination of variable assignments in the original program. 282 // For example, this is the original program in order: 283 // %0 = CONST_I32 0 284 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ? 285 // %1 = CONST_I32 1 286 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1 287 // %2 = CONST_I32 2 288 // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 1 289 // %3 = CONST_I32 3 290 // DBG_VALUE %3, !"b", !DIExpression() // a = 2, b = 3 291 // 292 // If %2 were to sink below %3, if we just sink DBG_VALUE %1 with it, the 293 // debug info will show the variable "b" is updated to 2, creating the 294 // variable assignment combination of (a = 0, b = 3), which is not possible in 295 // the original program: 296 // %0 = CONST_I32 0 297 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ? 298 // %1 = CONST_I32 1 299 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1 300 // %3 = CONST_I32 3 301 // DBG_VALUE %3, !"b", !DIExpression() // a = 0, b = 3 (Incorrect!) 302 // %2 = CONST_I32 2 303 // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 3 304 // 305 // To fix this,we leave an undef DBG_VALUE in its original place, so that the 306 // result will be 307 // %0 = CONST_I32 0 308 // DBG_VALUE %0, !"a", !DIExpression() // a = 0, b = ? 309 // %1 = CONST_I32 1 310 // DBG_VALUE %1, !"b", !DIExpression() // a = 0, b = 1 311 // DBG_VALUE $noreg, !"a", !DIExpression() // a = ?, b = 1 312 // %3 = CONST_I32 3 313 // DBG_VALUE %3, !"b", !DIExpression() // a = ?, b = 3 314 // %2 = CONST_I32 2 315 // DBG_VALUE %2, !"a", !DIExpression() // a = 2, b = 3 316 // Now in the middle "a" will be shown as "optimized out", but it wouldn't 317 // show the impossible combination of (a = 0, b = 3). 318 for (MachineInstr *DV : DbgValues) 319 DV->setDebugValueUndef(); 320 321 DbgValues.swap(NewDbgValues); 322 return; 323 } 324 325 // Clone 'Def', and also clone its eligible DBG_VALUEs to the place before 326 // 'Insert'. 327 // 328 // For DBG_VALUEs to be cloned properly, if 'Def' and 'Insert' are within the 329 // same BB, 'Insert' should be below 'Def'; if they are in different BBs, 330 // 'Insert' should be in one of 'Def's BBs successors. Def will be cloned 331 // regardless of the location. 332 // 333 // If NewReg is not $noreg, the newly cloned DBG_VALUEs will have the new 334 // register as its operand. 335 void WebAssemblyDebugValueManager::cloneSink(MachineInstr *Insert, 336 Register NewReg, 337 bool CloneDef) const { 338 MachineBasicBlock *MBB = Insert->getParent(); 339 MachineFunction *MF = MBB->getParent(); 340 341 SmallVector<MachineInstr *> SinkableDbgValues = 342 getSinkableDebugValues(Insert); 343 344 // Clone Def first. 345 if (CloneDef) { 346 MachineInstr *Clone = MF->CloneMachineInstr(Def); 347 if (NewReg != CurrentReg && NewReg.isValid()) 348 Clone->getOperand(0).setReg(NewReg); 349 MBB->insert(Insert, Clone); 350 } 351 352 if (DbgValues.empty()) 353 return; 354 355 // Clone sinkable DBG_VALUEs and insert them. 356 SmallVector<MachineInstr *, 1> NewDbgValues; 357 for (MachineInstr *DV : SinkableDbgValues) { 358 MachineInstr *Clone = MF->CloneMachineInstr(DV); 359 MBB->insert(Insert, Clone); 360 NewDbgValues.push_back(Clone); 361 } 362 363 if (NewReg != CurrentReg && NewReg.isValid()) 364 for (auto *DBI : NewDbgValues) 365 for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg)) 366 MO.setReg(NewReg); 367 } 368 369 // Update the register for Def and DBG_VALUEs. 370 void WebAssemblyDebugValueManager::updateReg(Register Reg) { 371 if (Reg != CurrentReg && Reg.isValid()) { 372 for (auto *DBI : DbgValues) 373 for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg)) 374 MO.setReg(Reg); 375 CurrentReg = Reg; 376 Def->getOperand(0).setReg(Reg); 377 } 378 } 379 380 void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) { 381 for (auto *DBI : DbgValues) { 382 auto IndexType = DBI->isIndirectDebugValue() 383 ? llvm::WebAssembly::TI_LOCAL_INDIRECT 384 : llvm::WebAssembly::TI_LOCAL; 385 for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg)) 386 MO.ChangeToTargetIndex(IndexType, LocalId); 387 } 388 } 389 390 // Remove Def, and set its DBG_VALUEs to undef. 391 void WebAssemblyDebugValueManager::removeDef() { 392 Def->removeFromParent(); 393 for (MachineInstr *DV : DbgValues) 394 DV->setDebugValueUndef(); 395 } 396