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 // Add the elements in B with variables that are not in A into 1634 // SymmetricDifference. 1635 for (const auto &Pair : B) { 1636 VariableID Var = Pair.first; 1637 if (A.count(Var) == 0) 1638 SymmetricDifference.push_back(Var); 1639 } 1640 1641 // Add SymmetricDifference elements to Join and return the result. 1642 for (const auto &Var : SymmetricDifference) 1643 Join.insert({Var, LocKind::None}); 1644 1645 assert(Join.size() == (IntersectSize + SymmetricDifference.size())); 1646 assert(Join.size() >= A.size() && Join.size() >= B.size()); 1647 return Join; 1648 } 1649 1650 AssignmentTrackingLowering::Assignment 1651 AssignmentTrackingLowering::joinAssignment(const Assignment &A, 1652 const Assignment &B) { 1653 // Partial order: 1654 // NoneOrPhi(null, null) > Known(v, ?s) 1655 1656 // If either are NoneOrPhi the join is NoneOrPhi. 1657 // If either value is different then the result is 1658 // NoneOrPhi (joining two values is a Phi). 1659 if (!A.isSameSourceAssignment(B)) 1660 return Assignment::makeNoneOrPhi(); 1661 if (A.Status == Assignment::NoneOrPhi) 1662 return Assignment::makeNoneOrPhi(); 1663 1664 // Source is used to lookup the value + expression in the debug program if 1665 // the stack slot gets assigned a value earlier than expected. Because 1666 // we're only tracking the one dbg.assign, we can't capture debug PHIs. 1667 // It's unlikely that we're losing out on much coverage by avoiding that 1668 // extra work. 1669 // The Source may differ in this situation: 1670 // Pred.1: 1671 // dbg.assign i32 0, ..., !1, ... 1672 // Pred.2: 1673 // dbg.assign i32 1, ..., !1, ... 1674 // Here the same assignment (!1) was performed in both preds in the source, 1675 // but we can't use either one unless they are identical (e.g. .we don't 1676 // want to arbitrarily pick between constant values). 1677 auto JoinSource = [&]() -> DbgAssignIntrinsic * { 1678 if (A.Source == B.Source) 1679 return A.Source; 1680 if (A.Source == nullptr || B.Source == nullptr) 1681 return nullptr; 1682 if (A.Source->isIdenticalTo(B.Source)) 1683 return A.Source; 1684 return nullptr; 1685 }; 1686 DbgAssignIntrinsic *Source = JoinSource(); 1687 assert(A.Status == B.Status && A.Status == Assignment::Known); 1688 assert(A.ID == B.ID); 1689 return Assignment::make(A.ID, Source); 1690 } 1691 1692 AssignmentTrackingLowering::AssignmentMap 1693 AssignmentTrackingLowering::joinAssignmentMap(const AssignmentMap &A, 1694 const AssignmentMap &B) { 1695 // Join A and B. 1696 // 1697 // U = join(a, b) for a in A, b in B where Var(a) == Var(b) 1698 // D = join(x, ⊤) for x where Var(x) is in A xor B 1699 // Join = U ∪ D 1700 // 1701 // This is achieved by performing a join on elements from A and B with 1702 // variables common to both A and B (join elements indexed by var intersect), 1703 // then adding LocKind::None elements for vars in A xor B. The latter part is 1704 // equivalent to performing join on elements with variables in A xor B with 1705 // Status::NoneOrPhi (⊤) since join(x, ⊤) = ⊤. 1706 AssignmentMap Join(std::max(A.size(), B.size())); 1707 SmallVector<VariableID, 16> SymmetricDifference; 1708 // Insert the join of the elements with common vars into Join. Add the 1709 // remaining elements to into SymmetricDifference. 1710 for (const auto &[Var, AV] : A) { 1711 // If this Var doesn't exist in B then add it to the symmetric difference 1712 // set. 1713 auto R = B.find(Var); 1714 if (R == B.end()) { 1715 SymmetricDifference.push_back(Var); 1716 continue; 1717 } 1718 // There is an entry for Var in both, join it. 1719 Join[Var] = joinAssignment(AV, R->second); 1720 } 1721 unsigned IntersectSize = Join.size(); 1722 (void)IntersectSize; 1723 1724 // Add the elements in B with variables that are not in A into 1725 // SymmetricDifference. 1726 for (const auto &Pair : B) { 1727 VariableID Var = Pair.first; 1728 if (A.count(Var) == 0) 1729 SymmetricDifference.push_back(Var); 1730 } 1731 1732 // Add SymmetricDifference elements to Join and return the result. 1733 for (auto Var : SymmetricDifference) 1734 Join.insert({Var, Assignment::makeNoneOrPhi()}); 1735 1736 assert(Join.size() == (IntersectSize + SymmetricDifference.size())); 1737 assert(Join.size() >= A.size() && Join.size() >= B.size()); 1738 return Join; 1739 } 1740 1741 AssignmentTrackingLowering::BlockInfo 1742 AssignmentTrackingLowering::joinBlockInfo(const BlockInfo &A, 1743 const BlockInfo &B) { 1744 BlockInfo Join; 1745 Join.LiveLoc = joinLocMap(A.LiveLoc, B.LiveLoc); 1746 Join.StackHomeValue = joinAssignmentMap(A.StackHomeValue, B.StackHomeValue); 1747 Join.DebugValue = joinAssignmentMap(A.DebugValue, B.DebugValue); 1748 assert(Join.isValid()); 1749 return Join; 1750 } 1751 1752 bool AssignmentTrackingLowering::join( 1753 const BasicBlock &BB, const SmallPtrSet<BasicBlock *, 16> &Visited) { 1754 BlockInfo BBLiveIn; 1755 bool FirstJoin = true; 1756 // LiveIn locs for BB is the join of the already-processed preds' LiveOut 1757 // locs. 1758 for (auto I = pred_begin(&BB), E = pred_end(&BB); I != E; I++) { 1759 // Ignore backedges if we have not visited the predecessor yet. As the 1760 // predecessor hasn't yet had locations propagated into it, most locations 1761 // will not yet be valid, so treat them as all being uninitialized and 1762 // potentially valid. If a location guessed to be correct here is 1763 // invalidated later, we will remove it when we revisit this block. This 1764 // is essentially the same as initialising all LocKinds and Assignments to 1765 // an implicit ⊥ value which is the identity value for the join operation. 1766 const BasicBlock *Pred = *I; 1767 if (!Visited.count(Pred)) 1768 continue; 1769 1770 auto PredLiveOut = LiveOut.find(Pred); 1771 // Pred must have been processed already. See comment at start of this loop. 1772 assert(PredLiveOut != LiveOut.end()); 1773 1774 // Perform the join of BBLiveIn (current live-in info) and PrevLiveOut. 1775 if (FirstJoin) 1776 BBLiveIn = PredLiveOut->second; 1777 else 1778 BBLiveIn = joinBlockInfo(std::move(BBLiveIn), PredLiveOut->second); 1779 FirstJoin = false; 1780 } 1781 1782 auto CurrentLiveInEntry = LiveIn.find(&BB); 1783 // Check if there isn't an entry, or there is but the LiveIn set has changed 1784 // (expensive check). 1785 if (CurrentLiveInEntry == LiveIn.end() || 1786 BBLiveIn != CurrentLiveInEntry->second) { 1787 LiveIn[&BB] = std::move(BBLiveIn); 1788 // A change has occured. 1789 return true; 1790 } 1791 // No change. 1792 return false; 1793 } 1794 1795 /// Return true if A fully contains B. 1796 static bool fullyContains(DIExpression::FragmentInfo A, 1797 DIExpression::FragmentInfo B) { 1798 auto ALeft = A.OffsetInBits; 1799 auto BLeft = B.OffsetInBits; 1800 if (BLeft < ALeft) 1801 return false; 1802 1803 auto ARight = ALeft + A.SizeInBits; 1804 auto BRight = BLeft + B.SizeInBits; 1805 if (BRight > ARight) 1806 return false; 1807 return true; 1808 } 1809 1810 static std::optional<at::AssignmentInfo> 1811 getUntaggedStoreAssignmentInfo(const Instruction &I, const DataLayout &Layout) { 1812 // Don't bother checking if this is an AllocaInst. We know this 1813 // instruction has no tag which means there are no variables associated 1814 // with it. 1815 if (const auto *SI = dyn_cast<StoreInst>(&I)) 1816 return at::getAssignmentInfo(Layout, SI); 1817 if (const auto *MI = dyn_cast<MemIntrinsic>(&I)) 1818 return at::getAssignmentInfo(Layout, MI); 1819 // Alloca or non-store-like inst. 1820 return std::nullopt; 1821 } 1822 1823 /// Build a map of {Variable x: Variables y} where all variable fragments 1824 /// contained within the variable fragment x are in set y. This means that 1825 /// y does not contain all overlaps because partial overlaps are excluded. 1826 /// 1827 /// While we're iterating over the function, add single location defs for 1828 /// dbg.declares to \p FnVarLocs 1829 /// 1830 /// Finally, populate UntaggedStoreVars with a mapping of untagged stores to 1831 /// the stored-to variable fragments. 1832 /// 1833 /// These tasks are bundled together to reduce the number of times we need 1834 /// to iterate over the function as they can be achieved together in one pass. 1835 static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( 1836 Function &Fn, FunctionVarLocsBuilder *FnVarLocs, 1837 AssignmentTrackingLowering::UntaggedStoreAssignmentMap &UntaggedStoreVars) { 1838 DenseSet<DebugVariable> Seen; 1839 // Map of Variable: [Fragments]. 1840 DenseMap<DebugAggregate, SmallVector<DebugVariable, 8>> FragmentMap; 1841 // Iterate over all instructions: 1842 // - dbg.declare -> add single location variable record 1843 // - dbg.* -> Add fragments to FragmentMap 1844 // - untagged store -> Add fragments to FragmentMap and update 1845 // UntaggedStoreVars. 1846 // We need to add fragments for untagged stores too so that we can correctly 1847 // clobber overlapped fragment locations later. 1848 for (auto &BB : Fn) { 1849 for (auto &I : BB) { 1850 if (auto *DDI = dyn_cast<DbgDeclareInst>(&I)) { 1851 FnVarLocs->addSingleLocVar(DebugVariable(DDI), DDI->getExpression(), 1852 DDI->getDebugLoc(), DDI->getAddress()); 1853 } else if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { 1854 DebugVariable DV = DebugVariable(DII); 1855 DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()}; 1856 if (Seen.insert(DV).second) 1857 FragmentMap[DA].push_back(DV); 1858 } else if (auto Info = getUntaggedStoreAssignmentInfo( 1859 I, Fn.getParent()->getDataLayout())) { 1860 // Find markers linked to this alloca. 1861 for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(Info->Base)) { 1862 // Discard the fragment if it covers the entire variable. 1863 std::optional<DIExpression::FragmentInfo> FragInfo = 1864 [&Info, DAI]() -> std::optional<DIExpression::FragmentInfo> { 1865 DIExpression::FragmentInfo F; 1866 F.OffsetInBits = Info->OffsetInBits; 1867 F.SizeInBits = Info->SizeInBits; 1868 if (auto ExistingFrag = DAI->getExpression()->getFragmentInfo()) 1869 F.OffsetInBits += ExistingFrag->OffsetInBits; 1870 if (auto Sz = DAI->getVariable()->getSizeInBits()) { 1871 if (F.OffsetInBits == 0 && F.SizeInBits == *Sz) 1872 return std::nullopt; 1873 } 1874 return F; 1875 }(); 1876 1877 DebugVariable DV = DebugVariable(DAI->getVariable(), FragInfo, 1878 DAI->getDebugLoc().getInlinedAt()); 1879 DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()}; 1880 1881 // Cache this info for later. 1882 UntaggedStoreVars[&I].push_back( 1883 {FnVarLocs->insertVariable(DV), *Info}); 1884 1885 if (Seen.insert(DV).second) 1886 FragmentMap[DA].push_back(DV); 1887 } 1888 } 1889 } 1890 } 1891 1892 // Sort the fragment map for each DebugAggregate in non-descending 1893 // order of fragment size. Assert no entries are duplicates. 1894 for (auto &Pair : FragmentMap) { 1895 SmallVector<DebugVariable, 8> &Frags = Pair.second; 1896 std::sort( 1897 Frags.begin(), Frags.end(), [](DebugVariable Next, DebugVariable Elmt) { 1898 assert(!(Elmt.getFragmentOrDefault() == Next.getFragmentOrDefault())); 1899 return Elmt.getFragmentOrDefault().SizeInBits > 1900 Next.getFragmentOrDefault().SizeInBits; 1901 }); 1902 } 1903 1904 // Build the map. 1905 AssignmentTrackingLowering::OverlapMap Map; 1906 for (auto Pair : FragmentMap) { 1907 auto &Frags = Pair.second; 1908 for (auto It = Frags.begin(), IEnd = Frags.end(); It != IEnd; ++It) { 1909 DIExpression::FragmentInfo Frag = It->getFragmentOrDefault(); 1910 // Find the frags that this is contained within. 1911 // 1912 // Because Frags is sorted by size and none have the same offset and 1913 // size, we know that this frag can only be contained by subsequent 1914 // elements. 1915 SmallVector<DebugVariable, 8>::iterator OtherIt = It; 1916 ++OtherIt; 1917 VariableID ThisVar = FnVarLocs->insertVariable(*It); 1918 for (; OtherIt != IEnd; ++OtherIt) { 1919 DIExpression::FragmentInfo OtherFrag = OtherIt->getFragmentOrDefault(); 1920 VariableID OtherVar = FnVarLocs->insertVariable(*OtherIt); 1921 if (fullyContains(OtherFrag, Frag)) 1922 Map[OtherVar].push_back(ThisVar); 1923 } 1924 } 1925 } 1926 1927 return Map; 1928 } 1929 1930 bool AssignmentTrackingLowering::run(FunctionVarLocsBuilder *FnVarLocsBuilder) { 1931 if (Fn.size() > MaxNumBlocks) { 1932 LLVM_DEBUG(dbgs() << "[AT] Dropping var locs in: " << Fn.getName() 1933 << ": too many blocks (" << Fn.size() << ")\n"); 1934 at::deleteAll(&Fn); 1935 return false; 1936 } 1937 1938 FnVarLocs = FnVarLocsBuilder; 1939 1940 // The general structure here is inspired by VarLocBasedImpl.cpp 1941 // (LiveDebugValues). 1942 1943 // Build the variable fragment overlap map. 1944 // Note that this pass doesn't handle partial overlaps correctly (FWIW 1945 // neither does LiveDebugVariables) because that is difficult to do and 1946 // appears to be rare occurance. 1947 VarContains = 1948 buildOverlapMapAndRecordDeclares(Fn, FnVarLocs, UntaggedStoreVars); 1949 1950 // Prepare for traversal. 1951 ReversePostOrderTraversal<Function *> RPOT(&Fn); 1952 std::priority_queue<unsigned int, std::vector<unsigned int>, 1953 std::greater<unsigned int>> 1954 Worklist; 1955 std::priority_queue<unsigned int, std::vector<unsigned int>, 1956 std::greater<unsigned int>> 1957 Pending; 1958 DenseMap<unsigned int, BasicBlock *> OrderToBB; 1959 DenseMap<BasicBlock *, unsigned int> BBToOrder; 1960 { // Init OrderToBB and BBToOrder. 1961 unsigned int RPONumber = 0; 1962 for (auto RI = RPOT.begin(), RE = RPOT.end(); RI != RE; ++RI) { 1963 OrderToBB[RPONumber] = *RI; 1964 BBToOrder[*RI] = RPONumber; 1965 Worklist.push(RPONumber); 1966 ++RPONumber; 1967 } 1968 LiveIn.init(RPONumber); 1969 LiveOut.init(RPONumber); 1970 } 1971 1972 // Perform the traversal. 1973 // 1974 // This is a standard "union of predecessor outs" dataflow problem. To solve 1975 // it, we perform join() and process() using the two worklist method until 1976 // the LiveIn data for each block becomes unchanging. The "proof" that this 1977 // terminates can be put together by looking at the comments around LocKind, 1978 // Assignment, and the various join methods, which show that all the elements 1979 // involved are made up of join-semilattices; LiveIn(n) can only 1980 // monotonically increase in value throughout the dataflow. 1981 // 1982 SmallPtrSet<BasicBlock *, 16> Visited; 1983 while (!Worklist.empty()) { 1984 // We track what is on the pending worklist to avoid inserting the same 1985 // thing twice. 1986 SmallPtrSet<BasicBlock *, 16> OnPending; 1987 LLVM_DEBUG(dbgs() << "Processing Worklist\n"); 1988 while (!Worklist.empty()) { 1989 BasicBlock *BB = OrderToBB[Worklist.top()]; 1990 LLVM_DEBUG(dbgs() << "\nPop BB " << BB->getName() << "\n"); 1991 Worklist.pop(); 1992 bool InChanged = join(*BB, Visited); 1993 // Always consider LiveIn changed on the first visit. 1994 InChanged |= Visited.insert(BB).second; 1995 if (InChanged) { 1996 LLVM_DEBUG(dbgs() << BB->getName() << " has new InLocs, process it\n"); 1997 // Mutate a copy of LiveIn while processing BB. After calling process 1998 // LiveSet is the LiveOut set for BB. 1999 BlockInfo LiveSet = LiveIn[BB]; 2000 2001 // Process the instructions in the block. 2002 process(*BB, &LiveSet); 2003 2004 // Relatively expensive check: has anything changed in LiveOut for BB? 2005 if (LiveOut[BB] != LiveSet) { 2006 LLVM_DEBUG(dbgs() << BB->getName() 2007 << " has new OutLocs, add succs to worklist: [ "); 2008 LiveOut[BB] = std::move(LiveSet); 2009 for (auto I = succ_begin(BB), E = succ_end(BB); I != E; I++) { 2010 if (OnPending.insert(*I).second) { 2011 LLVM_DEBUG(dbgs() << I->getName() << " "); 2012 Pending.push(BBToOrder[*I]); 2013 } 2014 } 2015 LLVM_DEBUG(dbgs() << "]\n"); 2016 } 2017 } 2018 } 2019 Worklist.swap(Pending); 2020 // At this point, pending must be empty, since it was just the empty 2021 // worklist 2022 assert(Pending.empty() && "Pending should be empty"); 2023 } 2024 2025 // That's the hard part over. Now we just have some admin to do. 2026 2027 // Record whether we inserted any intrinsics. 2028 bool InsertedAnyIntrinsics = false; 2029 2030 // Identify and add defs for single location variables. 2031 // 2032 // Go through all of the defs that we plan to add. If the aggregate variable 2033 // it's a part of is not in the NotAlwaysStackHomed set we can emit a single 2034 // location def and omit the rest. Add an entry to AlwaysStackHomed so that 2035 // we can identify those uneeded defs later. 2036 DenseSet<DebugAggregate> AlwaysStackHomed; 2037 for (const auto &Pair : InsertBeforeMap) { 2038 const auto &Vec = Pair.second; 2039 for (VarLocInfo VarLoc : Vec) { 2040 DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID); 2041 DebugAggregate Aggr{Var.getVariable(), Var.getInlinedAt()}; 2042 2043 // Skip this Var if it's not always stack homed. 2044 if (NotAlwaysStackHomed.contains(Aggr)) 2045 continue; 2046 2047 // Skip complex cases such as when different fragments of a variable have 2048 // been split into different allocas. Skipping in this case means falling 2049 // back to using a list of defs (which could reduce coverage, but is no 2050 // less correct). 2051 bool Simple = 2052 VarLoc.Expr->getNumElements() == 1 && VarLoc.Expr->startsWithDeref(); 2053 if (!Simple) { 2054 NotAlwaysStackHomed.insert(Aggr); 2055 continue; 2056 } 2057 2058 // All source assignments to this variable remain and all stores to any 2059 // part of the variable store to the same address (with varying 2060 // offsets). We can just emit a single location for the whole variable. 2061 // 2062 // Unless we've already done so, create the single location def now. 2063 if (AlwaysStackHomed.insert(Aggr).second) { 2064 assert(isa<AllocaInst>(VarLoc.V)); 2065 // TODO: When more complex cases are handled VarLoc.Expr should be 2066 // built appropriately rather than always using an empty DIExpression. 2067 // The assert below is a reminder. 2068 assert(Simple); 2069 VarLoc.Expr = DIExpression::get(Fn.getContext(), std::nullopt); 2070 DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID); 2071 FnVarLocs->addSingleLocVar(Var, VarLoc.Expr, VarLoc.DL, VarLoc.V); 2072 InsertedAnyIntrinsics = true; 2073 } 2074 } 2075 } 2076 2077 // Insert the other DEFs. 2078 for (const auto &[InsertBefore, Vec] : InsertBeforeMap) { 2079 SmallVector<VarLocInfo> NewDefs; 2080 for (const VarLocInfo &VarLoc : Vec) { 2081 DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID); 2082 DebugAggregate Aggr{Var.getVariable(), Var.getInlinedAt()}; 2083 // If this variable is always stack homed then we have already inserted a 2084 // dbg.declare and deleted this dbg.value. 2085 if (AlwaysStackHomed.contains(Aggr)) 2086 continue; 2087 NewDefs.push_back(VarLoc); 2088 InsertedAnyIntrinsics = true; 2089 } 2090 2091 FnVarLocs->setWedge(InsertBefore, std::move(NewDefs)); 2092 } 2093 2094 InsertedAnyIntrinsics |= emitPromotedVarLocs(FnVarLocs); 2095 2096 return InsertedAnyIntrinsics; 2097 } 2098 2099 bool AssignmentTrackingLowering::emitPromotedVarLocs( 2100 FunctionVarLocsBuilder *FnVarLocs) { 2101 bool InsertedAnyIntrinsics = false; 2102 // Go through every block, translating debug intrinsics for fully promoted 2103 // variables into FnVarLocs location defs. No analysis required for these. 2104 for (auto &BB : Fn) { 2105 for (auto &I : BB) { 2106 // Skip instructions other than dbg.values and dbg.assigns. 2107 auto *DVI = dyn_cast<DbgValueInst>(&I); 2108 if (!DVI) 2109 continue; 2110 // Skip variables that haven't been promoted - we've dealt with those 2111 // already. 2112 if (VarsWithStackSlot->contains(getAggregate(DVI))) 2113 continue; 2114 // Wrapper to get a single value (or undef) from DVI. 2115 auto GetValue = [DVI]() -> Value * { 2116 // We can't handle variadic DIExpressions yet so treat those as 2117 // kill locations. 2118 if (DVI->isKillLocation() || DVI->getValue() == nullptr || 2119 DVI->hasArgList()) 2120 return PoisonValue::get(Type::getInt32Ty(DVI->getContext())); 2121 return DVI->getValue(); 2122 }; 2123 Instruction *InsertBefore = I.getNextNode(); 2124 assert(InsertBefore && "Unexpected: debug intrinsics after a terminator"); 2125 FnVarLocs->addVarLoc(InsertBefore, DebugVariable(DVI), 2126 DVI->getExpression(), DVI->getDebugLoc(), 2127 GetValue()); 2128 InsertedAnyIntrinsics = true; 2129 } 2130 } 2131 return InsertedAnyIntrinsics; 2132 } 2133 2134 /// Remove redundant definitions within sequences of consecutive location defs. 2135 /// This is done using a backward scan to keep the last def describing a 2136 /// specific variable/fragment. 2137 /// 2138 /// This implements removeRedundantDbgInstrsUsingBackwardScan from 2139 /// lib/Transforms/Utils/BasicBlockUtils.cpp for locations described with 2140 /// FunctionVarLocsBuilder instead of with intrinsics. 2141 static bool 2142 removeRedundantDbgLocsUsingBackwardScan(const BasicBlock *BB, 2143 FunctionVarLocsBuilder &FnVarLocs) { 2144 bool Changed = false; 2145 SmallDenseSet<DebugVariable> VariableSet; 2146 2147 // Scan over the entire block, not just over the instructions mapped by 2148 // FnVarLocs, because wedges in FnVarLocs may only be seperated by debug 2149 // instructions. 2150 for (const Instruction &I : reverse(*BB)) { 2151 if (!isa<DbgVariableIntrinsic>(I)) { 2152 // Sequence of consecutive defs ended. Clear map for the next one. 2153 VariableSet.clear(); 2154 } 2155 2156 // Get the location defs that start just before this instruction. 2157 const auto *Locs = FnVarLocs.getWedge(&I); 2158 if (!Locs) 2159 continue; 2160 2161 NumWedgesScanned++; 2162 bool ChangedThisWedge = false; 2163 // The new pruned set of defs, reversed because we're scanning backwards. 2164 SmallVector<VarLocInfo> NewDefsReversed; 2165 2166 // Iterate over the existing defs in reverse. 2167 for (auto RIt = Locs->rbegin(), REnd = Locs->rend(); RIt != REnd; ++RIt) { 2168 NumDefsScanned++; 2169 const DebugVariable &Key = FnVarLocs.getVariable(RIt->VariableID); 2170 bool FirstDefOfFragment = VariableSet.insert(Key).second; 2171 2172 // If the same variable fragment is described more than once it is enough 2173 // to keep the last one (i.e. the first found in this reverse iteration). 2174 if (FirstDefOfFragment) { 2175 // New def found: keep it. 2176 NewDefsReversed.push_back(*RIt); 2177 } else { 2178 // Redundant def found: throw it away. Since the wedge of defs is being 2179 // rebuilt, doing nothing is the same as deleting an entry. 2180 ChangedThisWedge = true; 2181 NumDefsRemoved++; 2182 } 2183 continue; 2184 } 2185 2186 // Un-reverse the defs and replace the wedge with the pruned version. 2187 if (ChangedThisWedge) { 2188 std::reverse(NewDefsReversed.begin(), NewDefsReversed.end()); 2189 FnVarLocs.setWedge(&I, std::move(NewDefsReversed)); 2190 NumWedgesChanged++; 2191 Changed = true; 2192 } 2193 } 2194 2195 return Changed; 2196 } 2197 2198 /// Remove redundant location defs using a forward scan. This can remove a 2199 /// location definition that is redundant due to indicating that a variable has 2200 /// the same value as is already being indicated by an earlier def. 2201 /// 2202 /// This implements removeRedundantDbgInstrsUsingForwardScan from 2203 /// lib/Transforms/Utils/BasicBlockUtils.cpp for locations described with 2204 /// FunctionVarLocsBuilder instead of with intrinsics 2205 static bool 2206 removeRedundantDbgLocsUsingForwardScan(const BasicBlock *BB, 2207 FunctionVarLocsBuilder &FnVarLocs) { 2208 bool Changed = false; 2209 DenseMap<DebugVariable, std::pair<Value *, DIExpression *>> VariableMap; 2210 2211 // Scan over the entire block, not just over the instructions mapped by 2212 // FnVarLocs, because wedges in FnVarLocs may only be seperated by debug 2213 // instructions. 2214 for (const Instruction &I : *BB) { 2215 // Get the defs that come just before this instruction. 2216 const auto *Locs = FnVarLocs.getWedge(&I); 2217 if (!Locs) 2218 continue; 2219 2220 NumWedgesScanned++; 2221 bool ChangedThisWedge = false; 2222 // The new pruned set of defs. 2223 SmallVector<VarLocInfo> NewDefs; 2224 2225 // Iterate over the existing defs. 2226 for (const VarLocInfo &Loc : *Locs) { 2227 NumDefsScanned++; 2228 DebugVariable Key(FnVarLocs.getVariable(Loc.VariableID).getVariable(), 2229 std::nullopt, Loc.DL.getInlinedAt()); 2230 auto VMI = VariableMap.find(Key); 2231 2232 // Update the map if we found a new value/expression describing the 2233 // variable, or if the variable wasn't mapped already. 2234 if (VMI == VariableMap.end() || VMI->second.first != Loc.V || 2235 VMI->second.second != Loc.Expr) { 2236 VariableMap[Key] = {Loc.V, Loc.Expr}; 2237 NewDefs.push_back(Loc); 2238 continue; 2239 } 2240 2241 // Did not insert this Loc, which is the same as removing it. 2242 ChangedThisWedge = true; 2243 NumDefsRemoved++; 2244 } 2245 2246 // Replace the existing wedge with the pruned version. 2247 if (ChangedThisWedge) { 2248 FnVarLocs.setWedge(&I, std::move(NewDefs)); 2249 NumWedgesChanged++; 2250 Changed = true; 2251 } 2252 } 2253 2254 return Changed; 2255 } 2256 2257 static bool 2258 removeUndefDbgLocsFromEntryBlock(const BasicBlock *BB, 2259 FunctionVarLocsBuilder &FnVarLocs) { 2260 assert(BB->isEntryBlock()); 2261 // Do extra work to ensure that we remove semantically unimportant undefs. 2262 // 2263 // This is to work around the fact that SelectionDAG will hoist dbg.values 2264 // using argument values to the top of the entry block. That can move arg 2265 // dbg.values before undef and constant dbg.values which they previously 2266 // followed. The easiest thing to do is to just try to feed SelectionDAG 2267 // input it's happy with. 2268 // 2269 // Map of {Variable x: Fragments y} where the fragments y of variable x have 2270 // have at least one non-undef location defined already. Don't use directly, 2271 // instead call DefineBits and HasDefinedBits. 2272 SmallDenseMap<DebugAggregate, SmallDenseSet<DIExpression::FragmentInfo>> 2273 VarsWithDef; 2274 // Specify that V (a fragment of A) has a non-undef location. 2275 auto DefineBits = [&VarsWithDef](DebugAggregate A, DebugVariable V) { 2276 VarsWithDef[A].insert(V.getFragmentOrDefault()); 2277 }; 2278 // Return true if a non-undef location has been defined for V (a fragment of 2279 // A). Doesn't imply that the location is currently non-undef, just that a 2280 // non-undef location has been seen previously. 2281 auto HasDefinedBits = [&VarsWithDef](DebugAggregate A, DebugVariable V) { 2282 auto FragsIt = VarsWithDef.find(A); 2283 if (FragsIt == VarsWithDef.end()) 2284 return false; 2285 return llvm::any_of(FragsIt->second, [V](auto Frag) { 2286 return DIExpression::fragmentsOverlap(Frag, V.getFragmentOrDefault()); 2287 }); 2288 }; 2289 2290 bool Changed = false; 2291 DenseMap<DebugVariable, std::pair<Value *, DIExpression *>> VariableMap; 2292 2293 // Scan over the entire block, not just over the instructions mapped by 2294 // FnVarLocs, because wedges in FnVarLocs may only be seperated by debug 2295 // instructions. 2296 for (const Instruction &I : *BB) { 2297 // Get the defs that come just before this instruction. 2298 const auto *Locs = FnVarLocs.getWedge(&I); 2299 if (!Locs) 2300 continue; 2301 2302 NumWedgesScanned++; 2303 bool ChangedThisWedge = false; 2304 // The new pruned set of defs. 2305 SmallVector<VarLocInfo> NewDefs; 2306 2307 // Iterate over the existing defs. 2308 for (const VarLocInfo &Loc : *Locs) { 2309 NumDefsScanned++; 2310 DebugAggregate Aggr{FnVarLocs.getVariable(Loc.VariableID).getVariable(), 2311 Loc.DL.getInlinedAt()}; 2312 DebugVariable Var = FnVarLocs.getVariable(Loc.VariableID); 2313 2314 // Remove undef entries that are encountered before any non-undef 2315 // intrinsics from the entry block. 2316 if (isa<UndefValue>(Loc.V) && !HasDefinedBits(Aggr, Var)) { 2317 // Did not insert this Loc, which is the same as removing it. 2318 NumDefsRemoved++; 2319 ChangedThisWedge = true; 2320 continue; 2321 } 2322 2323 DefineBits(Aggr, Var); 2324 NewDefs.push_back(Loc); 2325 } 2326 2327 // Replace the existing wedge with the pruned version. 2328 if (ChangedThisWedge) { 2329 FnVarLocs.setWedge(&I, std::move(NewDefs)); 2330 NumWedgesChanged++; 2331 Changed = true; 2332 } 2333 } 2334 2335 return Changed; 2336 } 2337 2338 static bool removeRedundantDbgLocs(const BasicBlock *BB, 2339 FunctionVarLocsBuilder &FnVarLocs) { 2340 bool MadeChanges = false; 2341 MadeChanges |= removeRedundantDbgLocsUsingBackwardScan(BB, FnVarLocs); 2342 if (BB->isEntryBlock()) 2343 MadeChanges |= removeUndefDbgLocsFromEntryBlock(BB, FnVarLocs); 2344 MadeChanges |= removeRedundantDbgLocsUsingForwardScan(BB, FnVarLocs); 2345 2346 if (MadeChanges) 2347 LLVM_DEBUG(dbgs() << "Removed redundant dbg locs from: " << BB->getName() 2348 << "\n"); 2349 return MadeChanges; 2350 } 2351 2352 static DenseSet<DebugAggregate> findVarsWithStackSlot(Function &Fn) { 2353 DenseSet<DebugAggregate> Result; 2354 for (auto &BB : Fn) { 2355 for (auto &I : BB) { 2356 // Any variable linked to an instruction is considered 2357 // interesting. Ideally we only need to check Allocas, however, a 2358 // DIAssignID might get dropped from an alloca but not stores. In that 2359 // case, we need to consider the variable interesting for NFC behaviour 2360 // with this change. TODO: Consider only looking at allocas. 2361 for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(&I)) { 2362 Result.insert({DAI->getVariable(), DAI->getDebugLoc().getInlinedAt()}); 2363 } 2364 } 2365 } 2366 return Result; 2367 } 2368 2369 static void analyzeFunction(Function &Fn, const DataLayout &Layout, 2370 FunctionVarLocsBuilder *FnVarLocs) { 2371 // The analysis will generate location definitions for all variables, but we 2372 // only need to perform a dataflow on the set of variables which have a stack 2373 // slot. Find those now. 2374 DenseSet<DebugAggregate> VarsWithStackSlot = findVarsWithStackSlot(Fn); 2375 2376 bool Changed = false; 2377 2378 // Use a scope block to clean up AssignmentTrackingLowering before running 2379 // MemLocFragmentFill to reduce peak memory consumption. 2380 { 2381 AssignmentTrackingLowering Pass(Fn, Layout, &VarsWithStackSlot); 2382 Changed = Pass.run(FnVarLocs); 2383 } 2384 2385 if (Changed) { 2386 MemLocFragmentFill Pass(Fn, &VarsWithStackSlot); 2387 Pass.run(FnVarLocs); 2388 2389 // Remove redundant entries. As well as reducing memory consumption and 2390 // avoiding waiting cycles later by burning some now, this has another 2391 // important job. That is to work around some SelectionDAG quirks. See 2392 // removeRedundantDbgLocsUsingForwardScan comments for more info on that. 2393 for (auto &BB : Fn) 2394 removeRedundantDbgLocs(&BB, *FnVarLocs); 2395 } 2396 } 2397 2398 bool AssignmentTrackingAnalysis::runOnFunction(Function &F) { 2399 if (!isAssignmentTrackingEnabled(*F.getParent())) 2400 return false; 2401 2402 LLVM_DEBUG(dbgs() << "AssignmentTrackingAnalysis run on " << F.getName() 2403 << "\n"); 2404 auto DL = std::make_unique<DataLayout>(F.getParent()); 2405 2406 // Clear previous results. 2407 Results->clear(); 2408 2409 FunctionVarLocsBuilder Builder; 2410 analyzeFunction(F, *DL.get(), &Builder); 2411 2412 // Save these results. 2413 Results->init(Builder); 2414 2415 if (PrintResults && isFunctionInPrintList(F.getName())) 2416 Results->print(errs(), F); 2417 2418 // Return false because this pass does not modify the function. 2419 return false; 2420 } 2421 2422 AssignmentTrackingAnalysis::AssignmentTrackingAnalysis() 2423 : FunctionPass(ID), Results(std::make_unique<FunctionVarLocs>()) {} 2424 2425 char AssignmentTrackingAnalysis::ID = 0; 2426 2427 INITIALIZE_PASS(AssignmentTrackingAnalysis, DEBUG_TYPE, 2428 "Assignment Tracking Analysis", false, true) 2429