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