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