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