1 #include "llvm/CodeGen/AssignmentTrackingAnalysis.h" 2 #include "llvm/ADT/DenseMapInfo.h" 3 #include "llvm/ADT/IntervalMap.h" 4 #include "llvm/ADT/PostOrderIterator.h" 5 #include "llvm/ADT/STLExtras.h" 6 #include "llvm/ADT/SmallSet.h" 7 #include "llvm/ADT/Statistic.h" 8 #include "llvm/ADT/UniqueVector.h" 9 #include "llvm/Analysis/Interval.h" 10 #include "llvm/BinaryFormat/Dwarf.h" 11 #include "llvm/IR/BasicBlock.h" 12 #include "llvm/IR/DataLayout.h" 13 #include "llvm/IR/DebugInfo.h" 14 #include "llvm/IR/Function.h" 15 #include "llvm/IR/Instruction.h" 16 #include "llvm/IR/IntrinsicInst.h" 17 #include "llvm/IR/PassManager.h" 18 #include "llvm/IR/PrintPasses.h" 19 #include "llvm/InitializePasses.h" 20 #include "llvm/Support/CommandLine.h" 21 #include "llvm/Support/ErrorHandling.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 24 #include <assert.h> 25 #include <cstdint> 26 #include <optional> 27 #include <sstream> 28 #include <unordered_map> 29 30 using namespace llvm; 31 #define DEBUG_TYPE "debug-ata" 32 33 STATISTIC(NumDefsScanned, "Number of dbg locs that get scanned for removal"); 34 STATISTIC(NumDefsRemoved, "Number of dbg locs removed"); 35 STATISTIC(NumWedgesScanned, "Number of dbg wedges scanned"); 36 STATISTIC(NumWedgesChanged, "Number of dbg wedges changed"); 37 38 static cl::opt<unsigned> 39 MaxNumBlocks("debug-ata-max-blocks", cl::init(10000), 40 cl::desc("Maximum num basic blocks before debug info dropped"), 41 cl::Hidden); 42 /// Option for debugging the pass, determines if the memory location fragment 43 /// filling happens after generating the variable locations. 44 static cl::opt<bool> EnableMemLocFragFill("mem-loc-frag-fill", cl::init(true), 45 cl::Hidden); 46 /// Print the results of the analysis. Respects -filter-print-funcs. 47 static cl::opt<bool> PrintResults("print-debug-ata", cl::init(false), 48 cl::Hidden); 49 50 // Implicit conversions are disabled for enum class types, so unfortunately we 51 // need to create a DenseMapInfo wrapper around the specified underlying type. 52 template <> struct llvm::DenseMapInfo<VariableID> { 53 using Wrapped = DenseMapInfo<unsigned>; 54 static inline VariableID getEmptyKey() { 55 return static_cast<VariableID>(Wrapped::getEmptyKey()); 56 } 57 static inline VariableID getTombstoneKey() { 58 return static_cast<VariableID>(Wrapped::getTombstoneKey()); 59 } 60 static unsigned getHashValue(const VariableID &Val) { 61 return Wrapped::getHashValue(static_cast<unsigned>(Val)); 62 } 63 static bool isEqual(const VariableID &LHS, const VariableID &RHS) { 64 return LHS == RHS; 65 } 66 }; 67 68 /// Helper class to build FunctionVarLocs, since that class isn't easy to 69 /// modify. TODO: There's not a great deal of value in the split, it could be 70 /// worth merging the two classes. 71 class FunctionVarLocsBuilder { 72 friend FunctionVarLocs; 73 UniqueVector<DebugVariable> Variables; 74 // Use an unordered_map so we don't invalidate iterators after 75 // insert/modifications. 76 std::unordered_map<const Instruction *, SmallVector<VarLocInfo>> 77 VarLocsBeforeInst; 78 79 SmallVector<VarLocInfo> SingleLocVars; 80 81 public: 82 /// Find or insert \p V and return the ID. 83 VariableID insertVariable(DebugVariable V) { 84 return static_cast<VariableID>(Variables.insert(V)); 85 } 86 87 /// Get a variable from its \p ID. 88 const DebugVariable &getVariable(VariableID ID) const { 89 return Variables[static_cast<unsigned>(ID)]; 90 } 91 92 /// Return ptr to wedge of defs or nullptr if no defs come just before /p 93 /// Before. 94 const SmallVectorImpl<VarLocInfo> *getWedge(const Instruction *Before) const { 95 auto R = VarLocsBeforeInst.find(Before); 96 if (R == VarLocsBeforeInst.end()) 97 return nullptr; 98 return &R->second; 99 } 100 101 /// Replace the defs that come just before /p Before with /p Wedge. 102 void setWedge(const Instruction *Before, SmallVector<VarLocInfo> &&Wedge) { 103 VarLocsBeforeInst[Before] = std::move(Wedge); 104 } 105 106 /// Add a def for a variable that is valid for its lifetime. 107 void addSingleLocVar(DebugVariable Var, DIExpression *Expr, DebugLoc DL, 108 Value *V) { 109 VarLocInfo VarLoc; 110 VarLoc.VariableID = insertVariable(Var); 111 VarLoc.Expr = Expr; 112 VarLoc.DL = DL; 113 VarLoc.V = V; 114 SingleLocVars.emplace_back(VarLoc); 115 } 116 117 /// Add a def to the wedge of defs just before /p Before. 118 void addVarLoc(Instruction *Before, DebugVariable Var, DIExpression *Expr, 119 DebugLoc DL, Value *V) { 120 VarLocInfo VarLoc; 121 VarLoc.VariableID = insertVariable(Var); 122 VarLoc.Expr = Expr; 123 VarLoc.DL = DL; 124 VarLoc.V = V; 125 VarLocsBeforeInst[Before].emplace_back(VarLoc); 126 } 127 }; 128 129 void FunctionVarLocs::print(raw_ostream &OS, const Function &Fn) const { 130 // Print the variable table first. TODO: Sorting by variable could make the 131 // output more stable? 132 unsigned Counter = -1; 133 OS << "=== Variables ===\n"; 134 for (const DebugVariable &V : Variables) { 135 ++Counter; 136 // Skip first entry because it is a dummy entry. 137 if (Counter == 0) { 138 continue; 139 } 140 OS << "[" << Counter << "] " << V.getVariable()->getName(); 141 if (auto F = V.getFragment()) 142 OS << " bits [" << F->OffsetInBits << ", " 143 << F->OffsetInBits + F->SizeInBits << ")"; 144 if (const auto *IA = V.getInlinedAt()) 145 OS << " inlined-at " << *IA; 146 OS << "\n"; 147 } 148 149 auto PrintLoc = [&OS](const VarLocInfo &Loc) { 150 OS << "DEF Var=[" << (unsigned)Loc.VariableID << "]" 151 << " Expr=" << *Loc.Expr << " V=" << *Loc.V << "\n"; 152 }; 153 154 // Print the single location variables. 155 OS << "=== Single location vars ===\n"; 156 for (auto It = single_locs_begin(), End = single_locs_end(); It != End; 157 ++It) { 158 PrintLoc(*It); 159 } 160 161 // Print the non-single-location defs in line with IR. 162 OS << "=== In-line variable defs ==="; 163 for (const BasicBlock &BB : Fn) { 164 OS << "\n" << BB.getName() << ":\n"; 165 for (const Instruction &I : BB) { 166 for (auto It = locs_begin(&I), End = locs_end(&I); It != End; ++It) { 167 PrintLoc(*It); 168 } 169 OS << I << "\n"; 170 } 171 } 172 } 173 174 void FunctionVarLocs::init(FunctionVarLocsBuilder &Builder) { 175 // Add the single-location variables first. 176 for (const auto &VarLoc : Builder.SingleLocVars) 177 VarLocRecords.emplace_back(VarLoc); 178 // Mark the end of the section. 179 SingleVarLocEnd = VarLocRecords.size(); 180 181 // Insert a contiguous block of VarLocInfos for each instruction, mapping it 182 // to the start and end position in the vector with VarLocsBeforeInst. 183 for (auto &P : Builder.VarLocsBeforeInst) { 184 unsigned BlockStart = VarLocRecords.size(); 185 for (const VarLocInfo &VarLoc : P.second) 186 VarLocRecords.emplace_back(VarLoc); 187 unsigned BlockEnd = VarLocRecords.size(); 188 // Record the start and end indices. 189 if (BlockEnd != BlockStart) 190 VarLocsBeforeInst[P.first] = {BlockStart, BlockEnd}; 191 } 192 193 // Copy the Variables vector from the builder's UniqueVector. 194 assert(Variables.empty() && "Expect clear before init"); 195 // UniqueVectors IDs are one-based (which means the VarLocInfo VarID values 196 // are one-based) so reserve an extra and insert a dummy. 197 Variables.reserve(Builder.Variables.size() + 1); 198 Variables.push_back(DebugVariable(nullptr, std::nullopt, nullptr)); 199 Variables.append(Builder.Variables.begin(), Builder.Variables.end()); 200 } 201 202 void FunctionVarLocs::clear() { 203 Variables.clear(); 204 VarLocRecords.clear(); 205 VarLocsBeforeInst.clear(); 206 SingleVarLocEnd = 0; 207 } 208 209 /// Walk backwards along constant GEPs and bitcasts to the base storage from \p 210 /// Start as far as possible. Prepend \Expression with the offset and append it 211 /// with a DW_OP_deref that haes been implicit until now. Returns the walked-to 212 /// value and modified expression. 213 static std::pair<Value *, DIExpression *> 214 walkToAllocaAndPrependOffsetDeref(const DataLayout &DL, Value *Start, 215 DIExpression *Expression) { 216 APInt OffsetInBytes(DL.getTypeSizeInBits(Start->getType()), false); 217 Value *End = 218 Start->stripAndAccumulateInBoundsConstantOffsets(DL, OffsetInBytes); 219 SmallVector<uint64_t, 3> Ops; 220 if (OffsetInBytes.getBoolValue()) { 221 Ops = {dwarf::DW_OP_plus_uconst, OffsetInBytes.getZExtValue()}; 222 Expression = DIExpression::prependOpcodes( 223 Expression, Ops, /*StackValue=*/false, /*EntryValue=*/false); 224 } 225 Expression = DIExpression::append(Expression, {dwarf::DW_OP_deref}); 226 return {End, Expression}; 227 } 228 229 /// Extract the offset used in \p DIExpr. Returns std::nullopt if the expression 230 /// doesn't explicitly describe a memory location with DW_OP_deref or if the 231 /// expression is too complex to interpret. 232 static std::optional<int64_t> 233 getDerefOffsetInBytes(const DIExpression *DIExpr) { 234 int64_t Offset = 0; 235 const unsigned NumElements = DIExpr->getNumElements(); 236 const auto Elements = DIExpr->getElements(); 237 unsigned ExpectedDerefIdx = 0; 238 // Extract the offset. 239 if (NumElements > 2 && Elements[0] == dwarf::DW_OP_plus_uconst) { 240 Offset = Elements[1]; 241 ExpectedDerefIdx = 2; 242 } else if (NumElements > 3 && Elements[0] == dwarf::DW_OP_constu) { 243 ExpectedDerefIdx = 3; 244 if (Elements[2] == dwarf::DW_OP_plus) 245 Offset = Elements[1]; 246 else if (Elements[2] == dwarf::DW_OP_minus) 247 Offset = -Elements[1]; 248 else 249 return std::nullopt; 250 } 251 252 // If that's all there is it means there's no deref. 253 if (ExpectedDerefIdx >= NumElements) 254 return std::nullopt; 255 256 // Check the next element is DW_OP_deref - otherwise this is too complex or 257 // isn't a deref expression. 258 if (Elements[ExpectedDerefIdx] != dwarf::DW_OP_deref) 259 return std::nullopt; 260 261 // Check the final operation is either the DW_OP_deref or is a fragment. 262 if (NumElements == ExpectedDerefIdx + 1) 263 return Offset; // Ends with deref. 264 unsigned ExpectedFragFirstIdx = ExpectedDerefIdx + 1; 265 unsigned ExpectedFragFinalIdx = ExpectedFragFirstIdx + 2; 266 if (NumElements == ExpectedFragFinalIdx + 1 && 267 Elements[ExpectedFragFirstIdx] == dwarf::DW_OP_LLVM_fragment) 268 return Offset; // Ends with deref + fragment. 269 270 // Don't bother trying to interpret anything more complex. 271 return std::nullopt; 272 } 273 274 /// A whole (unfragmented) source variable. 275 using DebugAggregate = std::pair<const DILocalVariable *, const DILocation *>; 276 static DebugAggregate getAggregate(const DbgVariableIntrinsic *DII) { 277 return DebugAggregate(DII->getVariable(), DII->getDebugLoc().getInlinedAt()); 278 } 279 static DebugAggregate getAggregate(const DebugVariable &Var) { 280 return DebugAggregate(Var.getVariable(), Var.getInlinedAt()); 281 } 282 283 namespace { 284 /// In dwarf emission, the following sequence 285 /// 1. dbg.value ... Fragment(0, 64) 286 /// 2. dbg.value ... Fragment(0, 32) 287 /// effectively sets Fragment(32, 32) to undef (each def sets all bits not in 288 /// the intersection of the fragments to having "no location"). This makes 289 /// sense for implicit location values because splitting the computed values 290 /// could be troublesome, and is probably quite uncommon. When we convert 291 /// dbg.assigns to dbg.value+deref this kind of thing is common, and describing 292 /// a location (memory) rather than a value means we don't need to worry about 293 /// splitting any values, so we try to recover the rest of the fragment 294 /// location here. 295 /// This class performs a(nother) dataflow analysis over the function, adding 296 /// variable locations so that any bits of a variable with a memory location 297 /// have that location explicitly reinstated at each subsequent variable 298 /// location definition that that doesn't overwrite those bits. i.e. after a 299 /// variable location def, insert new defs for the memory location with 300 /// fragments for the difference of "all bits currently in memory" and "the 301 /// fragment of the second def". 302 class MemLocFragmentFill { 303 Function &Fn; 304 FunctionVarLocsBuilder *FnVarLocs; 305 const DenseSet<DebugAggregate> *VarsWithStackSlot; 306 307 // 0 = no memory location. 308 using BaseAddress = unsigned; 309 using OffsetInBitsTy = unsigned; 310 using FragTraits = IntervalMapHalfOpenInfo<OffsetInBitsTy>; 311 using FragsInMemMap = IntervalMap< 312 OffsetInBitsTy, BaseAddress, 313 IntervalMapImpl::NodeSizer<OffsetInBitsTy, BaseAddress>::LeafSize, 314 FragTraits>; 315 FragsInMemMap::Allocator IntervalMapAlloc; 316 using VarFragMap = DenseMap<unsigned, FragsInMemMap>; 317 318 /// IDs for memory location base addresses in maps. Use 0 to indicate that 319 /// there's no memory location. 320 UniqueVector<Value *> Bases; 321 UniqueVector<DebugAggregate> Aggregates; 322 DenseMap<const BasicBlock *, VarFragMap> LiveIn; 323 DenseMap<const BasicBlock *, VarFragMap> LiveOut; 324 325 struct FragMemLoc { 326 unsigned Var; 327 unsigned Base; 328 unsigned OffsetInBits; 329 unsigned SizeInBits; 330 DebugLoc DL; 331 }; 332 using InsertMap = MapVector<Instruction *, SmallVector<FragMemLoc>>; 333 334 /// BBInsertBeforeMap holds a description for the set of location defs to be 335 /// inserted after the analysis is complete. It is updated during the dataflow 336 /// and the entry for a block is CLEARED each time it is (re-)visited. After 337 /// the dataflow is complete, each block entry will contain the set of defs 338 /// calculated during the final (fixed-point) iteration. 339 DenseMap<const BasicBlock *, InsertMap> BBInsertBeforeMap; 340 341 static bool intervalMapsAreEqual(const FragsInMemMap &A, 342 const FragsInMemMap &B) { 343 auto AIt = A.begin(), AEnd = A.end(); 344 auto BIt = B.begin(), BEnd = B.end(); 345 for (; AIt != AEnd; ++AIt, ++BIt) { 346 if (BIt == BEnd) 347 return false; // B has fewer elements than A. 348 if (AIt.start() != BIt.start() || AIt.stop() != BIt.stop()) 349 return false; // Interval is different. 350 if (*AIt != *BIt) 351 return false; // Value at interval is different. 352 } 353 // AIt == AEnd. Check BIt is also now at end. 354 return BIt == BEnd; 355 } 356 357 static bool varFragMapsAreEqual(const VarFragMap &A, const VarFragMap &B) { 358 if (A.size() != B.size()) 359 return false; 360 for (const auto &APair : A) { 361 auto BIt = B.find(APair.first); 362 if (BIt == B.end()) 363 return false; 364 if (!intervalMapsAreEqual(APair.second, BIt->second)) 365 return false; 366 } 367 return true; 368 } 369 370 /// Return a string for the value that \p BaseID represents. 371 std::string toString(unsigned BaseID) { 372 if (BaseID) 373 return Bases[BaseID]->getName().str(); 374 else 375 return "None"; 376 } 377 378 /// Format string describing an FragsInMemMap (IntervalMap) interval. 379 std::string toString(FragsInMemMap::const_iterator It, bool Newline = true) { 380 std::string String; 381 std::stringstream S(String); 382 if (It.valid()) { 383 S << "[" << It.start() << ", " << It.stop() 384 << "): " << toString(It.value()); 385 } else { 386 S << "invalid iterator (end)"; 387 } 388 if (Newline) 389 S << "\n"; 390 return S.str(); 391 }; 392 393 FragsInMemMap meetFragments(const FragsInMemMap &A, const FragsInMemMap &B) { 394 FragsInMemMap Result(IntervalMapAlloc); 395 for (auto AIt = A.begin(), AEnd = A.end(); AIt != AEnd; ++AIt) { 396 LLVM_DEBUG(dbgs() << "a " << toString(AIt)); 397 // This is basically copied from process() and inverted (process is 398 // performing something like a union whereas this is more of an 399 // intersect). 400 401 // There's no work to do if interval `a` overlaps no fragments in map `B`. 402 if (!B.overlaps(AIt.start(), AIt.stop())) 403 continue; 404 405 // Does StartBit intersect an existing fragment? 406 auto FirstOverlap = B.find(AIt.start()); 407 assert(FirstOverlap != B.end()); 408 bool IntersectStart = FirstOverlap.start() < AIt.start(); 409 LLVM_DEBUG(dbgs() << "- FirstOverlap " << toString(FirstOverlap, false) 410 << ", IntersectStart: " << IntersectStart << "\n"); 411 412 // Does EndBit intersect an existing fragment? 413 auto LastOverlap = B.find(AIt.stop()); 414 bool IntersectEnd = 415 LastOverlap != B.end() && LastOverlap.start() < AIt.stop(); 416 LLVM_DEBUG(dbgs() << "- LastOverlap " << toString(LastOverlap, false) 417 << ", IntersectEnd: " << IntersectEnd << "\n"); 418 419 // Check if both ends of `a` intersect the same interval `b`. 420 if (IntersectStart && IntersectEnd && FirstOverlap == LastOverlap) { 421 // Insert `a` (`a` is contained in `b`) if the values match. 422 // [ a ] 423 // [ - b - ] 424 // - 425 // [ r ] 426 LLVM_DEBUG(dbgs() << "- a is contained within " 427 << toString(FirstOverlap)); 428 if (*AIt && *AIt == *FirstOverlap) 429 Result.insert(AIt.start(), AIt.stop(), *AIt); 430 } else { 431 // There's an overlap but `a` is not fully contained within 432 // `b`. Shorten any end-point intersections. 433 // [ - a - ] 434 // [ - b - ] 435 // - 436 // [ r ] 437 auto Next = FirstOverlap; 438 if (IntersectStart) { 439 LLVM_DEBUG(dbgs() << "- insert intersection of a and " 440 << toString(FirstOverlap)); 441 if (*AIt && *AIt == *FirstOverlap) 442 Result.insert(AIt.start(), FirstOverlap.stop(), *AIt); 443 ++Next; 444 } 445 // [ - a - ] 446 // [ - b - ] 447 // - 448 // [ r ] 449 if (IntersectEnd) { 450 LLVM_DEBUG(dbgs() << "- insert intersection of a and " 451 << toString(LastOverlap)); 452 if (*AIt && *AIt == *LastOverlap) 453 Result.insert(LastOverlap.start(), AIt.stop(), *AIt); 454 } 455 456 // Insert all intervals in map `B` that are contained within interval 457 // `a` where the values match. 458 // [ - - a - - ] 459 // [ b1 ] [ b2 ] 460 // - 461 // [ r1 ] [ r2 ] 462 while (Next != B.end() && Next.start() < AIt.stop() && 463 Next.stop() <= AIt.stop()) { 464 LLVM_DEBUG(dbgs() 465 << "- insert intersection of a and " << toString(Next)); 466 if (*AIt && *AIt == *Next) 467 Result.insert(Next.start(), Next.stop(), *Next); 468 ++Next; 469 } 470 } 471 } 472 return Result; 473 } 474 475 /// Meet \p A and \p B, storing the result in \p A. 476 void meetVars(VarFragMap &A, const VarFragMap &B) { 477 // Meet A and B. 478 // 479 // Result = meet(a, b) for a in A, b in B where Var(a) == Var(b) 480 for (auto It = A.begin(), End = A.end(); It != End; ++It) { 481 unsigned AVar = It->first; 482 FragsInMemMap &AFrags = It->second; 483 auto BIt = B.find(AVar); 484 if (BIt == B.end()) { 485 A.erase(It); 486 continue; // Var has no bits defined in B. 487 } 488 LLVM_DEBUG(dbgs() << "meet fragment maps for " 489 << Aggregates[AVar].first->getName() << "\n"); 490 AFrags = meetFragments(AFrags, BIt->second); 491 } 492 } 493 494 bool meet(const BasicBlock &BB, 495 const SmallPtrSet<BasicBlock *, 16> &Visited) { 496 LLVM_DEBUG(dbgs() << "meet block info from preds of " << BB.getName() 497 << "\n"); 498 499 VarFragMap BBLiveIn; 500 bool FirstMeet = true; 501 // LiveIn locs for BB is the meet of the already-processed preds' LiveOut 502 // locs. 503 for (auto I = pred_begin(&BB), E = pred_end(&BB); I != E; I++) { 504 // Ignore preds that haven't been processed yet. This is essentially the 505 // same as initialising all variables to implicit top value (⊤) which is 506 // the identity value for the meet operation. 507 const BasicBlock *Pred = *I; 508 if (!Visited.count(Pred)) 509 continue; 510 511 auto PredLiveOut = LiveOut.find(Pred); 512 assert(PredLiveOut != LiveOut.end()); 513 514 if (FirstMeet) { 515 LLVM_DEBUG(dbgs() << "BBLiveIn = " << Pred->getName() << "\n"); 516 BBLiveIn = PredLiveOut->second; 517 FirstMeet = false; 518 } else { 519 LLVM_DEBUG(dbgs() << "BBLiveIn = meet BBLiveIn, " << Pred->getName() 520 << "\n"); 521 meetVars(BBLiveIn, PredLiveOut->second); 522 } 523 524 // An empty set is ⊥ for the intersect-like meet operation. If we've 525 // already got ⊥ there's no need to run the code - we know the result is 526 // ⊥ since `meet(a, ⊥) = ⊥`. 527 if (BBLiveIn.size() == 0) 528 break; 529 } 530 531 auto CurrentLiveInEntry = LiveIn.find(&BB); 532 // If there's no LiveIn entry for the block yet, add it. 533 if (CurrentLiveInEntry == LiveIn.end()) { 534 LLVM_DEBUG(dbgs() << "change=true (first) on meet on " << BB.getName() 535 << "\n"); 536 LiveIn[&BB] = std::move(BBLiveIn); 537 return /*Changed=*/true; 538 } 539 540 // If the LiveIn set has changed (expensive check) update it and return 541 // true. 542 if (!varFragMapsAreEqual(BBLiveIn, CurrentLiveInEntry->second)) { 543 LLVM_DEBUG(dbgs() << "change=true on meet on " << BB.getName() << "\n"); 544 CurrentLiveInEntry->second = std::move(BBLiveIn); 545 return /*Changed=*/true; 546 } 547 548 LLVM_DEBUG(dbgs() << "change=false on meet on " << BB.getName() << "\n"); 549 return /*Changed=*/false; 550 } 551 552 void insertMemLoc(BasicBlock &BB, Instruction &Before, unsigned Var, 553 unsigned StartBit, unsigned EndBit, unsigned Base, 554 DebugLoc DL) { 555 assert(StartBit < EndBit && "Cannot create fragment of size <= 0"); 556 if (!Base) 557 return; 558 FragMemLoc Loc; 559 Loc.Var = Var; 560 Loc.OffsetInBits = StartBit; 561 Loc.SizeInBits = EndBit - StartBit; 562 assert(Base && "Expected a non-zero ID for Base address"); 563 Loc.Base = Base; 564 Loc.DL = DL; 565 BBInsertBeforeMap[&BB][&Before].push_back(Loc); 566 LLVM_DEBUG(dbgs() << "Add mem def for " << Aggregates[Var].first->getName() 567 << " bits [" << StartBit << ", " << EndBit << ")\n"); 568 } 569 570 void addDef(const VarLocInfo &VarLoc, Instruction &Before, BasicBlock &BB, 571 VarFragMap &LiveSet) { 572 DebugVariable DbgVar = FnVarLocs->getVariable(VarLoc.VariableID); 573 if (skipVariable(DbgVar.getVariable())) 574 return; 575 // Don't bother doing anything for this variables if we know it's fully 576 // promoted. We're only interested in variables that (sometimes) live on 577 // the stack here. 578 if (!VarsWithStackSlot->count(getAggregate(DbgVar))) 579 return; 580 unsigned Var = Aggregates.insert( 581 DebugAggregate(DbgVar.getVariable(), VarLoc.DL.getInlinedAt())); 582 583 // [StartBit: EndBit) are the bits affected by this def. 584 const DIExpression *DIExpr = VarLoc.Expr; 585 unsigned StartBit; 586 unsigned EndBit; 587 if (auto Frag = DIExpr->getFragmentInfo()) { 588 StartBit = Frag->OffsetInBits; 589 EndBit = StartBit + Frag->SizeInBits; 590 } else { 591 assert(static_cast<bool>(DbgVar.getVariable()->getSizeInBits())); 592 StartBit = 0; 593 EndBit = *DbgVar.getVariable()->getSizeInBits(); 594 } 595 596 // We will only fill fragments for simple memory-describing dbg.value 597 // intrinsics. If the fragment offset is the same as the offset from the 598 // base pointer, do The Thing, otherwise fall back to normal dbg.value 599 // behaviour. AssignmentTrackingLowering has generated DIExpressions 600 // written in terms of the base pointer. 601 // TODO: Remove this condition since the fragment offset doesn't always 602 // equal the offset from base pointer (e.g. for a SROA-split variable). 603 const auto DerefOffsetInBytes = getDerefOffsetInBytes(DIExpr); 604 const unsigned Base = 605 DerefOffsetInBytes && *DerefOffsetInBytes * 8 == StartBit 606 ? Bases.insert(VarLoc.V) 607 : 0; 608 LLVM_DEBUG(dbgs() << "DEF " << DbgVar.getVariable()->getName() << " [" 609 << StartBit << ", " << EndBit << "): " << toString(Base) 610 << "\n"); 611 612 // First of all, any locs that use mem that are disrupted need reinstating. 613 // Unfortunately, IntervalMap doesn't let us insert intervals that overlap 614 // with existing intervals so this code involves a lot of fiddling around 615 // with intervals to do that manually. 616 auto FragIt = LiveSet.find(Var); 617 618 // Check if the variable does not exist in the map. 619 if (FragIt == LiveSet.end()) { 620 // Add this variable to the BB map. 621 auto P = LiveSet.try_emplace(Var, FragsInMemMap(IntervalMapAlloc)); 622 assert(P.second && "Var already in map?"); 623 // Add the interval to the fragment map. 624 P.first->second.insert(StartBit, EndBit, Base); 625 return; 626 } 627 // The variable has an entry in the map. 628 629 FragsInMemMap &FragMap = FragIt->second; 630 // First check the easy case: the new fragment `f` doesn't overlap with any 631 // intervals. 632 if (!FragMap.overlaps(StartBit, EndBit)) { 633 LLVM_DEBUG(dbgs() << "- No overlaps\n"); 634 FragMap.insert(StartBit, EndBit, Base); 635 return; 636 } 637 // There is at least one overlap. 638 639 // Does StartBit intersect an existing fragment? 640 auto FirstOverlap = FragMap.find(StartBit); 641 assert(FirstOverlap != FragMap.end()); 642 bool IntersectStart = FirstOverlap.start() < StartBit; 643 644 // Does EndBit intersect an existing fragment? 645 auto LastOverlap = FragMap.find(EndBit); 646 bool IntersectEnd = LastOverlap.valid() && LastOverlap.start() < EndBit; 647 648 // Check if both ends of `f` intersect the same interval `i`. 649 if (IntersectStart && IntersectEnd && FirstOverlap == LastOverlap) { 650 LLVM_DEBUG(dbgs() << "- Intersect single interval @ both ends\n"); 651 // Shorten `i` so that there's space to insert `f`. 652 // [ f ] 653 // [ - i - ] 654 // + 655 // [ i ][ f ][ i ] 656 657 // Save values for use after inserting a new interval. 658 auto EndBitOfOverlap = FirstOverlap.stop(); 659 unsigned OverlapValue = FirstOverlap.value(); 660 661 // Shorten the overlapping interval. 662 FirstOverlap.setStop(StartBit); 663 insertMemLoc(BB, Before, Var, FirstOverlap.start(), StartBit, 664 OverlapValue, VarLoc.DL); 665 666 // Insert a new interval to represent the end part. 667 FragMap.insert(EndBit, EndBitOfOverlap, OverlapValue); 668 insertMemLoc(BB, Before, Var, EndBit, EndBitOfOverlap, OverlapValue, 669 VarLoc.DL); 670 671 // Insert the new (middle) fragment now there is space. 672 FragMap.insert(StartBit, EndBit, Base); 673 } else { 674 // There's an overlap but `f` may not be fully contained within 675 // `i`. Shorten any end-point intersections so that we can then 676 // insert `f`. 677 // [ - f - ] 678 // [ - i - ] 679 // | | 680 // [ i ] 681 // Shorten any end-point intersections. 682 if (IntersectStart) { 683 LLVM_DEBUG(dbgs() << "- Intersect interval at start\n"); 684 // Split off at the intersection. 685 FirstOverlap.setStop(StartBit); 686 insertMemLoc(BB, Before, Var, FirstOverlap.start(), StartBit, 687 *FirstOverlap, VarLoc.DL); 688 } 689 // [ - f - ] 690 // [ - i - ] 691 // | | 692 // [ i ] 693 if (IntersectEnd) { 694 LLVM_DEBUG(dbgs() << "- Intersect interval at end\n"); 695 // Split off at the intersection. 696 LastOverlap.setStart(EndBit); 697 insertMemLoc(BB, Before, Var, EndBit, LastOverlap.stop(), *LastOverlap, 698 VarLoc.DL); 699 } 700 701 LLVM_DEBUG(dbgs() << "- Erase intervals contained within\n"); 702 // FirstOverlap and LastOverlap have been shortened such that they're 703 // no longer overlapping with [StartBit, EndBit). Delete any overlaps 704 // that remain (these will be fully contained within `f`). 705 // [ - f - ] } 706 // [ - i - ] } Intersection shortening that has happened above. 707 // | | } 708 // [ i ] } 709 // ----------------- 710 // [i2 ] } Intervals fully contained within `f` get erased. 711 // ----------------- 712 // [ - f - ][ i ] } Completed insertion. 713 auto It = FirstOverlap; 714 if (IntersectStart) 715 ++It; // IntersectStart: first overlap has been shortened. 716 while (It.valid() && It.start() >= StartBit && It.stop() <= EndBit) { 717 LLVM_DEBUG(dbgs() << "- Erase " << toString(It)); 718 It.erase(); // This increments It after removing the interval. 719 } 720 // We've dealt with all the overlaps now! 721 assert(!FragMap.overlaps(StartBit, EndBit)); 722 LLVM_DEBUG(dbgs() << "- Insert DEF into now-empty space\n"); 723 FragMap.insert(StartBit, EndBit, Base); 724 } 725 } 726 727 bool skipVariable(const DILocalVariable *V) { return !V->getSizeInBits(); } 728 729 void process(BasicBlock &BB, VarFragMap &LiveSet) { 730 BBInsertBeforeMap[&BB].clear(); 731 for (auto &I : BB) { 732 if (const auto *Locs = FnVarLocs->getWedge(&I)) { 733 for (const VarLocInfo &Loc : *Locs) { 734 addDef(Loc, I, *I.getParent(), LiveSet); 735 } 736 } 737 } 738 } 739 740 public: 741 MemLocFragmentFill(Function &Fn, 742 const DenseSet<DebugAggregate> *VarsWithStackSlot) 743 : Fn(Fn), VarsWithStackSlot(VarsWithStackSlot) {} 744 745 /// Add variable locations to \p FnVarLocs so that any bits of a variable 746 /// with a memory location have that location explicitly reinstated at each 747 /// subsequent variable location definition that that doesn't overwrite those 748 /// bits. i.e. after a variable location def, insert new defs for the memory 749 /// location with fragments for the difference of "all bits currently in 750 /// memory" and "the fragment of the second def". e.g. 751 /// 752 /// Before: 753 /// 754 /// var x bits 0 to 63: value in memory 755 /// more instructions 756 /// var x bits 0 to 31: value is %0 757 /// 758 /// After: 759 /// 760 /// var x bits 0 to 63: value in memory 761 /// more instructions 762 /// var x bits 0 to 31: value is %0 763 /// var x bits 32 to 61: value in memory ; <-- new loc def 764 /// 765 void run(FunctionVarLocsBuilder *FnVarLocs) { 766 if (!EnableMemLocFragFill) 767 return; 768 769 this->FnVarLocs = FnVarLocs; 770 771 // Prepare for traversal. 772 // 773 ReversePostOrderTraversal<Function *> RPOT(&Fn); 774 std::priority_queue<unsigned int, std::vector<unsigned int>, 775 std::greater<unsigned int>> 776 Worklist; 777 std::priority_queue<unsigned int, std::vector<unsigned int>, 778 std::greater<unsigned int>> 779 Pending; 780 DenseMap<unsigned int, BasicBlock *> OrderToBB; 781 DenseMap<BasicBlock *, unsigned int> BBToOrder; 782 { // Init OrderToBB and BBToOrder. 783 unsigned int RPONumber = 0; 784 for (auto RI = RPOT.begin(), RE = RPOT.end(); RI != RE; ++RI) { 785 OrderToBB[RPONumber] = *RI; 786 BBToOrder[*RI] = RPONumber; 787 Worklist.push(RPONumber); 788 ++RPONumber; 789 } 790 LiveIn.init(RPONumber); 791 LiveOut.init(RPONumber); 792 } 793 794 // Perform the traversal. 795 // 796 // This is a standard "intersect of predecessor outs" dataflow problem. To 797 // solve it, we perform meet() and process() using the two worklist method 798 // until the LiveIn data for each block becomes unchanging. 799 // 800 // This dataflow is essentially working on maps of sets and at each meet we 801 // intersect the maps and the mapped sets. So, initialized live-in maps 802 // monotonically decrease in value throughout the dataflow. 803 SmallPtrSet<BasicBlock *, 16> Visited; 804 while (!Worklist.empty() || !Pending.empty()) { 805 // We track what is on the pending worklist to avoid inserting the same 806 // thing twice. We could avoid this with a custom priority queue, but 807 // this is probably not worth it. 808 SmallPtrSet<BasicBlock *, 16> OnPending; 809 LLVM_DEBUG(dbgs() << "Processing Worklist\n"); 810 while (!Worklist.empty()) { 811 BasicBlock *BB = OrderToBB[Worklist.top()]; 812 LLVM_DEBUG(dbgs() << "\nPop BB " << BB->getName() << "\n"); 813 Worklist.pop(); 814 bool InChanged = meet(*BB, Visited); 815 // Always consider LiveIn changed on the first visit. 816 InChanged |= Visited.insert(BB).second; 817 if (InChanged) { 818 LLVM_DEBUG(dbgs() 819 << BB->getName() << " has new InLocs, process it\n"); 820 // Mutate a copy of LiveIn while processing BB. Once we've processed 821 // the terminator LiveSet is the LiveOut set for BB. 822 // This is an expensive copy! 823 VarFragMap LiveSet = LiveIn[BB]; 824 825 // Process the instructions in the block. 826 process(*BB, LiveSet); 827 828 // Relatively expensive check: has anything changed in LiveOut for BB? 829 if (!varFragMapsAreEqual(LiveOut[BB], LiveSet)) { 830 LLVM_DEBUG(dbgs() << BB->getName() 831 << " has new OutLocs, add succs to worklist: [ "); 832 LiveOut[BB] = std::move(LiveSet); 833 for (auto I = succ_begin(BB), E = succ_end(BB); I != E; I++) { 834 if (OnPending.insert(*I).second) { 835 LLVM_DEBUG(dbgs() << I->getName() << " "); 836 Pending.push(BBToOrder[*I]); 837 } 838 } 839 LLVM_DEBUG(dbgs() << "]\n"); 840 } 841 } 842 } 843 Worklist.swap(Pending); 844 // At this point, pending must be empty, since it was just the empty 845 // worklist 846 assert(Pending.empty() && "Pending should be empty"); 847 } 848 849 // Insert new location defs. 850 for (auto Pair : BBInsertBeforeMap) { 851 InsertMap &Map = Pair.second; 852 for (auto Pair : Map) { 853 Instruction *InsertBefore = Pair.first; 854 assert(InsertBefore && "should never be null"); 855 auto FragMemLocs = Pair.second; 856 auto &Ctx = Fn.getContext(); 857 858 for (auto FragMemLoc : FragMemLocs) { 859 DIExpression *Expr = DIExpression::get(Ctx, std::nullopt); 860 Expr = *DIExpression::createFragmentExpression( 861 Expr, FragMemLoc.OffsetInBits, FragMemLoc.SizeInBits); 862 Expr = DIExpression::prepend(Expr, DIExpression::DerefAfter, 863 FragMemLoc.OffsetInBits / 8); 864 DebugVariable Var(Aggregates[FragMemLoc.Var].first, Expr, 865 FragMemLoc.DL.getInlinedAt()); 866 FnVarLocs->addVarLoc(InsertBefore, Var, Expr, FragMemLoc.DL, 867 Bases[FragMemLoc.Base]); 868 } 869 } 870 } 871 } 872 }; 873 874 /// AssignmentTrackingLowering encapsulates a dataflow analysis over a function 875 /// that interprets assignment tracking debug info metadata and stores in IR to 876 /// create a map of variable locations. 877 class AssignmentTrackingLowering { 878 public: 879 /// The kind of location in use for a variable, where Mem is the stack home, 880 /// Val is an SSA value or const, and None means that there is not one single 881 /// kind (either because there are multiple or because there is none; it may 882 /// prove useful to split this into two values in the future). 883 /// 884 /// LocKind is a join-semilattice with the partial order: 885 /// None > Mem, Val 886 /// 887 /// i.e. 888 /// join(Mem, Mem) = Mem 889 /// join(Val, Val) = Val 890 /// join(Mem, Val) = None 891 /// join(None, Mem) = None 892 /// join(None, Val) = None 893 /// join(None, None) = None 894 /// 895 /// Note: the order is not `None > Val > Mem` because we're using DIAssignID 896 /// to name assignments and are not tracking the actual stored values. 897 /// Therefore currently there's no way to ensure that Mem values and Val 898 /// values are the same. This could be a future extension, though it's not 899 /// clear that many additional locations would be recovered that way in 900 /// practice as the likelihood of this sitation arising naturally seems 901 /// incredibly low. 902 enum class LocKind { Mem, Val, None }; 903 904 /// An abstraction of the assignment of a value to a variable or memory 905 /// location. 906 /// 907 /// An Assignment is Known or NoneOrPhi. A Known Assignment means we have a 908 /// DIAssignID ptr that represents it. NoneOrPhi means that we don't (or 909 /// can't) know the ID of the last assignment that took place. 910 /// 911 /// The Status of the Assignment (Known or NoneOrPhi) is another 912 /// join-semilattice. The partial order is: 913 /// NoneOrPhi > Known {id_0, id_1, ...id_N} 914 /// 915 /// i.e. for all values x and y where x != y: 916 /// join(x, x) = x 917 /// join(x, y) = NoneOrPhi 918 struct Assignment { 919 enum S { Known, NoneOrPhi } Status; 920 /// ID of the assignment. nullptr if Status is not Known. 921 DIAssignID *ID; 922 /// The dbg.assign that marks this dbg-def. Mem-defs don't use this field. 923 /// May be nullptr. 924 DbgAssignIntrinsic *Source; 925 926 bool isSameSourceAssignment(const Assignment &Other) const { 927 // Don't include Source in the equality check. Assignments are 928 // defined by their ID, not debug intrinsic(s). 929 return std::tie(Status, ID) == std::tie(Other.Status, Other.ID); 930 } 931 void dump(raw_ostream &OS) { 932 static const char *LUT[] = {"Known", "NoneOrPhi"}; 933 OS << LUT[Status] << "(id="; 934 if (ID) 935 OS << ID; 936 else 937 OS << "null"; 938 OS << ", s="; 939 if (Source) 940 OS << *Source; 941 else 942 OS << "null"; 943 OS << ")"; 944 } 945 946 static Assignment make(DIAssignID *ID, DbgAssignIntrinsic *Source) { 947 return Assignment(Known, ID, Source); 948 } 949 static Assignment makeFromMemDef(DIAssignID *ID) { 950 return Assignment(Known, ID, nullptr); 951 } 952 static Assignment makeNoneOrPhi() { 953 return Assignment(NoneOrPhi, nullptr, nullptr); 954 } 955 // Again, need a Top value? 956 Assignment() 957 : Status(NoneOrPhi), ID(nullptr), Source(nullptr) { 958 } // Can we delete this? 959 Assignment(S Status, DIAssignID *ID, DbgAssignIntrinsic *Source) 960 : Status(Status), ID(ID), Source(Source) { 961 // If the Status is Known then we expect there to be an assignment ID. 962 assert(Status == NoneOrPhi || ID); 963 } 964 }; 965 966 using AssignmentMap = DenseMap<VariableID, Assignment>; 967 using LocMap = DenseMap<VariableID, LocKind>; 968 using OverlapMap = DenseMap<VariableID, SmallVector<VariableID, 4>>; 969 using UntaggedStoreAssignmentMap = 970 DenseMap<const Instruction *, 971 SmallVector<std::pair<VariableID, at::AssignmentInfo>>>; 972 973 private: 974 /// Map a variable to the set of variables that it fully contains. 975 OverlapMap VarContains; 976 /// Map untagged stores to the variable fragments they assign to. Used by 977 /// processUntaggedInstruction. 978 UntaggedStoreAssignmentMap UntaggedStoreVars; 979 980 // Machinery to defer inserting dbg.values. 981 using InsertMap = MapVector<Instruction *, SmallVector<VarLocInfo>>; 982 InsertMap InsertBeforeMap; 983 /// Clear the location definitions currently cached for insertion after /p 984 /// After. 985 void resetInsertionPoint(Instruction &After); 986 void emitDbgValue(LocKind Kind, const DbgVariableIntrinsic *Source, 987 Instruction *After); 988 989 static bool mapsAreEqual(const AssignmentMap &A, const AssignmentMap &B) { 990 if (A.size() != B.size()) 991 return false; 992 for (const auto &Pair : A) { 993 VariableID Var = Pair.first; 994 const Assignment &AV = Pair.second; 995 auto R = B.find(Var); 996 // Check if this entry exists in B, otherwise ret false. 997 if (R == B.end()) 998 return false; 999 // Check that the assignment value is the same. 1000 if (!AV.isSameSourceAssignment(R->second)) 1001 return false; 1002 } 1003 return true; 1004 } 1005 1006 /// Represents the stack and debug assignments in a block. Used to describe 1007 /// the live-in and live-out values for blocks, as well as the "current" 1008 /// value as we process each instruction in a block. 1009 struct BlockInfo { 1010 /// Dominating assignment to memory for each variable. 1011 AssignmentMap StackHomeValue; 1012 /// Dominating assignemnt to each variable. 1013 AssignmentMap DebugValue; 1014 /// Location kind for each variable. LiveLoc indicates whether the 1015 /// dominating assignment in StackHomeValue (LocKind::Mem), DebugValue 1016 /// (LocKind::Val), or neither (LocKind::None) is valid, in that order of 1017 /// preference. This cannot be derived by inspecting DebugValue and 1018 /// StackHomeValue due to the fact that there's no distinction in 1019 /// Assignment (the class) between whether an assignment is unknown or a 1020 /// merge of multiple assignments (both are Status::NoneOrPhi). In other 1021 /// words, the memory location may well be valid while both DebugValue and 1022 /// StackHomeValue contain Assignments that have a Status of NoneOrPhi. 1023 LocMap LiveLoc; 1024 1025 /// Compare every element in each map to determine structural equality 1026 /// (slow). 1027 bool operator==(const BlockInfo &Other) const { 1028 return LiveLoc == Other.LiveLoc && 1029 mapsAreEqual(StackHomeValue, Other.StackHomeValue) && 1030 mapsAreEqual(DebugValue, Other.DebugValue); 1031 } 1032 bool operator!=(const BlockInfo &Other) const { return !(*this == Other); } 1033 bool isValid() { 1034 return LiveLoc.size() == DebugValue.size() && 1035 LiveLoc.size() == StackHomeValue.size(); 1036 } 1037 }; 1038 1039 Function &Fn; 1040 const DataLayout &Layout; 1041 const DenseSet<DebugAggregate> *VarsWithStackSlot; 1042 FunctionVarLocsBuilder *FnVarLocs; 1043 DenseMap<const BasicBlock *, BlockInfo> LiveIn; 1044 DenseMap<const BasicBlock *, BlockInfo> LiveOut; 1045 1046 /// Helper for process methods to track variables touched each frame. 1047 DenseSet<VariableID> VarsTouchedThisFrame; 1048 1049 /// The set of variables that sometimes are not located in their stack home. 1050 DenseSet<DebugAggregate> NotAlwaysStackHomed; 1051 1052 VariableID getVariableID(const DebugVariable &Var) { 1053 return static_cast<VariableID>(FnVarLocs->insertVariable(Var)); 1054 } 1055 1056 /// Join the LiveOut values of preds that are contained in \p Visited into 1057 /// LiveIn[BB]. Return True if LiveIn[BB] has changed as a result. LiveIn[BB] 1058 /// values monotonically increase. See the @link joinMethods join methods 1059 /// @endlink documentation for more info. 1060 bool join(const BasicBlock &BB, const SmallPtrSet<BasicBlock *, 16> &Visited); 1061 ///@name joinMethods 1062 /// Functions that implement `join` (the least upper bound) for the 1063 /// join-semilattice types used in the dataflow. There is an explicit bottom 1064 /// value (⊥) for some types and and explicit top value (⊤) for all types. 1065 /// By definition: 1066 /// 1067 /// Join(A, B) >= A && Join(A, B) >= B 1068 /// Join(A, ⊥) = A 1069 /// Join(A, ⊤) = ⊤ 1070 /// 1071 /// These invariants are important for monotonicity. 1072 /// 1073 /// For the map-type functions, all unmapped keys in an empty map are 1074 /// associated with a bottom value (⊥). This represents their values being 1075 /// unknown. Unmapped keys in non-empty maps (joining two maps with a key 1076 /// only present in one) represents either a variable going out of scope or 1077 /// dropped debug info. It is assumed the key is associated with a top value 1078 /// (⊤) in this case (unknown location / assignment). 1079 ///@{ 1080 static LocKind joinKind(LocKind A, LocKind B); 1081 static LocMap joinLocMap(const LocMap &A, const LocMap &B); 1082 static Assignment joinAssignment(const Assignment &A, const Assignment &B); 1083 static AssignmentMap joinAssignmentMap(const AssignmentMap &A, 1084 const AssignmentMap &B); 1085 static BlockInfo joinBlockInfo(const BlockInfo &A, const BlockInfo &B); 1086 ///@} 1087 1088 /// Process the instructions in \p BB updating \p LiveSet along the way. \p 1089 /// LiveSet must be initialized with the current live-in locations before 1090 /// calling this. 1091 void process(BasicBlock &BB, BlockInfo *LiveSet); 1092 ///@name processMethods 1093 /// Methods to process instructions in order to update the LiveSet (current 1094 /// location information). 1095 ///@{ 1096 void processNonDbgInstruction(Instruction &I, BlockInfo *LiveSet); 1097 void processDbgInstruction(Instruction &I, BlockInfo *LiveSet); 1098 /// Update \p LiveSet after encountering an instruction with a DIAssignID 1099 /// attachment, \p I. 1100 void processTaggedInstruction(Instruction &I, BlockInfo *LiveSet); 1101 /// Update \p LiveSet after encountering an instruciton without a DIAssignID 1102 /// attachment, \p I. 1103 void processUntaggedInstruction(Instruction &I, BlockInfo *LiveSet); 1104 void processDbgAssign(DbgAssignIntrinsic &DAI, BlockInfo *LiveSet); 1105 void processDbgValue(DbgValueInst &DVI, BlockInfo *LiveSet); 1106 /// Add an assignment to memory for the variable /p Var. 1107 void addMemDef(BlockInfo *LiveSet, VariableID Var, const Assignment &AV); 1108 /// Add an assignment to the variable /p Var. 1109 void addDbgDef(BlockInfo *LiveSet, VariableID Var, const Assignment &AV); 1110 ///@} 1111 1112 /// Set the LocKind for \p Var. 1113 void setLocKind(BlockInfo *LiveSet, VariableID Var, LocKind K); 1114 /// Get the live LocKind for a \p Var. Requires addMemDef or addDbgDef to 1115 /// have been called for \p Var first. 1116 LocKind getLocKind(BlockInfo *LiveSet, VariableID Var); 1117 /// Return true if \p Var has an assignment in \p M matching \p AV. 1118 bool hasVarWithAssignment(VariableID Var, const Assignment &AV, 1119 const AssignmentMap &M); 1120 1121 /// Emit info for variables that are fully promoted. 1122 bool emitPromotedVarLocs(FunctionVarLocsBuilder *FnVarLocs); 1123 1124 public: 1125 AssignmentTrackingLowering(Function &Fn, const DataLayout &Layout, 1126 const DenseSet<DebugAggregate> *VarsWithStackSlot) 1127 : Fn(Fn), Layout(Layout), VarsWithStackSlot(VarsWithStackSlot) {} 1128 /// Run the analysis, adding variable location info to \p FnVarLocs. Returns 1129 /// true if any variable locations have been added to FnVarLocs. 1130 bool run(FunctionVarLocsBuilder *FnVarLocs); 1131 }; 1132 } // namespace 1133 1134 void AssignmentTrackingLowering::setLocKind(BlockInfo *LiveSet, VariableID Var, 1135 LocKind K) { 1136 auto SetKind = [this](BlockInfo *LiveSet, VariableID Var, LocKind K) { 1137 VarsTouchedThisFrame.insert(Var); 1138 LiveSet->LiveLoc[Var] = K; 1139 }; 1140 SetKind(LiveSet, Var, K); 1141 1142 // Update the LocKind for all fragments contained within Var. 1143 for (VariableID Frag : VarContains[Var]) 1144 SetKind(LiveSet, Frag, K); 1145 } 1146 1147 AssignmentTrackingLowering::LocKind 1148 AssignmentTrackingLowering::getLocKind(BlockInfo *LiveSet, VariableID Var) { 1149 auto Pair = LiveSet->LiveLoc.find(Var); 1150 assert(Pair != LiveSet->LiveLoc.end()); 1151 return Pair->second; 1152 } 1153 1154 void AssignmentTrackingLowering::addMemDef(BlockInfo *LiveSet, VariableID Var, 1155 const Assignment &AV) { 1156 auto AddDef = [](BlockInfo *LiveSet, VariableID Var, Assignment AV) { 1157 LiveSet->StackHomeValue[Var] = AV; 1158 // Add default (Var -> ⊤) to DebugValue if Var isn't in DebugValue yet. 1159 LiveSet->DebugValue.insert({Var, Assignment::makeNoneOrPhi()}); 1160 // Add default (Var -> ⊤) to LiveLocs if Var isn't in LiveLocs yet. Callers 1161 // of addMemDef will call setLocKind to override. 1162 LiveSet->LiveLoc.insert({Var, LocKind::None}); 1163 }; 1164 AddDef(LiveSet, Var, AV); 1165 1166 // Use this assigment for all fragments contained within Var, but do not 1167 // provide a Source because we cannot convert Var's value to a value for the 1168 // fragment. 1169 Assignment FragAV = AV; 1170 FragAV.Source = nullptr; 1171 for (VariableID Frag : VarContains[Var]) 1172 AddDef(LiveSet, Frag, FragAV); 1173 } 1174 1175 void AssignmentTrackingLowering::addDbgDef(BlockInfo *LiveSet, VariableID Var, 1176 const Assignment &AV) { 1177 auto AddDef = [](BlockInfo *LiveSet, VariableID Var, Assignment AV) { 1178 LiveSet->DebugValue[Var] = AV; 1179 // Add default (Var -> ⊤) to StackHome if Var isn't in StackHome yet. 1180 LiveSet->StackHomeValue.insert({Var, Assignment::makeNoneOrPhi()}); 1181 // Add default (Var -> ⊤) to LiveLocs if Var isn't in LiveLocs yet. Callers 1182 // of addDbgDef will call setLocKind to override. 1183 LiveSet->LiveLoc.insert({Var, LocKind::None}); 1184 }; 1185 AddDef(LiveSet, Var, AV); 1186 1187 // Use this assigment for all fragments contained within Var, but do not 1188 // provide a Source because we cannot convert Var's value to a value for the 1189 // fragment. 1190 Assignment FragAV = AV; 1191 FragAV.Source = nullptr; 1192 for (VariableID Frag : VarContains[Var]) 1193 AddDef(LiveSet, Frag, FragAV); 1194 } 1195 1196 static DIAssignID *getIDFromInst(const Instruction &I) { 1197 return cast<DIAssignID>(I.getMetadata(LLVMContext::MD_DIAssignID)); 1198 } 1199 1200 static DIAssignID *getIDFromMarker(const DbgAssignIntrinsic &DAI) { 1201 return cast<DIAssignID>(DAI.getAssignID()); 1202 } 1203 1204 /// Return true if \p Var has an assignment in \p M matching \p AV. 1205 bool AssignmentTrackingLowering::hasVarWithAssignment(VariableID Var, 1206 const Assignment &AV, 1207 const AssignmentMap &M) { 1208 auto AssignmentIsMapped = [](VariableID Var, const Assignment &AV, 1209 const AssignmentMap &M) { 1210 auto R = M.find(Var); 1211 if (R == M.end()) 1212 return false; 1213 return AV.isSameSourceAssignment(R->second); 1214 }; 1215 1216 if (!AssignmentIsMapped(Var, AV, M)) 1217 return false; 1218 1219 // Check all the frags contained within Var as these will have all been 1220 // mapped to AV at the last store to Var. 1221 for (VariableID Frag : VarContains[Var]) 1222 if (!AssignmentIsMapped(Frag, AV, M)) 1223 return false; 1224 return true; 1225 } 1226 1227 #ifndef NDEBUG 1228 const char *locStr(AssignmentTrackingLowering::LocKind Loc) { 1229 using LocKind = AssignmentTrackingLowering::LocKind; 1230 switch (Loc) { 1231 case LocKind::Val: 1232 return "Val"; 1233 case LocKind::Mem: 1234 return "Mem"; 1235 case LocKind::None: 1236 return "None"; 1237 }; 1238 llvm_unreachable("unknown LocKind"); 1239 } 1240 #endif 1241 1242 void AssignmentTrackingLowering::emitDbgValue( 1243 AssignmentTrackingLowering::LocKind Kind, 1244 const DbgVariableIntrinsic *Source, Instruction *After) { 1245 1246 DILocation *DL = Source->getDebugLoc(); 1247 auto Emit = [this, Source, After, DL](Value *Val, DIExpression *Expr) { 1248 assert(Expr); 1249 if (!Val) 1250 Val = PoisonValue::get(Type::getInt1Ty(Source->getContext())); 1251 1252 // Find a suitable insert point. 1253 Instruction *InsertBefore = After->getNextNode(); 1254 assert(InsertBefore && "Shouldn't be inserting after a terminator"); 1255 1256 VariableID Var = getVariableID(DebugVariable(Source)); 1257 VarLocInfo VarLoc; 1258 VarLoc.VariableID = static_cast<VariableID>(Var); 1259 VarLoc.Expr = Expr; 1260 VarLoc.V = Val; 1261 VarLoc.DL = DL; 1262 // Insert it into the map for later. 1263 InsertBeforeMap[InsertBefore].push_back(VarLoc); 1264 }; 1265 1266 // NOTE: This block can mutate Kind. 1267 if (Kind == LocKind::Mem) { 1268 const auto *DAI = cast<DbgAssignIntrinsic>(Source); 1269 // Check the address hasn't been dropped (e.g. the debug uses may not have 1270 // been replaced before deleting a Value). 1271 if (DAI->isKillAddress()) { 1272 // The address isn't valid so treat this as a non-memory def. 1273 Kind = LocKind::Val; 1274 } else { 1275 Value *Val = DAI->getAddress(); 1276 DIExpression *Expr = DAI->getAddressExpression(); 1277 assert(!Expr->getFragmentInfo() && 1278 "fragment info should be stored in value-expression only"); 1279 // Copy the fragment info over from the value-expression to the new 1280 // DIExpression. 1281 if (auto OptFragInfo = Source->getExpression()->getFragmentInfo()) { 1282 auto FragInfo = *OptFragInfo; 1283 Expr = *DIExpression::createFragmentExpression( 1284 Expr, FragInfo.OffsetInBits, FragInfo.SizeInBits); 1285 } 1286 // The address-expression has an implicit deref, add it now. 1287 std::tie(Val, Expr) = 1288 walkToAllocaAndPrependOffsetDeref(Layout, Val, Expr); 1289 Emit(Val, Expr); 1290 return; 1291 } 1292 } 1293 1294 if (Kind == LocKind::Val) { 1295 /// Get the value component, converting to Undef if it is variadic. 1296 Value *Val = 1297 Source->hasArgList() ? nullptr : Source->getVariableLocationOp(0); 1298 Emit(Val, Source->getExpression()); 1299 return; 1300 } 1301 1302 if (Kind == LocKind::None) { 1303 Emit(nullptr, Source->getExpression()); 1304 return; 1305 } 1306 } 1307 1308 void AssignmentTrackingLowering::processNonDbgInstruction( 1309 Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) { 1310 if (I.hasMetadata(LLVMContext::MD_DIAssignID)) 1311 processTaggedInstruction(I, LiveSet); 1312 else 1313 processUntaggedInstruction(I, LiveSet); 1314 } 1315 1316 void AssignmentTrackingLowering::processUntaggedInstruction( 1317 Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) { 1318 // Interpret stack stores that are not tagged as an assignment in memory for 1319 // the variables associated with that address. These stores may not be tagged 1320 // because a) the store cannot be represented using dbg.assigns (non-const 1321 // length or offset) or b) the tag was accidentally dropped during 1322 // optimisations. For these stores we fall back to assuming that the stack 1323 // home is a valid location for the variables. The benefit is that this 1324 // prevents us missing an assignment and therefore incorrectly maintaining 1325 // earlier location definitions, and in many cases it should be a reasonable 1326 // assumption. However, this will occasionally lead to slight 1327 // inaccuracies. The value of a hoisted untagged store will be visible 1328 // "early", for example. 1329 assert(!I.hasMetadata(LLVMContext::MD_DIAssignID)); 1330 auto It = UntaggedStoreVars.find(&I); 1331 if (It == UntaggedStoreVars.end()) 1332 return; // No variables associated with the store destination. 1333 1334 LLVM_DEBUG(dbgs() << "processUntaggedInstruction on UNTAGGED INST " << I 1335 << "\n"); 1336 // Iterate over the variables that this store affects, add a NoneOrPhi dbg 1337 // and mem def, set lockind to Mem, and emit a location def for each. 1338 for (auto [Var, Info] : It->second) { 1339 // This instruction is treated as both a debug and memory assignment, 1340 // meaning the memory location should be used. We don't have an assignment 1341 // ID though so use Assignment::makeNoneOrPhi() to create an imaginary one. 1342 addMemDef(LiveSet, Var, Assignment::makeNoneOrPhi()); 1343 addDbgDef(LiveSet, Var, Assignment::makeNoneOrPhi()); 1344 setLocKind(LiveSet, Var, LocKind::Mem); 1345 LLVM_DEBUG(dbgs() << " setting Stack LocKind to: " << locStr(LocKind::Mem) 1346 << "\n"); 1347 // Build the dbg location def to insert. 1348 // 1349 // DIExpression: Add fragment and offset. 1350 DebugVariable V = FnVarLocs->getVariable(Var); 1351 DIExpression *DIE = DIExpression::get(I.getContext(), std::nullopt); 1352 if (auto Frag = V.getFragment()) { 1353 auto R = DIExpression::createFragmentExpression(DIE, Frag->OffsetInBits, 1354 Frag->SizeInBits); 1355 assert(R && "unexpected createFragmentExpression failure"); 1356 DIE = *R; 1357 } 1358 SmallVector<uint64_t, 3> Ops; 1359 if (Info.OffsetInBits) 1360 Ops = {dwarf::DW_OP_plus_uconst, Info.OffsetInBits / 8}; 1361 Ops.push_back(dwarf::DW_OP_deref); 1362 DIE = DIExpression::prependOpcodes(DIE, Ops, /*StackValue=*/false, 1363 /*EntryValue=*/false); 1364 // Find a suitable insert point. 1365 Instruction *InsertBefore = I.getNextNode(); 1366 assert(InsertBefore && "Shouldn't be inserting after a terminator"); 1367 1368 // Get DILocation for this unrecorded assignment. 1369 DILocation *InlinedAt = const_cast<DILocation *>(V.getInlinedAt()); 1370 const DILocation *DILoc = DILocation::get( 1371 Fn.getContext(), 0, 0, V.getVariable()->getScope(), InlinedAt); 1372 1373 VarLocInfo VarLoc; 1374 VarLoc.VariableID = static_cast<VariableID>(Var); 1375 VarLoc.Expr = DIE; 1376 VarLoc.V = const_cast<AllocaInst *>(Info.Base); 1377 VarLoc.DL = DILoc; 1378 // 3. Insert it into the map for later. 1379 InsertBeforeMap[InsertBefore].push_back(VarLoc); 1380 } 1381 } 1382 1383 void AssignmentTrackingLowering::processTaggedInstruction( 1384 Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) { 1385 auto Linked = at::getAssignmentMarkers(&I); 1386 // No dbg.assign intrinsics linked. 1387 // FIXME: All vars that have a stack slot this store modifies that don't have 1388 // a dbg.assign linked to it should probably treat this like an untagged 1389 // store. 1390 if (Linked.empty()) 1391 return; 1392 1393 LLVM_DEBUG(dbgs() << "processTaggedInstruction on " << I << "\n"); 1394 for (DbgAssignIntrinsic *DAI : Linked) { 1395 VariableID Var = getVariableID(DebugVariable(DAI)); 1396 // Something has gone wrong if VarsWithStackSlot doesn't contain a variable 1397 // that is linked to a store. 1398 assert(VarsWithStackSlot->count(getAggregate(DAI)) && 1399 "expected DAI's variable to have stack slot"); 1400 1401 Assignment AV = Assignment::makeFromMemDef(getIDFromInst(I)); 1402 addMemDef(LiveSet, Var, AV); 1403 1404 LLVM_DEBUG(dbgs() << " linked to " << *DAI << "\n"); 1405 LLVM_DEBUG(dbgs() << " LiveLoc " << locStr(getLocKind(LiveSet, Var)) 1406 << " -> "); 1407 1408 // The last assignment to the stack is now AV. Check if the last debug 1409 // assignment has a matching Assignment. 1410 if (hasVarWithAssignment(Var, AV, LiveSet->DebugValue)) { 1411 // The StackHomeValue and DebugValue for this variable match so we can 1412 // emit a stack home location here. 1413 LLVM_DEBUG(dbgs() << "Mem, Stack matches Debug program\n";); 1414 LLVM_DEBUG(dbgs() << " Stack val: "; AV.dump(dbgs()); dbgs() << "\n"); 1415 LLVM_DEBUG(dbgs() << " Debug val: "; 1416 LiveSet->DebugValue[Var].dump(dbgs()); dbgs() << "\n"); 1417 setLocKind(LiveSet, Var, LocKind::Mem); 1418 emitDbgValue(LocKind::Mem, DAI, &I); 1419 continue; 1420 } 1421 1422 // The StackHomeValue and DebugValue for this variable do not match. I.e. 1423 // The value currently stored in the stack is not what we'd expect to 1424 // see, so we cannot use emit a stack home location here. Now we will 1425 // look at the live LocKind for the variable and determine an appropriate 1426 // dbg.value to emit. 1427 LocKind PrevLoc = getLocKind(LiveSet, Var); 1428 switch (PrevLoc) { 1429 case LocKind::Val: { 1430 // The value in memory in memory has changed but we're not currently 1431 // using the memory location. Do nothing. 1432 LLVM_DEBUG(dbgs() << "Val, (unchanged)\n";); 1433 setLocKind(LiveSet, Var, LocKind::Val); 1434 } break; 1435 case LocKind::Mem: { 1436 // There's been an assignment to memory that we were using as a 1437 // location for this variable, and the Assignment doesn't match what 1438 // we'd expect to see in memory. 1439 if (LiveSet->DebugValue[Var].Status == Assignment::NoneOrPhi) { 1440 // We need to terminate any previously open location now. 1441 LLVM_DEBUG(dbgs() << "None, No Debug value available\n";); 1442 setLocKind(LiveSet, Var, LocKind::None); 1443 emitDbgValue(LocKind::None, DAI, &I); 1444 } else { 1445 // The previous DebugValue Value can be used here. 1446 LLVM_DEBUG(dbgs() << "Val, Debug value is Known\n";); 1447 setLocKind(LiveSet, Var, LocKind::Val); 1448 Assignment PrevAV = LiveSet->DebugValue.lookup(Var); 1449 if (PrevAV.Source) { 1450 emitDbgValue(LocKind::Val, PrevAV.Source, &I); 1451 } else { 1452 // PrevAV.Source is nullptr so we must emit undef here. 1453 emitDbgValue(LocKind::None, DAI, &I); 1454 } 1455 } 1456 } break; 1457 case LocKind::None: { 1458 // There's been an assignment to memory and we currently are 1459 // not tracking a location for the variable. Do not emit anything. 1460 LLVM_DEBUG(dbgs() << "None, (unchanged)\n";); 1461 setLocKind(LiveSet, Var, LocKind::None); 1462 } break; 1463 } 1464 } 1465 } 1466 1467 void AssignmentTrackingLowering::processDbgAssign(DbgAssignIntrinsic &DAI, 1468 BlockInfo *LiveSet) { 1469 // Only bother tracking variables that are at some point stack homed. Other 1470 // variables can be dealt with trivially later. 1471 if (!VarsWithStackSlot->count(getAggregate(&DAI))) 1472 return; 1473 1474 VariableID Var = getVariableID(DebugVariable(&DAI)); 1475 Assignment AV = Assignment::make(getIDFromMarker(DAI), &DAI); 1476 addDbgDef(LiveSet, Var, AV); 1477 1478 LLVM_DEBUG(dbgs() << "processDbgAssign on " << DAI << "\n";); 1479 LLVM_DEBUG(dbgs() << " LiveLoc " << locStr(getLocKind(LiveSet, Var)) 1480 << " -> "); 1481 1482 // Check if the DebugValue and StackHomeValue both hold the same 1483 // Assignment. 1484 if (hasVarWithAssignment(Var, AV, LiveSet->StackHomeValue)) { 1485 // They match. We can use the stack home because the debug intrinsics state 1486 // that an assignment happened here, and we know that specific assignment 1487 // was the last one to take place in memory for this variable. 1488 LocKind Kind; 1489 if (DAI.isKillAddress()) { 1490 LLVM_DEBUG( 1491 dbgs() 1492 << "Val, Stack matches Debug program but address is killed\n";); 1493 Kind = LocKind::Val; 1494 } else { 1495 LLVM_DEBUG(dbgs() << "Mem, Stack matches Debug program\n";); 1496 Kind = LocKind::Mem; 1497 }; 1498 setLocKind(LiveSet, Var, Kind); 1499 emitDbgValue(Kind, &DAI, &DAI); 1500 } else { 1501 // The last assignment to the memory location isn't the one that we want to 1502 // show to the user so emit a dbg.value(Value). Value may be undef. 1503 LLVM_DEBUG(dbgs() << "Val, Stack contents is unknown\n";); 1504 setLocKind(LiveSet, Var, LocKind::Val); 1505 emitDbgValue(LocKind::Val, &DAI, &DAI); 1506 } 1507 } 1508 1509 void AssignmentTrackingLowering::processDbgValue(DbgValueInst &DVI, 1510 BlockInfo *LiveSet) { 1511 // Only other tracking variables that are at some point stack homed. 1512 // Other variables can be dealt with trivally later. 1513 if (!VarsWithStackSlot->count(getAggregate(&DVI))) 1514 return; 1515 1516 VariableID Var = getVariableID(DebugVariable(&DVI)); 1517 // We have no ID to create an Assignment with so we mark this assignment as 1518 // NoneOrPhi. Note that the dbg.value still exists, we just cannot determine 1519 // the assignment responsible for setting this value. 1520 // This is fine; dbg.values are essentially interchangable with unlinked 1521 // dbg.assigns, and some passes such as mem2reg and instcombine add them to 1522 // PHIs for promoted variables. 1523 Assignment AV = Assignment::makeNoneOrPhi(); 1524 addDbgDef(LiveSet, Var, AV); 1525 1526 LLVM_DEBUG(dbgs() << "processDbgValue on " << DVI << "\n";); 1527 LLVM_DEBUG(dbgs() << " LiveLoc " << locStr(getLocKind(LiveSet, Var)) 1528 << " -> Val, dbg.value override"); 1529 1530 setLocKind(LiveSet, Var, LocKind::Val); 1531 emitDbgValue(LocKind::Val, &DVI, &DVI); 1532 } 1533 1534 void AssignmentTrackingLowering::processDbgInstruction( 1535 Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) { 1536 if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I)) 1537 processDbgAssign(*DAI, LiveSet); 1538 else if (auto *DVI = dyn_cast<DbgValueInst>(&I)) 1539 processDbgValue(*DVI, LiveSet); 1540 } 1541 1542 void AssignmentTrackingLowering::resetInsertionPoint(Instruction &After) { 1543 assert(!After.isTerminator() && "Can't insert after a terminator"); 1544 auto R = InsertBeforeMap.find(After.getNextNode()); 1545 if (R == InsertBeforeMap.end()) 1546 return; 1547 R->second.clear(); 1548 } 1549 1550 void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { 1551 for (auto II = BB.begin(), EI = BB.end(); II != EI;) { 1552 assert(VarsTouchedThisFrame.empty()); 1553 // Process the instructions in "frames". A "frame" includes a single 1554 // non-debug instruction followed any debug instructions before the 1555 // next non-debug instruction. 1556 if (!isa<DbgInfoIntrinsic>(&*II)) { 1557 if (II->isTerminator()) 1558 break; 1559 resetInsertionPoint(*II); 1560 processNonDbgInstruction(*II, LiveSet); 1561 assert(LiveSet->isValid()); 1562 ++II; 1563 } 1564 while (II != EI) { 1565 if (!isa<DbgInfoIntrinsic>(&*II)) 1566 break; 1567 resetInsertionPoint(*II); 1568 processDbgInstruction(*II, LiveSet); 1569 assert(LiveSet->isValid()); 1570 ++II; 1571 } 1572 1573 // We've processed everything in the "frame". Now determine which variables 1574 // cannot be represented by a dbg.declare. 1575 for (auto Var : VarsTouchedThisFrame) { 1576 LocKind Loc = getLocKind(LiveSet, Var); 1577 // If a variable's LocKind is anything other than LocKind::Mem then we 1578 // must note that it cannot be represented with a dbg.declare. 1579 // Note that this check is enough without having to check the result of 1580 // joins() because for join to produce anything other than Mem after 1581 // we've already seen a Mem we'd be joining None or Val with Mem. In that 1582 // case, we've already hit this codepath when we set the LocKind to Val 1583 // or None in that block. 1584 if (Loc != LocKind::Mem) { 1585 DebugVariable DbgVar = FnVarLocs->getVariable(Var); 1586 DebugAggregate Aggr{DbgVar.getVariable(), DbgVar.getInlinedAt()}; 1587 NotAlwaysStackHomed.insert(Aggr); 1588 } 1589 } 1590 VarsTouchedThisFrame.clear(); 1591 } 1592 } 1593 1594 AssignmentTrackingLowering::LocKind 1595 AssignmentTrackingLowering::joinKind(LocKind A, LocKind B) { 1596 // Partial order: 1597 // None > Mem, Val 1598 return A == B ? A : LocKind::None; 1599 } 1600 1601 AssignmentTrackingLowering::LocMap 1602 AssignmentTrackingLowering::joinLocMap(const LocMap &A, const LocMap &B) { 1603 // Join A and B. 1604 // 1605 // U = join(a, b) for a in A, b in B where Var(a) == Var(b) 1606 // D = join(x, ⊤) for x where Var(x) is in A xor B 1607 // Join = U ∪ D 1608 // 1609 // This is achieved by performing a join on elements from A and B with 1610 // variables common to both A and B (join elements indexed by var intersect), 1611 // then adding LocKind::None elements for vars in A xor B. The latter part is 1612 // equivalent to performing join on elements with variables in A xor B with 1613 // LocKind::None (⊤) since join(x, ⊤) = ⊤. 1614 LocMap Join(std::max(A.size(), B.size())); 1615 SmallVector<VariableID, 16> SymmetricDifference; 1616 // Insert the join of the elements with common vars into Join. Add the 1617 // remaining elements to into SymmetricDifference. 1618 for (const auto &[Var, Loc] : A) { 1619 // If this Var doesn't exist in B then add it to the symmetric difference 1620 // set. 1621 auto R = B.find(Var); 1622 if (R == B.end()) { 1623 SymmetricDifference.push_back(Var); 1624 continue; 1625 } 1626 // There is an entry for Var in both, join it. 1627 Join[Var] = joinKind(Loc, R->second); 1628 } 1629 unsigned IntersectSize = Join.size(); 1630 (void)IntersectSize; 1631 1632 // Check if A and B contain the same variables. 1633 if (SymmetricDifference.empty() && A.size() == B.size()) 1634 return Join; 1635 1636 // Add the elements in B with variables that are not in A into 1637 // SymmetricDifference. 1638 for (const auto &Pair : B) { 1639 VariableID Var = Pair.first; 1640 if (A.count(Var) == 0) 1641 SymmetricDifference.push_back(Var); 1642 } 1643 1644 // Add SymmetricDifference elements to Join and return the result. 1645 for (const auto &Var : SymmetricDifference) 1646 Join.insert({Var, LocKind::None}); 1647 1648 assert(Join.size() == (IntersectSize + SymmetricDifference.size())); 1649 assert(Join.size() >= A.size() && Join.size() >= B.size()); 1650 return Join; 1651 } 1652 1653 AssignmentTrackingLowering::Assignment 1654 AssignmentTrackingLowering::joinAssignment(const Assignment &A, 1655 const Assignment &B) { 1656 // Partial order: 1657 // NoneOrPhi(null, null) > Known(v, ?s) 1658 1659 // If either are NoneOrPhi the join is NoneOrPhi. 1660 // If either value is different then the result is 1661 // NoneOrPhi (joining two values is a Phi). 1662 if (!A.isSameSourceAssignment(B)) 1663 return Assignment::makeNoneOrPhi(); 1664 if (A.Status == Assignment::NoneOrPhi) 1665 return Assignment::makeNoneOrPhi(); 1666 1667 // Source is used to lookup the value + expression in the debug program if 1668 // the stack slot gets assigned a value earlier than expected. Because 1669 // we're only tracking the one dbg.assign, we can't capture debug PHIs. 1670 // It's unlikely that we're losing out on much coverage by avoiding that 1671 // extra work. 1672 // The Source may differ in this situation: 1673 // Pred.1: 1674 // dbg.assign i32 0, ..., !1, ... 1675 // Pred.2: 1676 // dbg.assign i32 1, ..., !1, ... 1677 // Here the same assignment (!1) was performed in both preds in the source, 1678 // but we can't use either one unless they are identical (e.g. .we don't 1679 // want to arbitrarily pick between constant values). 1680 auto JoinSource = [&]() -> DbgAssignIntrinsic * { 1681 if (A.Source == B.Source) 1682 return A.Source; 1683 if (A.Source == nullptr || B.Source == nullptr) 1684 return nullptr; 1685 if (A.Source->isIdenticalTo(B.Source)) 1686 return A.Source; 1687 return nullptr; 1688 }; 1689 DbgAssignIntrinsic *Source = JoinSource(); 1690 assert(A.Status == B.Status && A.Status == Assignment::Known); 1691 assert(A.ID == B.ID); 1692 return Assignment::make(A.ID, Source); 1693 } 1694 1695 AssignmentTrackingLowering::AssignmentMap 1696 AssignmentTrackingLowering::joinAssignmentMap(const AssignmentMap &A, 1697 const AssignmentMap &B) { 1698 // Join A and B. 1699 // 1700 // U = join(a, b) for a in A, b in B where Var(a) == Var(b) 1701 // D = join(x, ⊤) for x where Var(x) is in A xor B 1702 // Join = U ∪ D 1703 // 1704 // This is achieved by performing a join on elements from A and B with 1705 // variables common to both A and B (join elements indexed by var intersect), 1706 // then adding LocKind::None elements for vars in A xor B. The latter part is 1707 // equivalent to performing join on elements with variables in A xor B with 1708 // Status::NoneOrPhi (⊤) since join(x, ⊤) = ⊤. 1709 AssignmentMap Join(std::max(A.size(), B.size())); 1710 SmallVector<VariableID, 16> SymmetricDifference; 1711 // Insert the join of the elements with common vars into Join. Add the 1712 // remaining elements to into SymmetricDifference. 1713 for (const auto &[Var, AV] : A) { 1714 // If this Var doesn't exist in B then add it to the symmetric difference 1715 // set. 1716 auto R = B.find(Var); 1717 if (R == B.end()) { 1718 SymmetricDifference.push_back(Var); 1719 continue; 1720 } 1721 // There is an entry for Var in both, join it. 1722 Join[Var] = joinAssignment(AV, R->second); 1723 } 1724 unsigned IntersectSize = Join.size(); 1725 (void)IntersectSize; 1726 1727 // Check if A and B contain the same variables. 1728 if (SymmetricDifference.empty() && A.size() == B.size()) 1729 return Join; 1730 1731 // Add the elements in B with variables that are not in A into 1732 // SymmetricDifference. 1733 for (const auto &Pair : B) { 1734 VariableID Var = Pair.first; 1735 if (A.count(Var) == 0) 1736 SymmetricDifference.push_back(Var); 1737 } 1738 1739 // Add SymmetricDifference elements to Join and return the result. 1740 for (auto Var : SymmetricDifference) 1741 Join.insert({Var, Assignment::makeNoneOrPhi()}); 1742 1743 assert(Join.size() == (IntersectSize + SymmetricDifference.size())); 1744 assert(Join.size() >= A.size() && Join.size() >= B.size()); 1745 return Join; 1746 } 1747 1748 AssignmentTrackingLowering::BlockInfo 1749 AssignmentTrackingLowering::joinBlockInfo(const BlockInfo &A, 1750 const BlockInfo &B) { 1751 BlockInfo Join; 1752 Join.LiveLoc = joinLocMap(A.LiveLoc, B.LiveLoc); 1753 Join.StackHomeValue = joinAssignmentMap(A.StackHomeValue, B.StackHomeValue); 1754 Join.DebugValue = joinAssignmentMap(A.DebugValue, B.DebugValue); 1755 assert(Join.isValid()); 1756 return Join; 1757 } 1758 1759 bool AssignmentTrackingLowering::join( 1760 const BasicBlock &BB, const SmallPtrSet<BasicBlock *, 16> &Visited) { 1761 BlockInfo BBLiveIn; 1762 bool FirstJoin = true; 1763 // LiveIn locs for BB is the join of the already-processed preds' LiveOut 1764 // locs. 1765 for (auto I = pred_begin(&BB), E = pred_end(&BB); I != E; I++) { 1766 // Ignore backedges if we have not visited the predecessor yet. As the 1767 // predecessor hasn't yet had locations propagated into it, most locations 1768 // will not yet be valid, so treat them as all being uninitialized and 1769 // potentially valid. If a location guessed to be correct here is 1770 // invalidated later, we will remove it when we revisit this block. This 1771 // is essentially the same as initialising all LocKinds and Assignments to 1772 // an implicit ⊥ value which is the identity value for the join operation. 1773 const BasicBlock *Pred = *I; 1774 if (!Visited.count(Pred)) 1775 continue; 1776 1777 auto PredLiveOut = LiveOut.find(Pred); 1778 // Pred must have been processed already. See comment at start of this loop. 1779 assert(PredLiveOut != LiveOut.end()); 1780 1781 // Perform the join of BBLiveIn (current live-in info) and PrevLiveOut. 1782 if (FirstJoin) 1783 BBLiveIn = PredLiveOut->second; 1784 else 1785 BBLiveIn = joinBlockInfo(std::move(BBLiveIn), PredLiveOut->second); 1786 FirstJoin = false; 1787 } 1788 1789 auto CurrentLiveInEntry = LiveIn.find(&BB); 1790 // Check if there isn't an entry, or there is but the LiveIn set has changed 1791 // (expensive check). 1792 if (CurrentLiveInEntry == LiveIn.end() || 1793 BBLiveIn != CurrentLiveInEntry->second) { 1794 LiveIn[&BB] = std::move(BBLiveIn); 1795 // A change has occured. 1796 return true; 1797 } 1798 // No change. 1799 return false; 1800 } 1801 1802 /// Return true if A fully contains B. 1803 static bool fullyContains(DIExpression::FragmentInfo A, 1804 DIExpression::FragmentInfo B) { 1805 auto ALeft = A.OffsetInBits; 1806 auto BLeft = B.OffsetInBits; 1807 if (BLeft < ALeft) 1808 return false; 1809 1810 auto ARight = ALeft + A.SizeInBits; 1811 auto BRight = BLeft + B.SizeInBits; 1812 if (BRight > ARight) 1813 return false; 1814 return true; 1815 } 1816 1817 static std::optional<at::AssignmentInfo> 1818 getUntaggedStoreAssignmentInfo(const Instruction &I, const DataLayout &Layout) { 1819 // Don't bother checking if this is an AllocaInst. We know this 1820 // instruction has no tag which means there are no variables associated 1821 // with it. 1822 if (const auto *SI = dyn_cast<StoreInst>(&I)) 1823 return at::getAssignmentInfo(Layout, SI); 1824 if (const auto *MI = dyn_cast<MemIntrinsic>(&I)) 1825 return at::getAssignmentInfo(Layout, MI); 1826 // Alloca or non-store-like inst. 1827 return std::nullopt; 1828 } 1829 1830 /// Build a map of {Variable x: Variables y} where all variable fragments 1831 /// contained within the variable fragment x are in set y. This means that 1832 /// y does not contain all overlaps because partial overlaps are excluded. 1833 /// 1834 /// While we're iterating over the function, add single location defs for 1835 /// dbg.declares to \p FnVarLocs 1836 /// 1837 /// Finally, populate UntaggedStoreVars with a mapping of untagged stores to 1838 /// the stored-to variable fragments. 1839 /// 1840 /// These tasks are bundled together to reduce the number of times we need 1841 /// to iterate over the function as they can be achieved together in one pass. 1842 static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( 1843 Function &Fn, FunctionVarLocsBuilder *FnVarLocs, 1844 AssignmentTrackingLowering::UntaggedStoreAssignmentMap &UntaggedStoreVars) { 1845 DenseSet<DebugVariable> Seen; 1846 // Map of Variable: [Fragments]. 1847 DenseMap<DebugAggregate, SmallVector<DebugVariable, 8>> FragmentMap; 1848 // Iterate over all instructions: 1849 // - dbg.declare -> add single location variable record 1850 // - dbg.* -> Add fragments to FragmentMap 1851 // - untagged store -> Add fragments to FragmentMap and update 1852 // UntaggedStoreVars. 1853 // We need to add fragments for untagged stores too so that we can correctly 1854 // clobber overlapped fragment locations later. 1855 for (auto &BB : Fn) { 1856 for (auto &I : BB) { 1857 if (auto *DDI = dyn_cast<DbgDeclareInst>(&I)) { 1858 FnVarLocs->addSingleLocVar(DebugVariable(DDI), DDI->getExpression(), 1859 DDI->getDebugLoc(), DDI->getAddress()); 1860 } else if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { 1861 DebugVariable DV = DebugVariable(DII); 1862 DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()}; 1863 if (Seen.insert(DV).second) 1864 FragmentMap[DA].push_back(DV); 1865 } else if (auto Info = getUntaggedStoreAssignmentInfo( 1866 I, Fn.getParent()->getDataLayout())) { 1867 // Find markers linked to this alloca. 1868 for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(Info->Base)) { 1869 // Discard the fragment if it covers the entire variable. 1870 std::optional<DIExpression::FragmentInfo> FragInfo = 1871 [&Info, DAI]() -> std::optional<DIExpression::FragmentInfo> { 1872 DIExpression::FragmentInfo F; 1873 F.OffsetInBits = Info->OffsetInBits; 1874 F.SizeInBits = Info->SizeInBits; 1875 if (auto ExistingFrag = DAI->getExpression()->getFragmentInfo()) 1876 F.OffsetInBits += ExistingFrag->OffsetInBits; 1877 if (auto Sz = DAI->getVariable()->getSizeInBits()) { 1878 if (F.OffsetInBits == 0 && F.SizeInBits == *Sz) 1879 return std::nullopt; 1880 } 1881 return F; 1882 }(); 1883 1884 DebugVariable DV = DebugVariable(DAI->getVariable(), FragInfo, 1885 DAI->getDebugLoc().getInlinedAt()); 1886 DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()}; 1887 1888 // Cache this info for later. 1889 UntaggedStoreVars[&I].push_back( 1890 {FnVarLocs->insertVariable(DV), *Info}); 1891 1892 if (Seen.insert(DV).second) 1893 FragmentMap[DA].push_back(DV); 1894 } 1895 } 1896 } 1897 } 1898 1899 // Sort the fragment map for each DebugAggregate in non-descending 1900 // order of fragment size. Assert no entries are duplicates. 1901 for (auto &Pair : FragmentMap) { 1902 SmallVector<DebugVariable, 8> &Frags = Pair.second; 1903 std::sort( 1904 Frags.begin(), Frags.end(), [](DebugVariable Next, DebugVariable Elmt) { 1905 assert(!(Elmt.getFragmentOrDefault() == Next.getFragmentOrDefault())); 1906 return Elmt.getFragmentOrDefault().SizeInBits > 1907 Next.getFragmentOrDefault().SizeInBits; 1908 }); 1909 } 1910 1911 // Build the map. 1912 AssignmentTrackingLowering::OverlapMap Map; 1913 for (auto Pair : FragmentMap) { 1914 auto &Frags = Pair.second; 1915 for (auto It = Frags.begin(), IEnd = Frags.end(); It != IEnd; ++It) { 1916 DIExpression::FragmentInfo Frag = It->getFragmentOrDefault(); 1917 // Find the frags that this is contained within. 1918 // 1919 // Because Frags is sorted by size and none have the same offset and 1920 // size, we know that this frag can only be contained by subsequent 1921 // elements. 1922 SmallVector<DebugVariable, 8>::iterator OtherIt = It; 1923 ++OtherIt; 1924 VariableID ThisVar = FnVarLocs->insertVariable(*It); 1925 for (; OtherIt != IEnd; ++OtherIt) { 1926 DIExpression::FragmentInfo OtherFrag = OtherIt->getFragmentOrDefault(); 1927 VariableID OtherVar = FnVarLocs->insertVariable(*OtherIt); 1928 if (fullyContains(OtherFrag, Frag)) 1929 Map[OtherVar].push_back(ThisVar); 1930 } 1931 } 1932 } 1933 1934 return Map; 1935 } 1936 1937 bool AssignmentTrackingLowering::run(FunctionVarLocsBuilder *FnVarLocsBuilder) { 1938 if (Fn.size() > MaxNumBlocks) { 1939 LLVM_DEBUG(dbgs() << "[AT] Dropping var locs in: " << Fn.getName() 1940 << ": too many blocks (" << Fn.size() << ")\n"); 1941 at::deleteAll(&Fn); 1942 return false; 1943 } 1944 1945 FnVarLocs = FnVarLocsBuilder; 1946 1947 // The general structure here is inspired by VarLocBasedImpl.cpp 1948 // (LiveDebugValues). 1949 1950 // Build the variable fragment overlap map. 1951 // Note that this pass doesn't handle partial overlaps correctly (FWIW 1952 // neither does LiveDebugVariables) because that is difficult to do and 1953 // appears to be rare occurance. 1954 VarContains = 1955 buildOverlapMapAndRecordDeclares(Fn, FnVarLocs, UntaggedStoreVars); 1956 1957 // Prepare for traversal. 1958 ReversePostOrderTraversal<Function *> RPOT(&Fn); 1959 std::priority_queue<unsigned int, std::vector<unsigned int>, 1960 std::greater<unsigned int>> 1961 Worklist; 1962 std::priority_queue<unsigned int, std::vector<unsigned int>, 1963 std::greater<unsigned int>> 1964 Pending; 1965 DenseMap<unsigned int, BasicBlock *> OrderToBB; 1966 DenseMap<BasicBlock *, unsigned int> BBToOrder; 1967 { // Init OrderToBB and BBToOrder. 1968 unsigned int RPONumber = 0; 1969 for (auto RI = RPOT.begin(), RE = RPOT.end(); RI != RE; ++RI) { 1970 OrderToBB[RPONumber] = *RI; 1971 BBToOrder[*RI] = RPONumber; 1972 Worklist.push(RPONumber); 1973 ++RPONumber; 1974 } 1975 LiveIn.init(RPONumber); 1976 LiveOut.init(RPONumber); 1977 } 1978 1979 // Perform the traversal. 1980 // 1981 // This is a standard "union of predecessor outs" dataflow problem. To solve 1982 // it, we perform join() and process() using the two worklist method until 1983 // the LiveIn data for each block becomes unchanging. The "proof" that this 1984 // terminates can be put together by looking at the comments around LocKind, 1985 // Assignment, and the various join methods, which show that all the elements 1986 // involved are made up of join-semilattices; LiveIn(n) can only 1987 // monotonically increase in value throughout the dataflow. 1988 // 1989 SmallPtrSet<BasicBlock *, 16> Visited; 1990 while (!Worklist.empty()) { 1991 // We track what is on the pending worklist to avoid inserting the same 1992 // thing twice. 1993 SmallPtrSet<BasicBlock *, 16> OnPending; 1994 LLVM_DEBUG(dbgs() << "Processing Worklist\n"); 1995 while (!Worklist.empty()) { 1996 BasicBlock *BB = OrderToBB[Worklist.top()]; 1997 LLVM_DEBUG(dbgs() << "\nPop BB " << BB->getName() << "\n"); 1998 Worklist.pop(); 1999 bool InChanged = join(*BB, Visited); 2000 // Always consider LiveIn changed on the first visit. 2001 InChanged |= Visited.insert(BB).second; 2002 if (InChanged) { 2003 LLVM_DEBUG(dbgs() << BB->getName() << " has new InLocs, process it\n"); 2004 // Mutate a copy of LiveIn while processing BB. After calling process 2005 // LiveSet is the LiveOut set for BB. 2006 BlockInfo LiveSet = LiveIn[BB]; 2007 2008 // Process the instructions in the block. 2009 process(*BB, &LiveSet); 2010 2011 // Relatively expensive check: has anything changed in LiveOut for BB? 2012 if (LiveOut[BB] != LiveSet) { 2013 LLVM_DEBUG(dbgs() << BB->getName() 2014 << " has new OutLocs, add succs to worklist: [ "); 2015 LiveOut[BB] = std::move(LiveSet); 2016 for (auto I = succ_begin(BB), E = succ_end(BB); I != E; I++) { 2017 if (OnPending.insert(*I).second) { 2018 LLVM_DEBUG(dbgs() << I->getName() << " "); 2019 Pending.push(BBToOrder[*I]); 2020 } 2021 } 2022 LLVM_DEBUG(dbgs() << "]\n"); 2023 } 2024 } 2025 } 2026 Worklist.swap(Pending); 2027 // At this point, pending must be empty, since it was just the empty 2028 // worklist 2029 assert(Pending.empty() && "Pending should be empty"); 2030 } 2031 2032 // That's the hard part over. Now we just have some admin to do. 2033 2034 // Record whether we inserted any intrinsics. 2035 bool InsertedAnyIntrinsics = false; 2036 2037 // Identify and add defs for single location variables. 2038 // 2039 // Go through all of the defs that we plan to add. If the aggregate variable 2040 // it's a part of is not in the NotAlwaysStackHomed set we can emit a single 2041 // location def and omit the rest. Add an entry to AlwaysStackHomed so that 2042 // we can identify those uneeded defs later. 2043 DenseSet<DebugAggregate> AlwaysStackHomed; 2044 for (const auto &Pair : InsertBeforeMap) { 2045 const auto &Vec = Pair.second; 2046 for (VarLocInfo VarLoc : Vec) { 2047 DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID); 2048 DebugAggregate Aggr{Var.getVariable(), Var.getInlinedAt()}; 2049 2050 // Skip this Var if it's not always stack homed. 2051 if (NotAlwaysStackHomed.contains(Aggr)) 2052 continue; 2053 2054 // Skip complex cases such as when different fragments of a variable have 2055 // been split into different allocas. Skipping in this case means falling 2056 // back to using a list of defs (which could reduce coverage, but is no 2057 // less correct). 2058 bool Simple = 2059 VarLoc.Expr->getNumElements() == 1 && VarLoc.Expr->startsWithDeref(); 2060 if (!Simple) { 2061 NotAlwaysStackHomed.insert(Aggr); 2062 continue; 2063 } 2064 2065 // All source assignments to this variable remain and all stores to any 2066 // part of the variable store to the same address (with varying 2067 // offsets). We can just emit a single location for the whole variable. 2068 // 2069 // Unless we've already done so, create the single location def now. 2070 if (AlwaysStackHomed.insert(Aggr).second) { 2071 assert(isa<AllocaInst>(VarLoc.V)); 2072 // TODO: When more complex cases are handled VarLoc.Expr should be 2073 // built appropriately rather than always using an empty DIExpression. 2074 // The assert below is a reminder. 2075 assert(Simple); 2076 VarLoc.Expr = DIExpression::get(Fn.getContext(), std::nullopt); 2077 DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID); 2078 FnVarLocs->addSingleLocVar(Var, VarLoc.Expr, VarLoc.DL, VarLoc.V); 2079 InsertedAnyIntrinsics = true; 2080 } 2081 } 2082 } 2083 2084 // Insert the other DEFs. 2085 for (const auto &[InsertBefore, Vec] : InsertBeforeMap) { 2086 SmallVector<VarLocInfo> NewDefs; 2087 for (const VarLocInfo &VarLoc : Vec) { 2088 DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID); 2089 DebugAggregate Aggr{Var.getVariable(), Var.getInlinedAt()}; 2090 // If this variable is always stack homed then we have already inserted a 2091 // dbg.declare and deleted this dbg.value. 2092 if (AlwaysStackHomed.contains(Aggr)) 2093 continue; 2094 NewDefs.push_back(VarLoc); 2095 InsertedAnyIntrinsics = true; 2096 } 2097 2098 FnVarLocs->setWedge(InsertBefore, std::move(NewDefs)); 2099 } 2100 2101 InsertedAnyIntrinsics |= emitPromotedVarLocs(FnVarLocs); 2102 2103 return InsertedAnyIntrinsics; 2104 } 2105 2106 bool AssignmentTrackingLowering::emitPromotedVarLocs( 2107 FunctionVarLocsBuilder *FnVarLocs) { 2108 bool InsertedAnyIntrinsics = false; 2109 // Go through every block, translating debug intrinsics for fully promoted 2110 // variables into FnVarLocs location defs. No analysis required for these. 2111 for (auto &BB : Fn) { 2112 for (auto &I : BB) { 2113 // Skip instructions other than dbg.values and dbg.assigns. 2114 auto *DVI = dyn_cast<DbgValueInst>(&I); 2115 if (!DVI) 2116 continue; 2117 // Skip variables that haven't been promoted - we've dealt with those 2118 // already. 2119 if (VarsWithStackSlot->contains(getAggregate(DVI))) 2120 continue; 2121 // Wrapper to get a single value (or undef) from DVI. 2122 auto GetValue = [DVI]() -> Value * { 2123 // We can't handle variadic DIExpressions yet so treat those as 2124 // kill locations. 2125 if (DVI->isKillLocation() || DVI->getValue() == nullptr || 2126 DVI->hasArgList()) 2127 return PoisonValue::get(Type::getInt32Ty(DVI->getContext())); 2128 return DVI->getValue(); 2129 }; 2130 Instruction *InsertBefore = I.getNextNode(); 2131 assert(InsertBefore && "Unexpected: debug intrinsics after a terminator"); 2132 FnVarLocs->addVarLoc(InsertBefore, DebugVariable(DVI), 2133 DVI->getExpression(), DVI->getDebugLoc(), 2134 GetValue()); 2135 InsertedAnyIntrinsics = true; 2136 } 2137 } 2138 return InsertedAnyIntrinsics; 2139 } 2140 2141 /// Remove redundant definitions within sequences of consecutive location defs. 2142 /// This is done using a backward scan to keep the last def describing a 2143 /// specific variable/fragment. 2144 /// 2145 /// This implements removeRedundantDbgInstrsUsingBackwardScan from 2146 /// lib/Transforms/Utils/BasicBlockUtils.cpp for locations described with 2147 /// FunctionVarLocsBuilder instead of with intrinsics. 2148 static bool 2149 removeRedundantDbgLocsUsingBackwardScan(const BasicBlock *BB, 2150 FunctionVarLocsBuilder &FnVarLocs) { 2151 bool Changed = false; 2152 SmallDenseSet<DebugVariable> VariableSet; 2153 2154 // Scan over the entire block, not just over the instructions mapped by 2155 // FnVarLocs, because wedges in FnVarLocs may only be seperated by debug 2156 // instructions. 2157 for (const Instruction &I : reverse(*BB)) { 2158 if (!isa<DbgVariableIntrinsic>(I)) { 2159 // Sequence of consecutive defs ended. Clear map for the next one. 2160 VariableSet.clear(); 2161 } 2162 2163 // Get the location defs that start just before this instruction. 2164 const auto *Locs = FnVarLocs.getWedge(&I); 2165 if (!Locs) 2166 continue; 2167 2168 NumWedgesScanned++; 2169 bool ChangedThisWedge = false; 2170 // The new pruned set of defs, reversed because we're scanning backwards. 2171 SmallVector<VarLocInfo> NewDefsReversed; 2172 2173 // Iterate over the existing defs in reverse. 2174 for (auto RIt = Locs->rbegin(), REnd = Locs->rend(); RIt != REnd; ++RIt) { 2175 NumDefsScanned++; 2176 const DebugVariable &Key = FnVarLocs.getVariable(RIt->VariableID); 2177 bool FirstDefOfFragment = VariableSet.insert(Key).second; 2178 2179 // If the same variable fragment is described more than once it is enough 2180 // to keep the last one (i.e. the first found in this reverse iteration). 2181 if (FirstDefOfFragment) { 2182 // New def found: keep it. 2183 NewDefsReversed.push_back(*RIt); 2184 } else { 2185 // Redundant def found: throw it away. Since the wedge of defs is being 2186 // rebuilt, doing nothing is the same as deleting an entry. 2187 ChangedThisWedge = true; 2188 NumDefsRemoved++; 2189 } 2190 continue; 2191 } 2192 2193 // Un-reverse the defs and replace the wedge with the pruned version. 2194 if (ChangedThisWedge) { 2195 std::reverse(NewDefsReversed.begin(), NewDefsReversed.end()); 2196 FnVarLocs.setWedge(&I, std::move(NewDefsReversed)); 2197 NumWedgesChanged++; 2198 Changed = true; 2199 } 2200 } 2201 2202 return Changed; 2203 } 2204 2205 /// Remove redundant location defs using a forward scan. This can remove a 2206 /// location definition that is redundant due to indicating that a variable has 2207 /// the same value as is already being indicated by an earlier def. 2208 /// 2209 /// This implements removeRedundantDbgInstrsUsingForwardScan from 2210 /// lib/Transforms/Utils/BasicBlockUtils.cpp for locations described with 2211 /// FunctionVarLocsBuilder instead of with intrinsics 2212 static bool 2213 removeRedundantDbgLocsUsingForwardScan(const BasicBlock *BB, 2214 FunctionVarLocsBuilder &FnVarLocs) { 2215 bool Changed = false; 2216 DenseMap<DebugVariable, std::pair<Value *, DIExpression *>> VariableMap; 2217 2218 // Scan over the entire block, not just over the instructions mapped by 2219 // FnVarLocs, because wedges in FnVarLocs may only be seperated by debug 2220 // instructions. 2221 for (const Instruction &I : *BB) { 2222 // Get the defs that come just before this instruction. 2223 const auto *Locs = FnVarLocs.getWedge(&I); 2224 if (!Locs) 2225 continue; 2226 2227 NumWedgesScanned++; 2228 bool ChangedThisWedge = false; 2229 // The new pruned set of defs. 2230 SmallVector<VarLocInfo> NewDefs; 2231 2232 // Iterate over the existing defs. 2233 for (const VarLocInfo &Loc : *Locs) { 2234 NumDefsScanned++; 2235 DebugVariable Key(FnVarLocs.getVariable(Loc.VariableID).getVariable(), 2236 std::nullopt, Loc.DL.getInlinedAt()); 2237 auto VMI = VariableMap.find(Key); 2238 2239 // Update the map if we found a new value/expression describing the 2240 // variable, or if the variable wasn't mapped already. 2241 if (VMI == VariableMap.end() || VMI->second.first != Loc.V || 2242 VMI->second.second != Loc.Expr) { 2243 VariableMap[Key] = {Loc.V, Loc.Expr}; 2244 NewDefs.push_back(Loc); 2245 continue; 2246 } 2247 2248 // Did not insert this Loc, which is the same as removing it. 2249 ChangedThisWedge = true; 2250 NumDefsRemoved++; 2251 } 2252 2253 // Replace the existing wedge with the pruned version. 2254 if (ChangedThisWedge) { 2255 FnVarLocs.setWedge(&I, std::move(NewDefs)); 2256 NumWedgesChanged++; 2257 Changed = true; 2258 } 2259 } 2260 2261 return Changed; 2262 } 2263 2264 static bool 2265 removeUndefDbgLocsFromEntryBlock(const BasicBlock *BB, 2266 FunctionVarLocsBuilder &FnVarLocs) { 2267 assert(BB->isEntryBlock()); 2268 // Do extra work to ensure that we remove semantically unimportant undefs. 2269 // 2270 // This is to work around the fact that SelectionDAG will hoist dbg.values 2271 // using argument values to the top of the entry block. That can move arg 2272 // dbg.values before undef and constant dbg.values which they previously 2273 // followed. The easiest thing to do is to just try to feed SelectionDAG 2274 // input it's happy with. 2275 // 2276 // Map of {Variable x: Fragments y} where the fragments y of variable x have 2277 // have at least one non-undef location defined already. Don't use directly, 2278 // instead call DefineBits and HasDefinedBits. 2279 SmallDenseMap<DebugAggregate, SmallDenseSet<DIExpression::FragmentInfo>> 2280 VarsWithDef; 2281 // Specify that V (a fragment of A) has a non-undef location. 2282 auto DefineBits = [&VarsWithDef](DebugAggregate A, DebugVariable V) { 2283 VarsWithDef[A].insert(V.getFragmentOrDefault()); 2284 }; 2285 // Return true if a non-undef location has been defined for V (a fragment of 2286 // A). Doesn't imply that the location is currently non-undef, just that a 2287 // non-undef location has been seen previously. 2288 auto HasDefinedBits = [&VarsWithDef](DebugAggregate A, DebugVariable V) { 2289 auto FragsIt = VarsWithDef.find(A); 2290 if (FragsIt == VarsWithDef.end()) 2291 return false; 2292 return llvm::any_of(FragsIt->second, [V](auto Frag) { 2293 return DIExpression::fragmentsOverlap(Frag, V.getFragmentOrDefault()); 2294 }); 2295 }; 2296 2297 bool Changed = false; 2298 DenseMap<DebugVariable, std::pair<Value *, DIExpression *>> VariableMap; 2299 2300 // Scan over the entire block, not just over the instructions mapped by 2301 // FnVarLocs, because wedges in FnVarLocs may only be seperated by debug 2302 // instructions. 2303 for (const Instruction &I : *BB) { 2304 // Get the defs that come just before this instruction. 2305 const auto *Locs = FnVarLocs.getWedge(&I); 2306 if (!Locs) 2307 continue; 2308 2309 NumWedgesScanned++; 2310 bool ChangedThisWedge = false; 2311 // The new pruned set of defs. 2312 SmallVector<VarLocInfo> NewDefs; 2313 2314 // Iterate over the existing defs. 2315 for (const VarLocInfo &Loc : *Locs) { 2316 NumDefsScanned++; 2317 DebugAggregate Aggr{FnVarLocs.getVariable(Loc.VariableID).getVariable(), 2318 Loc.DL.getInlinedAt()}; 2319 DebugVariable Var = FnVarLocs.getVariable(Loc.VariableID); 2320 2321 // Remove undef entries that are encountered before any non-undef 2322 // intrinsics from the entry block. 2323 if (isa<UndefValue>(Loc.V) && !HasDefinedBits(Aggr, Var)) { 2324 // Did not insert this Loc, which is the same as removing it. 2325 NumDefsRemoved++; 2326 ChangedThisWedge = true; 2327 continue; 2328 } 2329 2330 DefineBits(Aggr, Var); 2331 NewDefs.push_back(Loc); 2332 } 2333 2334 // Replace the existing wedge with the pruned version. 2335 if (ChangedThisWedge) { 2336 FnVarLocs.setWedge(&I, std::move(NewDefs)); 2337 NumWedgesChanged++; 2338 Changed = true; 2339 } 2340 } 2341 2342 return Changed; 2343 } 2344 2345 static bool removeRedundantDbgLocs(const BasicBlock *BB, 2346 FunctionVarLocsBuilder &FnVarLocs) { 2347 bool MadeChanges = false; 2348 MadeChanges |= removeRedundantDbgLocsUsingBackwardScan(BB, FnVarLocs); 2349 if (BB->isEntryBlock()) 2350 MadeChanges |= removeUndefDbgLocsFromEntryBlock(BB, FnVarLocs); 2351 MadeChanges |= removeRedundantDbgLocsUsingForwardScan(BB, FnVarLocs); 2352 2353 if (MadeChanges) 2354 LLVM_DEBUG(dbgs() << "Removed redundant dbg locs from: " << BB->getName() 2355 << "\n"); 2356 return MadeChanges; 2357 } 2358 2359 static DenseSet<DebugAggregate> findVarsWithStackSlot(Function &Fn) { 2360 DenseSet<DebugAggregate> Result; 2361 for (auto &BB : Fn) { 2362 for (auto &I : BB) { 2363 // Any variable linked to an instruction is considered 2364 // interesting. Ideally we only need to check Allocas, however, a 2365 // DIAssignID might get dropped from an alloca but not stores. In that 2366 // case, we need to consider the variable interesting for NFC behaviour 2367 // with this change. TODO: Consider only looking at allocas. 2368 for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(&I)) { 2369 Result.insert({DAI->getVariable(), DAI->getDebugLoc().getInlinedAt()}); 2370 } 2371 } 2372 } 2373 return Result; 2374 } 2375 2376 static void analyzeFunction(Function &Fn, const DataLayout &Layout, 2377 FunctionVarLocsBuilder *FnVarLocs) { 2378 // The analysis will generate location definitions for all variables, but we 2379 // only need to perform a dataflow on the set of variables which have a stack 2380 // slot. Find those now. 2381 DenseSet<DebugAggregate> VarsWithStackSlot = findVarsWithStackSlot(Fn); 2382 2383 bool Changed = false; 2384 2385 // Use a scope block to clean up AssignmentTrackingLowering before running 2386 // MemLocFragmentFill to reduce peak memory consumption. 2387 { 2388 AssignmentTrackingLowering Pass(Fn, Layout, &VarsWithStackSlot); 2389 Changed = Pass.run(FnVarLocs); 2390 } 2391 2392 if (Changed) { 2393 MemLocFragmentFill Pass(Fn, &VarsWithStackSlot); 2394 Pass.run(FnVarLocs); 2395 2396 // Remove redundant entries. As well as reducing memory consumption and 2397 // avoiding waiting cycles later by burning some now, this has another 2398 // important job. That is to work around some SelectionDAG quirks. See 2399 // removeRedundantDbgLocsUsingForwardScan comments for more info on that. 2400 for (auto &BB : Fn) 2401 removeRedundantDbgLocs(&BB, *FnVarLocs); 2402 } 2403 } 2404 2405 bool AssignmentTrackingAnalysis::runOnFunction(Function &F) { 2406 if (!isAssignmentTrackingEnabled(*F.getParent())) 2407 return false; 2408 2409 LLVM_DEBUG(dbgs() << "AssignmentTrackingAnalysis run on " << F.getName() 2410 << "\n"); 2411 auto DL = std::make_unique<DataLayout>(F.getParent()); 2412 2413 // Clear previous results. 2414 Results->clear(); 2415 2416 FunctionVarLocsBuilder Builder; 2417 analyzeFunction(F, *DL.get(), &Builder); 2418 2419 // Save these results. 2420 Results->init(Builder); 2421 2422 if (PrintResults && isFunctionInPrintList(F.getName())) 2423 Results->print(errs(), F); 2424 2425 // Return false because this pass does not modify the function. 2426 return false; 2427 } 2428 2429 AssignmentTrackingAnalysis::AssignmentTrackingAnalysis() 2430 : FunctionPass(ID), Results(std::make_unique<FunctionVarLocs>()) {} 2431 2432 char AssignmentTrackingAnalysis::ID = 0; 2433 2434 INITIALIZE_PASS(AssignmentTrackingAnalysis, DEBUG_TYPE, 2435 "Assignment Tracking Analysis", false, true) 2436