xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1297eecfbSDimitry Andric //===-- AssignmentTrackingAnalysis.cpp ------------------------------------===//
2297eecfbSDimitry Andric //
3297eecfbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4297eecfbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5297eecfbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6297eecfbSDimitry Andric //
7297eecfbSDimitry Andric //===----------------------------------------------------------------------===//
8297eecfbSDimitry Andric 
9bdd1243dSDimitry Andric #include "llvm/CodeGen/AssignmentTrackingAnalysis.h"
1006c3fb27SDimitry Andric #include "LiveDebugValues/LiveDebugValues.h"
1106c3fb27SDimitry Andric #include "llvm/ADT/BitVector.h"
12bdd1243dSDimitry Andric #include "llvm/ADT/DenseMapInfo.h"
13bdd1243dSDimitry Andric #include "llvm/ADT/IntervalMap.h"
14bdd1243dSDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
15bdd1243dSDimitry Andric #include "llvm/ADT/STLExtras.h"
16bdd1243dSDimitry Andric #include "llvm/ADT/Statistic.h"
17bdd1243dSDimitry Andric #include "llvm/ADT/UniqueVector.h"
18bdd1243dSDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
19bdd1243dSDimitry Andric #include "llvm/IR/BasicBlock.h"
20bdd1243dSDimitry Andric #include "llvm/IR/DataLayout.h"
21bdd1243dSDimitry Andric #include "llvm/IR/DebugInfo.h"
227a6dacacSDimitry Andric #include "llvm/IR/DebugProgramInstruction.h"
23bdd1243dSDimitry Andric #include "llvm/IR/Function.h"
24bdd1243dSDimitry Andric #include "llvm/IR/Instruction.h"
25bdd1243dSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
26*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h"
27bdd1243dSDimitry Andric #include "llvm/IR/PassManager.h"
28bdd1243dSDimitry Andric #include "llvm/IR/PrintPasses.h"
29bdd1243dSDimitry Andric #include "llvm/InitializePasses.h"
30bdd1243dSDimitry Andric #include "llvm/Support/CommandLine.h"
31bdd1243dSDimitry Andric #include "llvm/Support/ErrorHandling.h"
32bdd1243dSDimitry Andric #include "llvm/Support/raw_ostream.h"
33bdd1243dSDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
34bdd1243dSDimitry Andric #include <assert.h>
35bdd1243dSDimitry Andric #include <cstdint>
36bdd1243dSDimitry Andric #include <optional>
375f757f3fSDimitry Andric #include <queue>
38bdd1243dSDimitry Andric #include <sstream>
39bdd1243dSDimitry Andric #include <unordered_map>
40bdd1243dSDimitry Andric 
41bdd1243dSDimitry Andric using namespace llvm;
42bdd1243dSDimitry Andric #define DEBUG_TYPE "debug-ata"
43bdd1243dSDimitry Andric 
44bdd1243dSDimitry Andric STATISTIC(NumDefsScanned, "Number of dbg locs that get scanned for removal");
45bdd1243dSDimitry Andric STATISTIC(NumDefsRemoved, "Number of dbg locs removed");
46bdd1243dSDimitry Andric STATISTIC(NumWedgesScanned, "Number of dbg wedges scanned");
47bdd1243dSDimitry Andric STATISTIC(NumWedgesChanged, "Number of dbg wedges changed");
48bdd1243dSDimitry Andric 
49bdd1243dSDimitry Andric static cl::opt<unsigned>
50bdd1243dSDimitry Andric     MaxNumBlocks("debug-ata-max-blocks", cl::init(10000),
51bdd1243dSDimitry Andric                  cl::desc("Maximum num basic blocks before debug info dropped"),
52bdd1243dSDimitry Andric                  cl::Hidden);
53bdd1243dSDimitry Andric /// Option for debugging the pass, determines if the memory location fragment
54bdd1243dSDimitry Andric /// filling happens after generating the variable locations.
55bdd1243dSDimitry Andric static cl::opt<bool> EnableMemLocFragFill("mem-loc-frag-fill", cl::init(true),
56bdd1243dSDimitry Andric                                           cl::Hidden);
57bdd1243dSDimitry Andric /// Print the results of the analysis. Respects -filter-print-funcs.
58bdd1243dSDimitry Andric static cl::opt<bool> PrintResults("print-debug-ata", cl::init(false),
59bdd1243dSDimitry Andric                                   cl::Hidden);
60bdd1243dSDimitry Andric 
6106c3fb27SDimitry Andric /// Coalesce adjacent dbg locs describing memory locations that have contiguous
6206c3fb27SDimitry Andric /// fragments. This reduces the cost of LiveDebugValues which does SSA
6306c3fb27SDimitry Andric /// construction for each explicitly stated variable fragment.
6406c3fb27SDimitry Andric static cl::opt<cl::boolOrDefault>
6506c3fb27SDimitry Andric     CoalesceAdjacentFragmentsOpt("debug-ata-coalesce-frags", cl::Hidden);
6606c3fb27SDimitry Andric 
67bdd1243dSDimitry Andric // Implicit conversions are disabled for enum class types, so unfortunately we
68bdd1243dSDimitry Andric // need to create a DenseMapInfo wrapper around the specified underlying type.
69bdd1243dSDimitry Andric template <> struct llvm::DenseMapInfo<VariableID> {
70bdd1243dSDimitry Andric   using Wrapped = DenseMapInfo<unsigned>;
71bdd1243dSDimitry Andric   static inline VariableID getEmptyKey() {
72bdd1243dSDimitry Andric     return static_cast<VariableID>(Wrapped::getEmptyKey());
73bdd1243dSDimitry Andric   }
74bdd1243dSDimitry Andric   static inline VariableID getTombstoneKey() {
75bdd1243dSDimitry Andric     return static_cast<VariableID>(Wrapped::getTombstoneKey());
76bdd1243dSDimitry Andric   }
77bdd1243dSDimitry Andric   static unsigned getHashValue(const VariableID &Val) {
78bdd1243dSDimitry Andric     return Wrapped::getHashValue(static_cast<unsigned>(Val));
79bdd1243dSDimitry Andric   }
80bdd1243dSDimitry Andric   static bool isEqual(const VariableID &LHS, const VariableID &RHS) {
81bdd1243dSDimitry Andric     return LHS == RHS;
82bdd1243dSDimitry Andric   }
83bdd1243dSDimitry Andric };
84bdd1243dSDimitry Andric 
85*0fca6ea1SDimitry Andric using VarLocInsertPt = PointerUnion<const Instruction *, const DbgRecord *>;
867a6dacacSDimitry Andric 
877a6dacacSDimitry Andric namespace std {
887a6dacacSDimitry Andric template <> struct hash<VarLocInsertPt> {
897a6dacacSDimitry Andric   using argument_type = VarLocInsertPt;
907a6dacacSDimitry Andric   using result_type = std::size_t;
917a6dacacSDimitry Andric 
927a6dacacSDimitry Andric   result_type operator()(const argument_type &Arg) const {
937a6dacacSDimitry Andric     return std::hash<void *>()(Arg.getOpaqueValue());
947a6dacacSDimitry Andric   }
957a6dacacSDimitry Andric };
967a6dacacSDimitry Andric } // namespace std
977a6dacacSDimitry Andric 
98bdd1243dSDimitry Andric /// Helper class to build FunctionVarLocs, since that class isn't easy to
99bdd1243dSDimitry Andric /// modify. TODO: There's not a great deal of value in the split, it could be
100bdd1243dSDimitry Andric /// worth merging the two classes.
101bdd1243dSDimitry Andric class FunctionVarLocsBuilder {
102bdd1243dSDimitry Andric   friend FunctionVarLocs;
103bdd1243dSDimitry Andric   UniqueVector<DebugVariable> Variables;
104bdd1243dSDimitry Andric   // Use an unordered_map so we don't invalidate iterators after
105bdd1243dSDimitry Andric   // insert/modifications.
1067a6dacacSDimitry Andric   std::unordered_map<VarLocInsertPt, SmallVector<VarLocInfo>> VarLocsBeforeInst;
107bdd1243dSDimitry Andric 
108bdd1243dSDimitry Andric   SmallVector<VarLocInfo> SingleLocVars;
109bdd1243dSDimitry Andric 
110bdd1243dSDimitry Andric public:
11106c3fb27SDimitry Andric   unsigned getNumVariables() const { return Variables.size(); }
11206c3fb27SDimitry Andric 
113bdd1243dSDimitry Andric   /// Find or insert \p V and return the ID.
114bdd1243dSDimitry Andric   VariableID insertVariable(DebugVariable V) {
115bdd1243dSDimitry Andric     return static_cast<VariableID>(Variables.insert(V));
116bdd1243dSDimitry Andric   }
117bdd1243dSDimitry Andric 
118bdd1243dSDimitry Andric   /// Get a variable from its \p ID.
119bdd1243dSDimitry Andric   const DebugVariable &getVariable(VariableID ID) const {
120bdd1243dSDimitry Andric     return Variables[static_cast<unsigned>(ID)];
121bdd1243dSDimitry Andric   }
122bdd1243dSDimitry Andric 
123bdd1243dSDimitry Andric   /// Return ptr to wedge of defs or nullptr if no defs come just before /p
124bdd1243dSDimitry Andric   /// Before.
1257a6dacacSDimitry Andric   const SmallVectorImpl<VarLocInfo> *getWedge(VarLocInsertPt Before) const {
126bdd1243dSDimitry Andric     auto R = VarLocsBeforeInst.find(Before);
127bdd1243dSDimitry Andric     if (R == VarLocsBeforeInst.end())
128bdd1243dSDimitry Andric       return nullptr;
129bdd1243dSDimitry Andric     return &R->second;
130bdd1243dSDimitry Andric   }
131bdd1243dSDimitry Andric 
132bdd1243dSDimitry Andric   /// Replace the defs that come just before /p Before with /p Wedge.
1337a6dacacSDimitry Andric   void setWedge(VarLocInsertPt Before, SmallVector<VarLocInfo> &&Wedge) {
134bdd1243dSDimitry Andric     VarLocsBeforeInst[Before] = std::move(Wedge);
135bdd1243dSDimitry Andric   }
136bdd1243dSDimitry Andric 
137bdd1243dSDimitry Andric   /// Add a def for a variable that is valid for its lifetime.
138bdd1243dSDimitry Andric   void addSingleLocVar(DebugVariable Var, DIExpression *Expr, DebugLoc DL,
13906c3fb27SDimitry Andric                        RawLocationWrapper R) {
140bdd1243dSDimitry Andric     VarLocInfo VarLoc;
141bdd1243dSDimitry Andric     VarLoc.VariableID = insertVariable(Var);
142bdd1243dSDimitry Andric     VarLoc.Expr = Expr;
143bdd1243dSDimitry Andric     VarLoc.DL = DL;
14406c3fb27SDimitry Andric     VarLoc.Values = R;
145bdd1243dSDimitry Andric     SingleLocVars.emplace_back(VarLoc);
146bdd1243dSDimitry Andric   }
147bdd1243dSDimitry Andric 
148bdd1243dSDimitry Andric   /// Add a def to the wedge of defs just before /p Before.
1497a6dacacSDimitry Andric   void addVarLoc(VarLocInsertPt Before, DebugVariable Var, DIExpression *Expr,
15006c3fb27SDimitry Andric                  DebugLoc DL, RawLocationWrapper R) {
151bdd1243dSDimitry Andric     VarLocInfo VarLoc;
152bdd1243dSDimitry Andric     VarLoc.VariableID = insertVariable(Var);
153bdd1243dSDimitry Andric     VarLoc.Expr = Expr;
154bdd1243dSDimitry Andric     VarLoc.DL = DL;
15506c3fb27SDimitry Andric     VarLoc.Values = R;
156bdd1243dSDimitry Andric     VarLocsBeforeInst[Before].emplace_back(VarLoc);
157bdd1243dSDimitry Andric   }
158bdd1243dSDimitry Andric };
159bdd1243dSDimitry Andric 
160bdd1243dSDimitry Andric void FunctionVarLocs::print(raw_ostream &OS, const Function &Fn) const {
161bdd1243dSDimitry Andric   // Print the variable table first. TODO: Sorting by variable could make the
162bdd1243dSDimitry Andric   // output more stable?
163bdd1243dSDimitry Andric   unsigned Counter = -1;
164bdd1243dSDimitry Andric   OS << "=== Variables ===\n";
165bdd1243dSDimitry Andric   for (const DebugVariable &V : Variables) {
166bdd1243dSDimitry Andric     ++Counter;
167bdd1243dSDimitry Andric     // Skip first entry because it is a dummy entry.
168bdd1243dSDimitry Andric     if (Counter == 0) {
169bdd1243dSDimitry Andric       continue;
170bdd1243dSDimitry Andric     }
171bdd1243dSDimitry Andric     OS << "[" << Counter << "] " << V.getVariable()->getName();
172bdd1243dSDimitry Andric     if (auto F = V.getFragment())
173bdd1243dSDimitry Andric       OS << " bits [" << F->OffsetInBits << ", "
174bdd1243dSDimitry Andric          << F->OffsetInBits + F->SizeInBits << ")";
175bdd1243dSDimitry Andric     if (const auto *IA = V.getInlinedAt())
176bdd1243dSDimitry Andric       OS << " inlined-at " << *IA;
177bdd1243dSDimitry Andric     OS << "\n";
178bdd1243dSDimitry Andric   }
179bdd1243dSDimitry Andric 
180bdd1243dSDimitry Andric   auto PrintLoc = [&OS](const VarLocInfo &Loc) {
181bdd1243dSDimitry Andric     OS << "DEF Var=[" << (unsigned)Loc.VariableID << "]"
18206c3fb27SDimitry Andric        << " Expr=" << *Loc.Expr << " Values=(";
18306c3fb27SDimitry Andric     for (auto *Op : Loc.Values.location_ops()) {
18406c3fb27SDimitry Andric       errs() << Op->getName() << " ";
18506c3fb27SDimitry Andric     }
18606c3fb27SDimitry Andric     errs() << ")\n";
187bdd1243dSDimitry Andric   };
188bdd1243dSDimitry Andric 
189bdd1243dSDimitry Andric   // Print the single location variables.
190bdd1243dSDimitry Andric   OS << "=== Single location vars ===\n";
191bdd1243dSDimitry Andric   for (auto It = single_locs_begin(), End = single_locs_end(); It != End;
192bdd1243dSDimitry Andric        ++It) {
193bdd1243dSDimitry Andric     PrintLoc(*It);
194bdd1243dSDimitry Andric   }
195bdd1243dSDimitry Andric 
196bdd1243dSDimitry Andric   // Print the non-single-location defs in line with IR.
197bdd1243dSDimitry Andric   OS << "=== In-line variable defs ===";
198bdd1243dSDimitry Andric   for (const BasicBlock &BB : Fn) {
199bdd1243dSDimitry Andric     OS << "\n" << BB.getName() << ":\n";
200bdd1243dSDimitry Andric     for (const Instruction &I : BB) {
201bdd1243dSDimitry Andric       for (auto It = locs_begin(&I), End = locs_end(&I); It != End; ++It) {
202bdd1243dSDimitry Andric         PrintLoc(*It);
203bdd1243dSDimitry Andric       }
204bdd1243dSDimitry Andric       OS << I << "\n";
205bdd1243dSDimitry Andric     }
206bdd1243dSDimitry Andric   }
207bdd1243dSDimitry Andric }
208bdd1243dSDimitry Andric 
209bdd1243dSDimitry Andric void FunctionVarLocs::init(FunctionVarLocsBuilder &Builder) {
210bdd1243dSDimitry Andric   // Add the single-location variables first.
211bdd1243dSDimitry Andric   for (const auto &VarLoc : Builder.SingleLocVars)
212bdd1243dSDimitry Andric     VarLocRecords.emplace_back(VarLoc);
213bdd1243dSDimitry Andric   // Mark the end of the section.
214bdd1243dSDimitry Andric   SingleVarLocEnd = VarLocRecords.size();
215bdd1243dSDimitry Andric 
216bdd1243dSDimitry Andric   // Insert a contiguous block of VarLocInfos for each instruction, mapping it
2177a6dacacSDimitry Andric   // to the start and end position in the vector with VarLocsBeforeInst. This
218*0fca6ea1SDimitry Andric   // block includes VarLocs for any DbgVariableRecords attached to that
219*0fca6ea1SDimitry Andric   // instruction.
220bdd1243dSDimitry Andric   for (auto &P : Builder.VarLocsBeforeInst) {
221*0fca6ea1SDimitry Andric     // Process VarLocs attached to a DbgRecord alongside their marker
222*0fca6ea1SDimitry Andric     // Instruction.
223*0fca6ea1SDimitry Andric     if (isa<const DbgRecord *>(P.first))
2247a6dacacSDimitry Andric       continue;
2257a6dacacSDimitry Andric     const Instruction *I = cast<const Instruction *>(P.first);
226bdd1243dSDimitry Andric     unsigned BlockStart = VarLocRecords.size();
227*0fca6ea1SDimitry Andric     // Any VarLocInfos attached to a DbgRecord should now be remapped to their
228*0fca6ea1SDimitry Andric     // marker Instruction, in order of DbgRecord appearance and prior to any
2297a6dacacSDimitry Andric     // VarLocInfos attached directly to that instruction.
230*0fca6ea1SDimitry Andric     for (const DbgVariableRecord &DVR : filterDbgVars(I->getDbgRecordRange())) {
231*0fca6ea1SDimitry Andric       // Even though DVR defines a variable location, VarLocsBeforeInst can
2327a6dacacSDimitry Andric       // still be empty if that VarLoc was redundant.
233*0fca6ea1SDimitry Andric       if (!Builder.VarLocsBeforeInst.count(&DVR))
2347a6dacacSDimitry Andric         continue;
235*0fca6ea1SDimitry Andric       for (const VarLocInfo &VarLoc : Builder.VarLocsBeforeInst[&DVR])
2367a6dacacSDimitry Andric         VarLocRecords.emplace_back(VarLoc);
2377a6dacacSDimitry Andric     }
238bdd1243dSDimitry Andric     for (const VarLocInfo &VarLoc : P.second)
239bdd1243dSDimitry Andric       VarLocRecords.emplace_back(VarLoc);
240bdd1243dSDimitry Andric     unsigned BlockEnd = VarLocRecords.size();
241bdd1243dSDimitry Andric     // Record the start and end indices.
242bdd1243dSDimitry Andric     if (BlockEnd != BlockStart)
2437a6dacacSDimitry Andric       VarLocsBeforeInst[I] = {BlockStart, BlockEnd};
244bdd1243dSDimitry Andric   }
245bdd1243dSDimitry Andric 
246bdd1243dSDimitry Andric   // Copy the Variables vector from the builder's UniqueVector.
247bdd1243dSDimitry Andric   assert(Variables.empty() && "Expect clear before init");
248bdd1243dSDimitry Andric   // UniqueVectors IDs are one-based (which means the VarLocInfo VarID values
249bdd1243dSDimitry Andric   // are one-based) so reserve an extra and insert a dummy.
250bdd1243dSDimitry Andric   Variables.reserve(Builder.Variables.size() + 1);
251bdd1243dSDimitry Andric   Variables.push_back(DebugVariable(nullptr, std::nullopt, nullptr));
252bdd1243dSDimitry Andric   Variables.append(Builder.Variables.begin(), Builder.Variables.end());
253bdd1243dSDimitry Andric }
254bdd1243dSDimitry Andric 
255bdd1243dSDimitry Andric void FunctionVarLocs::clear() {
256bdd1243dSDimitry Andric   Variables.clear();
257bdd1243dSDimitry Andric   VarLocRecords.clear();
258bdd1243dSDimitry Andric   VarLocsBeforeInst.clear();
259bdd1243dSDimitry Andric   SingleVarLocEnd = 0;
260bdd1243dSDimitry Andric }
261bdd1243dSDimitry Andric 
262bdd1243dSDimitry Andric /// Walk backwards along constant GEPs and bitcasts to the base storage from \p
263bdd1243dSDimitry Andric /// Start as far as possible. Prepend \Expression with the offset and append it
264bdd1243dSDimitry Andric /// with a DW_OP_deref that haes been implicit until now. Returns the walked-to
265bdd1243dSDimitry Andric /// value and modified expression.
266bdd1243dSDimitry Andric static std::pair<Value *, DIExpression *>
267bdd1243dSDimitry Andric walkToAllocaAndPrependOffsetDeref(const DataLayout &DL, Value *Start,
268bdd1243dSDimitry Andric                                   DIExpression *Expression) {
269bdd1243dSDimitry Andric   APInt OffsetInBytes(DL.getTypeSizeInBits(Start->getType()), false);
270bdd1243dSDimitry Andric   Value *End =
271bdd1243dSDimitry Andric       Start->stripAndAccumulateInBoundsConstantOffsets(DL, OffsetInBytes);
272bdd1243dSDimitry Andric   SmallVector<uint64_t, 3> Ops;
273bdd1243dSDimitry Andric   if (OffsetInBytes.getBoolValue()) {
274bdd1243dSDimitry Andric     Ops = {dwarf::DW_OP_plus_uconst, OffsetInBytes.getZExtValue()};
275bdd1243dSDimitry Andric     Expression = DIExpression::prependOpcodes(
276bdd1243dSDimitry Andric         Expression, Ops, /*StackValue=*/false, /*EntryValue=*/false);
277bdd1243dSDimitry Andric   }
278bdd1243dSDimitry Andric   Expression = DIExpression::append(Expression, {dwarf::DW_OP_deref});
279bdd1243dSDimitry Andric   return {End, Expression};
280bdd1243dSDimitry Andric }
281bdd1243dSDimitry Andric 
282bdd1243dSDimitry Andric /// Extract the offset used in \p DIExpr. Returns std::nullopt if the expression
283bdd1243dSDimitry Andric /// doesn't explicitly describe a memory location with DW_OP_deref or if the
284bdd1243dSDimitry Andric /// expression is too complex to interpret.
285bdd1243dSDimitry Andric static std::optional<int64_t>
286bdd1243dSDimitry Andric getDerefOffsetInBytes(const DIExpression *DIExpr) {
287bdd1243dSDimitry Andric   int64_t Offset = 0;
288bdd1243dSDimitry Andric   const unsigned NumElements = DIExpr->getNumElements();
289bdd1243dSDimitry Andric   const auto Elements = DIExpr->getElements();
29006c3fb27SDimitry Andric   unsigned ExpectedDerefIdx = 0;
291bdd1243dSDimitry Andric   // Extract the offset.
292bdd1243dSDimitry Andric   if (NumElements > 2 && Elements[0] == dwarf::DW_OP_plus_uconst) {
293bdd1243dSDimitry Andric     Offset = Elements[1];
29406c3fb27SDimitry Andric     ExpectedDerefIdx = 2;
295bdd1243dSDimitry Andric   } else if (NumElements > 3 && Elements[0] == dwarf::DW_OP_constu) {
29606c3fb27SDimitry Andric     ExpectedDerefIdx = 3;
297bdd1243dSDimitry Andric     if (Elements[2] == dwarf::DW_OP_plus)
298bdd1243dSDimitry Andric       Offset = Elements[1];
299bdd1243dSDimitry Andric     else if (Elements[2] == dwarf::DW_OP_minus)
300bdd1243dSDimitry Andric       Offset = -Elements[1];
301bdd1243dSDimitry Andric     else
302bdd1243dSDimitry Andric       return std::nullopt;
303bdd1243dSDimitry Andric   }
304bdd1243dSDimitry Andric 
305bdd1243dSDimitry Andric   // If that's all there is it means there's no deref.
30606c3fb27SDimitry Andric   if (ExpectedDerefIdx >= NumElements)
307bdd1243dSDimitry Andric     return std::nullopt;
308bdd1243dSDimitry Andric 
309bdd1243dSDimitry Andric   // Check the next element is DW_OP_deref - otherwise this is too complex or
310bdd1243dSDimitry Andric   // isn't a deref expression.
31106c3fb27SDimitry Andric   if (Elements[ExpectedDerefIdx] != dwarf::DW_OP_deref)
312bdd1243dSDimitry Andric     return std::nullopt;
313bdd1243dSDimitry Andric 
314bdd1243dSDimitry Andric   // Check the final operation is either the DW_OP_deref or is a fragment.
31506c3fb27SDimitry Andric   if (NumElements == ExpectedDerefIdx + 1)
316bdd1243dSDimitry Andric     return Offset; // Ends with deref.
31706c3fb27SDimitry Andric   unsigned ExpectedFragFirstIdx = ExpectedDerefIdx + 1;
31806c3fb27SDimitry Andric   unsigned ExpectedFragFinalIdx = ExpectedFragFirstIdx + 2;
31906c3fb27SDimitry Andric   if (NumElements == ExpectedFragFinalIdx + 1 &&
32006c3fb27SDimitry Andric       Elements[ExpectedFragFirstIdx] == dwarf::DW_OP_LLVM_fragment)
321bdd1243dSDimitry Andric     return Offset; // Ends with deref + fragment.
322bdd1243dSDimitry Andric 
323bdd1243dSDimitry Andric   // Don't bother trying to interpret anything more complex.
324bdd1243dSDimitry Andric   return std::nullopt;
325bdd1243dSDimitry Andric }
326bdd1243dSDimitry Andric 
327bdd1243dSDimitry Andric /// A whole (unfragmented) source variable.
328bdd1243dSDimitry Andric using DebugAggregate = std::pair<const DILocalVariable *, const DILocation *>;
329bdd1243dSDimitry Andric static DebugAggregate getAggregate(const DbgVariableIntrinsic *DII) {
330bdd1243dSDimitry Andric   return DebugAggregate(DII->getVariable(), DII->getDebugLoc().getInlinedAt());
331bdd1243dSDimitry Andric }
332bdd1243dSDimitry Andric static DebugAggregate getAggregate(const DebugVariable &Var) {
333bdd1243dSDimitry Andric   return DebugAggregate(Var.getVariable(), Var.getInlinedAt());
334bdd1243dSDimitry Andric }
335bdd1243dSDimitry Andric 
33606c3fb27SDimitry Andric static bool shouldCoalesceFragments(Function &F) {
33706c3fb27SDimitry Andric   // Enabling fragment coalescing reduces compiler run time when instruction
33806c3fb27SDimitry Andric   // referencing is enabled. However, it may cause LiveDebugVariables to create
33906c3fb27SDimitry Andric   // incorrect locations. Since instruction-referencing mode effectively
34006c3fb27SDimitry Andric   // bypasses LiveDebugVariables we only enable coalescing if the cl::opt flag
34106c3fb27SDimitry Andric   // has not been explicitly set and instruction-referencing is turned on.
34206c3fb27SDimitry Andric   switch (CoalesceAdjacentFragmentsOpt) {
34306c3fb27SDimitry Andric   case cl::boolOrDefault::BOU_UNSET:
34406c3fb27SDimitry Andric     return debuginfoShouldUseDebugInstrRef(
34506c3fb27SDimitry Andric         Triple(F.getParent()->getTargetTriple()));
34606c3fb27SDimitry Andric   case cl::boolOrDefault::BOU_TRUE:
34706c3fb27SDimitry Andric     return true;
34806c3fb27SDimitry Andric   case cl::boolOrDefault::BOU_FALSE:
34906c3fb27SDimitry Andric     return false;
35006c3fb27SDimitry Andric   }
35106c3fb27SDimitry Andric   llvm_unreachable("Unknown boolOrDefault value");
35206c3fb27SDimitry Andric }
35306c3fb27SDimitry Andric 
354bdd1243dSDimitry Andric namespace {
355bdd1243dSDimitry Andric /// In dwarf emission, the following sequence
356bdd1243dSDimitry Andric ///    1. dbg.value ... Fragment(0, 64)
357bdd1243dSDimitry Andric ///    2. dbg.value ... Fragment(0, 32)
358bdd1243dSDimitry Andric /// effectively sets Fragment(32, 32) to undef (each def sets all bits not in
359bdd1243dSDimitry Andric /// the intersection of the fragments to having "no location"). This makes
360bdd1243dSDimitry Andric /// sense for implicit location values because splitting the computed values
361bdd1243dSDimitry Andric /// could be troublesome, and is probably quite uncommon.  When we convert
362bdd1243dSDimitry Andric /// dbg.assigns to dbg.value+deref this kind of thing is common, and describing
363bdd1243dSDimitry Andric /// a location (memory) rather than a value means we don't need to worry about
364bdd1243dSDimitry Andric /// splitting any values, so we try to recover the rest of the fragment
365bdd1243dSDimitry Andric /// location here.
366bdd1243dSDimitry Andric /// This class performs a(nother) dataflow analysis over the function, adding
367bdd1243dSDimitry Andric /// variable locations so that any bits of a variable with a memory location
368bdd1243dSDimitry Andric /// have that location explicitly reinstated at each subsequent variable
369bdd1243dSDimitry Andric /// location definition that that doesn't overwrite those bits. i.e. after a
370bdd1243dSDimitry Andric /// variable location def, insert new defs for the memory location with
371bdd1243dSDimitry Andric /// fragments for the difference of "all bits currently in memory" and "the
372bdd1243dSDimitry Andric /// fragment of the second def".
373bdd1243dSDimitry Andric class MemLocFragmentFill {
374bdd1243dSDimitry Andric   Function &Fn;
375bdd1243dSDimitry Andric   FunctionVarLocsBuilder *FnVarLocs;
376bdd1243dSDimitry Andric   const DenseSet<DebugAggregate> *VarsWithStackSlot;
37706c3fb27SDimitry Andric   bool CoalesceAdjacentFragments;
378bdd1243dSDimitry Andric 
379bdd1243dSDimitry Andric   // 0 = no memory location.
380bdd1243dSDimitry Andric   using BaseAddress = unsigned;
381bdd1243dSDimitry Andric   using OffsetInBitsTy = unsigned;
382bdd1243dSDimitry Andric   using FragTraits = IntervalMapHalfOpenInfo<OffsetInBitsTy>;
383bdd1243dSDimitry Andric   using FragsInMemMap = IntervalMap<
384bdd1243dSDimitry Andric       OffsetInBitsTy, BaseAddress,
385bdd1243dSDimitry Andric       IntervalMapImpl::NodeSizer<OffsetInBitsTy, BaseAddress>::LeafSize,
386bdd1243dSDimitry Andric       FragTraits>;
387bdd1243dSDimitry Andric   FragsInMemMap::Allocator IntervalMapAlloc;
388bdd1243dSDimitry Andric   using VarFragMap = DenseMap<unsigned, FragsInMemMap>;
389bdd1243dSDimitry Andric 
390bdd1243dSDimitry Andric   /// IDs for memory location base addresses in maps. Use 0 to indicate that
391bdd1243dSDimitry Andric   /// there's no memory location.
39206c3fb27SDimitry Andric   UniqueVector<RawLocationWrapper> Bases;
393bdd1243dSDimitry Andric   UniqueVector<DebugAggregate> Aggregates;
394bdd1243dSDimitry Andric   DenseMap<const BasicBlock *, VarFragMap> LiveIn;
395bdd1243dSDimitry Andric   DenseMap<const BasicBlock *, VarFragMap> LiveOut;
396bdd1243dSDimitry Andric 
397bdd1243dSDimitry Andric   struct FragMemLoc {
398bdd1243dSDimitry Andric     unsigned Var;
399bdd1243dSDimitry Andric     unsigned Base;
400bdd1243dSDimitry Andric     unsigned OffsetInBits;
401bdd1243dSDimitry Andric     unsigned SizeInBits;
402bdd1243dSDimitry Andric     DebugLoc DL;
403bdd1243dSDimitry Andric   };
4047a6dacacSDimitry Andric   using InsertMap = MapVector<VarLocInsertPt, SmallVector<FragMemLoc>>;
405bdd1243dSDimitry Andric 
406bdd1243dSDimitry Andric   /// BBInsertBeforeMap holds a description for the set of location defs to be
407bdd1243dSDimitry Andric   /// inserted after the analysis is complete. It is updated during the dataflow
408bdd1243dSDimitry Andric   /// and the entry for a block is CLEARED each time it is (re-)visited. After
409bdd1243dSDimitry Andric   /// the dataflow is complete, each block entry will contain the set of defs
410bdd1243dSDimitry Andric   /// calculated during the final (fixed-point) iteration.
411bdd1243dSDimitry Andric   DenseMap<const BasicBlock *, InsertMap> BBInsertBeforeMap;
412bdd1243dSDimitry Andric 
413bdd1243dSDimitry Andric   static bool intervalMapsAreEqual(const FragsInMemMap &A,
414bdd1243dSDimitry Andric                                    const FragsInMemMap &B) {
415bdd1243dSDimitry Andric     auto AIt = A.begin(), AEnd = A.end();
416bdd1243dSDimitry Andric     auto BIt = B.begin(), BEnd = B.end();
417bdd1243dSDimitry Andric     for (; AIt != AEnd; ++AIt, ++BIt) {
418bdd1243dSDimitry Andric       if (BIt == BEnd)
419bdd1243dSDimitry Andric         return false; // B has fewer elements than A.
420bdd1243dSDimitry Andric       if (AIt.start() != BIt.start() || AIt.stop() != BIt.stop())
421bdd1243dSDimitry Andric         return false; // Interval is different.
422bdd1243dSDimitry Andric       if (*AIt != *BIt)
423bdd1243dSDimitry Andric         return false; // Value at interval is different.
424bdd1243dSDimitry Andric     }
425bdd1243dSDimitry Andric     // AIt == AEnd. Check BIt is also now at end.
426bdd1243dSDimitry Andric     return BIt == BEnd;
427bdd1243dSDimitry Andric   }
428bdd1243dSDimitry Andric 
429bdd1243dSDimitry Andric   static bool varFragMapsAreEqual(const VarFragMap &A, const VarFragMap &B) {
430bdd1243dSDimitry Andric     if (A.size() != B.size())
431bdd1243dSDimitry Andric       return false;
432bdd1243dSDimitry Andric     for (const auto &APair : A) {
433bdd1243dSDimitry Andric       auto BIt = B.find(APair.first);
434bdd1243dSDimitry Andric       if (BIt == B.end())
435bdd1243dSDimitry Andric         return false;
436bdd1243dSDimitry Andric       if (!intervalMapsAreEqual(APair.second, BIt->second))
437bdd1243dSDimitry Andric         return false;
438bdd1243dSDimitry Andric     }
439bdd1243dSDimitry Andric     return true;
440bdd1243dSDimitry Andric   }
441bdd1243dSDimitry Andric 
442bdd1243dSDimitry Andric   /// Return a string for the value that \p BaseID represents.
443bdd1243dSDimitry Andric   std::string toString(unsigned BaseID) {
444bdd1243dSDimitry Andric     if (BaseID)
44506c3fb27SDimitry Andric       return Bases[BaseID].getVariableLocationOp(0)->getName().str();
446bdd1243dSDimitry Andric     else
447bdd1243dSDimitry Andric       return "None";
448bdd1243dSDimitry Andric   }
449bdd1243dSDimitry Andric 
450bdd1243dSDimitry Andric   /// Format string describing an FragsInMemMap (IntervalMap) interval.
451bdd1243dSDimitry Andric   std::string toString(FragsInMemMap::const_iterator It, bool Newline = true) {
452bdd1243dSDimitry Andric     std::string String;
453bdd1243dSDimitry Andric     std::stringstream S(String);
454bdd1243dSDimitry Andric     if (It.valid()) {
455bdd1243dSDimitry Andric       S << "[" << It.start() << ", " << It.stop()
456bdd1243dSDimitry Andric         << "): " << toString(It.value());
457bdd1243dSDimitry Andric     } else {
458bdd1243dSDimitry Andric       S << "invalid iterator (end)";
459bdd1243dSDimitry Andric     }
460bdd1243dSDimitry Andric     if (Newline)
461bdd1243dSDimitry Andric       S << "\n";
462bdd1243dSDimitry Andric     return S.str();
463bdd1243dSDimitry Andric   };
464bdd1243dSDimitry Andric 
465bdd1243dSDimitry Andric   FragsInMemMap meetFragments(const FragsInMemMap &A, const FragsInMemMap &B) {
466bdd1243dSDimitry Andric     FragsInMemMap Result(IntervalMapAlloc);
467bdd1243dSDimitry Andric     for (auto AIt = A.begin(), AEnd = A.end(); AIt != AEnd; ++AIt) {
468bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "a " << toString(AIt));
469bdd1243dSDimitry Andric       // This is basically copied from process() and inverted (process is
470bdd1243dSDimitry Andric       // performing something like a union whereas this is more of an
471bdd1243dSDimitry Andric       // intersect).
472bdd1243dSDimitry Andric 
473bdd1243dSDimitry Andric       // There's no work to do if interval `a` overlaps no fragments in map `B`.
474bdd1243dSDimitry Andric       if (!B.overlaps(AIt.start(), AIt.stop()))
475bdd1243dSDimitry Andric         continue;
476bdd1243dSDimitry Andric 
477bdd1243dSDimitry Andric       // Does StartBit intersect an existing fragment?
478bdd1243dSDimitry Andric       auto FirstOverlap = B.find(AIt.start());
479bdd1243dSDimitry Andric       assert(FirstOverlap != B.end());
480bdd1243dSDimitry Andric       bool IntersectStart = FirstOverlap.start() < AIt.start();
481bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "- FirstOverlap " << toString(FirstOverlap, false)
482bdd1243dSDimitry Andric                         << ", IntersectStart: " << IntersectStart << "\n");
483bdd1243dSDimitry Andric 
484bdd1243dSDimitry Andric       // Does EndBit intersect an existing fragment?
485bdd1243dSDimitry Andric       auto LastOverlap = B.find(AIt.stop());
486bdd1243dSDimitry Andric       bool IntersectEnd =
487bdd1243dSDimitry Andric           LastOverlap != B.end() && LastOverlap.start() < AIt.stop();
488bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "- LastOverlap " << toString(LastOverlap, false)
489bdd1243dSDimitry Andric                         << ", IntersectEnd: " << IntersectEnd << "\n");
490bdd1243dSDimitry Andric 
491bdd1243dSDimitry Andric       // Check if both ends of `a` intersect the same interval `b`.
492bdd1243dSDimitry Andric       if (IntersectStart && IntersectEnd && FirstOverlap == LastOverlap) {
493bdd1243dSDimitry Andric         // Insert `a` (`a` is contained in `b`) if the values match.
494bdd1243dSDimitry Andric         // [ a ]
495bdd1243dSDimitry Andric         // [ - b - ]
496bdd1243dSDimitry Andric         // -
497bdd1243dSDimitry Andric         // [ r ]
498bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "- a is contained within "
499bdd1243dSDimitry Andric                           << toString(FirstOverlap));
500bdd1243dSDimitry Andric         if (*AIt && *AIt == *FirstOverlap)
501bdd1243dSDimitry Andric           Result.insert(AIt.start(), AIt.stop(), *AIt);
502bdd1243dSDimitry Andric       } else {
503bdd1243dSDimitry Andric         // There's an overlap but `a` is not fully contained within
504bdd1243dSDimitry Andric         // `b`. Shorten any end-point intersections.
505bdd1243dSDimitry Andric         //     [ - a - ]
506bdd1243dSDimitry Andric         // [ - b - ]
507bdd1243dSDimitry Andric         // -
508bdd1243dSDimitry Andric         //     [ r ]
509bdd1243dSDimitry Andric         auto Next = FirstOverlap;
510bdd1243dSDimitry Andric         if (IntersectStart) {
511bdd1243dSDimitry Andric           LLVM_DEBUG(dbgs() << "- insert intersection of a and "
512bdd1243dSDimitry Andric                             << toString(FirstOverlap));
513bdd1243dSDimitry Andric           if (*AIt && *AIt == *FirstOverlap)
514bdd1243dSDimitry Andric             Result.insert(AIt.start(), FirstOverlap.stop(), *AIt);
515bdd1243dSDimitry Andric           ++Next;
516bdd1243dSDimitry Andric         }
517bdd1243dSDimitry Andric         // [ - a - ]
518bdd1243dSDimitry Andric         //     [ - b - ]
519bdd1243dSDimitry Andric         // -
520bdd1243dSDimitry Andric         //     [ r ]
521bdd1243dSDimitry Andric         if (IntersectEnd) {
522bdd1243dSDimitry Andric           LLVM_DEBUG(dbgs() << "- insert intersection of a and "
523bdd1243dSDimitry Andric                             << toString(LastOverlap));
524bdd1243dSDimitry Andric           if (*AIt && *AIt == *LastOverlap)
525bdd1243dSDimitry Andric             Result.insert(LastOverlap.start(), AIt.stop(), *AIt);
526bdd1243dSDimitry Andric         }
527bdd1243dSDimitry Andric 
528bdd1243dSDimitry Andric         // Insert all intervals in map `B` that are contained within interval
529bdd1243dSDimitry Andric         // `a` where the values match.
530bdd1243dSDimitry Andric         // [ -  - a -  - ]
531bdd1243dSDimitry Andric         // [ b1 ]   [ b2 ]
532bdd1243dSDimitry Andric         // -
533bdd1243dSDimitry Andric         // [ r1 ]   [ r2 ]
534bdd1243dSDimitry Andric         while (Next != B.end() && Next.start() < AIt.stop() &&
535bdd1243dSDimitry Andric                Next.stop() <= AIt.stop()) {
536bdd1243dSDimitry Andric           LLVM_DEBUG(dbgs()
537bdd1243dSDimitry Andric                      << "- insert intersection of a and " << toString(Next));
538bdd1243dSDimitry Andric           if (*AIt && *AIt == *Next)
539bdd1243dSDimitry Andric             Result.insert(Next.start(), Next.stop(), *Next);
540bdd1243dSDimitry Andric           ++Next;
541bdd1243dSDimitry Andric         }
542bdd1243dSDimitry Andric       }
543bdd1243dSDimitry Andric     }
544bdd1243dSDimitry Andric     return Result;
545bdd1243dSDimitry Andric   }
546bdd1243dSDimitry Andric 
547bdd1243dSDimitry Andric   /// Meet \p A and \p B, storing the result in \p A.
548bdd1243dSDimitry Andric   void meetVars(VarFragMap &A, const VarFragMap &B) {
549bdd1243dSDimitry Andric     // Meet A and B.
550bdd1243dSDimitry Andric     //
551bdd1243dSDimitry Andric     // Result = meet(a, b) for a in A, b in B where Var(a) == Var(b)
552bdd1243dSDimitry Andric     for (auto It = A.begin(), End = A.end(); It != End; ++It) {
553bdd1243dSDimitry Andric       unsigned AVar = It->first;
554bdd1243dSDimitry Andric       FragsInMemMap &AFrags = It->second;
555bdd1243dSDimitry Andric       auto BIt = B.find(AVar);
556bdd1243dSDimitry Andric       if (BIt == B.end()) {
557bdd1243dSDimitry Andric         A.erase(It);
558bdd1243dSDimitry Andric         continue; // Var has no bits defined in B.
559bdd1243dSDimitry Andric       }
560bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "meet fragment maps for "
561bdd1243dSDimitry Andric                         << Aggregates[AVar].first->getName() << "\n");
562bdd1243dSDimitry Andric       AFrags = meetFragments(AFrags, BIt->second);
563bdd1243dSDimitry Andric     }
564bdd1243dSDimitry Andric   }
565bdd1243dSDimitry Andric 
566bdd1243dSDimitry Andric   bool meet(const BasicBlock &BB,
567bdd1243dSDimitry Andric             const SmallPtrSet<BasicBlock *, 16> &Visited) {
568bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "meet block info from preds of " << BB.getName()
569bdd1243dSDimitry Andric                       << "\n");
570bdd1243dSDimitry Andric 
571bdd1243dSDimitry Andric     VarFragMap BBLiveIn;
572bdd1243dSDimitry Andric     bool FirstMeet = true;
573bdd1243dSDimitry Andric     // LiveIn locs for BB is the meet of the already-processed preds' LiveOut
574bdd1243dSDimitry Andric     // locs.
575*0fca6ea1SDimitry Andric     for (const BasicBlock *Pred : predecessors(&BB)) {
576bdd1243dSDimitry Andric       // Ignore preds that haven't been processed yet. This is essentially the
577bdd1243dSDimitry Andric       // same as initialising all variables to implicit top value (⊤) which is
578bdd1243dSDimitry Andric       // the identity value for the meet operation.
579bdd1243dSDimitry Andric       if (!Visited.count(Pred))
580bdd1243dSDimitry Andric         continue;
581bdd1243dSDimitry Andric 
582bdd1243dSDimitry Andric       auto PredLiveOut = LiveOut.find(Pred);
583bdd1243dSDimitry Andric       assert(PredLiveOut != LiveOut.end());
584bdd1243dSDimitry Andric 
585bdd1243dSDimitry Andric       if (FirstMeet) {
586bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "BBLiveIn = " << Pred->getName() << "\n");
587bdd1243dSDimitry Andric         BBLiveIn = PredLiveOut->second;
588bdd1243dSDimitry Andric         FirstMeet = false;
589bdd1243dSDimitry Andric       } else {
590bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "BBLiveIn = meet BBLiveIn, " << Pred->getName()
591bdd1243dSDimitry Andric                           << "\n");
592bdd1243dSDimitry Andric         meetVars(BBLiveIn, PredLiveOut->second);
593bdd1243dSDimitry Andric       }
594bdd1243dSDimitry Andric 
595bdd1243dSDimitry Andric       // An empty set is ⊥ for the intersect-like meet operation. If we've
596bdd1243dSDimitry Andric       // already got ⊥ there's no need to run the code - we know the result is
597bdd1243dSDimitry Andric       // ⊥ since `meet(a, ⊥) = ⊥`.
598bdd1243dSDimitry Andric       if (BBLiveIn.size() == 0)
599bdd1243dSDimitry Andric         break;
600bdd1243dSDimitry Andric     }
601bdd1243dSDimitry Andric 
602bdd1243dSDimitry Andric     auto CurrentLiveInEntry = LiveIn.find(&BB);
603bdd1243dSDimitry Andric     // If there's no LiveIn entry for the block yet, add it.
604bdd1243dSDimitry Andric     if (CurrentLiveInEntry == LiveIn.end()) {
605bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "change=true (first) on meet on " << BB.getName()
606bdd1243dSDimitry Andric                         << "\n");
607bdd1243dSDimitry Andric       LiveIn[&BB] = std::move(BBLiveIn);
608bdd1243dSDimitry Andric       return /*Changed=*/true;
609bdd1243dSDimitry Andric     }
610bdd1243dSDimitry Andric 
611bdd1243dSDimitry Andric     // If the LiveIn set has changed (expensive check) update it and return
612bdd1243dSDimitry Andric     // true.
613bdd1243dSDimitry Andric     if (!varFragMapsAreEqual(BBLiveIn, CurrentLiveInEntry->second)) {
614bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "change=true on meet on " << BB.getName() << "\n");
615bdd1243dSDimitry Andric       CurrentLiveInEntry->second = std::move(BBLiveIn);
616bdd1243dSDimitry Andric       return /*Changed=*/true;
617bdd1243dSDimitry Andric     }
618bdd1243dSDimitry Andric 
619bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "change=false on meet on " << BB.getName() << "\n");
620bdd1243dSDimitry Andric     return /*Changed=*/false;
621bdd1243dSDimitry Andric   }
622bdd1243dSDimitry Andric 
6237a6dacacSDimitry Andric   void insertMemLoc(BasicBlock &BB, VarLocInsertPt Before, unsigned Var,
624bdd1243dSDimitry Andric                     unsigned StartBit, unsigned EndBit, unsigned Base,
625bdd1243dSDimitry Andric                     DebugLoc DL) {
626bdd1243dSDimitry Andric     assert(StartBit < EndBit && "Cannot create fragment of size <= 0");
627bdd1243dSDimitry Andric     if (!Base)
628bdd1243dSDimitry Andric       return;
629bdd1243dSDimitry Andric     FragMemLoc Loc;
630bdd1243dSDimitry Andric     Loc.Var = Var;
631bdd1243dSDimitry Andric     Loc.OffsetInBits = StartBit;
632bdd1243dSDimitry Andric     Loc.SizeInBits = EndBit - StartBit;
633bdd1243dSDimitry Andric     assert(Base && "Expected a non-zero ID for Base address");
634bdd1243dSDimitry Andric     Loc.Base = Base;
635bdd1243dSDimitry Andric     Loc.DL = DL;
6367a6dacacSDimitry Andric     BBInsertBeforeMap[&BB][Before].push_back(Loc);
637bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "Add mem def for " << Aggregates[Var].first->getName()
638bdd1243dSDimitry Andric                       << " bits [" << StartBit << ", " << EndBit << ")\n");
639bdd1243dSDimitry Andric   }
640bdd1243dSDimitry Andric 
64106c3fb27SDimitry Andric   /// Inserts a new dbg def if the interval found when looking up \p StartBit
64206c3fb27SDimitry Andric   /// in \p FragMap starts before \p StartBit or ends after \p EndBit (which
64306c3fb27SDimitry Andric   /// indicates - assuming StartBit->EndBit has just been inserted - that the
64406c3fb27SDimitry Andric   /// slice has been coalesced in the map).
6457a6dacacSDimitry Andric   void coalesceFragments(BasicBlock &BB, VarLocInsertPt Before, unsigned Var,
64606c3fb27SDimitry Andric                          unsigned StartBit, unsigned EndBit, unsigned Base,
64706c3fb27SDimitry Andric                          DebugLoc DL, const FragsInMemMap &FragMap) {
64806c3fb27SDimitry Andric     if (!CoalesceAdjacentFragments)
64906c3fb27SDimitry Andric       return;
65006c3fb27SDimitry Andric     // We've inserted the location into the map. The map will have coalesced
65106c3fb27SDimitry Andric     // adjacent intervals (variable fragments) that describe the same memory
65206c3fb27SDimitry Andric     // location. Use this knowledge to insert a debug location that describes
65306c3fb27SDimitry Andric     // that coalesced fragment. This may eclipse other locs we've just
65406c3fb27SDimitry Andric     // inserted. This is okay as redundant locs will be cleaned up later.
65506c3fb27SDimitry Andric     auto CoalescedFrag = FragMap.find(StartBit);
65606c3fb27SDimitry Andric     // Bail if no coalescing has taken place.
65706c3fb27SDimitry Andric     if (CoalescedFrag.start() == StartBit && CoalescedFrag.stop() == EndBit)
65806c3fb27SDimitry Andric       return;
65906c3fb27SDimitry Andric 
66006c3fb27SDimitry Andric     LLVM_DEBUG(dbgs() << "- Insert loc for bits " << CoalescedFrag.start()
66106c3fb27SDimitry Andric                       << " to " << CoalescedFrag.stop() << "\n");
66206c3fb27SDimitry Andric     insertMemLoc(BB, Before, Var, CoalescedFrag.start(), CoalescedFrag.stop(),
66306c3fb27SDimitry Andric                  Base, DL);
66406c3fb27SDimitry Andric   }
66506c3fb27SDimitry Andric 
6667a6dacacSDimitry Andric   void addDef(const VarLocInfo &VarLoc, VarLocInsertPt Before, BasicBlock &BB,
667bdd1243dSDimitry Andric               VarFragMap &LiveSet) {
668bdd1243dSDimitry Andric     DebugVariable DbgVar = FnVarLocs->getVariable(VarLoc.VariableID);
669bdd1243dSDimitry Andric     if (skipVariable(DbgVar.getVariable()))
670bdd1243dSDimitry Andric       return;
671bdd1243dSDimitry Andric     // Don't bother doing anything for this variables if we know it's fully
672bdd1243dSDimitry Andric     // promoted. We're only interested in variables that (sometimes) live on
673bdd1243dSDimitry Andric     // the stack here.
674bdd1243dSDimitry Andric     if (!VarsWithStackSlot->count(getAggregate(DbgVar)))
675bdd1243dSDimitry Andric       return;
676bdd1243dSDimitry Andric     unsigned Var = Aggregates.insert(
677bdd1243dSDimitry Andric         DebugAggregate(DbgVar.getVariable(), VarLoc.DL.getInlinedAt()));
678bdd1243dSDimitry Andric 
679bdd1243dSDimitry Andric     // [StartBit: EndBit) are the bits affected by this def.
680bdd1243dSDimitry Andric     const DIExpression *DIExpr = VarLoc.Expr;
681bdd1243dSDimitry Andric     unsigned StartBit;
682bdd1243dSDimitry Andric     unsigned EndBit;
683bdd1243dSDimitry Andric     if (auto Frag = DIExpr->getFragmentInfo()) {
684bdd1243dSDimitry Andric       StartBit = Frag->OffsetInBits;
685bdd1243dSDimitry Andric       EndBit = StartBit + Frag->SizeInBits;
686bdd1243dSDimitry Andric     } else {
687bdd1243dSDimitry Andric       assert(static_cast<bool>(DbgVar.getVariable()->getSizeInBits()));
688bdd1243dSDimitry Andric       StartBit = 0;
689bdd1243dSDimitry Andric       EndBit = *DbgVar.getVariable()->getSizeInBits();
690bdd1243dSDimitry Andric     }
691bdd1243dSDimitry Andric 
692bdd1243dSDimitry Andric     // We will only fill fragments for simple memory-describing dbg.value
693bdd1243dSDimitry Andric     // intrinsics. If the fragment offset is the same as the offset from the
694bdd1243dSDimitry Andric     // base pointer, do The Thing, otherwise fall back to normal dbg.value
695bdd1243dSDimitry Andric     // behaviour. AssignmentTrackingLowering has generated DIExpressions
696bdd1243dSDimitry Andric     // written in terms of the base pointer.
697bdd1243dSDimitry Andric     // TODO: Remove this condition since the fragment offset doesn't always
698bdd1243dSDimitry Andric     // equal the offset from base pointer (e.g. for a SROA-split variable).
699bdd1243dSDimitry Andric     const auto DerefOffsetInBytes = getDerefOffsetInBytes(DIExpr);
700bdd1243dSDimitry Andric     const unsigned Base =
701bdd1243dSDimitry Andric         DerefOffsetInBytes && *DerefOffsetInBytes * 8 == StartBit
70206c3fb27SDimitry Andric             ? Bases.insert(VarLoc.Values)
703bdd1243dSDimitry Andric             : 0;
704bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "DEF " << DbgVar.getVariable()->getName() << " ["
705bdd1243dSDimitry Andric                       << StartBit << ", " << EndBit << "): " << toString(Base)
706bdd1243dSDimitry Andric                       << "\n");
707bdd1243dSDimitry Andric 
708bdd1243dSDimitry Andric     // First of all, any locs that use mem that are disrupted need reinstating.
709bdd1243dSDimitry Andric     // Unfortunately, IntervalMap doesn't let us insert intervals that overlap
710bdd1243dSDimitry Andric     // with existing intervals so this code involves a lot of fiddling around
711bdd1243dSDimitry Andric     // with intervals to do that manually.
712bdd1243dSDimitry Andric     auto FragIt = LiveSet.find(Var);
713bdd1243dSDimitry Andric 
714bdd1243dSDimitry Andric     // Check if the variable does not exist in the map.
715bdd1243dSDimitry Andric     if (FragIt == LiveSet.end()) {
716bdd1243dSDimitry Andric       // Add this variable to the BB map.
717bdd1243dSDimitry Andric       auto P = LiveSet.try_emplace(Var, FragsInMemMap(IntervalMapAlloc));
718bdd1243dSDimitry Andric       assert(P.second && "Var already in map?");
719bdd1243dSDimitry Andric       // Add the interval to the fragment map.
720bdd1243dSDimitry Andric       P.first->second.insert(StartBit, EndBit, Base);
721bdd1243dSDimitry Andric       return;
722bdd1243dSDimitry Andric     }
723bdd1243dSDimitry Andric     // The variable has an entry in the map.
724bdd1243dSDimitry Andric 
725bdd1243dSDimitry Andric     FragsInMemMap &FragMap = FragIt->second;
726bdd1243dSDimitry Andric     // First check the easy case: the new fragment `f` doesn't overlap with any
727bdd1243dSDimitry Andric     // intervals.
728bdd1243dSDimitry Andric     if (!FragMap.overlaps(StartBit, EndBit)) {
729bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "- No overlaps\n");
730bdd1243dSDimitry Andric       FragMap.insert(StartBit, EndBit, Base);
73106c3fb27SDimitry Andric       coalesceFragments(BB, Before, Var, StartBit, EndBit, Base, VarLoc.DL,
73206c3fb27SDimitry Andric                         FragMap);
733bdd1243dSDimitry Andric       return;
734bdd1243dSDimitry Andric     }
735bdd1243dSDimitry Andric     // There is at least one overlap.
736bdd1243dSDimitry Andric 
737bdd1243dSDimitry Andric     // Does StartBit intersect an existing fragment?
738bdd1243dSDimitry Andric     auto FirstOverlap = FragMap.find(StartBit);
739bdd1243dSDimitry Andric     assert(FirstOverlap != FragMap.end());
740bdd1243dSDimitry Andric     bool IntersectStart = FirstOverlap.start() < StartBit;
741bdd1243dSDimitry Andric 
742bdd1243dSDimitry Andric     // Does EndBit intersect an existing fragment?
743bdd1243dSDimitry Andric     auto LastOverlap = FragMap.find(EndBit);
744bdd1243dSDimitry Andric     bool IntersectEnd = LastOverlap.valid() && LastOverlap.start() < EndBit;
745bdd1243dSDimitry Andric 
746bdd1243dSDimitry Andric     // Check if both ends of `f` intersect the same interval `i`.
747bdd1243dSDimitry Andric     if (IntersectStart && IntersectEnd && FirstOverlap == LastOverlap) {
748bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "- Intersect single interval @ both ends\n");
749bdd1243dSDimitry Andric       // Shorten `i` so that there's space to insert `f`.
750bdd1243dSDimitry Andric       //      [ f ]
751bdd1243dSDimitry Andric       // [  -   i   -  ]
752bdd1243dSDimitry Andric       // +
753bdd1243dSDimitry Andric       // [ i ][ f ][ i ]
754bdd1243dSDimitry Andric 
755bdd1243dSDimitry Andric       // Save values for use after inserting a new interval.
756bdd1243dSDimitry Andric       auto EndBitOfOverlap = FirstOverlap.stop();
757bdd1243dSDimitry Andric       unsigned OverlapValue = FirstOverlap.value();
758bdd1243dSDimitry Andric 
759bdd1243dSDimitry Andric       // Shorten the overlapping interval.
760bdd1243dSDimitry Andric       FirstOverlap.setStop(StartBit);
761bdd1243dSDimitry Andric       insertMemLoc(BB, Before, Var, FirstOverlap.start(), StartBit,
762bdd1243dSDimitry Andric                    OverlapValue, VarLoc.DL);
763bdd1243dSDimitry Andric 
764bdd1243dSDimitry Andric       // Insert a new interval to represent the end part.
765bdd1243dSDimitry Andric       FragMap.insert(EndBit, EndBitOfOverlap, OverlapValue);
766bdd1243dSDimitry Andric       insertMemLoc(BB, Before, Var, EndBit, EndBitOfOverlap, OverlapValue,
767bdd1243dSDimitry Andric                    VarLoc.DL);
768bdd1243dSDimitry Andric 
769bdd1243dSDimitry Andric       // Insert the new (middle) fragment now there is space.
770bdd1243dSDimitry Andric       FragMap.insert(StartBit, EndBit, Base);
771bdd1243dSDimitry Andric     } else {
772bdd1243dSDimitry Andric       // There's an overlap but `f` may not be fully contained within
773bdd1243dSDimitry Andric       // `i`. Shorten any end-point intersections so that we can then
774bdd1243dSDimitry Andric       // insert `f`.
775bdd1243dSDimitry Andric       //      [ - f - ]
776bdd1243dSDimitry Andric       // [ - i - ]
777bdd1243dSDimitry Andric       // |   |
778bdd1243dSDimitry Andric       // [ i ]
779bdd1243dSDimitry Andric       // Shorten any end-point intersections.
780bdd1243dSDimitry Andric       if (IntersectStart) {
781bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "- Intersect interval at start\n");
782bdd1243dSDimitry Andric         // Split off at the intersection.
783bdd1243dSDimitry Andric         FirstOverlap.setStop(StartBit);
784bdd1243dSDimitry Andric         insertMemLoc(BB, Before, Var, FirstOverlap.start(), StartBit,
785bdd1243dSDimitry Andric                      *FirstOverlap, VarLoc.DL);
786bdd1243dSDimitry Andric       }
787bdd1243dSDimitry Andric       // [ - f - ]
788bdd1243dSDimitry Andric       //      [ - i - ]
789bdd1243dSDimitry Andric       //          |   |
790bdd1243dSDimitry Andric       //          [ i ]
791bdd1243dSDimitry Andric       if (IntersectEnd) {
792bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "- Intersect interval at end\n");
793bdd1243dSDimitry Andric         // Split off at the intersection.
794bdd1243dSDimitry Andric         LastOverlap.setStart(EndBit);
795bdd1243dSDimitry Andric         insertMemLoc(BB, Before, Var, EndBit, LastOverlap.stop(), *LastOverlap,
796bdd1243dSDimitry Andric                      VarLoc.DL);
797bdd1243dSDimitry Andric       }
798bdd1243dSDimitry Andric 
799bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "- Erase intervals contained within\n");
800bdd1243dSDimitry Andric       // FirstOverlap and LastOverlap have been shortened such that they're
801bdd1243dSDimitry Andric       // no longer overlapping with [StartBit, EndBit). Delete any overlaps
802bdd1243dSDimitry Andric       // that remain (these will be fully contained within `f`).
803bdd1243dSDimitry Andric       // [ - f - ]       }
804bdd1243dSDimitry Andric       //      [ - i - ]  } Intersection shortening that has happened above.
805bdd1243dSDimitry Andric       //          |   |  }
806bdd1243dSDimitry Andric       //          [ i ]  }
807bdd1243dSDimitry Andric       // -----------------
808bdd1243dSDimitry Andric       // [i2 ]           } Intervals fully contained within `f` get erased.
809bdd1243dSDimitry Andric       // -----------------
810bdd1243dSDimitry Andric       // [ - f - ][ i ]  } Completed insertion.
811bdd1243dSDimitry Andric       auto It = FirstOverlap;
812bdd1243dSDimitry Andric       if (IntersectStart)
813bdd1243dSDimitry Andric         ++It; // IntersectStart: first overlap has been shortened.
814bdd1243dSDimitry Andric       while (It.valid() && It.start() >= StartBit && It.stop() <= EndBit) {
815bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "- Erase " << toString(It));
816bdd1243dSDimitry Andric         It.erase(); // This increments It after removing the interval.
817bdd1243dSDimitry Andric       }
818bdd1243dSDimitry Andric       // We've dealt with all the overlaps now!
819bdd1243dSDimitry Andric       assert(!FragMap.overlaps(StartBit, EndBit));
820bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "- Insert DEF into now-empty space\n");
821bdd1243dSDimitry Andric       FragMap.insert(StartBit, EndBit, Base);
822bdd1243dSDimitry Andric     }
82306c3fb27SDimitry Andric 
82406c3fb27SDimitry Andric     coalesceFragments(BB, Before, Var, StartBit, EndBit, Base, VarLoc.DL,
82506c3fb27SDimitry Andric                       FragMap);
826bdd1243dSDimitry Andric   }
827bdd1243dSDimitry Andric 
828bdd1243dSDimitry Andric   bool skipVariable(const DILocalVariable *V) { return !V->getSizeInBits(); }
829bdd1243dSDimitry Andric 
830bdd1243dSDimitry Andric   void process(BasicBlock &BB, VarFragMap &LiveSet) {
831bdd1243dSDimitry Andric     BBInsertBeforeMap[&BB].clear();
832bdd1243dSDimitry Andric     for (auto &I : BB) {
833*0fca6ea1SDimitry Andric       for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
834*0fca6ea1SDimitry Andric         if (const auto *Locs = FnVarLocs->getWedge(&DVR)) {
8357a6dacacSDimitry Andric           for (const VarLocInfo &Loc : *Locs) {
836*0fca6ea1SDimitry Andric             addDef(Loc, &DVR, *I.getParent(), LiveSet);
8377a6dacacSDimitry Andric           }
8387a6dacacSDimitry Andric         }
8397a6dacacSDimitry Andric       }
840bdd1243dSDimitry Andric       if (const auto *Locs = FnVarLocs->getWedge(&I)) {
841bdd1243dSDimitry Andric         for (const VarLocInfo &Loc : *Locs) {
8427a6dacacSDimitry Andric           addDef(Loc, &I, *I.getParent(), LiveSet);
843bdd1243dSDimitry Andric         }
844bdd1243dSDimitry Andric       }
845bdd1243dSDimitry Andric     }
846bdd1243dSDimitry Andric   }
847bdd1243dSDimitry Andric 
848bdd1243dSDimitry Andric public:
849bdd1243dSDimitry Andric   MemLocFragmentFill(Function &Fn,
85006c3fb27SDimitry Andric                      const DenseSet<DebugAggregate> *VarsWithStackSlot,
85106c3fb27SDimitry Andric                      bool CoalesceAdjacentFragments)
85206c3fb27SDimitry Andric       : Fn(Fn), VarsWithStackSlot(VarsWithStackSlot),
85306c3fb27SDimitry Andric         CoalesceAdjacentFragments(CoalesceAdjacentFragments) {}
854bdd1243dSDimitry Andric 
855bdd1243dSDimitry Andric   /// Add variable locations to \p FnVarLocs so that any bits of a variable
856bdd1243dSDimitry Andric   /// with a memory location have that location explicitly reinstated at each
857bdd1243dSDimitry Andric   /// subsequent variable location definition that that doesn't overwrite those
858bdd1243dSDimitry Andric   /// bits. i.e. after a variable location def, insert new defs for the memory
859bdd1243dSDimitry Andric   /// location with fragments for the difference of "all bits currently in
860bdd1243dSDimitry Andric   /// memory" and "the fragment of the second def". e.g.
861bdd1243dSDimitry Andric   ///
862bdd1243dSDimitry Andric   ///     Before:
863bdd1243dSDimitry Andric   ///
864bdd1243dSDimitry Andric   ///     var x bits 0 to 63:  value in memory
865bdd1243dSDimitry Andric   ///     more instructions
866bdd1243dSDimitry Andric   ///     var x bits 0 to 31:  value is %0
867bdd1243dSDimitry Andric   ///
868bdd1243dSDimitry Andric   ///     After:
869bdd1243dSDimitry Andric   ///
870bdd1243dSDimitry Andric   ///     var x bits 0 to 63:  value in memory
871bdd1243dSDimitry Andric   ///     more instructions
872bdd1243dSDimitry Andric   ///     var x bits 0 to 31:  value is %0
873bdd1243dSDimitry Andric   ///     var x bits 32 to 61: value in memory ; <-- new loc def
874bdd1243dSDimitry Andric   ///
875bdd1243dSDimitry Andric   void run(FunctionVarLocsBuilder *FnVarLocs) {
876bdd1243dSDimitry Andric     if (!EnableMemLocFragFill)
877bdd1243dSDimitry Andric       return;
878bdd1243dSDimitry Andric 
879bdd1243dSDimitry Andric     this->FnVarLocs = FnVarLocs;
880bdd1243dSDimitry Andric 
881bdd1243dSDimitry Andric     // Prepare for traversal.
882bdd1243dSDimitry Andric     //
883bdd1243dSDimitry Andric     ReversePostOrderTraversal<Function *> RPOT(&Fn);
884bdd1243dSDimitry Andric     std::priority_queue<unsigned int, std::vector<unsigned int>,
885bdd1243dSDimitry Andric                         std::greater<unsigned int>>
886bdd1243dSDimitry Andric         Worklist;
887bdd1243dSDimitry Andric     std::priority_queue<unsigned int, std::vector<unsigned int>,
888bdd1243dSDimitry Andric                         std::greater<unsigned int>>
889bdd1243dSDimitry Andric         Pending;
890bdd1243dSDimitry Andric     DenseMap<unsigned int, BasicBlock *> OrderToBB;
891bdd1243dSDimitry Andric     DenseMap<BasicBlock *, unsigned int> BBToOrder;
892bdd1243dSDimitry Andric     { // Init OrderToBB and BBToOrder.
893bdd1243dSDimitry Andric       unsigned int RPONumber = 0;
894*0fca6ea1SDimitry Andric       for (BasicBlock *BB : RPOT) {
895*0fca6ea1SDimitry Andric         OrderToBB[RPONumber] = BB;
896*0fca6ea1SDimitry Andric         BBToOrder[BB] = RPONumber;
897bdd1243dSDimitry Andric         Worklist.push(RPONumber);
898bdd1243dSDimitry Andric         ++RPONumber;
899bdd1243dSDimitry Andric       }
900bdd1243dSDimitry Andric       LiveIn.init(RPONumber);
901bdd1243dSDimitry Andric       LiveOut.init(RPONumber);
902bdd1243dSDimitry Andric     }
903bdd1243dSDimitry Andric 
904bdd1243dSDimitry Andric     // Perform the traversal.
905bdd1243dSDimitry Andric     //
906bdd1243dSDimitry Andric     // This is a standard "intersect of predecessor outs" dataflow problem. To
907bdd1243dSDimitry Andric     // solve it, we perform meet() and process() using the two worklist method
908bdd1243dSDimitry Andric     // until the LiveIn data for each block becomes unchanging.
909bdd1243dSDimitry Andric     //
910bdd1243dSDimitry Andric     // This dataflow is essentially working on maps of sets and at each meet we
911bdd1243dSDimitry Andric     // intersect the maps and the mapped sets. So, initialized live-in maps
912bdd1243dSDimitry Andric     // monotonically decrease in value throughout the dataflow.
913bdd1243dSDimitry Andric     SmallPtrSet<BasicBlock *, 16> Visited;
914bdd1243dSDimitry Andric     while (!Worklist.empty() || !Pending.empty()) {
915bdd1243dSDimitry Andric       // We track what is on the pending worklist to avoid inserting the same
916bdd1243dSDimitry Andric       // thing twice.  We could avoid this with a custom priority queue, but
917bdd1243dSDimitry Andric       // this is probably not worth it.
918bdd1243dSDimitry Andric       SmallPtrSet<BasicBlock *, 16> OnPending;
919bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "Processing Worklist\n");
920bdd1243dSDimitry Andric       while (!Worklist.empty()) {
921bdd1243dSDimitry Andric         BasicBlock *BB = OrderToBB[Worklist.top()];
922bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "\nPop BB " << BB->getName() << "\n");
923bdd1243dSDimitry Andric         Worklist.pop();
924bdd1243dSDimitry Andric         bool InChanged = meet(*BB, Visited);
925bdd1243dSDimitry Andric         // Always consider LiveIn changed on the first visit.
926bdd1243dSDimitry Andric         InChanged |= Visited.insert(BB).second;
927bdd1243dSDimitry Andric         if (InChanged) {
928bdd1243dSDimitry Andric           LLVM_DEBUG(dbgs()
929bdd1243dSDimitry Andric                      << BB->getName() << " has new InLocs, process it\n");
930bdd1243dSDimitry Andric           //  Mutate a copy of LiveIn while processing BB. Once we've processed
931bdd1243dSDimitry Andric           //  the terminator LiveSet is the LiveOut set for BB.
932bdd1243dSDimitry Andric           //  This is an expensive copy!
933bdd1243dSDimitry Andric           VarFragMap LiveSet = LiveIn[BB];
934bdd1243dSDimitry Andric 
935bdd1243dSDimitry Andric           // Process the instructions in the block.
936bdd1243dSDimitry Andric           process(*BB, LiveSet);
937bdd1243dSDimitry Andric 
938bdd1243dSDimitry Andric           // Relatively expensive check: has anything changed in LiveOut for BB?
939bdd1243dSDimitry Andric           if (!varFragMapsAreEqual(LiveOut[BB], LiveSet)) {
940bdd1243dSDimitry Andric             LLVM_DEBUG(dbgs() << BB->getName()
941bdd1243dSDimitry Andric                               << " has new OutLocs, add succs to worklist: [ ");
942bdd1243dSDimitry Andric             LiveOut[BB] = std::move(LiveSet);
943*0fca6ea1SDimitry Andric             for (BasicBlock *Succ : successors(BB)) {
944*0fca6ea1SDimitry Andric               if (OnPending.insert(Succ).second) {
945*0fca6ea1SDimitry Andric                 LLVM_DEBUG(dbgs() << Succ->getName() << " ");
946*0fca6ea1SDimitry Andric                 Pending.push(BBToOrder[Succ]);
947bdd1243dSDimitry Andric               }
948bdd1243dSDimitry Andric             }
949bdd1243dSDimitry Andric             LLVM_DEBUG(dbgs() << "]\n");
950bdd1243dSDimitry Andric           }
951bdd1243dSDimitry Andric         }
952bdd1243dSDimitry Andric       }
953bdd1243dSDimitry Andric       Worklist.swap(Pending);
954bdd1243dSDimitry Andric       // At this point, pending must be empty, since it was just the empty
955bdd1243dSDimitry Andric       // worklist
956bdd1243dSDimitry Andric       assert(Pending.empty() && "Pending should be empty");
957bdd1243dSDimitry Andric     }
958bdd1243dSDimitry Andric 
959bdd1243dSDimitry Andric     // Insert new location defs.
96006c3fb27SDimitry Andric     for (auto &Pair : BBInsertBeforeMap) {
961bdd1243dSDimitry Andric       InsertMap &Map = Pair.second;
96206c3fb27SDimitry Andric       for (auto &Pair : Map) {
9637a6dacacSDimitry Andric         auto InsertBefore = Pair.first;
964bdd1243dSDimitry Andric         assert(InsertBefore && "should never be null");
965bdd1243dSDimitry Andric         auto FragMemLocs = Pair.second;
966bdd1243dSDimitry Andric         auto &Ctx = Fn.getContext();
967bdd1243dSDimitry Andric 
96806c3fb27SDimitry Andric         for (auto &FragMemLoc : FragMemLocs) {
969bdd1243dSDimitry Andric           DIExpression *Expr = DIExpression::get(Ctx, std::nullopt);
97006c3fb27SDimitry Andric           if (FragMemLoc.SizeInBits !=
97106c3fb27SDimitry Andric               *Aggregates[FragMemLoc.Var].first->getSizeInBits())
972bdd1243dSDimitry Andric             Expr = *DIExpression::createFragmentExpression(
973bdd1243dSDimitry Andric                 Expr, FragMemLoc.OffsetInBits, FragMemLoc.SizeInBits);
974bdd1243dSDimitry Andric           Expr = DIExpression::prepend(Expr, DIExpression::DerefAfter,
975bdd1243dSDimitry Andric                                        FragMemLoc.OffsetInBits / 8);
976bdd1243dSDimitry Andric           DebugVariable Var(Aggregates[FragMemLoc.Var].first, Expr,
977bdd1243dSDimitry Andric                             FragMemLoc.DL.getInlinedAt());
978bdd1243dSDimitry Andric           FnVarLocs->addVarLoc(InsertBefore, Var, Expr, FragMemLoc.DL,
979bdd1243dSDimitry Andric                                Bases[FragMemLoc.Base]);
980bdd1243dSDimitry Andric         }
981bdd1243dSDimitry Andric       }
982bdd1243dSDimitry Andric     }
983bdd1243dSDimitry Andric   }
984bdd1243dSDimitry Andric };
985bdd1243dSDimitry Andric 
986bdd1243dSDimitry Andric /// AssignmentTrackingLowering encapsulates a dataflow analysis over a function
987bdd1243dSDimitry Andric /// that interprets assignment tracking debug info metadata and stores in IR to
988bdd1243dSDimitry Andric /// create a map of variable locations.
989bdd1243dSDimitry Andric class AssignmentTrackingLowering {
990bdd1243dSDimitry Andric public:
991bdd1243dSDimitry Andric   /// The kind of location in use for a variable, where Mem is the stack home,
992bdd1243dSDimitry Andric   /// Val is an SSA value or const, and None means that there is not one single
993bdd1243dSDimitry Andric   /// kind (either because there are multiple or because there is none; it may
994bdd1243dSDimitry Andric   /// prove useful to split this into two values in the future).
995bdd1243dSDimitry Andric   ///
996bdd1243dSDimitry Andric   /// LocKind is a join-semilattice with the partial order:
997bdd1243dSDimitry Andric   /// None > Mem, Val
998bdd1243dSDimitry Andric   ///
999bdd1243dSDimitry Andric   /// i.e.
1000bdd1243dSDimitry Andric   /// join(Mem, Mem)   = Mem
1001bdd1243dSDimitry Andric   /// join(Val, Val)   = Val
1002bdd1243dSDimitry Andric   /// join(Mem, Val)   = None
1003bdd1243dSDimitry Andric   /// join(None, Mem)  = None
1004bdd1243dSDimitry Andric   /// join(None, Val)  = None
1005bdd1243dSDimitry Andric   /// join(None, None) = None
1006bdd1243dSDimitry Andric   ///
1007bdd1243dSDimitry Andric   /// Note: the order is not `None > Val > Mem` because we're using DIAssignID
1008bdd1243dSDimitry Andric   /// to name assignments and are not tracking the actual stored values.
1009bdd1243dSDimitry Andric   /// Therefore currently there's no way to ensure that Mem values and Val
1010bdd1243dSDimitry Andric   /// values are the same. This could be a future extension, though it's not
1011bdd1243dSDimitry Andric   /// clear that many additional locations would be recovered that way in
1012bdd1243dSDimitry Andric   /// practice as the likelihood of this sitation arising naturally seems
1013bdd1243dSDimitry Andric   /// incredibly low.
1014bdd1243dSDimitry Andric   enum class LocKind { Mem, Val, None };
1015bdd1243dSDimitry Andric 
1016bdd1243dSDimitry Andric   /// An abstraction of the assignment of a value to a variable or memory
1017bdd1243dSDimitry Andric   /// location.
1018bdd1243dSDimitry Andric   ///
1019bdd1243dSDimitry Andric   /// An Assignment is Known or NoneOrPhi. A Known Assignment means we have a
1020bdd1243dSDimitry Andric   /// DIAssignID ptr that represents it. NoneOrPhi means that we don't (or
1021bdd1243dSDimitry Andric   /// can't) know the ID of the last assignment that took place.
1022bdd1243dSDimitry Andric   ///
1023bdd1243dSDimitry Andric   /// The Status of the Assignment (Known or NoneOrPhi) is another
1024bdd1243dSDimitry Andric   /// join-semilattice. The partial order is:
1025bdd1243dSDimitry Andric   /// NoneOrPhi > Known {id_0, id_1, ...id_N}
1026bdd1243dSDimitry Andric   ///
1027bdd1243dSDimitry Andric   /// i.e. for all values x and y where x != y:
1028bdd1243dSDimitry Andric   /// join(x, x) = x
1029bdd1243dSDimitry Andric   /// join(x, y) = NoneOrPhi
1030*0fca6ea1SDimitry Andric   using AssignRecord = PointerUnion<DbgAssignIntrinsic *, DbgVariableRecord *>;
1031bdd1243dSDimitry Andric   struct Assignment {
1032bdd1243dSDimitry Andric     enum S { Known, NoneOrPhi } Status;
1033bdd1243dSDimitry Andric     /// ID of the assignment. nullptr if Status is not Known.
1034bdd1243dSDimitry Andric     DIAssignID *ID;
1035bdd1243dSDimitry Andric     /// The dbg.assign that marks this dbg-def. Mem-defs don't use this field.
1036bdd1243dSDimitry Andric     /// May be nullptr.
10377a6dacacSDimitry Andric     AssignRecord Source;
1038bdd1243dSDimitry Andric 
1039bdd1243dSDimitry Andric     bool isSameSourceAssignment(const Assignment &Other) const {
1040bdd1243dSDimitry Andric       // Don't include Source in the equality check. Assignments are
1041bdd1243dSDimitry Andric       // defined by their ID, not debug intrinsic(s).
1042bdd1243dSDimitry Andric       return std::tie(Status, ID) == std::tie(Other.Status, Other.ID);
1043bdd1243dSDimitry Andric     }
1044bdd1243dSDimitry Andric     void dump(raw_ostream &OS) {
1045bdd1243dSDimitry Andric       static const char *LUT[] = {"Known", "NoneOrPhi"};
1046bdd1243dSDimitry Andric       OS << LUT[Status] << "(id=";
1047bdd1243dSDimitry Andric       if (ID)
1048bdd1243dSDimitry Andric         OS << ID;
1049bdd1243dSDimitry Andric       else
1050bdd1243dSDimitry Andric         OS << "null";
1051bdd1243dSDimitry Andric       OS << ", s=";
10527a6dacacSDimitry Andric       if (Source.isNull())
1053bdd1243dSDimitry Andric         OS << "null";
10547a6dacacSDimitry Andric       else if (isa<DbgAssignIntrinsic *>(Source))
10557a6dacacSDimitry Andric         OS << Source.get<DbgAssignIntrinsic *>();
10567a6dacacSDimitry Andric       else
1057*0fca6ea1SDimitry Andric         OS << Source.get<DbgVariableRecord *>();
1058bdd1243dSDimitry Andric       OS << ")";
1059bdd1243dSDimitry Andric     }
1060bdd1243dSDimitry Andric 
1061bdd1243dSDimitry Andric     static Assignment make(DIAssignID *ID, DbgAssignIntrinsic *Source) {
1062bdd1243dSDimitry Andric       return Assignment(Known, ID, Source);
1063bdd1243dSDimitry Andric     }
1064*0fca6ea1SDimitry Andric     static Assignment make(DIAssignID *ID, DbgVariableRecord *Source) {
10657a6dacacSDimitry Andric       assert(Source->isDbgAssign() &&
1066*0fca6ea1SDimitry Andric              "Cannot make an assignment from a non-assign DbgVariableRecord");
10677a6dacacSDimitry Andric       return Assignment(Known, ID, Source);
10687a6dacacSDimitry Andric     }
10697a6dacacSDimitry Andric     static Assignment make(DIAssignID *ID, AssignRecord Source) {
10707a6dacacSDimitry Andric       return Assignment(Known, ID, Source);
10717a6dacacSDimitry Andric     }
1072bdd1243dSDimitry Andric     static Assignment makeFromMemDef(DIAssignID *ID) {
10737a6dacacSDimitry Andric       return Assignment(Known, ID);
1074bdd1243dSDimitry Andric     }
10757a6dacacSDimitry Andric     static Assignment makeNoneOrPhi() { return Assignment(NoneOrPhi, nullptr); }
1076bdd1243dSDimitry Andric     // Again, need a Top value?
10777a6dacacSDimitry Andric     Assignment() : Status(NoneOrPhi), ID(nullptr) {} // Can we delete this?
10787a6dacacSDimitry Andric     Assignment(S Status, DIAssignID *ID) : Status(Status), ID(ID) {
10797a6dacacSDimitry Andric       // If the Status is Known then we expect there to be an assignment ID.
10807a6dacacSDimitry Andric       assert(Status == NoneOrPhi || ID);
10817a6dacacSDimitry Andric     }
1082bdd1243dSDimitry Andric     Assignment(S Status, DIAssignID *ID, DbgAssignIntrinsic *Source)
1083bdd1243dSDimitry Andric         : Status(Status), ID(ID), Source(Source) {
1084bdd1243dSDimitry Andric       // If the Status is Known then we expect there to be an assignment ID.
1085bdd1243dSDimitry Andric       assert(Status == NoneOrPhi || ID);
1086bdd1243dSDimitry Andric     }
1087*0fca6ea1SDimitry Andric     Assignment(S Status, DIAssignID *ID, DbgVariableRecord *Source)
10887a6dacacSDimitry Andric         : Status(Status), ID(ID), Source(Source) {
10897a6dacacSDimitry Andric       // If the Status is Known then we expect there to be an assignment ID.
10907a6dacacSDimitry Andric       assert(Status == NoneOrPhi || ID);
10917a6dacacSDimitry Andric     }
10927a6dacacSDimitry Andric     Assignment(S Status, DIAssignID *ID, AssignRecord Source)
10937a6dacacSDimitry Andric         : Status(Status), ID(ID), Source(Source) {
10947a6dacacSDimitry Andric       // If the Status is Known then we expect there to be an assignment ID.
10957a6dacacSDimitry Andric       assert(Status == NoneOrPhi || ID);
10967a6dacacSDimitry Andric     }
1097bdd1243dSDimitry Andric   };
1098bdd1243dSDimitry Andric 
109906c3fb27SDimitry Andric   using AssignmentMap = SmallVector<Assignment>;
110006c3fb27SDimitry Andric   using LocMap = SmallVector<LocKind>;
110106c3fb27SDimitry Andric   using OverlapMap = DenseMap<VariableID, SmallVector<VariableID>>;
1102bdd1243dSDimitry Andric   using UntaggedStoreAssignmentMap =
1103bdd1243dSDimitry Andric       DenseMap<const Instruction *,
1104bdd1243dSDimitry Andric                SmallVector<std::pair<VariableID, at::AssignmentInfo>>>;
1105bdd1243dSDimitry Andric 
1106bdd1243dSDimitry Andric private:
110706c3fb27SDimitry Andric   /// The highest numbered VariableID for partially promoted variables plus 1,
110806c3fb27SDimitry Andric   /// the values for which start at 1.
110906c3fb27SDimitry Andric   unsigned TrackedVariablesVectorSize = 0;
1110bdd1243dSDimitry Andric   /// Map a variable to the set of variables that it fully contains.
1111bdd1243dSDimitry Andric   OverlapMap VarContains;
1112bdd1243dSDimitry Andric   /// Map untagged stores to the variable fragments they assign to. Used by
1113bdd1243dSDimitry Andric   /// processUntaggedInstruction.
1114bdd1243dSDimitry Andric   UntaggedStoreAssignmentMap UntaggedStoreVars;
1115bdd1243dSDimitry Andric 
1116bdd1243dSDimitry Andric   // Machinery to defer inserting dbg.values.
11177a6dacacSDimitry Andric   using InstInsertMap = MapVector<VarLocInsertPt, SmallVector<VarLocInfo>>;
11187a6dacacSDimitry Andric   InstInsertMap InsertBeforeMap;
1119bdd1243dSDimitry Andric   /// Clear the location definitions currently cached for insertion after /p
1120bdd1243dSDimitry Andric   /// After.
1121bdd1243dSDimitry Andric   void resetInsertionPoint(Instruction &After);
1122*0fca6ea1SDimitry Andric   void resetInsertionPoint(DbgVariableRecord &After);
11237a6dacacSDimitry Andric 
11247a6dacacSDimitry Andric   // emitDbgValue can be called with:
1125*0fca6ea1SDimitry Andric   //   Source=[AssignRecord|DbgValueInst*|DbgAssignIntrinsic*|DbgVariableRecord*]
11267a6dacacSDimitry Andric   // Since AssignRecord can be cast to one of the latter two types, and all
11277a6dacacSDimitry Andric   // other types have a shared interface, we use a template to handle the latter
11287a6dacacSDimitry Andric   // three types, and an explicit overload for AssignRecord that forwards to
11297a6dacacSDimitry Andric   // the template version with the right type.
11307a6dacacSDimitry Andric   void emitDbgValue(LocKind Kind, AssignRecord Source, VarLocInsertPt After);
11317a6dacacSDimitry Andric   template <typename T>
11327a6dacacSDimitry Andric   void emitDbgValue(LocKind Kind, const T Source, VarLocInsertPt After);
1133bdd1243dSDimitry Andric 
113406c3fb27SDimitry Andric   static bool mapsAreEqual(const BitVector &Mask, const AssignmentMap &A,
113506c3fb27SDimitry Andric                            const AssignmentMap &B) {
113606c3fb27SDimitry Andric     return llvm::all_of(Mask.set_bits(), [&](unsigned VarID) {
113706c3fb27SDimitry Andric       return A[VarID].isSameSourceAssignment(B[VarID]);
113806c3fb27SDimitry Andric     });
1139bdd1243dSDimitry Andric   }
1140bdd1243dSDimitry Andric 
1141bdd1243dSDimitry Andric   /// Represents the stack and debug assignments in a block. Used to describe
1142bdd1243dSDimitry Andric   /// the live-in and live-out values for blocks, as well as the "current"
1143bdd1243dSDimitry Andric   /// value as we process each instruction in a block.
1144bdd1243dSDimitry Andric   struct BlockInfo {
114506c3fb27SDimitry Andric     /// The set of variables (VariableID) being tracked in this block.
114606c3fb27SDimitry Andric     BitVector VariableIDsInBlock;
114706c3fb27SDimitry Andric     /// Dominating assignment to memory for each variable, indexed by
114806c3fb27SDimitry Andric     /// VariableID.
1149bdd1243dSDimitry Andric     AssignmentMap StackHomeValue;
115006c3fb27SDimitry Andric     /// Dominating assignemnt to each variable, indexed by VariableID.
1151bdd1243dSDimitry Andric     AssignmentMap DebugValue;
1152bdd1243dSDimitry Andric     /// Location kind for each variable. LiveLoc indicates whether the
1153bdd1243dSDimitry Andric     /// dominating assignment in StackHomeValue (LocKind::Mem), DebugValue
1154bdd1243dSDimitry Andric     /// (LocKind::Val), or neither (LocKind::None) is valid, in that order of
1155bdd1243dSDimitry Andric     /// preference. This cannot be derived by inspecting DebugValue and
1156bdd1243dSDimitry Andric     /// StackHomeValue due to the fact that there's no distinction in
1157bdd1243dSDimitry Andric     /// Assignment (the class) between whether an assignment is unknown or a
1158bdd1243dSDimitry Andric     /// merge of multiple assignments (both are Status::NoneOrPhi). In other
1159bdd1243dSDimitry Andric     /// words, the memory location may well be valid while both DebugValue and
1160bdd1243dSDimitry Andric     /// StackHomeValue contain Assignments that have a Status of NoneOrPhi.
116106c3fb27SDimitry Andric     /// Indexed by VariableID.
1162bdd1243dSDimitry Andric     LocMap LiveLoc;
1163bdd1243dSDimitry Andric 
116406c3fb27SDimitry Andric   public:
116506c3fb27SDimitry Andric     enum AssignmentKind { Stack, Debug };
116606c3fb27SDimitry Andric     const AssignmentMap &getAssignmentMap(AssignmentKind Kind) const {
116706c3fb27SDimitry Andric       switch (Kind) {
116806c3fb27SDimitry Andric       case Stack:
116906c3fb27SDimitry Andric         return StackHomeValue;
117006c3fb27SDimitry Andric       case Debug:
117106c3fb27SDimitry Andric         return DebugValue;
117206c3fb27SDimitry Andric       }
117306c3fb27SDimitry Andric       llvm_unreachable("Unknown AssignmentKind");
117406c3fb27SDimitry Andric     }
117506c3fb27SDimitry Andric     AssignmentMap &getAssignmentMap(AssignmentKind Kind) {
117606c3fb27SDimitry Andric       return const_cast<AssignmentMap &>(
117706c3fb27SDimitry Andric           const_cast<const BlockInfo *>(this)->getAssignmentMap(Kind));
117806c3fb27SDimitry Andric     }
117906c3fb27SDimitry Andric 
118006c3fb27SDimitry Andric     bool isVariableTracked(VariableID Var) const {
118106c3fb27SDimitry Andric       return VariableIDsInBlock[static_cast<unsigned>(Var)];
118206c3fb27SDimitry Andric     }
118306c3fb27SDimitry Andric 
118406c3fb27SDimitry Andric     const Assignment &getAssignment(AssignmentKind Kind, VariableID Var) const {
118506c3fb27SDimitry Andric       assert(isVariableTracked(Var) && "Var not tracked in block");
118606c3fb27SDimitry Andric       return getAssignmentMap(Kind)[static_cast<unsigned>(Var)];
118706c3fb27SDimitry Andric     }
118806c3fb27SDimitry Andric 
118906c3fb27SDimitry Andric     LocKind getLocKind(VariableID Var) const {
119006c3fb27SDimitry Andric       assert(isVariableTracked(Var) && "Var not tracked in block");
119106c3fb27SDimitry Andric       return LiveLoc[static_cast<unsigned>(Var)];
119206c3fb27SDimitry Andric     }
119306c3fb27SDimitry Andric 
119406c3fb27SDimitry Andric     /// Set LocKind for \p Var only: does not set LocKind for VariableIDs of
119506c3fb27SDimitry Andric     /// fragments contained win \p Var.
119606c3fb27SDimitry Andric     void setLocKind(VariableID Var, LocKind K) {
119706c3fb27SDimitry Andric       VariableIDsInBlock.set(static_cast<unsigned>(Var));
119806c3fb27SDimitry Andric       LiveLoc[static_cast<unsigned>(Var)] = K;
119906c3fb27SDimitry Andric     }
120006c3fb27SDimitry Andric 
120106c3fb27SDimitry Andric     /// Set the assignment in the \p Kind assignment map for \p Var only: does
120206c3fb27SDimitry Andric     /// not set the assignment for VariableIDs of fragments contained win \p
120306c3fb27SDimitry Andric     /// Var.
120406c3fb27SDimitry Andric     void setAssignment(AssignmentKind Kind, VariableID Var,
120506c3fb27SDimitry Andric                        const Assignment &AV) {
120606c3fb27SDimitry Andric       VariableIDsInBlock.set(static_cast<unsigned>(Var));
120706c3fb27SDimitry Andric       getAssignmentMap(Kind)[static_cast<unsigned>(Var)] = AV;
120806c3fb27SDimitry Andric     }
120906c3fb27SDimitry Andric 
121006c3fb27SDimitry Andric     /// Return true if there is an assignment matching \p AV in the \p Kind
121106c3fb27SDimitry Andric     /// assignment map. Does consider assignments for VariableIDs of fragments
121206c3fb27SDimitry Andric     /// contained win \p Var.
121306c3fb27SDimitry Andric     bool hasAssignment(AssignmentKind Kind, VariableID Var,
121406c3fb27SDimitry Andric                        const Assignment &AV) const {
121506c3fb27SDimitry Andric       if (!isVariableTracked(Var))
121606c3fb27SDimitry Andric         return false;
121706c3fb27SDimitry Andric       return AV.isSameSourceAssignment(getAssignment(Kind, Var));
121806c3fb27SDimitry Andric     }
121906c3fb27SDimitry Andric 
1220bdd1243dSDimitry Andric     /// Compare every element in each map to determine structural equality
1221bdd1243dSDimitry Andric     /// (slow).
1222bdd1243dSDimitry Andric     bool operator==(const BlockInfo &Other) const {
122306c3fb27SDimitry Andric       return VariableIDsInBlock == Other.VariableIDsInBlock &&
122406c3fb27SDimitry Andric              LiveLoc == Other.LiveLoc &&
122506c3fb27SDimitry Andric              mapsAreEqual(VariableIDsInBlock, StackHomeValue,
122606c3fb27SDimitry Andric                           Other.StackHomeValue) &&
122706c3fb27SDimitry Andric              mapsAreEqual(VariableIDsInBlock, DebugValue, Other.DebugValue);
1228bdd1243dSDimitry Andric     }
1229bdd1243dSDimitry Andric     bool operator!=(const BlockInfo &Other) const { return !(*this == Other); }
1230bdd1243dSDimitry Andric     bool isValid() {
1231bdd1243dSDimitry Andric       return LiveLoc.size() == DebugValue.size() &&
1232bdd1243dSDimitry Andric              LiveLoc.size() == StackHomeValue.size();
1233bdd1243dSDimitry Andric     }
123406c3fb27SDimitry Andric 
123506c3fb27SDimitry Andric     /// Clear everything and initialise with ⊤-values for all variables.
123606c3fb27SDimitry Andric     void init(int NumVars) {
123706c3fb27SDimitry Andric       StackHomeValue.clear();
123806c3fb27SDimitry Andric       DebugValue.clear();
123906c3fb27SDimitry Andric       LiveLoc.clear();
124006c3fb27SDimitry Andric       VariableIDsInBlock = BitVector(NumVars);
124106c3fb27SDimitry Andric       StackHomeValue.insert(StackHomeValue.begin(), NumVars,
124206c3fb27SDimitry Andric                             Assignment::makeNoneOrPhi());
124306c3fb27SDimitry Andric       DebugValue.insert(DebugValue.begin(), NumVars,
124406c3fb27SDimitry Andric                         Assignment::makeNoneOrPhi());
124506c3fb27SDimitry Andric       LiveLoc.insert(LiveLoc.begin(), NumVars, LocKind::None);
124606c3fb27SDimitry Andric     }
124706c3fb27SDimitry Andric 
124806c3fb27SDimitry Andric     /// Helper for join.
124906c3fb27SDimitry Andric     template <typename ElmtType, typename FnInputType>
125006c3fb27SDimitry Andric     static void joinElmt(int Index, SmallVector<ElmtType> &Target,
125106c3fb27SDimitry Andric                          const SmallVector<ElmtType> &A,
125206c3fb27SDimitry Andric                          const SmallVector<ElmtType> &B,
125306c3fb27SDimitry Andric                          ElmtType (*Fn)(FnInputType, FnInputType)) {
125406c3fb27SDimitry Andric       Target[Index] = Fn(A[Index], B[Index]);
125506c3fb27SDimitry Andric     }
125606c3fb27SDimitry Andric 
125706c3fb27SDimitry Andric     /// See comment for AssignmentTrackingLowering::joinBlockInfo.
125806c3fb27SDimitry Andric     static BlockInfo join(const BlockInfo &A, const BlockInfo &B, int NumVars) {
125906c3fb27SDimitry Andric       // Join A and B.
126006c3fb27SDimitry Andric       //
126106c3fb27SDimitry Andric       // Intersect = join(a, b) for a in A, b in B where Var(a) == Var(b)
126206c3fb27SDimitry Andric       // Difference = join(x, ⊤) for x where Var(x) is in A xor B
126306c3fb27SDimitry Andric       // Join = Intersect ∪ Difference
126406c3fb27SDimitry Andric       //
126506c3fb27SDimitry Andric       // This is achieved by performing a join on elements from A and B with
126606c3fb27SDimitry Andric       // variables common to both A and B (join elements indexed by var
126706c3fb27SDimitry Andric       // intersect), then adding ⊤-value elements for vars in A xor B. The
126806c3fb27SDimitry Andric       // latter part is equivalent to performing join on elements with variables
126906c3fb27SDimitry Andric       // in A xor B with the ⊤-value for the map element since join(x, ⊤) = ⊤.
127006c3fb27SDimitry Andric       // BlockInfo::init initializes all variable entries to the ⊤ value so we
127106c3fb27SDimitry Andric       // don't need to explicitly perform that step as Join.VariableIDsInBlock
127206c3fb27SDimitry Andric       // is set to the union of the variables in A and B at the end of this
127306c3fb27SDimitry Andric       // function.
127406c3fb27SDimitry Andric       BlockInfo Join;
127506c3fb27SDimitry Andric       Join.init(NumVars);
127606c3fb27SDimitry Andric 
127706c3fb27SDimitry Andric       BitVector Intersect = A.VariableIDsInBlock;
127806c3fb27SDimitry Andric       Intersect &= B.VariableIDsInBlock;
127906c3fb27SDimitry Andric 
128006c3fb27SDimitry Andric       for (auto VarID : Intersect.set_bits()) {
128106c3fb27SDimitry Andric         joinElmt(VarID, Join.LiveLoc, A.LiveLoc, B.LiveLoc, joinKind);
128206c3fb27SDimitry Andric         joinElmt(VarID, Join.DebugValue, A.DebugValue, B.DebugValue,
128306c3fb27SDimitry Andric                  joinAssignment);
128406c3fb27SDimitry Andric         joinElmt(VarID, Join.StackHomeValue, A.StackHomeValue, B.StackHomeValue,
128506c3fb27SDimitry Andric                  joinAssignment);
128606c3fb27SDimitry Andric       }
128706c3fb27SDimitry Andric 
128806c3fb27SDimitry Andric       Join.VariableIDsInBlock = A.VariableIDsInBlock;
128906c3fb27SDimitry Andric       Join.VariableIDsInBlock |= B.VariableIDsInBlock;
129006c3fb27SDimitry Andric       assert(Join.isValid());
129106c3fb27SDimitry Andric       return Join;
129206c3fb27SDimitry Andric     }
1293bdd1243dSDimitry Andric   };
1294bdd1243dSDimitry Andric 
1295bdd1243dSDimitry Andric   Function &Fn;
1296bdd1243dSDimitry Andric   const DataLayout &Layout;
1297bdd1243dSDimitry Andric   const DenseSet<DebugAggregate> *VarsWithStackSlot;
1298bdd1243dSDimitry Andric   FunctionVarLocsBuilder *FnVarLocs;
1299bdd1243dSDimitry Andric   DenseMap<const BasicBlock *, BlockInfo> LiveIn;
1300bdd1243dSDimitry Andric   DenseMap<const BasicBlock *, BlockInfo> LiveOut;
1301bdd1243dSDimitry Andric 
1302bdd1243dSDimitry Andric   /// Helper for process methods to track variables touched each frame.
1303bdd1243dSDimitry Andric   DenseSet<VariableID> VarsTouchedThisFrame;
1304bdd1243dSDimitry Andric 
1305bdd1243dSDimitry Andric   /// The set of variables that sometimes are not located in their stack home.
1306bdd1243dSDimitry Andric   DenseSet<DebugAggregate> NotAlwaysStackHomed;
1307bdd1243dSDimitry Andric 
1308bdd1243dSDimitry Andric   VariableID getVariableID(const DebugVariable &Var) {
1309bdd1243dSDimitry Andric     return static_cast<VariableID>(FnVarLocs->insertVariable(Var));
1310bdd1243dSDimitry Andric   }
1311bdd1243dSDimitry Andric 
1312bdd1243dSDimitry Andric   /// Join the LiveOut values of preds that are contained in \p Visited into
1313bdd1243dSDimitry Andric   /// LiveIn[BB]. Return True if LiveIn[BB] has changed as a result. LiveIn[BB]
1314bdd1243dSDimitry Andric   /// values monotonically increase. See the @link joinMethods join methods
1315bdd1243dSDimitry Andric   /// @endlink documentation for more info.
1316bdd1243dSDimitry Andric   bool join(const BasicBlock &BB, const SmallPtrSet<BasicBlock *, 16> &Visited);
1317bdd1243dSDimitry Andric   ///@name joinMethods
1318bdd1243dSDimitry Andric   /// Functions that implement `join` (the least upper bound) for the
1319bdd1243dSDimitry Andric   /// join-semilattice types used in the dataflow. There is an explicit bottom
1320bdd1243dSDimitry Andric   /// value (⊥) for some types and and explicit top value (⊤) for all types.
1321bdd1243dSDimitry Andric   /// By definition:
1322bdd1243dSDimitry Andric   ///
1323bdd1243dSDimitry Andric   ///     Join(A, B) >= A && Join(A, B) >= B
1324bdd1243dSDimitry Andric   ///     Join(A, ⊥) = A
1325bdd1243dSDimitry Andric   ///     Join(A, ⊤) = ⊤
1326bdd1243dSDimitry Andric   ///
1327bdd1243dSDimitry Andric   /// These invariants are important for monotonicity.
1328bdd1243dSDimitry Andric   ///
1329bdd1243dSDimitry Andric   /// For the map-type functions, all unmapped keys in an empty map are
1330bdd1243dSDimitry Andric   /// associated with a bottom value (⊥). This represents their values being
1331bdd1243dSDimitry Andric   /// unknown. Unmapped keys in non-empty maps (joining two maps with a key
1332bdd1243dSDimitry Andric   /// only present in one) represents either a variable going out of scope or
1333bdd1243dSDimitry Andric   /// dropped debug info. It is assumed the key is associated with a top value
1334bdd1243dSDimitry Andric   /// (⊤) in this case (unknown location / assignment).
1335bdd1243dSDimitry Andric   ///@{
1336bdd1243dSDimitry Andric   static LocKind joinKind(LocKind A, LocKind B);
1337bdd1243dSDimitry Andric   static Assignment joinAssignment(const Assignment &A, const Assignment &B);
133806c3fb27SDimitry Andric   BlockInfo joinBlockInfo(const BlockInfo &A, const BlockInfo &B);
1339bdd1243dSDimitry Andric   ///@}
1340bdd1243dSDimitry Andric 
1341bdd1243dSDimitry Andric   /// Process the instructions in \p BB updating \p LiveSet along the way. \p
1342bdd1243dSDimitry Andric   /// LiveSet must be initialized with the current live-in locations before
1343bdd1243dSDimitry Andric   /// calling this.
1344bdd1243dSDimitry Andric   void process(BasicBlock &BB, BlockInfo *LiveSet);
1345bdd1243dSDimitry Andric   ///@name processMethods
1346bdd1243dSDimitry Andric   /// Methods to process instructions in order to update the LiveSet (current
1347bdd1243dSDimitry Andric   /// location information).
1348bdd1243dSDimitry Andric   ///@{
1349bdd1243dSDimitry Andric   void processNonDbgInstruction(Instruction &I, BlockInfo *LiveSet);
135006c3fb27SDimitry Andric   void processDbgInstruction(DbgInfoIntrinsic &I, BlockInfo *LiveSet);
1351bdd1243dSDimitry Andric   /// Update \p LiveSet after encountering an instruction with a DIAssignID
1352bdd1243dSDimitry Andric   /// attachment, \p I.
1353bdd1243dSDimitry Andric   void processTaggedInstruction(Instruction &I, BlockInfo *LiveSet);
1354bdd1243dSDimitry Andric   /// Update \p LiveSet after encountering an instruciton without a DIAssignID
1355bdd1243dSDimitry Andric   /// attachment, \p I.
1356bdd1243dSDimitry Andric   void processUntaggedInstruction(Instruction &I, BlockInfo *LiveSet);
13577a6dacacSDimitry Andric   void processDbgAssign(AssignRecord Assign, BlockInfo *LiveSet);
1358*0fca6ea1SDimitry Andric   void processDbgVariableRecord(DbgVariableRecord &DVR, BlockInfo *LiveSet);
1359*0fca6ea1SDimitry Andric   void processDbgValue(
1360*0fca6ea1SDimitry Andric       PointerUnion<DbgValueInst *, DbgVariableRecord *> DbgValueRecord,
13617a6dacacSDimitry Andric       BlockInfo *LiveSet);
1362bdd1243dSDimitry Andric   /// Add an assignment to memory for the variable /p Var.
1363bdd1243dSDimitry Andric   void addMemDef(BlockInfo *LiveSet, VariableID Var, const Assignment &AV);
1364bdd1243dSDimitry Andric   /// Add an assignment to the variable /p Var.
1365bdd1243dSDimitry Andric   void addDbgDef(BlockInfo *LiveSet, VariableID Var, const Assignment &AV);
1366bdd1243dSDimitry Andric   ///@}
1367bdd1243dSDimitry Andric 
1368bdd1243dSDimitry Andric   /// Set the LocKind for \p Var.
1369bdd1243dSDimitry Andric   void setLocKind(BlockInfo *LiveSet, VariableID Var, LocKind K);
1370bdd1243dSDimitry Andric   /// Get the live LocKind for a \p Var. Requires addMemDef or addDbgDef to
1371bdd1243dSDimitry Andric   /// have been called for \p Var first.
1372bdd1243dSDimitry Andric   LocKind getLocKind(BlockInfo *LiveSet, VariableID Var);
1373bdd1243dSDimitry Andric   /// Return true if \p Var has an assignment in \p M matching \p AV.
137406c3fb27SDimitry Andric   bool hasVarWithAssignment(BlockInfo *LiveSet, BlockInfo::AssignmentKind Kind,
137506c3fb27SDimitry Andric                             VariableID Var, const Assignment &AV);
137606c3fb27SDimitry Andric   /// Return the set of VariableIDs corresponding the fragments contained fully
137706c3fb27SDimitry Andric   /// within the variable/fragment \p Var.
137806c3fb27SDimitry Andric   ArrayRef<VariableID> getContainedFragments(VariableID Var) const;
137906c3fb27SDimitry Andric 
138006c3fb27SDimitry Andric   /// Mark \p Var as having been touched this frame. Note, this applies only
138106c3fb27SDimitry Andric   /// to the exact fragment \p Var and not to any fragments contained within.
138206c3fb27SDimitry Andric   void touchFragment(VariableID Var);
1383bdd1243dSDimitry Andric 
1384bdd1243dSDimitry Andric   /// Emit info for variables that are fully promoted.
1385bdd1243dSDimitry Andric   bool emitPromotedVarLocs(FunctionVarLocsBuilder *FnVarLocs);
1386bdd1243dSDimitry Andric 
1387bdd1243dSDimitry Andric public:
1388bdd1243dSDimitry Andric   AssignmentTrackingLowering(Function &Fn, const DataLayout &Layout,
1389bdd1243dSDimitry Andric                              const DenseSet<DebugAggregate> *VarsWithStackSlot)
1390bdd1243dSDimitry Andric       : Fn(Fn), Layout(Layout), VarsWithStackSlot(VarsWithStackSlot) {}
1391bdd1243dSDimitry Andric   /// Run the analysis, adding variable location info to \p FnVarLocs. Returns
1392bdd1243dSDimitry Andric   /// true if any variable locations have been added to FnVarLocs.
1393bdd1243dSDimitry Andric   bool run(FunctionVarLocsBuilder *FnVarLocs);
1394bdd1243dSDimitry Andric };
1395bdd1243dSDimitry Andric } // namespace
1396bdd1243dSDimitry Andric 
139706c3fb27SDimitry Andric ArrayRef<VariableID>
139806c3fb27SDimitry Andric AssignmentTrackingLowering::getContainedFragments(VariableID Var) const {
139906c3fb27SDimitry Andric   auto R = VarContains.find(Var);
140006c3fb27SDimitry Andric   if (R == VarContains.end())
140106c3fb27SDimitry Andric     return std::nullopt;
140206c3fb27SDimitry Andric   return R->second;
140306c3fb27SDimitry Andric }
140406c3fb27SDimitry Andric 
140506c3fb27SDimitry Andric void AssignmentTrackingLowering::touchFragment(VariableID Var) {
140606c3fb27SDimitry Andric   VarsTouchedThisFrame.insert(Var);
140706c3fb27SDimitry Andric }
140806c3fb27SDimitry Andric 
1409bdd1243dSDimitry Andric void AssignmentTrackingLowering::setLocKind(BlockInfo *LiveSet, VariableID Var,
1410bdd1243dSDimitry Andric                                             LocKind K) {
1411bdd1243dSDimitry Andric   auto SetKind = [this](BlockInfo *LiveSet, VariableID Var, LocKind K) {
141206c3fb27SDimitry Andric     LiveSet->setLocKind(Var, K);
141306c3fb27SDimitry Andric     touchFragment(Var);
1414bdd1243dSDimitry Andric   };
1415bdd1243dSDimitry Andric   SetKind(LiveSet, Var, K);
1416bdd1243dSDimitry Andric 
1417bdd1243dSDimitry Andric   // Update the LocKind for all fragments contained within Var.
141806c3fb27SDimitry Andric   for (VariableID Frag : getContainedFragments(Var))
1419bdd1243dSDimitry Andric     SetKind(LiveSet, Frag, K);
1420bdd1243dSDimitry Andric }
1421bdd1243dSDimitry Andric 
1422bdd1243dSDimitry Andric AssignmentTrackingLowering::LocKind
1423bdd1243dSDimitry Andric AssignmentTrackingLowering::getLocKind(BlockInfo *LiveSet, VariableID Var) {
142406c3fb27SDimitry Andric   return LiveSet->getLocKind(Var);
1425bdd1243dSDimitry Andric }
1426bdd1243dSDimitry Andric 
1427bdd1243dSDimitry Andric void AssignmentTrackingLowering::addMemDef(BlockInfo *LiveSet, VariableID Var,
1428bdd1243dSDimitry Andric                                            const Assignment &AV) {
142906c3fb27SDimitry Andric   LiveSet->setAssignment(BlockInfo::Stack, Var, AV);
1430bdd1243dSDimitry Andric 
1431bdd1243dSDimitry Andric   // Use this assigment for all fragments contained within Var, but do not
1432bdd1243dSDimitry Andric   // provide a Source because we cannot convert Var's value to a value for the
1433bdd1243dSDimitry Andric   // fragment.
1434bdd1243dSDimitry Andric   Assignment FragAV = AV;
1435bdd1243dSDimitry Andric   FragAV.Source = nullptr;
143606c3fb27SDimitry Andric   for (VariableID Frag : getContainedFragments(Var))
143706c3fb27SDimitry Andric     LiveSet->setAssignment(BlockInfo::Stack, Frag, FragAV);
1438bdd1243dSDimitry Andric }
1439bdd1243dSDimitry Andric 
1440bdd1243dSDimitry Andric void AssignmentTrackingLowering::addDbgDef(BlockInfo *LiveSet, VariableID Var,
1441bdd1243dSDimitry Andric                                            const Assignment &AV) {
144206c3fb27SDimitry Andric   LiveSet->setAssignment(BlockInfo::Debug, Var, AV);
1443bdd1243dSDimitry Andric 
1444bdd1243dSDimitry Andric   // Use this assigment for all fragments contained within Var, but do not
1445bdd1243dSDimitry Andric   // provide a Source because we cannot convert Var's value to a value for the
1446bdd1243dSDimitry Andric   // fragment.
1447bdd1243dSDimitry Andric   Assignment FragAV = AV;
1448bdd1243dSDimitry Andric   FragAV.Source = nullptr;
144906c3fb27SDimitry Andric   for (VariableID Frag : getContainedFragments(Var))
145006c3fb27SDimitry Andric     LiveSet->setAssignment(BlockInfo::Debug, Frag, FragAV);
1451bdd1243dSDimitry Andric }
1452bdd1243dSDimitry Andric 
1453bdd1243dSDimitry Andric static DIAssignID *getIDFromInst(const Instruction &I) {
1454bdd1243dSDimitry Andric   return cast<DIAssignID>(I.getMetadata(LLVMContext::MD_DIAssignID));
1455bdd1243dSDimitry Andric }
1456bdd1243dSDimitry Andric 
1457bdd1243dSDimitry Andric static DIAssignID *getIDFromMarker(const DbgAssignIntrinsic &DAI) {
1458bdd1243dSDimitry Andric   return cast<DIAssignID>(DAI.getAssignID());
1459bdd1243dSDimitry Andric }
1460bdd1243dSDimitry Andric 
1461*0fca6ea1SDimitry Andric static DIAssignID *getIDFromMarker(const DbgVariableRecord &DVR) {
1462*0fca6ea1SDimitry Andric   assert(DVR.isDbgAssign() &&
1463*0fca6ea1SDimitry Andric          "Cannot get a DIAssignID from a non-assign DbgVariableRecord!");
1464*0fca6ea1SDimitry Andric   return DVR.getAssignID();
14657a6dacacSDimitry Andric }
14667a6dacacSDimitry Andric 
1467bdd1243dSDimitry Andric /// Return true if \p Var has an assignment in \p M matching \p AV.
146806c3fb27SDimitry Andric bool AssignmentTrackingLowering::hasVarWithAssignment(
146906c3fb27SDimitry Andric     BlockInfo *LiveSet, BlockInfo::AssignmentKind Kind, VariableID Var,
147006c3fb27SDimitry Andric     const Assignment &AV) {
147106c3fb27SDimitry Andric   if (!LiveSet->hasAssignment(Kind, Var, AV))
1472bdd1243dSDimitry Andric     return false;
1473bdd1243dSDimitry Andric 
1474bdd1243dSDimitry Andric   // Check all the frags contained within Var as these will have all been
1475bdd1243dSDimitry Andric   // mapped to AV at the last store to Var.
147606c3fb27SDimitry Andric   for (VariableID Frag : getContainedFragments(Var))
147706c3fb27SDimitry Andric     if (!LiveSet->hasAssignment(Kind, Frag, AV))
1478bdd1243dSDimitry Andric       return false;
1479bdd1243dSDimitry Andric   return true;
1480bdd1243dSDimitry Andric }
1481bdd1243dSDimitry Andric 
1482bdd1243dSDimitry Andric #ifndef NDEBUG
1483bdd1243dSDimitry Andric const char *locStr(AssignmentTrackingLowering::LocKind Loc) {
1484bdd1243dSDimitry Andric   using LocKind = AssignmentTrackingLowering::LocKind;
1485bdd1243dSDimitry Andric   switch (Loc) {
1486bdd1243dSDimitry Andric   case LocKind::Val:
1487bdd1243dSDimitry Andric     return "Val";
1488bdd1243dSDimitry Andric   case LocKind::Mem:
1489bdd1243dSDimitry Andric     return "Mem";
1490bdd1243dSDimitry Andric   case LocKind::None:
1491bdd1243dSDimitry Andric     return "None";
1492bdd1243dSDimitry Andric   };
1493bdd1243dSDimitry Andric   llvm_unreachable("unknown LocKind");
1494bdd1243dSDimitry Andric }
1495bdd1243dSDimitry Andric #endif
1496bdd1243dSDimitry Andric 
1497*0fca6ea1SDimitry Andric VarLocInsertPt getNextNode(const DbgRecord *DVR) {
1498*0fca6ea1SDimitry Andric   auto NextIt = ++(DVR->getIterator());
1499*0fca6ea1SDimitry Andric   if (NextIt == DVR->getMarker()->getDbgRecordRange().end())
1500*0fca6ea1SDimitry Andric     return DVR->getMarker()->MarkedInstr;
15017a6dacacSDimitry Andric   return &*NextIt;
15027a6dacacSDimitry Andric }
15037a6dacacSDimitry Andric VarLocInsertPt getNextNode(const Instruction *Inst) {
15047a6dacacSDimitry Andric   const Instruction *Next = Inst->getNextNode();
1505*0fca6ea1SDimitry Andric   if (!Next->hasDbgRecords())
15067a6dacacSDimitry Andric     return Next;
1507*0fca6ea1SDimitry Andric   return &*Next->getDbgRecordRange().begin();
15087a6dacacSDimitry Andric }
15097a6dacacSDimitry Andric VarLocInsertPt getNextNode(VarLocInsertPt InsertPt) {
15107a6dacacSDimitry Andric   if (isa<const Instruction *>(InsertPt))
15117a6dacacSDimitry Andric     return getNextNode(cast<const Instruction *>(InsertPt));
1512*0fca6ea1SDimitry Andric   return getNextNode(cast<const DbgRecord *>(InsertPt));
15137a6dacacSDimitry Andric }
15147a6dacacSDimitry Andric 
15157a6dacacSDimitry Andric DbgAssignIntrinsic *CastToDbgAssign(DbgVariableIntrinsic *DVI) {
15167a6dacacSDimitry Andric   return cast<DbgAssignIntrinsic>(DVI);
15177a6dacacSDimitry Andric }
15187a6dacacSDimitry Andric 
1519*0fca6ea1SDimitry Andric DbgVariableRecord *CastToDbgAssign(DbgVariableRecord *DVR) {
1520*0fca6ea1SDimitry Andric   assert(DVR->isDbgAssign() &&
1521*0fca6ea1SDimitry Andric          "Attempted to cast non-assign DbgVariableRecord to DVRAssign.");
1522*0fca6ea1SDimitry Andric   return DVR;
15237a6dacacSDimitry Andric }
15247a6dacacSDimitry Andric 
1525bdd1243dSDimitry Andric void AssignmentTrackingLowering::emitDbgValue(
1526bdd1243dSDimitry Andric     AssignmentTrackingLowering::LocKind Kind,
15277a6dacacSDimitry Andric     AssignmentTrackingLowering::AssignRecord Source, VarLocInsertPt After) {
15287a6dacacSDimitry Andric   if (isa<DbgAssignIntrinsic *>(Source))
15297a6dacacSDimitry Andric     emitDbgValue(Kind, cast<DbgAssignIntrinsic *>(Source), After);
15307a6dacacSDimitry Andric   else
1531*0fca6ea1SDimitry Andric     emitDbgValue(Kind, cast<DbgVariableRecord *>(Source), After);
15327a6dacacSDimitry Andric }
15337a6dacacSDimitry Andric template <typename T>
15347a6dacacSDimitry Andric void AssignmentTrackingLowering::emitDbgValue(
15357a6dacacSDimitry Andric     AssignmentTrackingLowering::LocKind Kind, const T Source,
15367a6dacacSDimitry Andric     VarLocInsertPt After) {
1537bdd1243dSDimitry Andric 
1538bdd1243dSDimitry Andric   DILocation *DL = Source->getDebugLoc();
153906c3fb27SDimitry Andric   auto Emit = [this, Source, After, DL](Metadata *Val, DIExpression *Expr) {
1540bdd1243dSDimitry Andric     assert(Expr);
1541bdd1243dSDimitry Andric     if (!Val)
154206c3fb27SDimitry Andric       Val = ValueAsMetadata::get(
154306c3fb27SDimitry Andric           PoisonValue::get(Type::getInt1Ty(Source->getContext())));
1544bdd1243dSDimitry Andric 
1545bdd1243dSDimitry Andric     // Find a suitable insert point.
15467a6dacacSDimitry Andric     auto InsertBefore = getNextNode(After);
1547bdd1243dSDimitry Andric     assert(InsertBefore && "Shouldn't be inserting after a terminator");
1548bdd1243dSDimitry Andric 
1549bdd1243dSDimitry Andric     VariableID Var = getVariableID(DebugVariable(Source));
1550bdd1243dSDimitry Andric     VarLocInfo VarLoc;
1551bdd1243dSDimitry Andric     VarLoc.VariableID = static_cast<VariableID>(Var);
1552bdd1243dSDimitry Andric     VarLoc.Expr = Expr;
155306c3fb27SDimitry Andric     VarLoc.Values = RawLocationWrapper(Val);
1554bdd1243dSDimitry Andric     VarLoc.DL = DL;
1555bdd1243dSDimitry Andric     // Insert it into the map for later.
1556bdd1243dSDimitry Andric     InsertBeforeMap[InsertBefore].push_back(VarLoc);
1557bdd1243dSDimitry Andric   };
1558bdd1243dSDimitry Andric 
1559bdd1243dSDimitry Andric   // NOTE: This block can mutate Kind.
1560bdd1243dSDimitry Andric   if (Kind == LocKind::Mem) {
15617a6dacacSDimitry Andric     const auto *Assign = CastToDbgAssign(Source);
1562bdd1243dSDimitry Andric     // Check the address hasn't been dropped (e.g. the debug uses may not have
1563bdd1243dSDimitry Andric     // been replaced before deleting a Value).
15647a6dacacSDimitry Andric     if (Assign->isKillAddress()) {
1565bdd1243dSDimitry Andric       // The address isn't valid so treat this as a non-memory def.
1566bdd1243dSDimitry Andric       Kind = LocKind::Val;
1567bdd1243dSDimitry Andric     } else {
15687a6dacacSDimitry Andric       Value *Val = Assign->getAddress();
15697a6dacacSDimitry Andric       DIExpression *Expr = Assign->getAddressExpression();
1570bdd1243dSDimitry Andric       assert(!Expr->getFragmentInfo() &&
1571bdd1243dSDimitry Andric              "fragment info should be stored in value-expression only");
1572bdd1243dSDimitry Andric       // Copy the fragment info over from the value-expression to the new
1573bdd1243dSDimitry Andric       // DIExpression.
1574bdd1243dSDimitry Andric       if (auto OptFragInfo = Source->getExpression()->getFragmentInfo()) {
1575bdd1243dSDimitry Andric         auto FragInfo = *OptFragInfo;
1576bdd1243dSDimitry Andric         Expr = *DIExpression::createFragmentExpression(
1577bdd1243dSDimitry Andric             Expr, FragInfo.OffsetInBits, FragInfo.SizeInBits);
1578bdd1243dSDimitry Andric       }
1579bdd1243dSDimitry Andric       // The address-expression has an implicit deref, add it now.
1580bdd1243dSDimitry Andric       std::tie(Val, Expr) =
1581bdd1243dSDimitry Andric           walkToAllocaAndPrependOffsetDeref(Layout, Val, Expr);
158206c3fb27SDimitry Andric       Emit(ValueAsMetadata::get(Val), Expr);
1583bdd1243dSDimitry Andric       return;
1584bdd1243dSDimitry Andric     }
1585bdd1243dSDimitry Andric   }
1586bdd1243dSDimitry Andric 
1587bdd1243dSDimitry Andric   if (Kind == LocKind::Val) {
158806c3fb27SDimitry Andric     Emit(Source->getRawLocation(), Source->getExpression());
1589bdd1243dSDimitry Andric     return;
1590bdd1243dSDimitry Andric   }
1591bdd1243dSDimitry Andric 
1592bdd1243dSDimitry Andric   if (Kind == LocKind::None) {
1593bdd1243dSDimitry Andric     Emit(nullptr, Source->getExpression());
1594bdd1243dSDimitry Andric     return;
1595bdd1243dSDimitry Andric   }
1596bdd1243dSDimitry Andric }
1597bdd1243dSDimitry Andric 
1598bdd1243dSDimitry Andric void AssignmentTrackingLowering::processNonDbgInstruction(
1599bdd1243dSDimitry Andric     Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) {
1600bdd1243dSDimitry Andric   if (I.hasMetadata(LLVMContext::MD_DIAssignID))
1601bdd1243dSDimitry Andric     processTaggedInstruction(I, LiveSet);
1602bdd1243dSDimitry Andric   else
1603bdd1243dSDimitry Andric     processUntaggedInstruction(I, LiveSet);
1604bdd1243dSDimitry Andric }
1605bdd1243dSDimitry Andric 
1606bdd1243dSDimitry Andric void AssignmentTrackingLowering::processUntaggedInstruction(
1607bdd1243dSDimitry Andric     Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) {
1608bdd1243dSDimitry Andric   // Interpret stack stores that are not tagged as an assignment in memory for
1609bdd1243dSDimitry Andric   // the variables associated with that address. These stores may not be tagged
1610bdd1243dSDimitry Andric   // because a) the store cannot be represented using dbg.assigns (non-const
1611bdd1243dSDimitry Andric   // length or offset) or b) the tag was accidentally dropped during
1612bdd1243dSDimitry Andric   // optimisations. For these stores we fall back to assuming that the stack
1613bdd1243dSDimitry Andric   // home is a valid location for the variables. The benefit is that this
1614bdd1243dSDimitry Andric   // prevents us missing an assignment and therefore incorrectly maintaining
1615bdd1243dSDimitry Andric   // earlier location definitions, and in many cases it should be a reasonable
1616bdd1243dSDimitry Andric   // assumption. However, this will occasionally lead to slight
1617bdd1243dSDimitry Andric   // inaccuracies. The value of a hoisted untagged store will be visible
1618bdd1243dSDimitry Andric   // "early", for example.
1619bdd1243dSDimitry Andric   assert(!I.hasMetadata(LLVMContext::MD_DIAssignID));
1620bdd1243dSDimitry Andric   auto It = UntaggedStoreVars.find(&I);
1621bdd1243dSDimitry Andric   if (It == UntaggedStoreVars.end())
1622bdd1243dSDimitry Andric     return; // No variables associated with the store destination.
1623bdd1243dSDimitry Andric 
1624bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "processUntaggedInstruction on UNTAGGED INST " << I
1625bdd1243dSDimitry Andric                     << "\n");
1626bdd1243dSDimitry Andric   // Iterate over the variables that this store affects, add a NoneOrPhi dbg
1627bdd1243dSDimitry Andric   // and mem def, set lockind to Mem, and emit a location def for each.
1628bdd1243dSDimitry Andric   for (auto [Var, Info] : It->second) {
1629bdd1243dSDimitry Andric     // This instruction is treated as both a debug and memory assignment,
1630bdd1243dSDimitry Andric     // meaning the memory location should be used. We don't have an assignment
1631bdd1243dSDimitry Andric     // ID though so use Assignment::makeNoneOrPhi() to create an imaginary one.
1632bdd1243dSDimitry Andric     addMemDef(LiveSet, Var, Assignment::makeNoneOrPhi());
1633bdd1243dSDimitry Andric     addDbgDef(LiveSet, Var, Assignment::makeNoneOrPhi());
1634bdd1243dSDimitry Andric     setLocKind(LiveSet, Var, LocKind::Mem);
1635bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "  setting Stack LocKind to: " << locStr(LocKind::Mem)
1636bdd1243dSDimitry Andric                       << "\n");
1637bdd1243dSDimitry Andric     // Build the dbg location def to insert.
1638bdd1243dSDimitry Andric     //
1639bdd1243dSDimitry Andric     // DIExpression: Add fragment and offset.
1640bdd1243dSDimitry Andric     DebugVariable V = FnVarLocs->getVariable(Var);
1641bdd1243dSDimitry Andric     DIExpression *DIE = DIExpression::get(I.getContext(), std::nullopt);
1642bdd1243dSDimitry Andric     if (auto Frag = V.getFragment()) {
1643bdd1243dSDimitry Andric       auto R = DIExpression::createFragmentExpression(DIE, Frag->OffsetInBits,
1644bdd1243dSDimitry Andric                                                       Frag->SizeInBits);
1645bdd1243dSDimitry Andric       assert(R && "unexpected createFragmentExpression failure");
1646bdd1243dSDimitry Andric       DIE = *R;
1647bdd1243dSDimitry Andric     }
1648bdd1243dSDimitry Andric     SmallVector<uint64_t, 3> Ops;
1649bdd1243dSDimitry Andric     if (Info.OffsetInBits)
1650bdd1243dSDimitry Andric       Ops = {dwarf::DW_OP_plus_uconst, Info.OffsetInBits / 8};
1651bdd1243dSDimitry Andric     Ops.push_back(dwarf::DW_OP_deref);
1652bdd1243dSDimitry Andric     DIE = DIExpression::prependOpcodes(DIE, Ops, /*StackValue=*/false,
1653bdd1243dSDimitry Andric                                        /*EntryValue=*/false);
1654*0fca6ea1SDimitry Andric     // Find a suitable insert point, before the next instruction or DbgRecord
16557a6dacacSDimitry Andric     // after I.
16567a6dacacSDimitry Andric     auto InsertBefore = getNextNode(&I);
1657bdd1243dSDimitry Andric     assert(InsertBefore && "Shouldn't be inserting after a terminator");
1658bdd1243dSDimitry Andric 
1659bdd1243dSDimitry Andric     // Get DILocation for this unrecorded assignment.
1660bdd1243dSDimitry Andric     DILocation *InlinedAt = const_cast<DILocation *>(V.getInlinedAt());
1661bdd1243dSDimitry Andric     const DILocation *DILoc = DILocation::get(
1662bdd1243dSDimitry Andric         Fn.getContext(), 0, 0, V.getVariable()->getScope(), InlinedAt);
1663bdd1243dSDimitry Andric 
1664bdd1243dSDimitry Andric     VarLocInfo VarLoc;
1665bdd1243dSDimitry Andric     VarLoc.VariableID = static_cast<VariableID>(Var);
1666bdd1243dSDimitry Andric     VarLoc.Expr = DIE;
166706c3fb27SDimitry Andric     VarLoc.Values = RawLocationWrapper(
166806c3fb27SDimitry Andric         ValueAsMetadata::get(const_cast<AllocaInst *>(Info.Base)));
1669bdd1243dSDimitry Andric     VarLoc.DL = DILoc;
1670bdd1243dSDimitry Andric     // 3. Insert it into the map for later.
1671bdd1243dSDimitry Andric     InsertBeforeMap[InsertBefore].push_back(VarLoc);
1672bdd1243dSDimitry Andric   }
1673bdd1243dSDimitry Andric }
1674bdd1243dSDimitry Andric 
1675bdd1243dSDimitry Andric void AssignmentTrackingLowering::processTaggedInstruction(
1676bdd1243dSDimitry Andric     Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) {
1677bdd1243dSDimitry Andric   auto Linked = at::getAssignmentMarkers(&I);
1678*0fca6ea1SDimitry Andric   auto LinkedDPAssigns = at::getDVRAssignmentMarkers(&I);
1679bdd1243dSDimitry Andric   // No dbg.assign intrinsics linked.
1680bdd1243dSDimitry Andric   // FIXME: All vars that have a stack slot this store modifies that don't have
1681bdd1243dSDimitry Andric   // a dbg.assign linked to it should probably treat this like an untagged
1682bdd1243dSDimitry Andric   // store.
16837a6dacacSDimitry Andric   if (Linked.empty() && LinkedDPAssigns.empty())
1684bdd1243dSDimitry Andric     return;
1685bdd1243dSDimitry Andric 
1686bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "processTaggedInstruction on " << I << "\n");
16877a6dacacSDimitry Andric   auto ProcessLinkedAssign = [&](auto *Assign) {
16887a6dacacSDimitry Andric     VariableID Var = getVariableID(DebugVariable(Assign));
1689bdd1243dSDimitry Andric     // Something has gone wrong if VarsWithStackSlot doesn't contain a variable
1690bdd1243dSDimitry Andric     // that is linked to a store.
16917a6dacacSDimitry Andric     assert(VarsWithStackSlot->count(getAggregate(Assign)) &&
16927a6dacacSDimitry Andric            "expected Assign's variable to have stack slot");
1693bdd1243dSDimitry Andric 
1694bdd1243dSDimitry Andric     Assignment AV = Assignment::makeFromMemDef(getIDFromInst(I));
1695bdd1243dSDimitry Andric     addMemDef(LiveSet, Var, AV);
1696bdd1243dSDimitry Andric 
16977a6dacacSDimitry Andric     LLVM_DEBUG(dbgs() << "   linked to " << *Assign << "\n");
1698bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "   LiveLoc " << locStr(getLocKind(LiveSet, Var))
1699bdd1243dSDimitry Andric                       << " -> ");
1700bdd1243dSDimitry Andric 
1701bdd1243dSDimitry Andric     // The last assignment to the stack is now AV. Check if the last debug
1702bdd1243dSDimitry Andric     // assignment has a matching Assignment.
170306c3fb27SDimitry Andric     if (hasVarWithAssignment(LiveSet, BlockInfo::Debug, Var, AV)) {
1704bdd1243dSDimitry Andric       // The StackHomeValue and DebugValue for this variable match so we can
1705bdd1243dSDimitry Andric       // emit a stack home location here.
1706bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "Mem, Stack matches Debug program\n";);
1707bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "   Stack val: "; AV.dump(dbgs()); dbgs() << "\n");
1708bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "   Debug val: ";
170906c3fb27SDimitry Andric                  LiveSet->DebugValue[static_cast<unsigned>(Var)].dump(dbgs());
171006c3fb27SDimitry Andric                  dbgs() << "\n");
1711bdd1243dSDimitry Andric       setLocKind(LiveSet, Var, LocKind::Mem);
17127a6dacacSDimitry Andric       emitDbgValue(LocKind::Mem, Assign, &I);
17137a6dacacSDimitry Andric       return;
1714bdd1243dSDimitry Andric     }
1715bdd1243dSDimitry Andric 
1716bdd1243dSDimitry Andric     // The StackHomeValue and DebugValue for this variable do not match. I.e.
1717bdd1243dSDimitry Andric     // The value currently stored in the stack is not what we'd expect to
1718bdd1243dSDimitry Andric     // see, so we cannot use emit a stack home location here. Now we will
1719bdd1243dSDimitry Andric     // look at the live LocKind for the variable and determine an appropriate
1720bdd1243dSDimitry Andric     // dbg.value to emit.
1721bdd1243dSDimitry Andric     LocKind PrevLoc = getLocKind(LiveSet, Var);
1722bdd1243dSDimitry Andric     switch (PrevLoc) {
1723bdd1243dSDimitry Andric     case LocKind::Val: {
1724bdd1243dSDimitry Andric       // The value in memory in memory has changed but we're not currently
1725bdd1243dSDimitry Andric       // using the memory location. Do nothing.
1726bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "Val, (unchanged)\n";);
1727bdd1243dSDimitry Andric       setLocKind(LiveSet, Var, LocKind::Val);
1728bdd1243dSDimitry Andric     } break;
1729bdd1243dSDimitry Andric     case LocKind::Mem: {
1730bdd1243dSDimitry Andric       // There's been an assignment to memory that we were using as a
1731bdd1243dSDimitry Andric       // location for this variable, and the Assignment doesn't match what
1732bdd1243dSDimitry Andric       // we'd expect to see in memory.
173306c3fb27SDimitry Andric       Assignment DbgAV = LiveSet->getAssignment(BlockInfo::Debug, Var);
173406c3fb27SDimitry Andric       if (DbgAV.Status == Assignment::NoneOrPhi) {
1735bdd1243dSDimitry Andric         // We need to terminate any previously open location now.
1736bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "None, No Debug value available\n";);
1737bdd1243dSDimitry Andric         setLocKind(LiveSet, Var, LocKind::None);
17387a6dacacSDimitry Andric         emitDbgValue(LocKind::None, Assign, &I);
1739bdd1243dSDimitry Andric       } else {
1740bdd1243dSDimitry Andric         // The previous DebugValue Value can be used here.
1741bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "Val, Debug value is Known\n";);
1742bdd1243dSDimitry Andric         setLocKind(LiveSet, Var, LocKind::Val);
174306c3fb27SDimitry Andric         if (DbgAV.Source) {
174406c3fb27SDimitry Andric           emitDbgValue(LocKind::Val, DbgAV.Source, &I);
1745bdd1243dSDimitry Andric         } else {
1746bdd1243dSDimitry Andric           // PrevAV.Source is nullptr so we must emit undef here.
17477a6dacacSDimitry Andric           emitDbgValue(LocKind::None, Assign, &I);
1748bdd1243dSDimitry Andric         }
1749bdd1243dSDimitry Andric       }
1750bdd1243dSDimitry Andric     } break;
1751bdd1243dSDimitry Andric     case LocKind::None: {
1752bdd1243dSDimitry Andric       // There's been an assignment to memory and we currently are
1753bdd1243dSDimitry Andric       // not tracking a location for the variable. Do not emit anything.
1754bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "None, (unchanged)\n";);
1755bdd1243dSDimitry Andric       setLocKind(LiveSet, Var, LocKind::None);
1756bdd1243dSDimitry Andric     } break;
1757bdd1243dSDimitry Andric     }
17587a6dacacSDimitry Andric   };
17597a6dacacSDimitry Andric   for (DbgAssignIntrinsic *DAI : Linked)
17607a6dacacSDimitry Andric     ProcessLinkedAssign(DAI);
1761*0fca6ea1SDimitry Andric   for (DbgVariableRecord *DVR : LinkedDPAssigns)
1762*0fca6ea1SDimitry Andric     ProcessLinkedAssign(DVR);
1763bdd1243dSDimitry Andric }
1764bdd1243dSDimitry Andric 
17657a6dacacSDimitry Andric void AssignmentTrackingLowering::processDbgAssign(AssignRecord Assign,
1766bdd1243dSDimitry Andric                                                   BlockInfo *LiveSet) {
17677a6dacacSDimitry Andric   auto ProcessDbgAssignImpl = [&](auto *DbgAssign) {
1768bdd1243dSDimitry Andric     // Only bother tracking variables that are at some point stack homed. Other
1769bdd1243dSDimitry Andric     // variables can be dealt with trivially later.
17707a6dacacSDimitry Andric     if (!VarsWithStackSlot->count(getAggregate(DbgAssign)))
1771bdd1243dSDimitry Andric       return;
1772bdd1243dSDimitry Andric 
17737a6dacacSDimitry Andric     VariableID Var = getVariableID(DebugVariable(DbgAssign));
17747a6dacacSDimitry Andric     Assignment AV = Assignment::make(getIDFromMarker(*DbgAssign), DbgAssign);
1775bdd1243dSDimitry Andric     addDbgDef(LiveSet, Var, AV);
1776bdd1243dSDimitry Andric 
17777a6dacacSDimitry Andric     LLVM_DEBUG(dbgs() << "processDbgAssign on " << *DbgAssign << "\n";);
1778bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "   LiveLoc " << locStr(getLocKind(LiveSet, Var))
1779bdd1243dSDimitry Andric                       << " -> ");
1780bdd1243dSDimitry Andric 
1781bdd1243dSDimitry Andric     // Check if the DebugValue and StackHomeValue both hold the same
1782bdd1243dSDimitry Andric     // Assignment.
178306c3fb27SDimitry Andric     if (hasVarWithAssignment(LiveSet, BlockInfo::Stack, Var, AV)) {
17847a6dacacSDimitry Andric       // They match. We can use the stack home because the debug intrinsics
17857a6dacacSDimitry Andric       // state that an assignment happened here, and we know that specific
17867a6dacacSDimitry Andric       // assignment was the last one to take place in memory for this variable.
1787bdd1243dSDimitry Andric       LocKind Kind;
17887a6dacacSDimitry Andric       if (DbgAssign->isKillAddress()) {
1789bdd1243dSDimitry Andric         LLVM_DEBUG(
1790bdd1243dSDimitry Andric             dbgs()
1791bdd1243dSDimitry Andric                 << "Val, Stack matches Debug program but address is killed\n";);
1792bdd1243dSDimitry Andric         Kind = LocKind::Val;
1793bdd1243dSDimitry Andric       } else {
1794bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << "Mem, Stack matches Debug program\n";);
1795bdd1243dSDimitry Andric         Kind = LocKind::Mem;
1796bdd1243dSDimitry Andric       };
1797bdd1243dSDimitry Andric       setLocKind(LiveSet, Var, Kind);
17987a6dacacSDimitry Andric       emitDbgValue(Kind, DbgAssign, DbgAssign);
1799bdd1243dSDimitry Andric     } else {
18007a6dacacSDimitry Andric       // The last assignment to the memory location isn't the one that we want
18017a6dacacSDimitry Andric       // to show to the user so emit a dbg.value(Value). Value may be undef.
1802bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "Val, Stack contents is unknown\n";);
1803bdd1243dSDimitry Andric       setLocKind(LiveSet, Var, LocKind::Val);
18047a6dacacSDimitry Andric       emitDbgValue(LocKind::Val, DbgAssign, DbgAssign);
1805bdd1243dSDimitry Andric     }
18067a6dacacSDimitry Andric   };
1807*0fca6ea1SDimitry Andric   if (isa<DbgVariableRecord *>(Assign))
1808*0fca6ea1SDimitry Andric     return ProcessDbgAssignImpl(cast<DbgVariableRecord *>(Assign));
18097a6dacacSDimitry Andric   return ProcessDbgAssignImpl(cast<DbgAssignIntrinsic *>(Assign));
1810bdd1243dSDimitry Andric }
1811bdd1243dSDimitry Andric 
18127a6dacacSDimitry Andric void AssignmentTrackingLowering::processDbgValue(
1813*0fca6ea1SDimitry Andric     PointerUnion<DbgValueInst *, DbgVariableRecord *> DbgValueRecord,
1814bdd1243dSDimitry Andric     BlockInfo *LiveSet) {
18157a6dacacSDimitry Andric   auto ProcessDbgValueImpl = [&](auto *DbgValue) {
1816bdd1243dSDimitry Andric     // Only other tracking variables that are at some point stack homed.
1817bdd1243dSDimitry Andric     // Other variables can be dealt with trivally later.
18187a6dacacSDimitry Andric     if (!VarsWithStackSlot->count(getAggregate(DbgValue)))
1819bdd1243dSDimitry Andric       return;
1820bdd1243dSDimitry Andric 
18217a6dacacSDimitry Andric     VariableID Var = getVariableID(DebugVariable(DbgValue));
1822bdd1243dSDimitry Andric     // We have no ID to create an Assignment with so we mark this assignment as
1823bdd1243dSDimitry Andric     // NoneOrPhi. Note that the dbg.value still exists, we just cannot determine
1824bdd1243dSDimitry Andric     // the assignment responsible for setting this value.
1825bdd1243dSDimitry Andric     // This is fine; dbg.values are essentially interchangable with unlinked
1826bdd1243dSDimitry Andric     // dbg.assigns, and some passes such as mem2reg and instcombine add them to
1827bdd1243dSDimitry Andric     // PHIs for promoted variables.
1828bdd1243dSDimitry Andric     Assignment AV = Assignment::makeNoneOrPhi();
1829bdd1243dSDimitry Andric     addDbgDef(LiveSet, Var, AV);
1830bdd1243dSDimitry Andric 
18317a6dacacSDimitry Andric     LLVM_DEBUG(dbgs() << "processDbgValue on " << *DbgValue << "\n";);
1832bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "   LiveLoc " << locStr(getLocKind(LiveSet, Var))
1833bdd1243dSDimitry Andric                       << " -> Val, dbg.value override");
1834bdd1243dSDimitry Andric 
1835bdd1243dSDimitry Andric     setLocKind(LiveSet, Var, LocKind::Val);
18367a6dacacSDimitry Andric     emitDbgValue(LocKind::Val, DbgValue, DbgValue);
18377a6dacacSDimitry Andric   };
1838*0fca6ea1SDimitry Andric   if (isa<DbgVariableRecord *>(DbgValueRecord))
1839*0fca6ea1SDimitry Andric     return ProcessDbgValueImpl(cast<DbgVariableRecord *>(DbgValueRecord));
18407a6dacacSDimitry Andric   return ProcessDbgValueImpl(cast<DbgValueInst *>(DbgValueRecord));
1841bdd1243dSDimitry Andric }
1842bdd1243dSDimitry Andric 
18437a6dacacSDimitry Andric template <typename T> static bool hasZeroSizedFragment(T &DbgValue) {
18447a6dacacSDimitry Andric   if (auto F = DbgValue.getExpression()->getFragmentInfo())
184506c3fb27SDimitry Andric     return F->SizeInBits == 0;
184606c3fb27SDimitry Andric   return false;
184706c3fb27SDimitry Andric }
184806c3fb27SDimitry Andric 
1849bdd1243dSDimitry Andric void AssignmentTrackingLowering::processDbgInstruction(
185006c3fb27SDimitry Andric     DbgInfoIntrinsic &I, AssignmentTrackingLowering::BlockInfo *LiveSet) {
185106c3fb27SDimitry Andric   auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I);
185206c3fb27SDimitry Andric   if (!DVI)
185306c3fb27SDimitry Andric     return;
185406c3fb27SDimitry Andric 
185506c3fb27SDimitry Andric   // Ignore assignments to zero bits of the variable.
185606c3fb27SDimitry Andric   if (hasZeroSizedFragment(*DVI))
185706c3fb27SDimitry Andric     return;
185806c3fb27SDimitry Andric 
1859bdd1243dSDimitry Andric   if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I))
18607a6dacacSDimitry Andric     processDbgAssign(DAI, LiveSet);
1861bdd1243dSDimitry Andric   else if (auto *DVI = dyn_cast<DbgValueInst>(&I))
18627a6dacacSDimitry Andric     processDbgValue(DVI, LiveSet);
18637a6dacacSDimitry Andric }
1864*0fca6ea1SDimitry Andric void AssignmentTrackingLowering::processDbgVariableRecord(
1865*0fca6ea1SDimitry Andric     DbgVariableRecord &DVR, AssignmentTrackingLowering::BlockInfo *LiveSet) {
18667a6dacacSDimitry Andric   // Ignore assignments to zero bits of the variable.
1867*0fca6ea1SDimitry Andric   if (hasZeroSizedFragment(DVR))
18687a6dacacSDimitry Andric     return;
18697a6dacacSDimitry Andric 
1870*0fca6ea1SDimitry Andric   if (DVR.isDbgAssign())
1871*0fca6ea1SDimitry Andric     processDbgAssign(&DVR, LiveSet);
1872*0fca6ea1SDimitry Andric   else if (DVR.isDbgValue())
1873*0fca6ea1SDimitry Andric     processDbgValue(&DVR, LiveSet);
1874bdd1243dSDimitry Andric }
1875bdd1243dSDimitry Andric 
1876bdd1243dSDimitry Andric void AssignmentTrackingLowering::resetInsertionPoint(Instruction &After) {
1877bdd1243dSDimitry Andric   assert(!After.isTerminator() && "Can't insert after a terminator");
18787a6dacacSDimitry Andric   auto *R = InsertBeforeMap.find(getNextNode(&After));
18797a6dacacSDimitry Andric   if (R == InsertBeforeMap.end())
18807a6dacacSDimitry Andric     return;
18817a6dacacSDimitry Andric   R->second.clear();
18827a6dacacSDimitry Andric }
1883*0fca6ea1SDimitry Andric void AssignmentTrackingLowering::resetInsertionPoint(DbgVariableRecord &After) {
18847a6dacacSDimitry Andric   auto *R = InsertBeforeMap.find(getNextNode(&After));
1885bdd1243dSDimitry Andric   if (R == InsertBeforeMap.end())
1886bdd1243dSDimitry Andric     return;
1887bdd1243dSDimitry Andric   R->second.clear();
1888bdd1243dSDimitry Andric }
1889bdd1243dSDimitry Andric 
1890bdd1243dSDimitry Andric void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) {
1891*0fca6ea1SDimitry Andric   // If the block starts with DbgRecords, we need to process those DbgRecords as
18927a6dacacSDimitry Andric   // their own frame without processing any instructions first.
1893*0fca6ea1SDimitry Andric   bool ProcessedLeadingDbgRecords = !BB.begin()->hasDbgRecords();
1894bdd1243dSDimitry Andric   for (auto II = BB.begin(), EI = BB.end(); II != EI;) {
1895bdd1243dSDimitry Andric     assert(VarsTouchedThisFrame.empty());
1896bdd1243dSDimitry Andric     // Process the instructions in "frames". A "frame" includes a single
1897bdd1243dSDimitry Andric     // non-debug instruction followed any debug instructions before the
1898bdd1243dSDimitry Andric     // next non-debug instruction.
18997a6dacacSDimitry Andric 
1900*0fca6ea1SDimitry Andric     // Skip the current instruction if it has unprocessed DbgRecords attached
1901*0fca6ea1SDimitry Andric     // (see comment above `ProcessedLeadingDbgRecords`).
1902*0fca6ea1SDimitry Andric     if (ProcessedLeadingDbgRecords) {
19037a6dacacSDimitry Andric       // II is now either a debug intrinsic, a non-debug instruction with no
1904*0fca6ea1SDimitry Andric       // attached DbgRecords, or a non-debug instruction with attached processed
1905*0fca6ea1SDimitry Andric       // DbgRecords.
19067a6dacacSDimitry Andric       // II has not been processed.
1907bdd1243dSDimitry Andric       if (!isa<DbgInfoIntrinsic>(&*II)) {
1908bdd1243dSDimitry Andric         if (II->isTerminator())
1909bdd1243dSDimitry Andric           break;
1910bdd1243dSDimitry Andric         resetInsertionPoint(*II);
1911bdd1243dSDimitry Andric         processNonDbgInstruction(*II, LiveSet);
1912bdd1243dSDimitry Andric         assert(LiveSet->isValid());
1913bdd1243dSDimitry Andric         ++II;
1914bdd1243dSDimitry Andric       }
19157a6dacacSDimitry Andric     }
19167a6dacacSDimitry Andric     // II is now either a debug intrinsic, a non-debug instruction with no
1917*0fca6ea1SDimitry Andric     // attached DbgRecords, or a non-debug instruction with attached unprocessed
1918*0fca6ea1SDimitry Andric     // DbgRecords.
1919*0fca6ea1SDimitry Andric     if (II != EI && II->hasDbgRecords()) {
1920*0fca6ea1SDimitry Andric       // Skip over non-variable debug records (i.e., labels). They're going to
1921*0fca6ea1SDimitry Andric       // be read from IR (possibly re-ordering them within the debug record
1922*0fca6ea1SDimitry Andric       // range) rather than from the analysis results.
1923*0fca6ea1SDimitry Andric       for (DbgVariableRecord &DVR : filterDbgVars(II->getDbgRecordRange())) {
1924*0fca6ea1SDimitry Andric         resetInsertionPoint(DVR);
1925*0fca6ea1SDimitry Andric         processDbgVariableRecord(DVR, LiveSet);
19267a6dacacSDimitry Andric         assert(LiveSet->isValid());
19277a6dacacSDimitry Andric       }
19287a6dacacSDimitry Andric     }
1929*0fca6ea1SDimitry Andric     ProcessedLeadingDbgRecords = true;
1930bdd1243dSDimitry Andric     while (II != EI) {
193106c3fb27SDimitry Andric       auto *Dbg = dyn_cast<DbgInfoIntrinsic>(&*II);
193206c3fb27SDimitry Andric       if (!Dbg)
1933bdd1243dSDimitry Andric         break;
1934bdd1243dSDimitry Andric       resetInsertionPoint(*II);
193506c3fb27SDimitry Andric       processDbgInstruction(*Dbg, LiveSet);
1936bdd1243dSDimitry Andric       assert(LiveSet->isValid());
1937bdd1243dSDimitry Andric       ++II;
1938bdd1243dSDimitry Andric     }
1939*0fca6ea1SDimitry Andric     // II is now a non-debug instruction either with no attached DbgRecords, or
1940*0fca6ea1SDimitry Andric     // with attached processed DbgRecords. II has not been processed, and all
1941*0fca6ea1SDimitry Andric     // debug instructions or DbgRecords in the frame preceding II have been
19427a6dacacSDimitry Andric     // processed.
1943bdd1243dSDimitry Andric 
1944bdd1243dSDimitry Andric     // We've processed everything in the "frame". Now determine which variables
1945bdd1243dSDimitry Andric     // cannot be represented by a dbg.declare.
1946bdd1243dSDimitry Andric     for (auto Var : VarsTouchedThisFrame) {
1947bdd1243dSDimitry Andric       LocKind Loc = getLocKind(LiveSet, Var);
1948bdd1243dSDimitry Andric       // If a variable's LocKind is anything other than LocKind::Mem then we
1949bdd1243dSDimitry Andric       // must note that it cannot be represented with a dbg.declare.
1950bdd1243dSDimitry Andric       // Note that this check is enough without having to check the result of
1951bdd1243dSDimitry Andric       // joins() because for join to produce anything other than Mem after
1952bdd1243dSDimitry Andric       // we've already seen a Mem we'd be joining None or Val with Mem. In that
1953bdd1243dSDimitry Andric       // case, we've already hit this codepath when we set the LocKind to Val
1954bdd1243dSDimitry Andric       // or None in that block.
1955bdd1243dSDimitry Andric       if (Loc != LocKind::Mem) {
1956bdd1243dSDimitry Andric         DebugVariable DbgVar = FnVarLocs->getVariable(Var);
1957bdd1243dSDimitry Andric         DebugAggregate Aggr{DbgVar.getVariable(), DbgVar.getInlinedAt()};
1958bdd1243dSDimitry Andric         NotAlwaysStackHomed.insert(Aggr);
1959bdd1243dSDimitry Andric       }
1960bdd1243dSDimitry Andric     }
1961bdd1243dSDimitry Andric     VarsTouchedThisFrame.clear();
1962bdd1243dSDimitry Andric   }
1963bdd1243dSDimitry Andric }
1964bdd1243dSDimitry Andric 
1965bdd1243dSDimitry Andric AssignmentTrackingLowering::LocKind
1966bdd1243dSDimitry Andric AssignmentTrackingLowering::joinKind(LocKind A, LocKind B) {
1967bdd1243dSDimitry Andric   // Partial order:
1968bdd1243dSDimitry Andric   // None > Mem, Val
1969bdd1243dSDimitry Andric   return A == B ? A : LocKind::None;
1970bdd1243dSDimitry Andric }
1971bdd1243dSDimitry Andric 
1972bdd1243dSDimitry Andric AssignmentTrackingLowering::Assignment
1973bdd1243dSDimitry Andric AssignmentTrackingLowering::joinAssignment(const Assignment &A,
1974bdd1243dSDimitry Andric                                            const Assignment &B) {
1975bdd1243dSDimitry Andric   // Partial order:
1976bdd1243dSDimitry Andric   // NoneOrPhi(null, null) > Known(v, ?s)
1977bdd1243dSDimitry Andric 
1978bdd1243dSDimitry Andric   // If either are NoneOrPhi the join is NoneOrPhi.
1979bdd1243dSDimitry Andric   // If either value is different then the result is
1980bdd1243dSDimitry Andric   // NoneOrPhi (joining two values is a Phi).
1981bdd1243dSDimitry Andric   if (!A.isSameSourceAssignment(B))
1982bdd1243dSDimitry Andric     return Assignment::makeNoneOrPhi();
1983bdd1243dSDimitry Andric   if (A.Status == Assignment::NoneOrPhi)
1984bdd1243dSDimitry Andric     return Assignment::makeNoneOrPhi();
1985bdd1243dSDimitry Andric 
1986bdd1243dSDimitry Andric   // Source is used to lookup the value + expression in the debug program if
1987bdd1243dSDimitry Andric   // the stack slot gets assigned a value earlier than expected. Because
1988bdd1243dSDimitry Andric   // we're only tracking the one dbg.assign, we can't capture debug PHIs.
1989bdd1243dSDimitry Andric   // It's unlikely that we're losing out on much coverage by avoiding that
1990bdd1243dSDimitry Andric   // extra work.
1991bdd1243dSDimitry Andric   // The Source may differ in this situation:
1992bdd1243dSDimitry Andric   // Pred.1:
1993bdd1243dSDimitry Andric   //   dbg.assign i32 0, ..., !1, ...
1994bdd1243dSDimitry Andric   // Pred.2:
1995bdd1243dSDimitry Andric   //   dbg.assign i32 1, ..., !1, ...
1996bdd1243dSDimitry Andric   // Here the same assignment (!1) was performed in both preds in the source,
1997bdd1243dSDimitry Andric   // but we can't use either one unless they are identical (e.g. .we don't
1998bdd1243dSDimitry Andric   // want to arbitrarily pick between constant values).
19997a6dacacSDimitry Andric   auto JoinSource = [&]() -> AssignRecord {
2000bdd1243dSDimitry Andric     if (A.Source == B.Source)
2001bdd1243dSDimitry Andric       return A.Source;
20027a6dacacSDimitry Andric     if (!A.Source || !B.Source)
20037a6dacacSDimitry Andric       return AssignRecord();
2004*0fca6ea1SDimitry Andric     assert(isa<DbgVariableRecord *>(A.Source) ==
2005*0fca6ea1SDimitry Andric            isa<DbgVariableRecord *>(B.Source));
2006*0fca6ea1SDimitry Andric     if (isa<DbgVariableRecord *>(A.Source) &&
2007*0fca6ea1SDimitry Andric         cast<DbgVariableRecord *>(A.Source)->isEquivalentTo(
2008*0fca6ea1SDimitry Andric             *cast<DbgVariableRecord *>(B.Source)))
2009bdd1243dSDimitry Andric       return A.Source;
20107a6dacacSDimitry Andric     if (isa<DbgAssignIntrinsic *>(A.Source) &&
20117a6dacacSDimitry Andric         cast<DbgAssignIntrinsic *>(A.Source)->isIdenticalTo(
20127a6dacacSDimitry Andric             cast<DbgAssignIntrinsic *>(B.Source)))
20137a6dacacSDimitry Andric       return A.Source;
20147a6dacacSDimitry Andric     return AssignRecord();
2015bdd1243dSDimitry Andric   };
20167a6dacacSDimitry Andric   AssignRecord Source = JoinSource();
2017bdd1243dSDimitry Andric   assert(A.Status == B.Status && A.Status == Assignment::Known);
2018bdd1243dSDimitry Andric   assert(A.ID == B.ID);
2019bdd1243dSDimitry Andric   return Assignment::make(A.ID, Source);
2020bdd1243dSDimitry Andric }
2021bdd1243dSDimitry Andric 
2022bdd1243dSDimitry Andric AssignmentTrackingLowering::BlockInfo
2023bdd1243dSDimitry Andric AssignmentTrackingLowering::joinBlockInfo(const BlockInfo &A,
2024bdd1243dSDimitry Andric                                           const BlockInfo &B) {
202506c3fb27SDimitry Andric   return BlockInfo::join(A, B, TrackedVariablesVectorSize);
2026bdd1243dSDimitry Andric }
2027bdd1243dSDimitry Andric 
2028bdd1243dSDimitry Andric bool AssignmentTrackingLowering::join(
2029bdd1243dSDimitry Andric     const BasicBlock &BB, const SmallPtrSet<BasicBlock *, 16> &Visited) {
203006c3fb27SDimitry Andric 
203106c3fb27SDimitry Andric   SmallVector<const BasicBlock *> VisitedPreds;
2032bdd1243dSDimitry Andric   // Ignore backedges if we have not visited the predecessor yet. As the
2033bdd1243dSDimitry Andric   // predecessor hasn't yet had locations propagated into it, most locations
2034bdd1243dSDimitry Andric   // will not yet be valid, so treat them as all being uninitialized and
2035bdd1243dSDimitry Andric   // potentially valid. If a location guessed to be correct here is
2036bdd1243dSDimitry Andric   // invalidated later, we will remove it when we revisit this block. This
2037bdd1243dSDimitry Andric   // is essentially the same as initialising all LocKinds and Assignments to
2038bdd1243dSDimitry Andric   // an implicit ⊥ value which is the identity value for the join operation.
20397a6dacacSDimitry Andric   for (const BasicBlock *Pred : predecessors(&BB)) {
204006c3fb27SDimitry Andric     if (Visited.count(Pred))
204106c3fb27SDimitry Andric       VisitedPreds.push_back(Pred);
2042bdd1243dSDimitry Andric   }
2043bdd1243dSDimitry Andric 
204406c3fb27SDimitry Andric   // No preds visited yet.
204506c3fb27SDimitry Andric   if (VisitedPreds.empty()) {
204606c3fb27SDimitry Andric     auto It = LiveIn.try_emplace(&BB, BlockInfo());
204706c3fb27SDimitry Andric     bool DidInsert = It.second;
204806c3fb27SDimitry Andric     if (DidInsert)
204906c3fb27SDimitry Andric       It.first->second.init(TrackedVariablesVectorSize);
205006c3fb27SDimitry Andric     return /*Changed*/ DidInsert;
205106c3fb27SDimitry Andric   }
205206c3fb27SDimitry Andric 
205306c3fb27SDimitry Andric   // Exactly one visited pred. Copy the LiveOut from that pred into BB LiveIn.
205406c3fb27SDimitry Andric   if (VisitedPreds.size() == 1) {
205506c3fb27SDimitry Andric     const BlockInfo &PredLiveOut = LiveOut.find(VisitedPreds[0])->second;
205606c3fb27SDimitry Andric     auto CurrentLiveInEntry = LiveIn.find(&BB);
205706c3fb27SDimitry Andric 
205806c3fb27SDimitry Andric     // Check if there isn't an entry, or there is but the LiveIn set has
205906c3fb27SDimitry Andric     // changed (expensive check).
206006c3fb27SDimitry Andric     if (CurrentLiveInEntry == LiveIn.end())
206106c3fb27SDimitry Andric       LiveIn.insert(std::make_pair(&BB, PredLiveOut));
206206c3fb27SDimitry Andric     else if (PredLiveOut != CurrentLiveInEntry->second)
206306c3fb27SDimitry Andric       CurrentLiveInEntry->second = PredLiveOut;
206406c3fb27SDimitry Andric     else
206506c3fb27SDimitry Andric       return /*Changed*/ false;
206606c3fb27SDimitry Andric     return /*Changed*/ true;
206706c3fb27SDimitry Andric   }
206806c3fb27SDimitry Andric 
206906c3fb27SDimitry Andric   // More than one pred. Join LiveOuts of blocks 1 and 2.
207006c3fb27SDimitry Andric   assert(VisitedPreds.size() > 1);
207106c3fb27SDimitry Andric   const BlockInfo &PredLiveOut0 = LiveOut.find(VisitedPreds[0])->second;
207206c3fb27SDimitry Andric   const BlockInfo &PredLiveOut1 = LiveOut.find(VisitedPreds[1])->second;
207306c3fb27SDimitry Andric   BlockInfo BBLiveIn = joinBlockInfo(PredLiveOut0, PredLiveOut1);
207406c3fb27SDimitry Andric 
207506c3fb27SDimitry Andric   // Join the LiveOuts of subsequent blocks.
207606c3fb27SDimitry Andric   ArrayRef Tail = ArrayRef(VisitedPreds).drop_front(2);
207706c3fb27SDimitry Andric   for (const BasicBlock *Pred : Tail) {
207806c3fb27SDimitry Andric     const auto &PredLiveOut = LiveOut.find(Pred);
207906c3fb27SDimitry Andric     assert(PredLiveOut != LiveOut.end() &&
208006c3fb27SDimitry Andric            "block should have been processed already");
208106c3fb27SDimitry Andric     BBLiveIn = joinBlockInfo(std::move(BBLiveIn), PredLiveOut->second);
208206c3fb27SDimitry Andric   }
208306c3fb27SDimitry Andric 
208406c3fb27SDimitry Andric   // Save the joined result for BB.
2085bdd1243dSDimitry Andric   auto CurrentLiveInEntry = LiveIn.find(&BB);
2086bdd1243dSDimitry Andric   // Check if there isn't an entry, or there is but the LiveIn set has changed
2087bdd1243dSDimitry Andric   // (expensive check).
208806c3fb27SDimitry Andric   if (CurrentLiveInEntry == LiveIn.end())
208906c3fb27SDimitry Andric     LiveIn.try_emplace(&BB, std::move(BBLiveIn));
209006c3fb27SDimitry Andric   else if (BBLiveIn != CurrentLiveInEntry->second)
209106c3fb27SDimitry Andric     CurrentLiveInEntry->second = std::move(BBLiveIn);
209206c3fb27SDimitry Andric   else
209306c3fb27SDimitry Andric     return /*Changed*/ false;
209406c3fb27SDimitry Andric   return /*Changed*/ true;
2095bdd1243dSDimitry Andric }
2096bdd1243dSDimitry Andric 
2097bdd1243dSDimitry Andric /// Return true if A fully contains B.
2098bdd1243dSDimitry Andric static bool fullyContains(DIExpression::FragmentInfo A,
2099bdd1243dSDimitry Andric                           DIExpression::FragmentInfo B) {
2100bdd1243dSDimitry Andric   auto ALeft = A.OffsetInBits;
2101bdd1243dSDimitry Andric   auto BLeft = B.OffsetInBits;
2102bdd1243dSDimitry Andric   if (BLeft < ALeft)
2103bdd1243dSDimitry Andric     return false;
2104bdd1243dSDimitry Andric 
2105bdd1243dSDimitry Andric   auto ARight = ALeft + A.SizeInBits;
2106bdd1243dSDimitry Andric   auto BRight = BLeft + B.SizeInBits;
2107bdd1243dSDimitry Andric   if (BRight > ARight)
2108bdd1243dSDimitry Andric     return false;
2109bdd1243dSDimitry Andric   return true;
2110bdd1243dSDimitry Andric }
2111bdd1243dSDimitry Andric 
2112bdd1243dSDimitry Andric static std::optional<at::AssignmentInfo>
2113bdd1243dSDimitry Andric getUntaggedStoreAssignmentInfo(const Instruction &I, const DataLayout &Layout) {
2114bdd1243dSDimitry Andric   // Don't bother checking if this is an AllocaInst. We know this
2115bdd1243dSDimitry Andric   // instruction has no tag which means there are no variables associated
2116bdd1243dSDimitry Andric   // with it.
2117bdd1243dSDimitry Andric   if (const auto *SI = dyn_cast<StoreInst>(&I))
2118bdd1243dSDimitry Andric     return at::getAssignmentInfo(Layout, SI);
2119bdd1243dSDimitry Andric   if (const auto *MI = dyn_cast<MemIntrinsic>(&I))
2120bdd1243dSDimitry Andric     return at::getAssignmentInfo(Layout, MI);
2121bdd1243dSDimitry Andric   // Alloca or non-store-like inst.
2122bdd1243dSDimitry Andric   return std::nullopt;
2123bdd1243dSDimitry Andric }
2124bdd1243dSDimitry Andric 
21257a6dacacSDimitry Andric DbgDeclareInst *DynCastToDbgDeclare(DbgVariableIntrinsic *DVI) {
21267a6dacacSDimitry Andric   return dyn_cast<DbgDeclareInst>(DVI);
21277a6dacacSDimitry Andric }
21287a6dacacSDimitry Andric 
2129*0fca6ea1SDimitry Andric DbgVariableRecord *DynCastToDbgDeclare(DbgVariableRecord *DVR) {
2130*0fca6ea1SDimitry Andric   return DVR->isDbgDeclare() ? DVR : nullptr;
21317a6dacacSDimitry Andric }
21327a6dacacSDimitry Andric 
2133bdd1243dSDimitry Andric /// Build a map of {Variable x: Variables y} where all variable fragments
2134bdd1243dSDimitry Andric /// contained within the variable fragment x are in set y. This means that
2135bdd1243dSDimitry Andric /// y does not contain all overlaps because partial overlaps are excluded.
2136bdd1243dSDimitry Andric ///
2137bdd1243dSDimitry Andric /// While we're iterating over the function, add single location defs for
213806c3fb27SDimitry Andric /// dbg.declares to \p FnVarLocs.
213906c3fb27SDimitry Andric ///
214006c3fb27SDimitry Andric /// Variables that are interesting to this pass in are added to
214106c3fb27SDimitry Andric /// FnVarLocs->Variables first. TrackedVariablesVectorSize is set to the ID of
214206c3fb27SDimitry Andric /// the last interesting variable plus 1, meaning variables with ID 1
214306c3fb27SDimitry Andric /// (inclusive) to TrackedVariablesVectorSize (exclusive) are interesting. The
214406c3fb27SDimitry Andric /// subsequent variables are either stack homed or fully promoted.
2145bdd1243dSDimitry Andric ///
2146bdd1243dSDimitry Andric /// Finally, populate UntaggedStoreVars with a mapping of untagged stores to
2147bdd1243dSDimitry Andric /// the stored-to variable fragments.
2148bdd1243dSDimitry Andric ///
2149bdd1243dSDimitry Andric /// These tasks are bundled together to reduce the number of times we need
2150bdd1243dSDimitry Andric /// to iterate over the function as they can be achieved together in one pass.
2151bdd1243dSDimitry Andric static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares(
2152bdd1243dSDimitry Andric     Function &Fn, FunctionVarLocsBuilder *FnVarLocs,
215306c3fb27SDimitry Andric     const DenseSet<DebugAggregate> &VarsWithStackSlot,
215406c3fb27SDimitry Andric     AssignmentTrackingLowering::UntaggedStoreAssignmentMap &UntaggedStoreVars,
215506c3fb27SDimitry Andric     unsigned &TrackedVariablesVectorSize) {
2156bdd1243dSDimitry Andric   DenseSet<DebugVariable> Seen;
2157bdd1243dSDimitry Andric   // Map of Variable: [Fragments].
2158bdd1243dSDimitry Andric   DenseMap<DebugAggregate, SmallVector<DebugVariable, 8>> FragmentMap;
2159bdd1243dSDimitry Andric   // Iterate over all instructions:
2160bdd1243dSDimitry Andric   // - dbg.declare    -> add single location variable record
2161bdd1243dSDimitry Andric   // - dbg.*          -> Add fragments to FragmentMap
2162bdd1243dSDimitry Andric   // - untagged store -> Add fragments to FragmentMap and update
2163bdd1243dSDimitry Andric   //                     UntaggedStoreVars.
2164bdd1243dSDimitry Andric   // We need to add fragments for untagged stores too so that we can correctly
2165bdd1243dSDimitry Andric   // clobber overlapped fragment locations later.
21667a6dacacSDimitry Andric   SmallVector<DbgDeclareInst *> InstDeclares;
2167*0fca6ea1SDimitry Andric   SmallVector<DbgVariableRecord *> DPDeclares;
21687a6dacacSDimitry Andric   auto ProcessDbgRecord = [&](auto *Record, auto &DeclareList) {
21697a6dacacSDimitry Andric     if (auto *Declare = DynCastToDbgDeclare(Record)) {
21707a6dacacSDimitry Andric       DeclareList.push_back(Declare);
21717a6dacacSDimitry Andric       return;
21727a6dacacSDimitry Andric     }
21737a6dacacSDimitry Andric     DebugVariable DV = DebugVariable(Record);
2174bdd1243dSDimitry Andric     DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()};
217506c3fb27SDimitry Andric     if (!VarsWithStackSlot.contains(DA))
21767a6dacacSDimitry Andric       return;
2177bdd1243dSDimitry Andric     if (Seen.insert(DV).second)
2178bdd1243dSDimitry Andric       FragmentMap[DA].push_back(DV);
21797a6dacacSDimitry Andric   };
21807a6dacacSDimitry Andric   for (auto &BB : Fn) {
21817a6dacacSDimitry Andric     for (auto &I : BB) {
2182*0fca6ea1SDimitry Andric       for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
2183*0fca6ea1SDimitry Andric         ProcessDbgRecord(&DVR, DPDeclares);
21847a6dacacSDimitry Andric       if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) {
21857a6dacacSDimitry Andric         ProcessDbgRecord(DII, InstDeclares);
2186bdd1243dSDimitry Andric       } else if (auto Info = getUntaggedStoreAssignmentInfo(
2187*0fca6ea1SDimitry Andric                      I, Fn.getDataLayout())) {
2188bdd1243dSDimitry Andric         // Find markers linked to this alloca.
21897a6dacacSDimitry Andric         auto HandleDbgAssignForStore = [&](auto *Assign) {
21905f757f3fSDimitry Andric           std::optional<DIExpression::FragmentInfo> FragInfo;
21915f757f3fSDimitry Andric 
21925f757f3fSDimitry Andric           // Skip this assignment if the affected bits are outside of the
21935f757f3fSDimitry Andric           // variable fragment.
21945f757f3fSDimitry Andric           if (!at::calculateFragmentIntersect(
2195*0fca6ea1SDimitry Andric                   I.getDataLayout(), Info->Base,
21967a6dacacSDimitry Andric                   Info->OffsetInBits, Info->SizeInBits, Assign, FragInfo) ||
21975f757f3fSDimitry Andric               (FragInfo && FragInfo->SizeInBits == 0))
21987a6dacacSDimitry Andric             return;
21995f757f3fSDimitry Andric 
22005f757f3fSDimitry Andric           // FragInfo from calculateFragmentIntersect is nullopt if the
22015f757f3fSDimitry Andric           // resultant fragment matches DAI's fragment or entire variable - in
22025f757f3fSDimitry Andric           // which case copy the fragment info from DAI. If FragInfo is still
22035f757f3fSDimitry Andric           // nullopt after the copy it means "no fragment info" instead, which
22045f757f3fSDimitry Andric           // is how it is usually interpreted.
22055f757f3fSDimitry Andric           if (!FragInfo)
22067a6dacacSDimitry Andric             FragInfo = Assign->getExpression()->getFragmentInfo();
2207bdd1243dSDimitry Andric 
22087a6dacacSDimitry Andric           DebugVariable DV =
22097a6dacacSDimitry Andric               DebugVariable(Assign->getVariable(), FragInfo,
22107a6dacacSDimitry Andric                             Assign->getDebugLoc().getInlinedAt());
2211bdd1243dSDimitry Andric           DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()};
221206c3fb27SDimitry Andric           if (!VarsWithStackSlot.contains(DA))
22137a6dacacSDimitry Andric             return;
2214bdd1243dSDimitry Andric 
2215bdd1243dSDimitry Andric           // Cache this info for later.
2216bdd1243dSDimitry Andric           UntaggedStoreVars[&I].push_back(
2217bdd1243dSDimitry Andric               {FnVarLocs->insertVariable(DV), *Info});
2218bdd1243dSDimitry Andric 
2219bdd1243dSDimitry Andric           if (Seen.insert(DV).second)
2220bdd1243dSDimitry Andric             FragmentMap[DA].push_back(DV);
22217a6dacacSDimitry Andric         };
22227a6dacacSDimitry Andric         for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(Info->Base))
22237a6dacacSDimitry Andric           HandleDbgAssignForStore(DAI);
2224*0fca6ea1SDimitry Andric         for (DbgVariableRecord *DVR : at::getDVRAssignmentMarkers(Info->Base))
2225*0fca6ea1SDimitry Andric           HandleDbgAssignForStore(DVR);
2226bdd1243dSDimitry Andric       }
2227bdd1243dSDimitry Andric     }
2228bdd1243dSDimitry Andric   }
2229bdd1243dSDimitry Andric 
223006c3fb27SDimitry Andric   // Sort the fragment map for each DebugAggregate in ascending
223106c3fb27SDimitry Andric   // order of fragment size - there should be no duplicates.
2232bdd1243dSDimitry Andric   for (auto &Pair : FragmentMap) {
2233bdd1243dSDimitry Andric     SmallVector<DebugVariable, 8> &Frags = Pair.second;
223406c3fb27SDimitry Andric     std::sort(Frags.begin(), Frags.end(),
223506c3fb27SDimitry Andric               [](const DebugVariable &Next, const DebugVariable &Elmt) {
2236bdd1243dSDimitry Andric                 return Elmt.getFragmentOrDefault().SizeInBits >
2237bdd1243dSDimitry Andric                        Next.getFragmentOrDefault().SizeInBits;
2238bdd1243dSDimitry Andric               });
223906c3fb27SDimitry Andric     // Check for duplicates.
224006c3fb27SDimitry Andric     assert(std::adjacent_find(Frags.begin(), Frags.end()) == Frags.end());
2241bdd1243dSDimitry Andric   }
2242bdd1243dSDimitry Andric 
2243bdd1243dSDimitry Andric   // Build the map.
2244bdd1243dSDimitry Andric   AssignmentTrackingLowering::OverlapMap Map;
224506c3fb27SDimitry Andric   for (auto &Pair : FragmentMap) {
2246bdd1243dSDimitry Andric     auto &Frags = Pair.second;
2247bdd1243dSDimitry Andric     for (auto It = Frags.begin(), IEnd = Frags.end(); It != IEnd; ++It) {
2248bdd1243dSDimitry Andric       DIExpression::FragmentInfo Frag = It->getFragmentOrDefault();
2249bdd1243dSDimitry Andric       // Find the frags that this is contained within.
2250bdd1243dSDimitry Andric       //
2251bdd1243dSDimitry Andric       // Because Frags is sorted by size and none have the same offset and
2252bdd1243dSDimitry Andric       // size, we know that this frag can only be contained by subsequent
2253bdd1243dSDimitry Andric       // elements.
2254bdd1243dSDimitry Andric       SmallVector<DebugVariable, 8>::iterator OtherIt = It;
2255bdd1243dSDimitry Andric       ++OtherIt;
2256bdd1243dSDimitry Andric       VariableID ThisVar = FnVarLocs->insertVariable(*It);
2257bdd1243dSDimitry Andric       for (; OtherIt != IEnd; ++OtherIt) {
2258bdd1243dSDimitry Andric         DIExpression::FragmentInfo OtherFrag = OtherIt->getFragmentOrDefault();
2259bdd1243dSDimitry Andric         VariableID OtherVar = FnVarLocs->insertVariable(*OtherIt);
2260bdd1243dSDimitry Andric         if (fullyContains(OtherFrag, Frag))
2261bdd1243dSDimitry Andric           Map[OtherVar].push_back(ThisVar);
2262bdd1243dSDimitry Andric       }
2263bdd1243dSDimitry Andric     }
2264bdd1243dSDimitry Andric   }
2265bdd1243dSDimitry Andric 
226606c3fb27SDimitry Andric   // VariableIDs are 1-based so the variable-tracking bitvector needs
226706c3fb27SDimitry Andric   // NumVariables plus 1 bits.
226806c3fb27SDimitry Andric   TrackedVariablesVectorSize = FnVarLocs->getNumVariables() + 1;
226906c3fb27SDimitry Andric 
227006c3fb27SDimitry Andric   // Finally, insert the declares afterwards, so the first IDs are all
227106c3fb27SDimitry Andric   // partially stack homed vars.
22727a6dacacSDimitry Andric   for (auto *DDI : InstDeclares)
227306c3fb27SDimitry Andric     FnVarLocs->addSingleLocVar(DebugVariable(DDI), DDI->getExpression(),
227406c3fb27SDimitry Andric                                DDI->getDebugLoc(), DDI->getWrappedLocation());
2275*0fca6ea1SDimitry Andric   for (auto *DVR : DPDeclares)
2276*0fca6ea1SDimitry Andric     FnVarLocs->addSingleLocVar(DebugVariable(DVR), DVR->getExpression(),
2277*0fca6ea1SDimitry Andric                                DVR->getDebugLoc(),
2278*0fca6ea1SDimitry Andric                                RawLocationWrapper(DVR->getRawLocation()));
2279bdd1243dSDimitry Andric   return Map;
2280bdd1243dSDimitry Andric }
2281bdd1243dSDimitry Andric 
2282bdd1243dSDimitry Andric bool AssignmentTrackingLowering::run(FunctionVarLocsBuilder *FnVarLocsBuilder) {
2283bdd1243dSDimitry Andric   if (Fn.size() > MaxNumBlocks) {
2284bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "[AT] Dropping var locs in: " << Fn.getName()
2285bdd1243dSDimitry Andric                       << ": too many blocks (" << Fn.size() << ")\n");
2286bdd1243dSDimitry Andric     at::deleteAll(&Fn);
2287bdd1243dSDimitry Andric     return false;
2288bdd1243dSDimitry Andric   }
2289bdd1243dSDimitry Andric 
2290bdd1243dSDimitry Andric   FnVarLocs = FnVarLocsBuilder;
2291bdd1243dSDimitry Andric 
2292bdd1243dSDimitry Andric   // The general structure here is inspired by VarLocBasedImpl.cpp
2293bdd1243dSDimitry Andric   // (LiveDebugValues).
2294bdd1243dSDimitry Andric 
2295bdd1243dSDimitry Andric   // Build the variable fragment overlap map.
2296bdd1243dSDimitry Andric   // Note that this pass doesn't handle partial overlaps correctly (FWIW
2297bdd1243dSDimitry Andric   // neither does LiveDebugVariables) because that is difficult to do and
2298bdd1243dSDimitry Andric   // appears to be rare occurance.
229906c3fb27SDimitry Andric   VarContains = buildOverlapMapAndRecordDeclares(
230006c3fb27SDimitry Andric       Fn, FnVarLocs, *VarsWithStackSlot, UntaggedStoreVars,
230106c3fb27SDimitry Andric       TrackedVariablesVectorSize);
2302bdd1243dSDimitry Andric 
2303bdd1243dSDimitry Andric   // Prepare for traversal.
2304bdd1243dSDimitry Andric   ReversePostOrderTraversal<Function *> RPOT(&Fn);
2305bdd1243dSDimitry Andric   std::priority_queue<unsigned int, std::vector<unsigned int>,
2306bdd1243dSDimitry Andric                       std::greater<unsigned int>>
2307bdd1243dSDimitry Andric       Worklist;
2308bdd1243dSDimitry Andric   std::priority_queue<unsigned int, std::vector<unsigned int>,
2309bdd1243dSDimitry Andric                       std::greater<unsigned int>>
2310bdd1243dSDimitry Andric       Pending;
2311bdd1243dSDimitry Andric   DenseMap<unsigned int, BasicBlock *> OrderToBB;
2312bdd1243dSDimitry Andric   DenseMap<BasicBlock *, unsigned int> BBToOrder;
2313bdd1243dSDimitry Andric   { // Init OrderToBB and BBToOrder.
2314bdd1243dSDimitry Andric     unsigned int RPONumber = 0;
2315*0fca6ea1SDimitry Andric     for (BasicBlock *BB : RPOT) {
2316*0fca6ea1SDimitry Andric       OrderToBB[RPONumber] = BB;
2317*0fca6ea1SDimitry Andric       BBToOrder[BB] = RPONumber;
2318bdd1243dSDimitry Andric       Worklist.push(RPONumber);
2319bdd1243dSDimitry Andric       ++RPONumber;
2320bdd1243dSDimitry Andric     }
2321bdd1243dSDimitry Andric     LiveIn.init(RPONumber);
2322bdd1243dSDimitry Andric     LiveOut.init(RPONumber);
2323bdd1243dSDimitry Andric   }
2324bdd1243dSDimitry Andric 
2325bdd1243dSDimitry Andric   // Perform the traversal.
2326bdd1243dSDimitry Andric   //
2327bdd1243dSDimitry Andric   // This is a standard "union of predecessor outs" dataflow problem. To solve
2328bdd1243dSDimitry Andric   // it, we perform join() and process() using the two worklist method until
2329bdd1243dSDimitry Andric   // the LiveIn data for each block becomes unchanging. The "proof" that this
2330bdd1243dSDimitry Andric   // terminates can be put together by looking at the comments around LocKind,
2331bdd1243dSDimitry Andric   // Assignment, and the various join methods, which show that all the elements
2332bdd1243dSDimitry Andric   // involved are made up of join-semilattices; LiveIn(n) can only
2333bdd1243dSDimitry Andric   // monotonically increase in value throughout the dataflow.
2334bdd1243dSDimitry Andric   //
2335bdd1243dSDimitry Andric   SmallPtrSet<BasicBlock *, 16> Visited;
2336bdd1243dSDimitry Andric   while (!Worklist.empty()) {
2337bdd1243dSDimitry Andric     // We track what is on the pending worklist to avoid inserting the same
2338bdd1243dSDimitry Andric     // thing twice.
2339bdd1243dSDimitry Andric     SmallPtrSet<BasicBlock *, 16> OnPending;
2340bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "Processing Worklist\n");
2341bdd1243dSDimitry Andric     while (!Worklist.empty()) {
2342bdd1243dSDimitry Andric       BasicBlock *BB = OrderToBB[Worklist.top()];
2343bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "\nPop BB " << BB->getName() << "\n");
2344bdd1243dSDimitry Andric       Worklist.pop();
2345bdd1243dSDimitry Andric       bool InChanged = join(*BB, Visited);
2346bdd1243dSDimitry Andric       // Always consider LiveIn changed on the first visit.
2347bdd1243dSDimitry Andric       InChanged |= Visited.insert(BB).second;
2348bdd1243dSDimitry Andric       if (InChanged) {
2349bdd1243dSDimitry Andric         LLVM_DEBUG(dbgs() << BB->getName() << " has new InLocs, process it\n");
2350bdd1243dSDimitry Andric         // Mutate a copy of LiveIn while processing BB. After calling process
2351bdd1243dSDimitry Andric         // LiveSet is the LiveOut set for BB.
2352bdd1243dSDimitry Andric         BlockInfo LiveSet = LiveIn[BB];
2353bdd1243dSDimitry Andric 
2354bdd1243dSDimitry Andric         // Process the instructions in the block.
2355bdd1243dSDimitry Andric         process(*BB, &LiveSet);
2356bdd1243dSDimitry Andric 
2357bdd1243dSDimitry Andric         // Relatively expensive check: has anything changed in LiveOut for BB?
2358bdd1243dSDimitry Andric         if (LiveOut[BB] != LiveSet) {
2359bdd1243dSDimitry Andric           LLVM_DEBUG(dbgs() << BB->getName()
2360bdd1243dSDimitry Andric                             << " has new OutLocs, add succs to worklist: [ ");
2361bdd1243dSDimitry Andric           LiveOut[BB] = std::move(LiveSet);
2362*0fca6ea1SDimitry Andric           for (BasicBlock *Succ : successors(BB)) {
2363*0fca6ea1SDimitry Andric             if (OnPending.insert(Succ).second) {
2364*0fca6ea1SDimitry Andric               LLVM_DEBUG(dbgs() << Succ->getName() << " ");
2365*0fca6ea1SDimitry Andric               Pending.push(BBToOrder[Succ]);
2366bdd1243dSDimitry Andric             }
2367bdd1243dSDimitry Andric           }
2368bdd1243dSDimitry Andric           LLVM_DEBUG(dbgs() << "]\n");
2369bdd1243dSDimitry Andric         }
2370bdd1243dSDimitry Andric       }
2371bdd1243dSDimitry Andric     }
2372bdd1243dSDimitry Andric     Worklist.swap(Pending);
2373bdd1243dSDimitry Andric     // At this point, pending must be empty, since it was just the empty
2374bdd1243dSDimitry Andric     // worklist
2375bdd1243dSDimitry Andric     assert(Pending.empty() && "Pending should be empty");
2376bdd1243dSDimitry Andric   }
2377bdd1243dSDimitry Andric 
2378bdd1243dSDimitry Andric   // That's the hard part over. Now we just have some admin to do.
2379bdd1243dSDimitry Andric 
2380bdd1243dSDimitry Andric   // Record whether we inserted any intrinsics.
2381bdd1243dSDimitry Andric   bool InsertedAnyIntrinsics = false;
2382bdd1243dSDimitry Andric 
2383bdd1243dSDimitry Andric   // Identify and add defs for single location variables.
2384bdd1243dSDimitry Andric   //
2385bdd1243dSDimitry Andric   // Go through all of the defs that we plan to add. If the aggregate variable
2386bdd1243dSDimitry Andric   // it's a part of is not in the NotAlwaysStackHomed set we can emit a single
2387bdd1243dSDimitry Andric   // location def and omit the rest. Add an entry to AlwaysStackHomed so that
2388bdd1243dSDimitry Andric   // we can identify those uneeded defs later.
2389bdd1243dSDimitry Andric   DenseSet<DebugAggregate> AlwaysStackHomed;
2390bdd1243dSDimitry Andric   for (const auto &Pair : InsertBeforeMap) {
23917a6dacacSDimitry Andric     auto &Vec = Pair.second;
2392bdd1243dSDimitry Andric     for (VarLocInfo VarLoc : Vec) {
2393bdd1243dSDimitry Andric       DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID);
2394bdd1243dSDimitry Andric       DebugAggregate Aggr{Var.getVariable(), Var.getInlinedAt()};
2395bdd1243dSDimitry Andric 
2396bdd1243dSDimitry Andric       // Skip this Var if it's not always stack homed.
2397bdd1243dSDimitry Andric       if (NotAlwaysStackHomed.contains(Aggr))
2398bdd1243dSDimitry Andric         continue;
2399bdd1243dSDimitry Andric 
2400bdd1243dSDimitry Andric       // Skip complex cases such as when different fragments of a variable have
2401bdd1243dSDimitry Andric       // been split into different allocas. Skipping in this case means falling
2402bdd1243dSDimitry Andric       // back to using a list of defs (which could reduce coverage, but is no
2403bdd1243dSDimitry Andric       // less correct).
2404bdd1243dSDimitry Andric       bool Simple =
2405bdd1243dSDimitry Andric           VarLoc.Expr->getNumElements() == 1 && VarLoc.Expr->startsWithDeref();
2406bdd1243dSDimitry Andric       if (!Simple) {
2407bdd1243dSDimitry Andric         NotAlwaysStackHomed.insert(Aggr);
2408bdd1243dSDimitry Andric         continue;
2409bdd1243dSDimitry Andric       }
2410bdd1243dSDimitry Andric 
2411bdd1243dSDimitry Andric       // All source assignments to this variable remain and all stores to any
2412bdd1243dSDimitry Andric       // part of the variable store to the same address (with varying
2413bdd1243dSDimitry Andric       // offsets). We can just emit a single location for the whole variable.
2414bdd1243dSDimitry Andric       //
2415bdd1243dSDimitry Andric       // Unless we've already done so, create the single location def now.
2416bdd1243dSDimitry Andric       if (AlwaysStackHomed.insert(Aggr).second) {
241706c3fb27SDimitry Andric         assert(!VarLoc.Values.hasArgList());
2418bdd1243dSDimitry Andric         // TODO: When more complex cases are handled VarLoc.Expr should be
2419bdd1243dSDimitry Andric         // built appropriately rather than always using an empty DIExpression.
2420bdd1243dSDimitry Andric         // The assert below is a reminder.
2421bdd1243dSDimitry Andric         assert(Simple);
2422bdd1243dSDimitry Andric         VarLoc.Expr = DIExpression::get(Fn.getContext(), std::nullopt);
2423bdd1243dSDimitry Andric         DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID);
242406c3fb27SDimitry Andric         FnVarLocs->addSingleLocVar(Var, VarLoc.Expr, VarLoc.DL, VarLoc.Values);
2425bdd1243dSDimitry Andric         InsertedAnyIntrinsics = true;
2426bdd1243dSDimitry Andric       }
2427bdd1243dSDimitry Andric     }
2428bdd1243dSDimitry Andric   }
2429bdd1243dSDimitry Andric 
2430bdd1243dSDimitry Andric   // Insert the other DEFs.
2431bdd1243dSDimitry Andric   for (const auto &[InsertBefore, Vec] : InsertBeforeMap) {
2432bdd1243dSDimitry Andric     SmallVector<VarLocInfo> NewDefs;
2433bdd1243dSDimitry Andric     for (const VarLocInfo &VarLoc : Vec) {
2434bdd1243dSDimitry Andric       DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID);
2435bdd1243dSDimitry Andric       DebugAggregate Aggr{Var.getVariable(), Var.getInlinedAt()};
2436bdd1243dSDimitry Andric       // If this variable is always stack homed then we have already inserted a
2437bdd1243dSDimitry Andric       // dbg.declare and deleted this dbg.value.
2438bdd1243dSDimitry Andric       if (AlwaysStackHomed.contains(Aggr))
2439bdd1243dSDimitry Andric         continue;
2440bdd1243dSDimitry Andric       NewDefs.push_back(VarLoc);
2441bdd1243dSDimitry Andric       InsertedAnyIntrinsics = true;
2442bdd1243dSDimitry Andric     }
2443bdd1243dSDimitry Andric 
2444bdd1243dSDimitry Andric     FnVarLocs->setWedge(InsertBefore, std::move(NewDefs));
2445bdd1243dSDimitry Andric   }
2446bdd1243dSDimitry Andric 
2447bdd1243dSDimitry Andric   InsertedAnyIntrinsics |= emitPromotedVarLocs(FnVarLocs);
2448bdd1243dSDimitry Andric 
2449bdd1243dSDimitry Andric   return InsertedAnyIntrinsics;
2450bdd1243dSDimitry Andric }
2451bdd1243dSDimitry Andric 
2452bdd1243dSDimitry Andric bool AssignmentTrackingLowering::emitPromotedVarLocs(
2453bdd1243dSDimitry Andric     FunctionVarLocsBuilder *FnVarLocs) {
2454bdd1243dSDimitry Andric   bool InsertedAnyIntrinsics = false;
2455bdd1243dSDimitry Andric   // Go through every block, translating debug intrinsics for fully promoted
2456bdd1243dSDimitry Andric   // variables into FnVarLocs location defs. No analysis required for these.
24577a6dacacSDimitry Andric   auto TranslateDbgRecord = [&](auto *Record) {
24587a6dacacSDimitry Andric     // Skip variables that haven't been promoted - we've dealt with those
24597a6dacacSDimitry Andric     // already.
24607a6dacacSDimitry Andric     if (VarsWithStackSlot->contains(getAggregate(Record)))
24617a6dacacSDimitry Andric       return;
24627a6dacacSDimitry Andric     auto InsertBefore = getNextNode(Record);
24637a6dacacSDimitry Andric     assert(InsertBefore && "Unexpected: debug intrinsics after a terminator");
24647a6dacacSDimitry Andric     FnVarLocs->addVarLoc(InsertBefore, DebugVariable(Record),
24657a6dacacSDimitry Andric                          Record->getExpression(), Record->getDebugLoc(),
24667a6dacacSDimitry Andric                          RawLocationWrapper(Record->getRawLocation()));
24677a6dacacSDimitry Andric     InsertedAnyIntrinsics = true;
24687a6dacacSDimitry Andric   };
2469bdd1243dSDimitry Andric   for (auto &BB : Fn) {
2470bdd1243dSDimitry Andric     for (auto &I : BB) {
2471bdd1243dSDimitry Andric       // Skip instructions other than dbg.values and dbg.assigns.
2472*0fca6ea1SDimitry Andric       for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
2473*0fca6ea1SDimitry Andric         if (DVR.isDbgValue() || DVR.isDbgAssign())
2474*0fca6ea1SDimitry Andric           TranslateDbgRecord(&DVR);
2475bdd1243dSDimitry Andric       auto *DVI = dyn_cast<DbgValueInst>(&I);
24767a6dacacSDimitry Andric       if (DVI)
24777a6dacacSDimitry Andric         TranslateDbgRecord(DVI);
2478bdd1243dSDimitry Andric     }
2479bdd1243dSDimitry Andric   }
2480bdd1243dSDimitry Andric   return InsertedAnyIntrinsics;
2481bdd1243dSDimitry Andric }
2482bdd1243dSDimitry Andric 
2483bdd1243dSDimitry Andric /// Remove redundant definitions within sequences of consecutive location defs.
2484bdd1243dSDimitry Andric /// This is done using a backward scan to keep the last def describing a
2485bdd1243dSDimitry Andric /// specific variable/fragment.
2486bdd1243dSDimitry Andric ///
2487bdd1243dSDimitry Andric /// This implements removeRedundantDbgInstrsUsingBackwardScan from
2488bdd1243dSDimitry Andric /// lib/Transforms/Utils/BasicBlockUtils.cpp for locations described with
2489bdd1243dSDimitry Andric /// FunctionVarLocsBuilder instead of with intrinsics.
2490bdd1243dSDimitry Andric static bool
2491bdd1243dSDimitry Andric removeRedundantDbgLocsUsingBackwardScan(const BasicBlock *BB,
2492bdd1243dSDimitry Andric                                         FunctionVarLocsBuilder &FnVarLocs) {
2493bdd1243dSDimitry Andric   bool Changed = false;
24945f757f3fSDimitry Andric   SmallDenseMap<DebugAggregate, BitVector> VariableDefinedBytes;
2495bdd1243dSDimitry Andric   // Scan over the entire block, not just over the instructions mapped by
2496*0fca6ea1SDimitry Andric   // FnVarLocs, because wedges in FnVarLocs may only be separated by debug
2497bdd1243dSDimitry Andric   // instructions.
2498bdd1243dSDimitry Andric   for (const Instruction &I : reverse(*BB)) {
2499bdd1243dSDimitry Andric     if (!isa<DbgVariableIntrinsic>(I)) {
2500bdd1243dSDimitry Andric       // Sequence of consecutive defs ended. Clear map for the next one.
25015f757f3fSDimitry Andric       VariableDefinedBytes.clear();
2502bdd1243dSDimitry Andric     }
2503bdd1243dSDimitry Andric 
25047a6dacacSDimitry Andric     auto HandleLocsForWedge = [&](auto *WedgePosition) {
2505bdd1243dSDimitry Andric       // Get the location defs that start just before this instruction.
25067a6dacacSDimitry Andric       const auto *Locs = FnVarLocs.getWedge(WedgePosition);
2507bdd1243dSDimitry Andric       if (!Locs)
25087a6dacacSDimitry Andric         return;
2509bdd1243dSDimitry Andric 
2510bdd1243dSDimitry Andric       NumWedgesScanned++;
2511bdd1243dSDimitry Andric       bool ChangedThisWedge = false;
2512bdd1243dSDimitry Andric       // The new pruned set of defs, reversed because we're scanning backwards.
2513bdd1243dSDimitry Andric       SmallVector<VarLocInfo> NewDefsReversed;
2514bdd1243dSDimitry Andric 
2515bdd1243dSDimitry Andric       // Iterate over the existing defs in reverse.
2516bdd1243dSDimitry Andric       for (auto RIt = Locs->rbegin(), REnd = Locs->rend(); RIt != REnd; ++RIt) {
2517bdd1243dSDimitry Andric         NumDefsScanned++;
251806c3fb27SDimitry Andric         DebugAggregate Aggr =
251906c3fb27SDimitry Andric             getAggregate(FnVarLocs.getVariable(RIt->VariableID));
252006c3fb27SDimitry Andric         uint64_t SizeInBits = Aggr.first->getSizeInBits().value_or(0);
25215f757f3fSDimitry Andric         uint64_t SizeInBytes = divideCeil(SizeInBits, 8);
2522bdd1243dSDimitry Andric 
25235f757f3fSDimitry Andric         // Cutoff for large variables to prevent expensive bitvector operations.
25245f757f3fSDimitry Andric         const uint64_t MaxSizeBytes = 2048;
25255f757f3fSDimitry Andric 
25265f757f3fSDimitry Andric         if (SizeInBytes == 0 || SizeInBytes > MaxSizeBytes) {
252706c3fb27SDimitry Andric           // If the size is unknown (0) then keep this location def to be safe.
25285f757f3fSDimitry Andric           // Do the same for defs of large variables, which would be expensive
25295f757f3fSDimitry Andric           // to represent with a BitVector.
2530bdd1243dSDimitry Andric           NewDefsReversed.push_back(*RIt);
253106c3fb27SDimitry Andric           continue;
253206c3fb27SDimitry Andric         }
253306c3fb27SDimitry Andric 
253406c3fb27SDimitry Andric         // Only keep this location definition if it is not fully eclipsed by
253506c3fb27SDimitry Andric         // other definitions in this wedge that come after it
253606c3fb27SDimitry Andric 
25375f757f3fSDimitry Andric         // Inert the bytes the location definition defines.
253806c3fb27SDimitry Andric         auto InsertResult =
25395f757f3fSDimitry Andric             VariableDefinedBytes.try_emplace(Aggr, BitVector(SizeInBytes));
254006c3fb27SDimitry Andric         bool FirstDefinition = InsertResult.second;
25415f757f3fSDimitry Andric         BitVector &DefinedBytes = InsertResult.first->second;
254206c3fb27SDimitry Andric 
254306c3fb27SDimitry Andric         DIExpression::FragmentInfo Fragment =
254406c3fb27SDimitry Andric             RIt->Expr->getFragmentInfo().value_or(
254506c3fb27SDimitry Andric                 DIExpression::FragmentInfo(SizeInBits, 0));
254606c3fb27SDimitry Andric         bool InvalidFragment = Fragment.endInBits() > SizeInBits;
25475f757f3fSDimitry Andric         uint64_t StartInBytes = Fragment.startInBits() / 8;
25485f757f3fSDimitry Andric         uint64_t EndInBytes = divideCeil(Fragment.endInBits(), 8);
254906c3fb27SDimitry Andric 
25505f757f3fSDimitry Andric         // If this defines any previously undefined bytes, keep it.
255106c3fb27SDimitry Andric         if (FirstDefinition || InvalidFragment ||
25525f757f3fSDimitry Andric             DefinedBytes.find_first_unset_in(StartInBytes, EndInBytes) != -1) {
255306c3fb27SDimitry Andric           if (!InvalidFragment)
25545f757f3fSDimitry Andric             DefinedBytes.set(StartInBytes, EndInBytes);
255506c3fb27SDimitry Andric           NewDefsReversed.push_back(*RIt);
255606c3fb27SDimitry Andric           continue;
255706c3fb27SDimitry Andric         }
255806c3fb27SDimitry Andric 
2559bdd1243dSDimitry Andric         // Redundant def found: throw it away. Since the wedge of defs is being
2560bdd1243dSDimitry Andric         // rebuilt, doing nothing is the same as deleting an entry.
2561bdd1243dSDimitry Andric         ChangedThisWedge = true;
2562bdd1243dSDimitry Andric         NumDefsRemoved++;
2563bdd1243dSDimitry Andric       }
2564bdd1243dSDimitry Andric 
2565bdd1243dSDimitry Andric       // Un-reverse the defs and replace the wedge with the pruned version.
2566bdd1243dSDimitry Andric       if (ChangedThisWedge) {
2567bdd1243dSDimitry Andric         std::reverse(NewDefsReversed.begin(), NewDefsReversed.end());
25687a6dacacSDimitry Andric         FnVarLocs.setWedge(WedgePosition, std::move(NewDefsReversed));
2569bdd1243dSDimitry Andric         NumWedgesChanged++;
2570bdd1243dSDimitry Andric         Changed = true;
2571bdd1243dSDimitry Andric       }
25727a6dacacSDimitry Andric     };
25737a6dacacSDimitry Andric     HandleLocsForWedge(&I);
2574*0fca6ea1SDimitry Andric     for (DbgVariableRecord &DVR : reverse(filterDbgVars(I.getDbgRecordRange())))
2575*0fca6ea1SDimitry Andric       HandleLocsForWedge(&DVR);
2576bdd1243dSDimitry Andric   }
2577bdd1243dSDimitry Andric 
2578bdd1243dSDimitry Andric   return Changed;
2579bdd1243dSDimitry Andric }
2580bdd1243dSDimitry Andric 
2581bdd1243dSDimitry Andric /// Remove redundant location defs using a forward scan. This can remove a
2582bdd1243dSDimitry Andric /// location definition that is redundant due to indicating that a variable has
2583bdd1243dSDimitry Andric /// the same value as is already being indicated by an earlier def.
2584bdd1243dSDimitry Andric ///
2585bdd1243dSDimitry Andric /// This implements removeRedundantDbgInstrsUsingForwardScan from
2586bdd1243dSDimitry Andric /// lib/Transforms/Utils/BasicBlockUtils.cpp for locations described with
2587bdd1243dSDimitry Andric /// FunctionVarLocsBuilder instead of with intrinsics
2588bdd1243dSDimitry Andric static bool
2589bdd1243dSDimitry Andric removeRedundantDbgLocsUsingForwardScan(const BasicBlock *BB,
2590bdd1243dSDimitry Andric                                        FunctionVarLocsBuilder &FnVarLocs) {
2591bdd1243dSDimitry Andric   bool Changed = false;
259206c3fb27SDimitry Andric   DenseMap<DebugVariable, std::pair<RawLocationWrapper, DIExpression *>>
259306c3fb27SDimitry Andric       VariableMap;
2594bdd1243dSDimitry Andric 
2595bdd1243dSDimitry Andric   // Scan over the entire block, not just over the instructions mapped by
2596*0fca6ea1SDimitry Andric   // FnVarLocs, because wedges in FnVarLocs may only be separated by debug
2597bdd1243dSDimitry Andric   // instructions.
2598bdd1243dSDimitry Andric   for (const Instruction &I : *BB) {
2599bdd1243dSDimitry Andric     // Get the defs that come just before this instruction.
26007a6dacacSDimitry Andric     auto HandleLocsForWedge = [&](auto *WedgePosition) {
26017a6dacacSDimitry Andric       const auto *Locs = FnVarLocs.getWedge(WedgePosition);
2602bdd1243dSDimitry Andric       if (!Locs)
26037a6dacacSDimitry Andric         return;
2604bdd1243dSDimitry Andric 
2605bdd1243dSDimitry Andric       NumWedgesScanned++;
2606bdd1243dSDimitry Andric       bool ChangedThisWedge = false;
2607bdd1243dSDimitry Andric       // The new pruned set of defs.
2608bdd1243dSDimitry Andric       SmallVector<VarLocInfo> NewDefs;
2609bdd1243dSDimitry Andric 
2610bdd1243dSDimitry Andric       // Iterate over the existing defs.
2611bdd1243dSDimitry Andric       for (const VarLocInfo &Loc : *Locs) {
2612bdd1243dSDimitry Andric         NumDefsScanned++;
2613bdd1243dSDimitry Andric         DebugVariable Key(FnVarLocs.getVariable(Loc.VariableID).getVariable(),
2614bdd1243dSDimitry Andric                           std::nullopt, Loc.DL.getInlinedAt());
2615bdd1243dSDimitry Andric         auto VMI = VariableMap.find(Key);
2616bdd1243dSDimitry Andric 
2617bdd1243dSDimitry Andric         // Update the map if we found a new value/expression describing the
2618bdd1243dSDimitry Andric         // variable, or if the variable wasn't mapped already.
261906c3fb27SDimitry Andric         if (VMI == VariableMap.end() || VMI->second.first != Loc.Values ||
2620bdd1243dSDimitry Andric             VMI->second.second != Loc.Expr) {
262106c3fb27SDimitry Andric           VariableMap[Key] = {Loc.Values, Loc.Expr};
2622bdd1243dSDimitry Andric           NewDefs.push_back(Loc);
2623bdd1243dSDimitry Andric           continue;
2624bdd1243dSDimitry Andric         }
2625bdd1243dSDimitry Andric 
2626bdd1243dSDimitry Andric         // Did not insert this Loc, which is the same as removing it.
2627bdd1243dSDimitry Andric         ChangedThisWedge = true;
2628bdd1243dSDimitry Andric         NumDefsRemoved++;
2629bdd1243dSDimitry Andric       }
2630bdd1243dSDimitry Andric 
2631bdd1243dSDimitry Andric       // Replace the existing wedge with the pruned version.
2632bdd1243dSDimitry Andric       if (ChangedThisWedge) {
26337a6dacacSDimitry Andric         FnVarLocs.setWedge(WedgePosition, std::move(NewDefs));
2634bdd1243dSDimitry Andric         NumWedgesChanged++;
2635bdd1243dSDimitry Andric         Changed = true;
2636bdd1243dSDimitry Andric       }
26377a6dacacSDimitry Andric     };
26387a6dacacSDimitry Andric 
2639*0fca6ea1SDimitry Andric     for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
2640*0fca6ea1SDimitry Andric       HandleLocsForWedge(&DVR);
26417a6dacacSDimitry Andric     HandleLocsForWedge(&I);
2642bdd1243dSDimitry Andric   }
2643bdd1243dSDimitry Andric 
2644bdd1243dSDimitry Andric   return Changed;
2645bdd1243dSDimitry Andric }
2646bdd1243dSDimitry Andric 
2647bdd1243dSDimitry Andric static bool
2648bdd1243dSDimitry Andric removeUndefDbgLocsFromEntryBlock(const BasicBlock *BB,
2649bdd1243dSDimitry Andric                                  FunctionVarLocsBuilder &FnVarLocs) {
2650bdd1243dSDimitry Andric   assert(BB->isEntryBlock());
2651bdd1243dSDimitry Andric   // Do extra work to ensure that we remove semantically unimportant undefs.
2652bdd1243dSDimitry Andric   //
2653bdd1243dSDimitry Andric   // This is to work around the fact that SelectionDAG will hoist dbg.values
2654bdd1243dSDimitry Andric   // using argument values to the top of the entry block. That can move arg
2655bdd1243dSDimitry Andric   // dbg.values before undef and constant dbg.values which they previously
2656bdd1243dSDimitry Andric   // followed. The easiest thing to do is to just try to feed SelectionDAG
2657bdd1243dSDimitry Andric   // input it's happy with.
2658bdd1243dSDimitry Andric   //
2659bdd1243dSDimitry Andric   // Map of {Variable x: Fragments y} where the fragments y of variable x have
2660bdd1243dSDimitry Andric   // have at least one non-undef location defined already. Don't use directly,
2661bdd1243dSDimitry Andric   // instead call DefineBits and HasDefinedBits.
2662bdd1243dSDimitry Andric   SmallDenseMap<DebugAggregate, SmallDenseSet<DIExpression::FragmentInfo>>
2663bdd1243dSDimitry Andric       VarsWithDef;
2664bdd1243dSDimitry Andric   // Specify that V (a fragment of A) has a non-undef location.
2665bdd1243dSDimitry Andric   auto DefineBits = [&VarsWithDef](DebugAggregate A, DebugVariable V) {
2666bdd1243dSDimitry Andric     VarsWithDef[A].insert(V.getFragmentOrDefault());
2667bdd1243dSDimitry Andric   };
2668bdd1243dSDimitry Andric   // Return true if a non-undef location has been defined for V (a fragment of
2669bdd1243dSDimitry Andric   // A). Doesn't imply that the location is currently non-undef, just that a
2670bdd1243dSDimitry Andric   // non-undef location has been seen previously.
2671bdd1243dSDimitry Andric   auto HasDefinedBits = [&VarsWithDef](DebugAggregate A, DebugVariable V) {
2672bdd1243dSDimitry Andric     auto FragsIt = VarsWithDef.find(A);
2673bdd1243dSDimitry Andric     if (FragsIt == VarsWithDef.end())
2674bdd1243dSDimitry Andric       return false;
2675bdd1243dSDimitry Andric     return llvm::any_of(FragsIt->second, [V](auto Frag) {
2676bdd1243dSDimitry Andric       return DIExpression::fragmentsOverlap(Frag, V.getFragmentOrDefault());
2677bdd1243dSDimitry Andric     });
2678bdd1243dSDimitry Andric   };
2679bdd1243dSDimitry Andric 
2680bdd1243dSDimitry Andric   bool Changed = false;
2681bdd1243dSDimitry Andric   DenseMap<DebugVariable, std::pair<Value *, DIExpression *>> VariableMap;
2682bdd1243dSDimitry Andric 
2683bdd1243dSDimitry Andric   // Scan over the entire block, not just over the instructions mapped by
2684*0fca6ea1SDimitry Andric   // FnVarLocs, because wedges in FnVarLocs may only be separated by debug
2685bdd1243dSDimitry Andric   // instructions.
2686bdd1243dSDimitry Andric   for (const Instruction &I : *BB) {
2687bdd1243dSDimitry Andric     // Get the defs that come just before this instruction.
26887a6dacacSDimitry Andric     auto HandleLocsForWedge = [&](auto *WedgePosition) {
26897a6dacacSDimitry Andric       const auto *Locs = FnVarLocs.getWedge(WedgePosition);
2690bdd1243dSDimitry Andric       if (!Locs)
26917a6dacacSDimitry Andric         return;
2692bdd1243dSDimitry Andric 
2693bdd1243dSDimitry Andric       NumWedgesScanned++;
2694bdd1243dSDimitry Andric       bool ChangedThisWedge = false;
2695bdd1243dSDimitry Andric       // The new pruned set of defs.
2696bdd1243dSDimitry Andric       SmallVector<VarLocInfo> NewDefs;
2697bdd1243dSDimitry Andric 
2698bdd1243dSDimitry Andric       // Iterate over the existing defs.
2699bdd1243dSDimitry Andric       for (const VarLocInfo &Loc : *Locs) {
2700bdd1243dSDimitry Andric         NumDefsScanned++;
2701bdd1243dSDimitry Andric         DebugAggregate Aggr{FnVarLocs.getVariable(Loc.VariableID).getVariable(),
2702bdd1243dSDimitry Andric                             Loc.DL.getInlinedAt()};
2703bdd1243dSDimitry Andric         DebugVariable Var = FnVarLocs.getVariable(Loc.VariableID);
2704bdd1243dSDimitry Andric 
2705bdd1243dSDimitry Andric         // Remove undef entries that are encountered before any non-undef
2706bdd1243dSDimitry Andric         // intrinsics from the entry block.
270706c3fb27SDimitry Andric         if (Loc.Values.isKillLocation(Loc.Expr) && !HasDefinedBits(Aggr, Var)) {
2708bdd1243dSDimitry Andric           // Did not insert this Loc, which is the same as removing it.
2709bdd1243dSDimitry Andric           NumDefsRemoved++;
2710bdd1243dSDimitry Andric           ChangedThisWedge = true;
2711bdd1243dSDimitry Andric           continue;
2712bdd1243dSDimitry Andric         }
2713bdd1243dSDimitry Andric 
2714bdd1243dSDimitry Andric         DefineBits(Aggr, Var);
2715bdd1243dSDimitry Andric         NewDefs.push_back(Loc);
2716bdd1243dSDimitry Andric       }
2717bdd1243dSDimitry Andric 
2718bdd1243dSDimitry Andric       // Replace the existing wedge with the pruned version.
2719bdd1243dSDimitry Andric       if (ChangedThisWedge) {
27207a6dacacSDimitry Andric         FnVarLocs.setWedge(WedgePosition, std::move(NewDefs));
2721bdd1243dSDimitry Andric         NumWedgesChanged++;
2722bdd1243dSDimitry Andric         Changed = true;
2723bdd1243dSDimitry Andric       }
27247a6dacacSDimitry Andric     };
2725*0fca6ea1SDimitry Andric     for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
2726*0fca6ea1SDimitry Andric       HandleLocsForWedge(&DVR);
27277a6dacacSDimitry Andric     HandleLocsForWedge(&I);
2728bdd1243dSDimitry Andric   }
2729bdd1243dSDimitry Andric 
2730bdd1243dSDimitry Andric   return Changed;
2731bdd1243dSDimitry Andric }
2732bdd1243dSDimitry Andric 
2733bdd1243dSDimitry Andric static bool removeRedundantDbgLocs(const BasicBlock *BB,
2734bdd1243dSDimitry Andric                                    FunctionVarLocsBuilder &FnVarLocs) {
2735bdd1243dSDimitry Andric   bool MadeChanges = false;
2736bdd1243dSDimitry Andric   MadeChanges |= removeRedundantDbgLocsUsingBackwardScan(BB, FnVarLocs);
2737bdd1243dSDimitry Andric   if (BB->isEntryBlock())
2738bdd1243dSDimitry Andric     MadeChanges |= removeUndefDbgLocsFromEntryBlock(BB, FnVarLocs);
2739bdd1243dSDimitry Andric   MadeChanges |= removeRedundantDbgLocsUsingForwardScan(BB, FnVarLocs);
2740bdd1243dSDimitry Andric 
2741bdd1243dSDimitry Andric   if (MadeChanges)
2742bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "Removed redundant dbg locs from: " << BB->getName()
2743bdd1243dSDimitry Andric                       << "\n");
2744bdd1243dSDimitry Andric   return MadeChanges;
2745bdd1243dSDimitry Andric }
2746bdd1243dSDimitry Andric 
2747bdd1243dSDimitry Andric static DenseSet<DebugAggregate> findVarsWithStackSlot(Function &Fn) {
2748bdd1243dSDimitry Andric   DenseSet<DebugAggregate> Result;
2749bdd1243dSDimitry Andric   for (auto &BB : Fn) {
2750bdd1243dSDimitry Andric     for (auto &I : BB) {
2751bdd1243dSDimitry Andric       // Any variable linked to an instruction is considered
2752bdd1243dSDimitry Andric       // interesting. Ideally we only need to check Allocas, however, a
2753bdd1243dSDimitry Andric       // DIAssignID might get dropped from an alloca but not stores. In that
2754bdd1243dSDimitry Andric       // case, we need to consider the variable interesting for NFC behaviour
2755bdd1243dSDimitry Andric       // with this change. TODO: Consider only looking at allocas.
2756bdd1243dSDimitry Andric       for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(&I)) {
2757bdd1243dSDimitry Andric         Result.insert({DAI->getVariable(), DAI->getDebugLoc().getInlinedAt()});
2758bdd1243dSDimitry Andric       }
2759*0fca6ea1SDimitry Andric       for (DbgVariableRecord *DVR : at::getDVRAssignmentMarkers(&I)) {
2760*0fca6ea1SDimitry Andric         Result.insert({DVR->getVariable(), DVR->getDebugLoc().getInlinedAt()});
27617a6dacacSDimitry Andric       }
2762bdd1243dSDimitry Andric     }
2763bdd1243dSDimitry Andric   }
2764bdd1243dSDimitry Andric   return Result;
2765bdd1243dSDimitry Andric }
2766bdd1243dSDimitry Andric 
2767bdd1243dSDimitry Andric static void analyzeFunction(Function &Fn, const DataLayout &Layout,
2768bdd1243dSDimitry Andric                             FunctionVarLocsBuilder *FnVarLocs) {
2769bdd1243dSDimitry Andric   // The analysis will generate location definitions for all variables, but we
2770bdd1243dSDimitry Andric   // only need to perform a dataflow on the set of variables which have a stack
2771bdd1243dSDimitry Andric   // slot. Find those now.
2772bdd1243dSDimitry Andric   DenseSet<DebugAggregate> VarsWithStackSlot = findVarsWithStackSlot(Fn);
2773bdd1243dSDimitry Andric 
2774bdd1243dSDimitry Andric   bool Changed = false;
2775bdd1243dSDimitry Andric 
2776bdd1243dSDimitry Andric   // Use a scope block to clean up AssignmentTrackingLowering before running
2777bdd1243dSDimitry Andric   // MemLocFragmentFill to reduce peak memory consumption.
2778bdd1243dSDimitry Andric   {
2779bdd1243dSDimitry Andric     AssignmentTrackingLowering Pass(Fn, Layout, &VarsWithStackSlot);
2780bdd1243dSDimitry Andric     Changed = Pass.run(FnVarLocs);
2781bdd1243dSDimitry Andric   }
2782bdd1243dSDimitry Andric 
2783bdd1243dSDimitry Andric   if (Changed) {
278406c3fb27SDimitry Andric     MemLocFragmentFill Pass(Fn, &VarsWithStackSlot,
278506c3fb27SDimitry Andric                             shouldCoalesceFragments(Fn));
2786bdd1243dSDimitry Andric     Pass.run(FnVarLocs);
2787bdd1243dSDimitry Andric 
2788bdd1243dSDimitry Andric     // Remove redundant entries. As well as reducing memory consumption and
2789bdd1243dSDimitry Andric     // avoiding waiting cycles later by burning some now, this has another
2790bdd1243dSDimitry Andric     // important job. That is to work around some SelectionDAG quirks. See
2791bdd1243dSDimitry Andric     // removeRedundantDbgLocsUsingForwardScan comments for more info on that.
2792bdd1243dSDimitry Andric     for (auto &BB : Fn)
2793bdd1243dSDimitry Andric       removeRedundantDbgLocs(&BB, *FnVarLocs);
2794bdd1243dSDimitry Andric   }
2795bdd1243dSDimitry Andric }
2796bdd1243dSDimitry Andric 
2797297eecfbSDimitry Andric FunctionVarLocs
2798297eecfbSDimitry Andric DebugAssignmentTrackingAnalysis::run(Function &F,
2799297eecfbSDimitry Andric                                      FunctionAnalysisManager &FAM) {
2800297eecfbSDimitry Andric   if (!isAssignmentTrackingEnabled(*F.getParent()))
2801297eecfbSDimitry Andric     return FunctionVarLocs();
2802297eecfbSDimitry Andric 
2803*0fca6ea1SDimitry Andric   auto &DL = F.getDataLayout();
2804297eecfbSDimitry Andric 
2805297eecfbSDimitry Andric   FunctionVarLocsBuilder Builder;
2806297eecfbSDimitry Andric   analyzeFunction(F, DL, &Builder);
2807297eecfbSDimitry Andric 
2808297eecfbSDimitry Andric   // Save these results.
2809297eecfbSDimitry Andric   FunctionVarLocs Results;
2810297eecfbSDimitry Andric   Results.init(Builder);
2811297eecfbSDimitry Andric   return Results;
2812297eecfbSDimitry Andric }
2813297eecfbSDimitry Andric 
2814297eecfbSDimitry Andric AnalysisKey DebugAssignmentTrackingAnalysis::Key;
2815297eecfbSDimitry Andric 
2816297eecfbSDimitry Andric PreservedAnalyses
2817297eecfbSDimitry Andric DebugAssignmentTrackingPrinterPass::run(Function &F,
2818297eecfbSDimitry Andric                                         FunctionAnalysisManager &FAM) {
2819297eecfbSDimitry Andric   FAM.getResult<DebugAssignmentTrackingAnalysis>(F).print(OS, F);
2820297eecfbSDimitry Andric   return PreservedAnalyses::all();
2821297eecfbSDimitry Andric }
2822297eecfbSDimitry Andric 
2823bdd1243dSDimitry Andric bool AssignmentTrackingAnalysis::runOnFunction(Function &F) {
2824bdd1243dSDimitry Andric   if (!isAssignmentTrackingEnabled(*F.getParent()))
2825bdd1243dSDimitry Andric     return false;
2826bdd1243dSDimitry Andric 
2827bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "AssignmentTrackingAnalysis run on " << F.getName()
2828bdd1243dSDimitry Andric                     << "\n");
2829bdd1243dSDimitry Andric   auto DL = std::make_unique<DataLayout>(F.getParent());
2830bdd1243dSDimitry Andric 
2831bdd1243dSDimitry Andric   // Clear previous results.
2832bdd1243dSDimitry Andric   Results->clear();
2833bdd1243dSDimitry Andric 
2834bdd1243dSDimitry Andric   FunctionVarLocsBuilder Builder;
2835bdd1243dSDimitry Andric   analyzeFunction(F, *DL.get(), &Builder);
2836bdd1243dSDimitry Andric 
2837bdd1243dSDimitry Andric   // Save these results.
2838bdd1243dSDimitry Andric   Results->init(Builder);
2839bdd1243dSDimitry Andric 
2840bdd1243dSDimitry Andric   if (PrintResults && isFunctionInPrintList(F.getName()))
2841bdd1243dSDimitry Andric     Results->print(errs(), F);
2842bdd1243dSDimitry Andric 
2843bdd1243dSDimitry Andric   // Return false because this pass does not modify the function.
2844bdd1243dSDimitry Andric   return false;
2845bdd1243dSDimitry Andric }
2846bdd1243dSDimitry Andric 
2847bdd1243dSDimitry Andric AssignmentTrackingAnalysis::AssignmentTrackingAnalysis()
2848bdd1243dSDimitry Andric     : FunctionPass(ID), Results(std::make_unique<FunctionVarLocs>()) {}
2849bdd1243dSDimitry Andric 
2850bdd1243dSDimitry Andric char AssignmentTrackingAnalysis::ID = 0;
2851bdd1243dSDimitry Andric 
2852bdd1243dSDimitry Andric INITIALIZE_PASS(AssignmentTrackingAnalysis, DEBUG_TYPE,
2853bdd1243dSDimitry Andric                 "Assignment Tracking Analysis", false, true)
2854