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