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