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