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