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