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