xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1349cc55cSDimitry Andric //===- InstrRefBasedImpl.h - Tracking Debug Value MIs ---------------------===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric 
9349cc55cSDimitry Andric #ifndef LLVM_LIB_CODEGEN_LIVEDEBUGVALUES_INSTRREFBASEDLDV_H
10349cc55cSDimitry Andric #define LLVM_LIB_CODEGEN_LIVEDEBUGVALUES_INSTRREFBASEDLDV_H
11349cc55cSDimitry Andric 
12349cc55cSDimitry Andric #include "llvm/ADT/DenseMap.h"
13*81ad6265SDimitry Andric #include "llvm/ADT/IndexedMap.h"
14349cc55cSDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
15349cc55cSDimitry Andric #include "llvm/ADT/SmallVector.h"
16349cc55cSDimitry Andric #include "llvm/ADT/UniqueVector.h"
17349cc55cSDimitry Andric #include "llvm/CodeGen/LexicalScopes.h"
18349cc55cSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
19349cc55cSDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
20*81ad6265SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
21349cc55cSDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
22349cc55cSDimitry Andric 
23349cc55cSDimitry Andric #include "LiveDebugValues.h"
24349cc55cSDimitry Andric 
25349cc55cSDimitry Andric class TransferTracker;
26349cc55cSDimitry Andric 
27349cc55cSDimitry Andric // Forward dec of unit test class, so that we can peer into the LDV object.
28349cc55cSDimitry Andric class InstrRefLDVTest;
29349cc55cSDimitry Andric 
30349cc55cSDimitry Andric namespace LiveDebugValues {
31349cc55cSDimitry Andric 
32349cc55cSDimitry Andric class MLocTracker;
33349cc55cSDimitry Andric 
34349cc55cSDimitry Andric using namespace llvm;
35349cc55cSDimitry Andric 
36349cc55cSDimitry Andric /// Handle-class for a particular "location". This value-type uniquely
37349cc55cSDimitry Andric /// symbolises a register or stack location, allowing manipulation of locations
38349cc55cSDimitry Andric /// without concern for where that location is. Practically, this allows us to
39349cc55cSDimitry Andric /// treat the state of the machine at a particular point as an array of values,
40349cc55cSDimitry Andric /// rather than a map of values.
41349cc55cSDimitry Andric class LocIdx {
42349cc55cSDimitry Andric   unsigned Location;
43349cc55cSDimitry Andric 
44349cc55cSDimitry Andric   // Default constructor is private, initializing to an illegal location number.
45349cc55cSDimitry Andric   // Use only for "not an entry" elements in IndexedMaps.
46349cc55cSDimitry Andric   LocIdx() : Location(UINT_MAX) {}
47349cc55cSDimitry Andric 
48349cc55cSDimitry Andric public:
49349cc55cSDimitry Andric #define NUM_LOC_BITS 24
50349cc55cSDimitry Andric   LocIdx(unsigned L) : Location(L) {
51349cc55cSDimitry Andric     assert(L < (1 << NUM_LOC_BITS) && "Machine locations must fit in 24 bits");
52349cc55cSDimitry Andric   }
53349cc55cSDimitry Andric 
54349cc55cSDimitry Andric   static LocIdx MakeIllegalLoc() { return LocIdx(); }
55349cc55cSDimitry Andric   static LocIdx MakeTombstoneLoc() {
56349cc55cSDimitry Andric     LocIdx L = LocIdx();
57349cc55cSDimitry Andric     --L.Location;
58349cc55cSDimitry Andric     return L;
59349cc55cSDimitry Andric   }
60349cc55cSDimitry Andric 
61349cc55cSDimitry Andric   bool isIllegal() const { return Location == UINT_MAX; }
62349cc55cSDimitry Andric 
63349cc55cSDimitry Andric   uint64_t asU64() const { return Location; }
64349cc55cSDimitry Andric 
65349cc55cSDimitry Andric   bool operator==(unsigned L) const { return Location == L; }
66349cc55cSDimitry Andric 
67349cc55cSDimitry Andric   bool operator==(const LocIdx &L) const { return Location == L.Location; }
68349cc55cSDimitry Andric 
69349cc55cSDimitry Andric   bool operator!=(unsigned L) const { return !(*this == L); }
70349cc55cSDimitry Andric 
71349cc55cSDimitry Andric   bool operator!=(const LocIdx &L) const { return !(*this == L); }
72349cc55cSDimitry Andric 
73349cc55cSDimitry Andric   bool operator<(const LocIdx &Other) const {
74349cc55cSDimitry Andric     return Location < Other.Location;
75349cc55cSDimitry Andric   }
76349cc55cSDimitry Andric };
77349cc55cSDimitry Andric 
78349cc55cSDimitry Andric // The location at which a spilled value resides. It consists of a register and
79349cc55cSDimitry Andric // an offset.
80349cc55cSDimitry Andric struct SpillLoc {
81349cc55cSDimitry Andric   unsigned SpillBase;
82349cc55cSDimitry Andric   StackOffset SpillOffset;
83349cc55cSDimitry Andric   bool operator==(const SpillLoc &Other) const {
84349cc55cSDimitry Andric     return std::make_pair(SpillBase, SpillOffset) ==
85349cc55cSDimitry Andric            std::make_pair(Other.SpillBase, Other.SpillOffset);
86349cc55cSDimitry Andric   }
87349cc55cSDimitry Andric   bool operator<(const SpillLoc &Other) const {
88349cc55cSDimitry Andric     return std::make_tuple(SpillBase, SpillOffset.getFixed(),
89349cc55cSDimitry Andric                            SpillOffset.getScalable()) <
90349cc55cSDimitry Andric            std::make_tuple(Other.SpillBase, Other.SpillOffset.getFixed(),
91349cc55cSDimitry Andric                            Other.SpillOffset.getScalable());
92349cc55cSDimitry Andric   }
93349cc55cSDimitry Andric };
94349cc55cSDimitry Andric 
95349cc55cSDimitry Andric /// Unique identifier for a value defined by an instruction, as a value type.
96349cc55cSDimitry Andric /// Casts back and forth to a uint64_t. Probably replacable with something less
97349cc55cSDimitry Andric /// bit-constrained. Each value identifies the instruction and machine location
98349cc55cSDimitry Andric /// where the value is defined, although there may be no corresponding machine
99349cc55cSDimitry Andric /// operand for it (ex: regmasks clobbering values). The instructions are
100349cc55cSDimitry Andric /// one-based, and definitions that are PHIs have instruction number zero.
101349cc55cSDimitry Andric ///
102349cc55cSDimitry Andric /// The obvious limits of a 1M block function or 1M instruction blocks are
103349cc55cSDimitry Andric /// problematic; but by that point we should probably have bailed out of
104349cc55cSDimitry Andric /// trying to analyse the function.
105349cc55cSDimitry Andric class ValueIDNum {
106349cc55cSDimitry Andric   union {
107349cc55cSDimitry Andric     struct {
108349cc55cSDimitry Andric       uint64_t BlockNo : 20; /// The block where the def happens.
109349cc55cSDimitry Andric       uint64_t InstNo : 20;  /// The Instruction where the def happens.
110349cc55cSDimitry Andric                              /// One based, is distance from start of block.
111349cc55cSDimitry Andric       uint64_t LocNo
112349cc55cSDimitry Andric           : NUM_LOC_BITS; /// The machine location where the def happens.
113349cc55cSDimitry Andric     } s;
114349cc55cSDimitry Andric     uint64_t Value;
115349cc55cSDimitry Andric   } u;
116349cc55cSDimitry Andric 
117349cc55cSDimitry Andric   static_assert(sizeof(u) == 8, "Badly packed ValueIDNum?");
118349cc55cSDimitry Andric 
119349cc55cSDimitry Andric public:
120349cc55cSDimitry Andric   // Default-initialize to EmptyValue. This is necessary to make IndexedMaps
121349cc55cSDimitry Andric   // of values to work.
122349cc55cSDimitry Andric   ValueIDNum() { u.Value = EmptyValue.asU64(); }
123349cc55cSDimitry Andric 
124349cc55cSDimitry Andric   ValueIDNum(uint64_t Block, uint64_t Inst, uint64_t Loc) {
125349cc55cSDimitry Andric     u.s = {Block, Inst, Loc};
126349cc55cSDimitry Andric   }
127349cc55cSDimitry Andric 
128349cc55cSDimitry Andric   ValueIDNum(uint64_t Block, uint64_t Inst, LocIdx Loc) {
129349cc55cSDimitry Andric     u.s = {Block, Inst, Loc.asU64()};
130349cc55cSDimitry Andric   }
131349cc55cSDimitry Andric 
132349cc55cSDimitry Andric   uint64_t getBlock() const { return u.s.BlockNo; }
133349cc55cSDimitry Andric   uint64_t getInst() const { return u.s.InstNo; }
134349cc55cSDimitry Andric   uint64_t getLoc() const { return u.s.LocNo; }
135349cc55cSDimitry Andric   bool isPHI() const { return u.s.InstNo == 0; }
136349cc55cSDimitry Andric 
137349cc55cSDimitry Andric   uint64_t asU64() const { return u.Value; }
138349cc55cSDimitry Andric 
139349cc55cSDimitry Andric   static ValueIDNum fromU64(uint64_t v) {
140349cc55cSDimitry Andric     ValueIDNum Val;
141349cc55cSDimitry Andric     Val.u.Value = v;
142349cc55cSDimitry Andric     return Val;
143349cc55cSDimitry Andric   }
144349cc55cSDimitry Andric 
145349cc55cSDimitry Andric   bool operator<(const ValueIDNum &Other) const {
146349cc55cSDimitry Andric     return asU64() < Other.asU64();
147349cc55cSDimitry Andric   }
148349cc55cSDimitry Andric 
149349cc55cSDimitry Andric   bool operator==(const ValueIDNum &Other) const {
150349cc55cSDimitry Andric     return u.Value == Other.u.Value;
151349cc55cSDimitry Andric   }
152349cc55cSDimitry Andric 
153349cc55cSDimitry Andric   bool operator!=(const ValueIDNum &Other) const { return !(*this == Other); }
154349cc55cSDimitry Andric 
155349cc55cSDimitry Andric   std::string asString(const std::string &mlocname) const {
156349cc55cSDimitry Andric     return Twine("Value{bb: ")
157349cc55cSDimitry Andric         .concat(Twine(u.s.BlockNo)
158349cc55cSDimitry Andric                     .concat(Twine(", inst: ")
159349cc55cSDimitry Andric                                 .concat((u.s.InstNo ? Twine(u.s.InstNo)
160349cc55cSDimitry Andric                                                     : Twine("live-in"))
161349cc55cSDimitry Andric                                             .concat(Twine(", loc: ").concat(
162349cc55cSDimitry Andric                                                 Twine(mlocname)))
163349cc55cSDimitry Andric                                             .concat(Twine("}")))))
164349cc55cSDimitry Andric         .str();
165349cc55cSDimitry Andric   }
166349cc55cSDimitry Andric 
167349cc55cSDimitry Andric   static ValueIDNum EmptyValue;
168349cc55cSDimitry Andric   static ValueIDNum TombstoneValue;
169349cc55cSDimitry Andric };
170349cc55cSDimitry Andric 
171*81ad6265SDimitry Andric /// Type for a table of values in a block.
172*81ad6265SDimitry Andric using ValueTable = std::unique_ptr<ValueIDNum[]>;
173*81ad6265SDimitry Andric 
174*81ad6265SDimitry Andric /// Type for a table-of-table-of-values, i.e., the collection of either
175*81ad6265SDimitry Andric /// live-in or live-out values for each block in the function.
176*81ad6265SDimitry Andric using FuncValueTable = std::unique_ptr<ValueTable[]>;
177*81ad6265SDimitry Andric 
178349cc55cSDimitry Andric /// Thin wrapper around an integer -- designed to give more type safety to
179349cc55cSDimitry Andric /// spill location numbers.
180349cc55cSDimitry Andric class SpillLocationNo {
181349cc55cSDimitry Andric public:
182349cc55cSDimitry Andric   explicit SpillLocationNo(unsigned SpillNo) : SpillNo(SpillNo) {}
183349cc55cSDimitry Andric   unsigned SpillNo;
184349cc55cSDimitry Andric   unsigned id() const { return SpillNo; }
185349cc55cSDimitry Andric 
186349cc55cSDimitry Andric   bool operator<(const SpillLocationNo &Other) const {
187349cc55cSDimitry Andric     return SpillNo < Other.SpillNo;
188349cc55cSDimitry Andric   }
189349cc55cSDimitry Andric 
190349cc55cSDimitry Andric   bool operator==(const SpillLocationNo &Other) const {
191349cc55cSDimitry Andric     return SpillNo == Other.SpillNo;
192349cc55cSDimitry Andric   }
193349cc55cSDimitry Andric   bool operator!=(const SpillLocationNo &Other) const {
194349cc55cSDimitry Andric     return !(*this == Other);
195349cc55cSDimitry Andric   }
196349cc55cSDimitry Andric };
197349cc55cSDimitry Andric 
198349cc55cSDimitry Andric /// Meta qualifiers for a value. Pair of whatever expression is used to qualify
199*81ad6265SDimitry Andric /// the value, and Boolean of whether or not it's indirect.
200349cc55cSDimitry Andric class DbgValueProperties {
201349cc55cSDimitry Andric public:
202349cc55cSDimitry Andric   DbgValueProperties(const DIExpression *DIExpr, bool Indirect)
203349cc55cSDimitry Andric       : DIExpr(DIExpr), Indirect(Indirect) {}
204349cc55cSDimitry Andric 
205349cc55cSDimitry Andric   /// Extract properties from an existing DBG_VALUE instruction.
206349cc55cSDimitry Andric   DbgValueProperties(const MachineInstr &MI) {
207349cc55cSDimitry Andric     assert(MI.isDebugValue());
208349cc55cSDimitry Andric     DIExpr = MI.getDebugExpression();
209349cc55cSDimitry Andric     Indirect = MI.getOperand(1).isImm();
210349cc55cSDimitry Andric   }
211349cc55cSDimitry Andric 
212349cc55cSDimitry Andric   bool operator==(const DbgValueProperties &Other) const {
213349cc55cSDimitry Andric     return std::tie(DIExpr, Indirect) == std::tie(Other.DIExpr, Other.Indirect);
214349cc55cSDimitry Andric   }
215349cc55cSDimitry Andric 
216349cc55cSDimitry Andric   bool operator!=(const DbgValueProperties &Other) const {
217349cc55cSDimitry Andric     return !(*this == Other);
218349cc55cSDimitry Andric   }
219349cc55cSDimitry Andric 
220349cc55cSDimitry Andric   const DIExpression *DIExpr;
221349cc55cSDimitry Andric   bool Indirect;
222349cc55cSDimitry Andric };
223349cc55cSDimitry Andric 
224349cc55cSDimitry Andric /// Class recording the (high level) _value_ of a variable. Identifies either
225349cc55cSDimitry Andric /// the value of the variable as a ValueIDNum, or a constant MachineOperand.
226349cc55cSDimitry Andric /// This class also stores meta-information about how the value is qualified.
227349cc55cSDimitry Andric /// Used to reason about variable values when performing the second
228349cc55cSDimitry Andric /// (DebugVariable specific) dataflow analysis.
229349cc55cSDimitry Andric class DbgValue {
230349cc55cSDimitry Andric public:
231349cc55cSDimitry Andric   /// If Kind is Def, the value number that this value is based on. VPHIs set
232349cc55cSDimitry Andric   /// this field to EmptyValue if there is no machine-value for this VPHI, or
233349cc55cSDimitry Andric   /// the corresponding machine-value if there is one.
234349cc55cSDimitry Andric   ValueIDNum ID;
235349cc55cSDimitry Andric   /// If Kind is Const, the MachineOperand defining this value.
236349cc55cSDimitry Andric   Optional<MachineOperand> MO;
237349cc55cSDimitry Andric   /// For a NoVal or VPHI DbgValue, which block it was generated in.
238349cc55cSDimitry Andric   int BlockNo;
239349cc55cSDimitry Andric 
240349cc55cSDimitry Andric   /// Qualifiers for the ValueIDNum above.
241349cc55cSDimitry Andric   DbgValueProperties Properties;
242349cc55cSDimitry Andric 
243349cc55cSDimitry Andric   typedef enum {
244349cc55cSDimitry Andric     Undef, // Represents a DBG_VALUE $noreg in the transfer function only.
245349cc55cSDimitry Andric     Def,   // This value is defined by an inst, or is a PHI value.
246349cc55cSDimitry Andric     Const, // A constant value contained in the MachineOperand field.
247349cc55cSDimitry Andric     VPHI,  // Incoming values to BlockNo differ, those values must be joined by
248349cc55cSDimitry Andric            // a PHI in this block.
249349cc55cSDimitry Andric     NoVal, // Empty DbgValue indicating an unknown value. Used as initializer,
250349cc55cSDimitry Andric            // before dominating blocks values are propagated in.
251349cc55cSDimitry Andric   } KindT;
252349cc55cSDimitry Andric   /// Discriminator for whether this is a constant or an in-program value.
253349cc55cSDimitry Andric   KindT Kind;
254349cc55cSDimitry Andric 
255349cc55cSDimitry Andric   DbgValue(const ValueIDNum &Val, const DbgValueProperties &Prop, KindT Kind)
256349cc55cSDimitry Andric       : ID(Val), MO(None), BlockNo(0), Properties(Prop), Kind(Kind) {
257349cc55cSDimitry Andric     assert(Kind == Def);
258349cc55cSDimitry Andric   }
259349cc55cSDimitry Andric 
260349cc55cSDimitry Andric   DbgValue(unsigned BlockNo, const DbgValueProperties &Prop, KindT Kind)
261349cc55cSDimitry Andric       : ID(ValueIDNum::EmptyValue), MO(None), BlockNo(BlockNo),
262349cc55cSDimitry Andric         Properties(Prop), Kind(Kind) {
263349cc55cSDimitry Andric     assert(Kind == NoVal || Kind == VPHI);
264349cc55cSDimitry Andric   }
265349cc55cSDimitry Andric 
266349cc55cSDimitry Andric   DbgValue(const MachineOperand &MO, const DbgValueProperties &Prop, KindT Kind)
267349cc55cSDimitry Andric       : ID(ValueIDNum::EmptyValue), MO(MO), BlockNo(0), Properties(Prop),
268349cc55cSDimitry Andric         Kind(Kind) {
269349cc55cSDimitry Andric     assert(Kind == Const);
270349cc55cSDimitry Andric   }
271349cc55cSDimitry Andric 
272349cc55cSDimitry Andric   DbgValue(const DbgValueProperties &Prop, KindT Kind)
273349cc55cSDimitry Andric     : ID(ValueIDNum::EmptyValue), MO(None), BlockNo(0), Properties(Prop),
274349cc55cSDimitry Andric       Kind(Kind) {
275349cc55cSDimitry Andric     assert(Kind == Undef &&
276349cc55cSDimitry Andric            "Empty DbgValue constructor must pass in Undef kind");
277349cc55cSDimitry Andric   }
278349cc55cSDimitry Andric 
279349cc55cSDimitry Andric #ifndef NDEBUG
280349cc55cSDimitry Andric   void dump(const MLocTracker *MTrack) const;
281349cc55cSDimitry Andric #endif
282349cc55cSDimitry Andric 
283349cc55cSDimitry Andric   bool operator==(const DbgValue &Other) const {
284349cc55cSDimitry Andric     if (std::tie(Kind, Properties) != std::tie(Other.Kind, Other.Properties))
285349cc55cSDimitry Andric       return false;
286349cc55cSDimitry Andric     else if (Kind == Def && ID != Other.ID)
287349cc55cSDimitry Andric       return false;
288349cc55cSDimitry Andric     else if (Kind == NoVal && BlockNo != Other.BlockNo)
289349cc55cSDimitry Andric       return false;
290349cc55cSDimitry Andric     else if (Kind == Const)
291349cc55cSDimitry Andric       return MO->isIdenticalTo(*Other.MO);
292349cc55cSDimitry Andric     else if (Kind == VPHI && BlockNo != Other.BlockNo)
293349cc55cSDimitry Andric       return false;
294349cc55cSDimitry Andric     else if (Kind == VPHI && ID != Other.ID)
295349cc55cSDimitry Andric       return false;
296349cc55cSDimitry Andric 
297349cc55cSDimitry Andric     return true;
298349cc55cSDimitry Andric   }
299349cc55cSDimitry Andric 
300349cc55cSDimitry Andric   bool operator!=(const DbgValue &Other) const { return !(*this == Other); }
301349cc55cSDimitry Andric };
302349cc55cSDimitry Andric 
303349cc55cSDimitry Andric class LocIdxToIndexFunctor {
304349cc55cSDimitry Andric public:
305349cc55cSDimitry Andric   using argument_type = LocIdx;
306349cc55cSDimitry Andric   unsigned operator()(const LocIdx &L) const { return L.asU64(); }
307349cc55cSDimitry Andric };
308349cc55cSDimitry Andric 
309349cc55cSDimitry Andric /// Tracker for what values are in machine locations. Listens to the Things
310349cc55cSDimitry Andric /// being Done by various instructions, and maintains a table of what machine
311349cc55cSDimitry Andric /// locations have what values (as defined by a ValueIDNum).
312349cc55cSDimitry Andric ///
313349cc55cSDimitry Andric /// There are potentially a much larger number of machine locations on the
314349cc55cSDimitry Andric /// target machine than the actual working-set size of the function. On x86 for
315349cc55cSDimitry Andric /// example, we're extremely unlikely to want to track values through control
316349cc55cSDimitry Andric /// or debug registers. To avoid doing so, MLocTracker has several layers of
317349cc55cSDimitry Andric /// indirection going on, described below, to avoid unnecessarily tracking
318349cc55cSDimitry Andric /// any location.
319349cc55cSDimitry Andric ///
320349cc55cSDimitry Andric /// Here's a sort of diagram of the indexes, read from the bottom up:
321349cc55cSDimitry Andric ///
322349cc55cSDimitry Andric ///           Size on stack   Offset on stack
323349cc55cSDimitry Andric ///                 \              /
324349cc55cSDimitry Andric ///          Stack Idx (Where in slot is this?)
325349cc55cSDimitry Andric ///                         /
326349cc55cSDimitry Andric ///                        /
327349cc55cSDimitry Andric /// Slot Num (%stack.0)   /
328349cc55cSDimitry Andric /// FrameIdx => SpillNum /
329349cc55cSDimitry Andric ///              \      /
330349cc55cSDimitry Andric ///           SpillID (int)              Register number (int)
331349cc55cSDimitry Andric ///                      \                  /
332349cc55cSDimitry Andric ///                      LocationID => LocIdx
333349cc55cSDimitry Andric ///                                |
334349cc55cSDimitry Andric ///                       LocIdx => ValueIDNum
335349cc55cSDimitry Andric ///
336349cc55cSDimitry Andric /// The aim here is that the LocIdx => ValueIDNum vector is just an array of
337349cc55cSDimitry Andric /// values in numbered locations, so that later analyses can ignore whether the
338349cc55cSDimitry Andric /// location is a register or otherwise. To map a register / spill location to
339349cc55cSDimitry Andric /// a LocIdx, you have to use the (sparse) LocationID => LocIdx map. And to
340349cc55cSDimitry Andric /// build a LocationID for a stack slot, you need to combine identifiers for
341349cc55cSDimitry Andric /// which stack slot it is and where within that slot is being described.
342349cc55cSDimitry Andric ///
343349cc55cSDimitry Andric /// Register mask operands cause trouble by technically defining every register;
344349cc55cSDimitry Andric /// various hacks are used to avoid tracking registers that are never read and
345349cc55cSDimitry Andric /// only written by regmasks.
346349cc55cSDimitry Andric class MLocTracker {
347349cc55cSDimitry Andric public:
348349cc55cSDimitry Andric   MachineFunction &MF;
349349cc55cSDimitry Andric   const TargetInstrInfo &TII;
350349cc55cSDimitry Andric   const TargetRegisterInfo &TRI;
351349cc55cSDimitry Andric   const TargetLowering &TLI;
352349cc55cSDimitry Andric 
353349cc55cSDimitry Andric   /// IndexedMap type, mapping from LocIdx to ValueIDNum.
354349cc55cSDimitry Andric   using LocToValueType = IndexedMap<ValueIDNum, LocIdxToIndexFunctor>;
355349cc55cSDimitry Andric 
356349cc55cSDimitry Andric   /// Map of LocIdxes to the ValueIDNums that they store. This is tightly
357349cc55cSDimitry Andric   /// packed, entries only exist for locations that are being tracked.
358349cc55cSDimitry Andric   LocToValueType LocIdxToIDNum;
359349cc55cSDimitry Andric 
360349cc55cSDimitry Andric   /// "Map" of machine location IDs (i.e., raw register or spill number) to the
361349cc55cSDimitry Andric   /// LocIdx key / number for that location. There are always at least as many
362349cc55cSDimitry Andric   /// as the number of registers on the target -- if the value in the register
363349cc55cSDimitry Andric   /// is not being tracked, then the LocIdx value will be zero. New entries are
364349cc55cSDimitry Andric   /// appended if a new spill slot begins being tracked.
365349cc55cSDimitry Andric   /// This, and the corresponding reverse map persist for the analysis of the
366349cc55cSDimitry Andric   /// whole function, and is necessarying for decoding various vectors of
367349cc55cSDimitry Andric   /// values.
368349cc55cSDimitry Andric   std::vector<LocIdx> LocIDToLocIdx;
369349cc55cSDimitry Andric 
370349cc55cSDimitry Andric   /// Inverse map of LocIDToLocIdx.
371349cc55cSDimitry Andric   IndexedMap<unsigned, LocIdxToIndexFunctor> LocIdxToLocID;
372349cc55cSDimitry Andric 
373349cc55cSDimitry Andric   /// When clobbering register masks, we chose to not believe the machine model
374349cc55cSDimitry Andric   /// and don't clobber SP. Do the same for SP aliases, and for efficiency,
375349cc55cSDimitry Andric   /// keep a set of them here.
376349cc55cSDimitry Andric   SmallSet<Register, 8> SPAliases;
377349cc55cSDimitry Andric 
378349cc55cSDimitry Andric   /// Unique-ification of spill. Used to number them -- their LocID number is
379349cc55cSDimitry Andric   /// the index in SpillLocs minus one plus NumRegs.
380349cc55cSDimitry Andric   UniqueVector<SpillLoc> SpillLocs;
381349cc55cSDimitry Andric 
382349cc55cSDimitry Andric   // If we discover a new machine location, assign it an mphi with this
383349cc55cSDimitry Andric   // block number.
384349cc55cSDimitry Andric   unsigned CurBB;
385349cc55cSDimitry Andric 
386349cc55cSDimitry Andric   /// Cached local copy of the number of registers the target has.
387349cc55cSDimitry Andric   unsigned NumRegs;
388349cc55cSDimitry Andric 
389349cc55cSDimitry Andric   /// Number of slot indexes the target has -- distinct segments of a stack
390349cc55cSDimitry Andric   /// slot that can take on the value of a subregister, when a super-register
391349cc55cSDimitry Andric   /// is written to the stack.
392349cc55cSDimitry Andric   unsigned NumSlotIdxes;
393349cc55cSDimitry Andric 
394349cc55cSDimitry Andric   /// Collection of register mask operands that have been observed. Second part
395349cc55cSDimitry Andric   /// of pair indicates the instruction that they happened in. Used to
396349cc55cSDimitry Andric   /// reconstruct where defs happened if we start tracking a location later
397349cc55cSDimitry Andric   /// on.
398349cc55cSDimitry Andric   SmallVector<std::pair<const MachineOperand *, unsigned>, 32> Masks;
399349cc55cSDimitry Andric 
400349cc55cSDimitry Andric   /// Pair for describing a position within a stack slot -- first the size in
401349cc55cSDimitry Andric   /// bits, then the offset.
402349cc55cSDimitry Andric   typedef std::pair<unsigned short, unsigned short> StackSlotPos;
403349cc55cSDimitry Andric 
404349cc55cSDimitry Andric   /// Map from a size/offset pair describing a position in a stack slot, to a
405349cc55cSDimitry Andric   /// numeric identifier for that position. Allows easier identification of
406349cc55cSDimitry Andric   /// individual positions.
407349cc55cSDimitry Andric   DenseMap<StackSlotPos, unsigned> StackSlotIdxes;
408349cc55cSDimitry Andric 
409349cc55cSDimitry Andric   /// Inverse of StackSlotIdxes.
410349cc55cSDimitry Andric   DenseMap<unsigned, StackSlotPos> StackIdxesToPos;
411349cc55cSDimitry Andric 
412349cc55cSDimitry Andric   /// Iterator for locations and the values they contain. Dereferencing
413349cc55cSDimitry Andric   /// produces a struct/pair containing the LocIdx key for this location,
414349cc55cSDimitry Andric   /// and a reference to the value currently stored. Simplifies the process
415349cc55cSDimitry Andric   /// of seeking a particular location.
416349cc55cSDimitry Andric   class MLocIterator {
417349cc55cSDimitry Andric     LocToValueType &ValueMap;
418349cc55cSDimitry Andric     LocIdx Idx;
419349cc55cSDimitry Andric 
420349cc55cSDimitry Andric   public:
421349cc55cSDimitry Andric     class value_type {
422349cc55cSDimitry Andric     public:
423349cc55cSDimitry Andric       value_type(LocIdx Idx, ValueIDNum &Value) : Idx(Idx), Value(Value) {}
424349cc55cSDimitry Andric       const LocIdx Idx;  /// Read-only index of this location.
425349cc55cSDimitry Andric       ValueIDNum &Value; /// Reference to the stored value at this location.
426349cc55cSDimitry Andric     };
427349cc55cSDimitry Andric 
428349cc55cSDimitry Andric     MLocIterator(LocToValueType &ValueMap, LocIdx Idx)
429349cc55cSDimitry Andric         : ValueMap(ValueMap), Idx(Idx) {}
430349cc55cSDimitry Andric 
431349cc55cSDimitry Andric     bool operator==(const MLocIterator &Other) const {
432349cc55cSDimitry Andric       assert(&ValueMap == &Other.ValueMap);
433349cc55cSDimitry Andric       return Idx == Other.Idx;
434349cc55cSDimitry Andric     }
435349cc55cSDimitry Andric 
436349cc55cSDimitry Andric     bool operator!=(const MLocIterator &Other) const {
437349cc55cSDimitry Andric       return !(*this == Other);
438349cc55cSDimitry Andric     }
439349cc55cSDimitry Andric 
440349cc55cSDimitry Andric     void operator++() { Idx = LocIdx(Idx.asU64() + 1); }
441349cc55cSDimitry Andric 
442349cc55cSDimitry Andric     value_type operator*() { return value_type(Idx, ValueMap[LocIdx(Idx)]); }
443349cc55cSDimitry Andric   };
444349cc55cSDimitry Andric 
445349cc55cSDimitry Andric   MLocTracker(MachineFunction &MF, const TargetInstrInfo &TII,
446349cc55cSDimitry Andric               const TargetRegisterInfo &TRI, const TargetLowering &TLI);
447349cc55cSDimitry Andric 
448349cc55cSDimitry Andric   /// Produce location ID number for a Register. Provides some small amount of
449349cc55cSDimitry Andric   /// type safety.
450349cc55cSDimitry Andric   /// \param Reg The register we're looking up.
451349cc55cSDimitry Andric   unsigned getLocID(Register Reg) { return Reg.id(); }
452349cc55cSDimitry Andric 
453349cc55cSDimitry Andric   /// Produce location ID number for a spill position.
454349cc55cSDimitry Andric   /// \param Spill The number of the spill we're fetching the location for.
455349cc55cSDimitry Andric   /// \param SpillSubReg Subregister within the spill we're addressing.
456349cc55cSDimitry Andric   unsigned getLocID(SpillLocationNo Spill, unsigned SpillSubReg) {
457349cc55cSDimitry Andric     unsigned short Size = TRI.getSubRegIdxSize(SpillSubReg);
458349cc55cSDimitry Andric     unsigned short Offs = TRI.getSubRegIdxOffset(SpillSubReg);
459349cc55cSDimitry Andric     return getLocID(Spill, {Size, Offs});
460349cc55cSDimitry Andric   }
461349cc55cSDimitry Andric 
462349cc55cSDimitry Andric   /// Produce location ID number for a spill position.
463349cc55cSDimitry Andric   /// \param Spill The number of the spill we're fetching the location for.
464349cc55cSDimitry Andric   /// \apram SpillIdx size/offset within the spill slot to be addressed.
465349cc55cSDimitry Andric   unsigned getLocID(SpillLocationNo Spill, StackSlotPos Idx) {
466349cc55cSDimitry Andric     unsigned SlotNo = Spill.id() - 1;
467349cc55cSDimitry Andric     SlotNo *= NumSlotIdxes;
468349cc55cSDimitry Andric     assert(StackSlotIdxes.find(Idx) != StackSlotIdxes.end());
469349cc55cSDimitry Andric     SlotNo += StackSlotIdxes[Idx];
470349cc55cSDimitry Andric     SlotNo += NumRegs;
471349cc55cSDimitry Andric     return SlotNo;
472349cc55cSDimitry Andric   }
473349cc55cSDimitry Andric 
474349cc55cSDimitry Andric   /// Given a spill number, and a slot within the spill, calculate the ID number
475349cc55cSDimitry Andric   /// for that location.
476349cc55cSDimitry Andric   unsigned getSpillIDWithIdx(SpillLocationNo Spill, unsigned Idx) {
477349cc55cSDimitry Andric     unsigned SlotNo = Spill.id() - 1;
478349cc55cSDimitry Andric     SlotNo *= NumSlotIdxes;
479349cc55cSDimitry Andric     SlotNo += Idx;
480349cc55cSDimitry Andric     SlotNo += NumRegs;
481349cc55cSDimitry Andric     return SlotNo;
482349cc55cSDimitry Andric   }
483349cc55cSDimitry Andric 
484349cc55cSDimitry Andric   /// Return the spill number that a location ID corresponds to.
485349cc55cSDimitry Andric   SpillLocationNo locIDToSpill(unsigned ID) const {
486349cc55cSDimitry Andric     assert(ID >= NumRegs);
487349cc55cSDimitry Andric     ID -= NumRegs;
488349cc55cSDimitry Andric     // Truncate away the index part, leaving only the spill number.
489349cc55cSDimitry Andric     ID /= NumSlotIdxes;
490349cc55cSDimitry Andric     return SpillLocationNo(ID + 1); // The UniqueVector is one-based.
491349cc55cSDimitry Andric   }
492349cc55cSDimitry Andric 
493349cc55cSDimitry Andric   /// Returns the spill-slot size/offs that a location ID corresponds to.
494349cc55cSDimitry Andric   StackSlotPos locIDToSpillIdx(unsigned ID) const {
495349cc55cSDimitry Andric     assert(ID >= NumRegs);
496349cc55cSDimitry Andric     ID -= NumRegs;
497349cc55cSDimitry Andric     unsigned Idx = ID % NumSlotIdxes;
498349cc55cSDimitry Andric     return StackIdxesToPos.find(Idx)->second;
499349cc55cSDimitry Andric   }
500349cc55cSDimitry Andric 
50104eeddc0SDimitry Andric   unsigned getNumLocs() const { return LocIdxToIDNum.size(); }
502349cc55cSDimitry Andric 
503349cc55cSDimitry Andric   /// Reset all locations to contain a PHI value at the designated block. Used
504349cc55cSDimitry Andric   /// sometimes for actual PHI values, othertimes to indicate the block entry
505349cc55cSDimitry Andric   /// value (before any more information is known).
506349cc55cSDimitry Andric   void setMPhis(unsigned NewCurBB) {
507349cc55cSDimitry Andric     CurBB = NewCurBB;
508349cc55cSDimitry Andric     for (auto Location : locations())
509349cc55cSDimitry Andric       Location.Value = {CurBB, 0, Location.Idx};
510349cc55cSDimitry Andric   }
511349cc55cSDimitry Andric 
512349cc55cSDimitry Andric   /// Load values for each location from array of ValueIDNums. Take current
513349cc55cSDimitry Andric   /// bbnum just in case we read a value from a hitherto untouched register.
514*81ad6265SDimitry Andric   void loadFromArray(ValueTable &Locs, unsigned NewCurBB) {
515349cc55cSDimitry Andric     CurBB = NewCurBB;
516349cc55cSDimitry Andric     // Iterate over all tracked locations, and load each locations live-in
517349cc55cSDimitry Andric     // value into our local index.
518349cc55cSDimitry Andric     for (auto Location : locations())
519349cc55cSDimitry Andric       Location.Value = Locs[Location.Idx.asU64()];
520349cc55cSDimitry Andric   }
521349cc55cSDimitry Andric 
522349cc55cSDimitry Andric   /// Wipe any un-necessary location records after traversing a block.
52304eeddc0SDimitry Andric   void reset() {
524349cc55cSDimitry Andric     // We could reset all the location values too; however either loadFromArray
525349cc55cSDimitry Andric     // or setMPhis should be called before this object is re-used. Just
526349cc55cSDimitry Andric     // clear Masks, they're definitely not needed.
527349cc55cSDimitry Andric     Masks.clear();
528349cc55cSDimitry Andric   }
529349cc55cSDimitry Andric 
530349cc55cSDimitry Andric   /// Clear all data. Destroys the LocID <=> LocIdx map, which makes most of
531349cc55cSDimitry Andric   /// the information in this pass uninterpretable.
53204eeddc0SDimitry Andric   void clear() {
533349cc55cSDimitry Andric     reset();
534349cc55cSDimitry Andric     LocIDToLocIdx.clear();
535349cc55cSDimitry Andric     LocIdxToLocID.clear();
536349cc55cSDimitry Andric     LocIdxToIDNum.clear();
537349cc55cSDimitry Andric     // SpillLocs.reset(); XXX UniqueVector::reset assumes a SpillLoc casts from
538349cc55cSDimitry Andric     // 0
539349cc55cSDimitry Andric     SpillLocs = decltype(SpillLocs)();
540349cc55cSDimitry Andric     StackSlotIdxes.clear();
541349cc55cSDimitry Andric     StackIdxesToPos.clear();
542349cc55cSDimitry Andric 
543349cc55cSDimitry Andric     LocIDToLocIdx.resize(NumRegs, LocIdx::MakeIllegalLoc());
544349cc55cSDimitry Andric   }
545349cc55cSDimitry Andric 
546349cc55cSDimitry Andric   /// Set a locaiton to a certain value.
547349cc55cSDimitry Andric   void setMLoc(LocIdx L, ValueIDNum Num) {
548349cc55cSDimitry Andric     assert(L.asU64() < LocIdxToIDNum.size());
549349cc55cSDimitry Andric     LocIdxToIDNum[L] = Num;
550349cc55cSDimitry Andric   }
551349cc55cSDimitry Andric 
552349cc55cSDimitry Andric   /// Read the value of a particular location
553349cc55cSDimitry Andric   ValueIDNum readMLoc(LocIdx L) {
554349cc55cSDimitry Andric     assert(L.asU64() < LocIdxToIDNum.size());
555349cc55cSDimitry Andric     return LocIdxToIDNum[L];
556349cc55cSDimitry Andric   }
557349cc55cSDimitry Andric 
558349cc55cSDimitry Andric   /// Create a LocIdx for an untracked register ID. Initialize it to either an
559349cc55cSDimitry Andric   /// mphi value representing a live-in, or a recent register mask clobber.
560349cc55cSDimitry Andric   LocIdx trackRegister(unsigned ID);
561349cc55cSDimitry Andric 
562349cc55cSDimitry Andric   LocIdx lookupOrTrackRegister(unsigned ID) {
563349cc55cSDimitry Andric     LocIdx &Index = LocIDToLocIdx[ID];
564349cc55cSDimitry Andric     if (Index.isIllegal())
565349cc55cSDimitry Andric       Index = trackRegister(ID);
566349cc55cSDimitry Andric     return Index;
567349cc55cSDimitry Andric   }
568349cc55cSDimitry Andric 
569349cc55cSDimitry Andric   /// Is register R currently tracked by MLocTracker?
570349cc55cSDimitry Andric   bool isRegisterTracked(Register R) {
571349cc55cSDimitry Andric     LocIdx &Index = LocIDToLocIdx[R];
572349cc55cSDimitry Andric     return !Index.isIllegal();
573349cc55cSDimitry Andric   }
574349cc55cSDimitry Andric 
575349cc55cSDimitry Andric   /// Record a definition of the specified register at the given block / inst.
576349cc55cSDimitry Andric   /// This doesn't take a ValueIDNum, because the definition and its location
577349cc55cSDimitry Andric   /// are synonymous.
578349cc55cSDimitry Andric   void defReg(Register R, unsigned BB, unsigned Inst) {
579349cc55cSDimitry Andric     unsigned ID = getLocID(R);
580349cc55cSDimitry Andric     LocIdx Idx = lookupOrTrackRegister(ID);
581349cc55cSDimitry Andric     ValueIDNum ValueID = {BB, Inst, Idx};
582349cc55cSDimitry Andric     LocIdxToIDNum[Idx] = ValueID;
583349cc55cSDimitry Andric   }
584349cc55cSDimitry Andric 
585349cc55cSDimitry Andric   /// Set a register to a value number. To be used if the value number is
586349cc55cSDimitry Andric   /// known in advance.
587349cc55cSDimitry Andric   void setReg(Register R, ValueIDNum ValueID) {
588349cc55cSDimitry Andric     unsigned ID = getLocID(R);
589349cc55cSDimitry Andric     LocIdx Idx = lookupOrTrackRegister(ID);
590349cc55cSDimitry Andric     LocIdxToIDNum[Idx] = ValueID;
591349cc55cSDimitry Andric   }
592349cc55cSDimitry Andric 
593349cc55cSDimitry Andric   ValueIDNum readReg(Register R) {
594349cc55cSDimitry Andric     unsigned ID = getLocID(R);
595349cc55cSDimitry Andric     LocIdx Idx = lookupOrTrackRegister(ID);
596349cc55cSDimitry Andric     return LocIdxToIDNum[Idx];
597349cc55cSDimitry Andric   }
598349cc55cSDimitry Andric 
599349cc55cSDimitry Andric   /// Reset a register value to zero / empty. Needed to replicate the
600349cc55cSDimitry Andric   /// VarLoc implementation where a copy to/from a register effectively
601349cc55cSDimitry Andric   /// clears the contents of the source register. (Values can only have one
602349cc55cSDimitry Andric   ///  machine location in VarLocBasedImpl).
603349cc55cSDimitry Andric   void wipeRegister(Register R) {
604349cc55cSDimitry Andric     unsigned ID = getLocID(R);
605349cc55cSDimitry Andric     LocIdx Idx = LocIDToLocIdx[ID];
606349cc55cSDimitry Andric     LocIdxToIDNum[Idx] = ValueIDNum::EmptyValue;
607349cc55cSDimitry Andric   }
608349cc55cSDimitry Andric 
609349cc55cSDimitry Andric   /// Determine the LocIdx of an existing register.
610349cc55cSDimitry Andric   LocIdx getRegMLoc(Register R) {
611349cc55cSDimitry Andric     unsigned ID = getLocID(R);
612349cc55cSDimitry Andric     assert(ID < LocIDToLocIdx.size());
613349cc55cSDimitry Andric     assert(LocIDToLocIdx[ID] != UINT_MAX); // Sentinal for IndexedMap.
614349cc55cSDimitry Andric     return LocIDToLocIdx[ID];
615349cc55cSDimitry Andric   }
616349cc55cSDimitry Andric 
617349cc55cSDimitry Andric   /// Record a RegMask operand being executed. Defs any register we currently
618349cc55cSDimitry Andric   /// track, stores a pointer to the mask in case we have to account for it
619349cc55cSDimitry Andric   /// later.
620349cc55cSDimitry Andric   void writeRegMask(const MachineOperand *MO, unsigned CurBB, unsigned InstID);
621349cc55cSDimitry Andric 
622349cc55cSDimitry Andric   /// Find LocIdx for SpillLoc \p L, creating a new one if it's not tracked.
623d56accc7SDimitry Andric   /// Returns None when in scenarios where a spill slot could be tracked, but
624d56accc7SDimitry Andric   /// we would likely run into resource limitations.
625d56accc7SDimitry Andric   Optional<SpillLocationNo> getOrTrackSpillLoc(SpillLoc L);
626349cc55cSDimitry Andric 
627349cc55cSDimitry Andric   // Get LocIdx of a spill ID.
628349cc55cSDimitry Andric   LocIdx getSpillMLoc(unsigned SpillID) {
629349cc55cSDimitry Andric     assert(LocIDToLocIdx[SpillID] != UINT_MAX); // Sentinal for IndexedMap.
630349cc55cSDimitry Andric     return LocIDToLocIdx[SpillID];
631349cc55cSDimitry Andric   }
632349cc55cSDimitry Andric 
633349cc55cSDimitry Andric   /// Return true if Idx is a spill machine location.
634349cc55cSDimitry Andric   bool isSpill(LocIdx Idx) const { return LocIdxToLocID[Idx] >= NumRegs; }
635349cc55cSDimitry Andric 
636*81ad6265SDimitry Andric   /// How large is this location (aka, how wide is a value defined there?).
637*81ad6265SDimitry Andric   unsigned getLocSizeInBits(LocIdx L) const {
638*81ad6265SDimitry Andric     unsigned ID = LocIdxToLocID[L];
639*81ad6265SDimitry Andric     if (!isSpill(L)) {
640*81ad6265SDimitry Andric       return TRI.getRegSizeInBits(Register(ID), MF.getRegInfo());
641*81ad6265SDimitry Andric     } else {
642*81ad6265SDimitry Andric       // The slot location on the stack is uninteresting, we care about the
643*81ad6265SDimitry Andric       // position of the value within the slot (which comes with a size).
644*81ad6265SDimitry Andric       StackSlotPos Pos = locIDToSpillIdx(ID);
645*81ad6265SDimitry Andric       return Pos.first;
646*81ad6265SDimitry Andric     }
647*81ad6265SDimitry Andric   }
648*81ad6265SDimitry Andric 
649349cc55cSDimitry Andric   MLocIterator begin() { return MLocIterator(LocIdxToIDNum, 0); }
650349cc55cSDimitry Andric 
651349cc55cSDimitry Andric   MLocIterator end() {
652349cc55cSDimitry Andric     return MLocIterator(LocIdxToIDNum, LocIdxToIDNum.size());
653349cc55cSDimitry Andric   }
654349cc55cSDimitry Andric 
655349cc55cSDimitry Andric   /// Return a range over all locations currently tracked.
656349cc55cSDimitry Andric   iterator_range<MLocIterator> locations() {
657349cc55cSDimitry Andric     return llvm::make_range(begin(), end());
658349cc55cSDimitry Andric   }
659349cc55cSDimitry Andric 
660349cc55cSDimitry Andric   std::string LocIdxToName(LocIdx Idx) const;
661349cc55cSDimitry Andric 
662349cc55cSDimitry Andric   std::string IDAsString(const ValueIDNum &Num) const;
663349cc55cSDimitry Andric 
664349cc55cSDimitry Andric #ifndef NDEBUG
665349cc55cSDimitry Andric   LLVM_DUMP_METHOD void dump();
666349cc55cSDimitry Andric 
667349cc55cSDimitry Andric   LLVM_DUMP_METHOD void dump_mloc_map();
668349cc55cSDimitry Andric #endif
669349cc55cSDimitry Andric 
670349cc55cSDimitry Andric   /// Create a DBG_VALUE based on  machine location \p MLoc. Qualify it with the
671349cc55cSDimitry Andric   /// information in \pProperties, for variable Var. Don't insert it anywhere,
672349cc55cSDimitry Andric   /// just return the builder for it.
673349cc55cSDimitry Andric   MachineInstrBuilder emitLoc(Optional<LocIdx> MLoc, const DebugVariable &Var,
674349cc55cSDimitry Andric                               const DbgValueProperties &Properties);
675349cc55cSDimitry Andric };
676349cc55cSDimitry Andric 
6774824e7fdSDimitry Andric /// Types for recording sets of variable fragments that overlap. For a given
6784824e7fdSDimitry Andric /// local variable, we record all other fragments of that variable that could
6794824e7fdSDimitry Andric /// overlap it, to reduce search time.
6804824e7fdSDimitry Andric using FragmentOfVar =
6814824e7fdSDimitry Andric     std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;
6824824e7fdSDimitry Andric using OverlapMap =
6834824e7fdSDimitry Andric     DenseMap<FragmentOfVar, SmallVector<DIExpression::FragmentInfo, 1>>;
6844824e7fdSDimitry Andric 
685349cc55cSDimitry Andric /// Collection of DBG_VALUEs observed when traversing a block. Records each
686349cc55cSDimitry Andric /// variable and the value the DBG_VALUE refers to. Requires the machine value
687349cc55cSDimitry Andric /// location dataflow algorithm to have run already, so that values can be
688349cc55cSDimitry Andric /// identified.
689349cc55cSDimitry Andric class VLocTracker {
690349cc55cSDimitry Andric public:
691349cc55cSDimitry Andric   /// Map DebugVariable to the latest Value it's defined to have.
692349cc55cSDimitry Andric   /// Needs to be a MapVector because we determine order-in-the-input-MIR from
693349cc55cSDimitry Andric   /// the order in this container.
694349cc55cSDimitry Andric   /// We only retain the last DbgValue in each block for each variable, to
695349cc55cSDimitry Andric   /// determine the blocks live-out variable value. The Vars container forms the
696349cc55cSDimitry Andric   /// transfer function for this block, as part of the dataflow analysis. The
697349cc55cSDimitry Andric   /// movement of values between locations inside of a block is handled at a
698349cc55cSDimitry Andric   /// much later stage, in the TransferTracker class.
699349cc55cSDimitry Andric   MapVector<DebugVariable, DbgValue> Vars;
700d56accc7SDimitry Andric   SmallDenseMap<DebugVariable, const DILocation *, 8> Scopes;
701349cc55cSDimitry Andric   MachineBasicBlock *MBB = nullptr;
7024824e7fdSDimitry Andric   const OverlapMap &OverlappingFragments;
7034824e7fdSDimitry Andric   DbgValueProperties EmptyProperties;
704349cc55cSDimitry Andric 
705349cc55cSDimitry Andric public:
7064824e7fdSDimitry Andric   VLocTracker(const OverlapMap &O, const DIExpression *EmptyExpr)
7074824e7fdSDimitry Andric       : OverlappingFragments(O), EmptyProperties(EmptyExpr, false) {}
708349cc55cSDimitry Andric 
709349cc55cSDimitry Andric   void defVar(const MachineInstr &MI, const DbgValueProperties &Properties,
710349cc55cSDimitry Andric               Optional<ValueIDNum> ID) {
711349cc55cSDimitry Andric     assert(MI.isDebugValue() || MI.isDebugRef());
712349cc55cSDimitry Andric     DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
713349cc55cSDimitry Andric                       MI.getDebugLoc()->getInlinedAt());
714349cc55cSDimitry Andric     DbgValue Rec = (ID) ? DbgValue(*ID, Properties, DbgValue::Def)
715349cc55cSDimitry Andric                         : DbgValue(Properties, DbgValue::Undef);
716349cc55cSDimitry Andric 
717349cc55cSDimitry Andric     // Attempt insertion; overwrite if it's already mapped.
718349cc55cSDimitry Andric     auto Result = Vars.insert(std::make_pair(Var, Rec));
719349cc55cSDimitry Andric     if (!Result.second)
720349cc55cSDimitry Andric       Result.first->second = Rec;
721349cc55cSDimitry Andric     Scopes[Var] = MI.getDebugLoc().get();
7224824e7fdSDimitry Andric 
7234824e7fdSDimitry Andric     considerOverlaps(Var, MI.getDebugLoc().get());
724349cc55cSDimitry Andric   }
725349cc55cSDimitry Andric 
726349cc55cSDimitry Andric   void defVar(const MachineInstr &MI, const MachineOperand &MO) {
727349cc55cSDimitry Andric     // Only DBG_VALUEs can define constant-valued variables.
728349cc55cSDimitry Andric     assert(MI.isDebugValue());
729349cc55cSDimitry Andric     DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
730349cc55cSDimitry Andric                       MI.getDebugLoc()->getInlinedAt());
731349cc55cSDimitry Andric     DbgValueProperties Properties(MI);
732349cc55cSDimitry Andric     DbgValue Rec = DbgValue(MO, Properties, DbgValue::Const);
733349cc55cSDimitry Andric 
734349cc55cSDimitry Andric     // Attempt insertion; overwrite if it's already mapped.
735349cc55cSDimitry Andric     auto Result = Vars.insert(std::make_pair(Var, Rec));
736349cc55cSDimitry Andric     if (!Result.second)
737349cc55cSDimitry Andric       Result.first->second = Rec;
738349cc55cSDimitry Andric     Scopes[Var] = MI.getDebugLoc().get();
7394824e7fdSDimitry Andric 
7404824e7fdSDimitry Andric     considerOverlaps(Var, MI.getDebugLoc().get());
7414824e7fdSDimitry Andric   }
7424824e7fdSDimitry Andric 
7434824e7fdSDimitry Andric   void considerOverlaps(const DebugVariable &Var, const DILocation *Loc) {
7444824e7fdSDimitry Andric     auto Overlaps = OverlappingFragments.find(
7454824e7fdSDimitry Andric         {Var.getVariable(), Var.getFragmentOrDefault()});
7464824e7fdSDimitry Andric     if (Overlaps == OverlappingFragments.end())
7474824e7fdSDimitry Andric       return;
7484824e7fdSDimitry Andric 
7494824e7fdSDimitry Andric     // Otherwise: terminate any overlapped variable locations.
7504824e7fdSDimitry Andric     for (auto FragmentInfo : Overlaps->second) {
7514824e7fdSDimitry Andric       // The "empty" fragment is stored as DebugVariable::DefaultFragment, so
7524824e7fdSDimitry Andric       // that it overlaps with everything, however its cannonical representation
7534824e7fdSDimitry Andric       // in a DebugVariable is as "None".
7544824e7fdSDimitry Andric       Optional<DIExpression::FragmentInfo> OptFragmentInfo = FragmentInfo;
7554824e7fdSDimitry Andric       if (DebugVariable::isDefaultFragment(FragmentInfo))
7564824e7fdSDimitry Andric         OptFragmentInfo = None;
7574824e7fdSDimitry Andric 
7584824e7fdSDimitry Andric       DebugVariable Overlapped(Var.getVariable(), OptFragmentInfo,
7594824e7fdSDimitry Andric                                Var.getInlinedAt());
7604824e7fdSDimitry Andric       DbgValue Rec = DbgValue(EmptyProperties, DbgValue::Undef);
7614824e7fdSDimitry Andric 
7624824e7fdSDimitry Andric       // Attempt insertion; overwrite if it's already mapped.
7634824e7fdSDimitry Andric       auto Result = Vars.insert(std::make_pair(Overlapped, Rec));
7644824e7fdSDimitry Andric       if (!Result.second)
7654824e7fdSDimitry Andric         Result.first->second = Rec;
7664824e7fdSDimitry Andric       Scopes[Overlapped] = Loc;
7674824e7fdSDimitry Andric     }
768349cc55cSDimitry Andric   }
769d56accc7SDimitry Andric 
770d56accc7SDimitry Andric   void clear() {
771d56accc7SDimitry Andric     Vars.clear();
772d56accc7SDimitry Andric     Scopes.clear();
773d56accc7SDimitry Andric   }
774349cc55cSDimitry Andric };
775349cc55cSDimitry Andric 
776349cc55cSDimitry Andric // XXX XXX docs
777349cc55cSDimitry Andric class InstrRefBasedLDV : public LDVImpl {
778349cc55cSDimitry Andric public:
779349cc55cSDimitry Andric   friend class ::InstrRefLDVTest;
780349cc55cSDimitry Andric 
781349cc55cSDimitry Andric   using FragmentInfo = DIExpression::FragmentInfo;
782349cc55cSDimitry Andric   using OptFragmentInfo = Optional<DIExpression::FragmentInfo>;
783349cc55cSDimitry Andric 
784349cc55cSDimitry Andric   // Helper while building OverlapMap, a map of all fragments seen for a given
785349cc55cSDimitry Andric   // DILocalVariable.
786349cc55cSDimitry Andric   using VarToFragments =
787349cc55cSDimitry Andric       DenseMap<const DILocalVariable *, SmallSet<FragmentInfo, 4>>;
788349cc55cSDimitry Andric 
789349cc55cSDimitry Andric   /// Machine location/value transfer function, a mapping of which locations
790349cc55cSDimitry Andric   /// are assigned which new values.
791349cc55cSDimitry Andric   using MLocTransferMap = SmallDenseMap<LocIdx, ValueIDNum>;
792349cc55cSDimitry Andric 
793349cc55cSDimitry Andric   /// Live in/out structure for the variable values: a per-block map of
794349cc55cSDimitry Andric   /// variables to their values.
795349cc55cSDimitry Andric   using LiveIdxT = DenseMap<const MachineBasicBlock *, DbgValue *>;
796349cc55cSDimitry Andric 
797349cc55cSDimitry Andric   using VarAndLoc = std::pair<DebugVariable, DbgValue>;
798349cc55cSDimitry Andric 
799349cc55cSDimitry Andric   /// Type for a live-in value: the predecessor block, and its value.
800349cc55cSDimitry Andric   using InValueT = std::pair<MachineBasicBlock *, DbgValue *>;
801349cc55cSDimitry Andric 
802349cc55cSDimitry Andric   /// Vector (per block) of a collection (inner smallvector) of live-ins.
803349cc55cSDimitry Andric   /// Used as the result type for the variable value dataflow problem.
804349cc55cSDimitry Andric   using LiveInsT = SmallVector<SmallVector<VarAndLoc, 8>, 8>;
805349cc55cSDimitry Andric 
8061fd87a68SDimitry Andric   /// Mapping from lexical scopes to a DILocation in that scope.
8071fd87a68SDimitry Andric   using ScopeToDILocT = DenseMap<const LexicalScope *, const DILocation *>;
8081fd87a68SDimitry Andric 
8091fd87a68SDimitry Andric   /// Mapping from lexical scopes to variables in that scope.
8101fd87a68SDimitry Andric   using ScopeToVarsT = DenseMap<const LexicalScope *, SmallSet<DebugVariable, 4>>;
8111fd87a68SDimitry Andric 
8121fd87a68SDimitry Andric   /// Mapping from lexical scopes to blocks where variables in that scope are
8131fd87a68SDimitry Andric   /// assigned. Such blocks aren't necessarily "in" the lexical scope, it's
8141fd87a68SDimitry Andric   /// just a block where an assignment happens.
8151fd87a68SDimitry Andric   using ScopeToAssignBlocksT = DenseMap<const LexicalScope *, SmallPtrSet<MachineBasicBlock *, 4>>;
8161fd87a68SDimitry Andric 
817349cc55cSDimitry Andric private:
818349cc55cSDimitry Andric   MachineDominatorTree *DomTree;
819349cc55cSDimitry Andric   const TargetRegisterInfo *TRI;
820349cc55cSDimitry Andric   const MachineRegisterInfo *MRI;
821349cc55cSDimitry Andric   const TargetInstrInfo *TII;
822349cc55cSDimitry Andric   const TargetFrameLowering *TFI;
823349cc55cSDimitry Andric   const MachineFrameInfo *MFI;
824349cc55cSDimitry Andric   BitVector CalleeSavedRegs;
825349cc55cSDimitry Andric   LexicalScopes LS;
826349cc55cSDimitry Andric   TargetPassConfig *TPC;
827349cc55cSDimitry Andric 
828349cc55cSDimitry Andric   // An empty DIExpression. Used default / placeholder DbgValueProperties
829349cc55cSDimitry Andric   // objects, as we can't have null expressions.
830349cc55cSDimitry Andric   const DIExpression *EmptyExpr;
831349cc55cSDimitry Andric 
832349cc55cSDimitry Andric   /// Object to track machine locations as we step through a block. Could
833349cc55cSDimitry Andric   /// probably be a field rather than a pointer, as it's always used.
834349cc55cSDimitry Andric   MLocTracker *MTracker = nullptr;
835349cc55cSDimitry Andric 
836349cc55cSDimitry Andric   /// Number of the current block LiveDebugValues is stepping through.
837349cc55cSDimitry Andric   unsigned CurBB;
838349cc55cSDimitry Andric 
839349cc55cSDimitry Andric   /// Number of the current instruction LiveDebugValues is evaluating.
840349cc55cSDimitry Andric   unsigned CurInst;
841349cc55cSDimitry Andric 
842349cc55cSDimitry Andric   /// Variable tracker -- listens to DBG_VALUEs occurring as InstrRefBasedImpl
843349cc55cSDimitry Andric   /// steps through a block. Reads the values at each location from the
844349cc55cSDimitry Andric   /// MLocTracker object.
845349cc55cSDimitry Andric   VLocTracker *VTracker = nullptr;
846349cc55cSDimitry Andric 
847349cc55cSDimitry Andric   /// Tracker for transfers, listens to DBG_VALUEs and transfers of values
848349cc55cSDimitry Andric   /// between locations during stepping, creates new DBG_VALUEs when values move
849349cc55cSDimitry Andric   /// location.
850349cc55cSDimitry Andric   TransferTracker *TTracker = nullptr;
851349cc55cSDimitry Andric 
852349cc55cSDimitry Andric   /// Blocks which are artificial, i.e. blocks which exclusively contain
853349cc55cSDimitry Andric   /// instructions without DebugLocs, or with line 0 locations.
8541fd87a68SDimitry Andric   SmallPtrSet<MachineBasicBlock *, 16> ArtificialBlocks;
855349cc55cSDimitry Andric 
856349cc55cSDimitry Andric   // Mapping of blocks to and from their RPOT order.
857349cc55cSDimitry Andric   DenseMap<unsigned int, MachineBasicBlock *> OrderToBB;
858349cc55cSDimitry Andric   DenseMap<const MachineBasicBlock *, unsigned int> BBToOrder;
859349cc55cSDimitry Andric   DenseMap<unsigned, unsigned> BBNumToRPO;
860349cc55cSDimitry Andric 
861349cc55cSDimitry Andric   /// Pair of MachineInstr, and its 1-based offset into the containing block.
862349cc55cSDimitry Andric   using InstAndNum = std::pair<const MachineInstr *, unsigned>;
863349cc55cSDimitry Andric   /// Map from debug instruction number to the MachineInstr labelled with that
864349cc55cSDimitry Andric   /// number, and its location within the function. Used to transform
865349cc55cSDimitry Andric   /// instruction numbers in DBG_INSTR_REFs into machine value numbers.
866349cc55cSDimitry Andric   std::map<uint64_t, InstAndNum> DebugInstrNumToInstr;
867349cc55cSDimitry Andric 
868349cc55cSDimitry Andric   /// Record of where we observed a DBG_PHI instruction.
869349cc55cSDimitry Andric   class DebugPHIRecord {
870349cc55cSDimitry Andric   public:
871*81ad6265SDimitry Andric     /// Instruction number of this DBG_PHI.
872*81ad6265SDimitry Andric     uint64_t InstrNum;
873*81ad6265SDimitry Andric     /// Block where DBG_PHI occurred.
874*81ad6265SDimitry Andric     MachineBasicBlock *MBB;
875*81ad6265SDimitry Andric     /// The value number read by the DBG_PHI -- or None if it didn't refer to
876*81ad6265SDimitry Andric     /// a value.
877*81ad6265SDimitry Andric     Optional<ValueIDNum> ValueRead;
878*81ad6265SDimitry Andric     /// Register/Stack location the DBG_PHI reads -- or None if it referred to
879*81ad6265SDimitry Andric     /// something unexpected.
880*81ad6265SDimitry Andric     Optional<LocIdx> ReadLoc;
881349cc55cSDimitry Andric 
882349cc55cSDimitry Andric     operator unsigned() const { return InstrNum; }
883349cc55cSDimitry Andric   };
884349cc55cSDimitry Andric 
885349cc55cSDimitry Andric   /// Map from instruction numbers defined by DBG_PHIs to a record of what that
886349cc55cSDimitry Andric   /// DBG_PHI read and where. Populated and edited during the machine value
887349cc55cSDimitry Andric   /// location problem -- we use LLVMs SSA Updater to fix changes by
888349cc55cSDimitry Andric   /// optimizations that destroy PHI instructions.
889349cc55cSDimitry Andric   SmallVector<DebugPHIRecord, 32> DebugPHINumToValue;
890349cc55cSDimitry Andric 
891349cc55cSDimitry Andric   // Map of overlapping variable fragments.
892349cc55cSDimitry Andric   OverlapMap OverlapFragments;
893349cc55cSDimitry Andric   VarToFragments SeenFragments;
894349cc55cSDimitry Andric 
895d56accc7SDimitry Andric   /// Mapping of DBG_INSTR_REF instructions to their values, for those
896d56accc7SDimitry Andric   /// DBG_INSTR_REFs that call resolveDbgPHIs. These variable references solve
897d56accc7SDimitry Andric   /// a mini SSA problem caused by DBG_PHIs being cloned, this collection caches
898d56accc7SDimitry Andric   /// the result.
899d56accc7SDimitry Andric   DenseMap<MachineInstr *, Optional<ValueIDNum>> SeenDbgPHIs;
900d56accc7SDimitry Andric 
9014824e7fdSDimitry Andric   /// True if we need to examine call instructions for stack clobbers. We
9024824e7fdSDimitry Andric   /// normally assume that they don't clobber SP, but stack probes on Windows
9034824e7fdSDimitry Andric   /// do.
9044824e7fdSDimitry Andric   bool AdjustsStackInCalls = false;
9054824e7fdSDimitry Andric 
9064824e7fdSDimitry Andric   /// If AdjustsStackInCalls is true, this holds the name of the target's stack
9074824e7fdSDimitry Andric   /// probe function, which is the function we expect will alter the stack
9084824e7fdSDimitry Andric   /// pointer.
9094824e7fdSDimitry Andric   StringRef StackProbeSymbolName;
9104824e7fdSDimitry Andric 
911349cc55cSDimitry Andric   /// Tests whether this instruction is a spill to a stack slot.
912d56accc7SDimitry Andric   Optional<SpillLocationNo> isSpillInstruction(const MachineInstr &MI,
913d56accc7SDimitry Andric                                                MachineFunction *MF);
914349cc55cSDimitry Andric 
915349cc55cSDimitry Andric   /// Decide if @MI is a spill instruction and return true if it is. We use 2
916349cc55cSDimitry Andric   /// criteria to make this decision:
917349cc55cSDimitry Andric   /// - Is this instruction a store to a spill slot?
918349cc55cSDimitry Andric   /// - Is there a register operand that is both used and killed?
919349cc55cSDimitry Andric   /// TODO: Store optimization can fold spills into other stores (including
920349cc55cSDimitry Andric   /// other spills). We do not handle this yet (more than one memory operand).
921349cc55cSDimitry Andric   bool isLocationSpill(const MachineInstr &MI, MachineFunction *MF,
922349cc55cSDimitry Andric                        unsigned &Reg);
923349cc55cSDimitry Andric 
924349cc55cSDimitry Andric   /// If a given instruction is identified as a spill, return the spill slot
925349cc55cSDimitry Andric   /// and set \p Reg to the spilled register.
926349cc55cSDimitry Andric   Optional<SpillLocationNo> isRestoreInstruction(const MachineInstr &MI,
927349cc55cSDimitry Andric                                           MachineFunction *MF, unsigned &Reg);
928349cc55cSDimitry Andric 
929349cc55cSDimitry Andric   /// Given a spill instruction, extract the spill slot information, ensure it's
930349cc55cSDimitry Andric   /// tracked, and return the spill number.
931d56accc7SDimitry Andric   Optional<SpillLocationNo>
932d56accc7SDimitry Andric   extractSpillBaseRegAndOffset(const MachineInstr &MI);
933349cc55cSDimitry Andric 
934349cc55cSDimitry Andric   /// Observe a single instruction while stepping through a block.
935*81ad6265SDimitry Andric   void process(MachineInstr &MI, const ValueTable *MLiveOuts,
936*81ad6265SDimitry Andric                const ValueTable *MLiveIns);
937349cc55cSDimitry Andric 
938349cc55cSDimitry Andric   /// Examines whether \p MI is a DBG_VALUE and notifies trackers.
939349cc55cSDimitry Andric   /// \returns true if MI was recognized and processed.
940349cc55cSDimitry Andric   bool transferDebugValue(const MachineInstr &MI);
941349cc55cSDimitry Andric 
942349cc55cSDimitry Andric   /// Examines whether \p MI is a DBG_INSTR_REF and notifies trackers.
943349cc55cSDimitry Andric   /// \returns true if MI was recognized and processed.
944*81ad6265SDimitry Andric   bool transferDebugInstrRef(MachineInstr &MI, const ValueTable *MLiveOuts,
945*81ad6265SDimitry Andric                              const ValueTable *MLiveIns);
946349cc55cSDimitry Andric 
947349cc55cSDimitry Andric   /// Stores value-information about where this PHI occurred, and what
948349cc55cSDimitry Andric   /// instruction number is associated with it.
949349cc55cSDimitry Andric   /// \returns true if MI was recognized and processed.
950349cc55cSDimitry Andric   bool transferDebugPHI(MachineInstr &MI);
951349cc55cSDimitry Andric 
952349cc55cSDimitry Andric   /// Examines whether \p MI is copy instruction, and notifies trackers.
953349cc55cSDimitry Andric   /// \returns true if MI was recognized and processed.
954349cc55cSDimitry Andric   bool transferRegisterCopy(MachineInstr &MI);
955349cc55cSDimitry Andric 
956349cc55cSDimitry Andric   /// Examines whether \p MI is stack spill or restore  instruction, and
957349cc55cSDimitry Andric   /// notifies trackers. \returns true if MI was recognized and processed.
958349cc55cSDimitry Andric   bool transferSpillOrRestoreInst(MachineInstr &MI);
959349cc55cSDimitry Andric 
960349cc55cSDimitry Andric   /// Examines \p MI for any registers that it defines, and notifies trackers.
961349cc55cSDimitry Andric   void transferRegisterDef(MachineInstr &MI);
962349cc55cSDimitry Andric 
963349cc55cSDimitry Andric   /// Copy one location to the other, accounting for movement of subregisters
964349cc55cSDimitry Andric   /// too.
965349cc55cSDimitry Andric   void performCopy(Register Src, Register Dst);
966349cc55cSDimitry Andric 
967349cc55cSDimitry Andric   void accumulateFragmentMap(MachineInstr &MI);
968349cc55cSDimitry Andric 
969349cc55cSDimitry Andric   /// Determine the machine value number referred to by (potentially several)
970349cc55cSDimitry Andric   /// DBG_PHI instructions. Block duplication and tail folding can duplicate
971349cc55cSDimitry Andric   /// DBG_PHIs, shifting the position where values in registers merge, and
972349cc55cSDimitry Andric   /// forming another mini-ssa problem to solve.
973349cc55cSDimitry Andric   /// \p Here the position of a DBG_INSTR_REF seeking a machine value number
974349cc55cSDimitry Andric   /// \p InstrNum Debug instruction number defined by DBG_PHI instructions.
975349cc55cSDimitry Andric   /// \returns The machine value number at position Here, or None.
976349cc55cSDimitry Andric   Optional<ValueIDNum> resolveDbgPHIs(MachineFunction &MF,
977*81ad6265SDimitry Andric                                       const ValueTable *MLiveOuts,
978*81ad6265SDimitry Andric                                       const ValueTable *MLiveIns,
979*81ad6265SDimitry Andric                                       MachineInstr &Here, uint64_t InstrNum);
980349cc55cSDimitry Andric 
981d56accc7SDimitry Andric   Optional<ValueIDNum> resolveDbgPHIsImpl(MachineFunction &MF,
982*81ad6265SDimitry Andric                                           const ValueTable *MLiveOuts,
983*81ad6265SDimitry Andric                                           const ValueTable *MLiveIns,
984d56accc7SDimitry Andric                                           MachineInstr &Here,
985d56accc7SDimitry Andric                                           uint64_t InstrNum);
986d56accc7SDimitry Andric 
987349cc55cSDimitry Andric   /// Step through the function, recording register definitions and movements
988349cc55cSDimitry Andric   /// in an MLocTracker. Convert the observations into a per-block transfer
989349cc55cSDimitry Andric   /// function in \p MLocTransfer, suitable for using with the machine value
990349cc55cSDimitry Andric   /// location dataflow problem.
991349cc55cSDimitry Andric   void
992349cc55cSDimitry Andric   produceMLocTransferFunction(MachineFunction &MF,
993349cc55cSDimitry Andric                               SmallVectorImpl<MLocTransferMap> &MLocTransfer,
994349cc55cSDimitry Andric                               unsigned MaxNumBlocks);
995349cc55cSDimitry Andric 
996349cc55cSDimitry Andric   /// Solve the machine value location dataflow problem. Takes as input the
997349cc55cSDimitry Andric   /// transfer functions in \p MLocTransfer. Writes the output live-in and
998349cc55cSDimitry Andric   /// live-out arrays to the (initialized to zero) multidimensional arrays in
999349cc55cSDimitry Andric   /// \p MInLocs and \p MOutLocs. The outer dimension is indexed by block
1000349cc55cSDimitry Andric   /// number, the inner by LocIdx.
1001*81ad6265SDimitry Andric   void buildMLocValueMap(MachineFunction &MF, FuncValueTable &MInLocs,
1002*81ad6265SDimitry Andric                          FuncValueTable &MOutLocs,
1003349cc55cSDimitry Andric                          SmallVectorImpl<MLocTransferMap> &MLocTransfer);
1004349cc55cSDimitry Andric 
1005349cc55cSDimitry Andric   /// Examine the stack indexes (i.e. offsets within the stack) to find the
1006349cc55cSDimitry Andric   /// basic units of interference -- like reg units, but for the stack.
1007349cc55cSDimitry Andric   void findStackIndexInterference(SmallVectorImpl<unsigned> &Slots);
1008349cc55cSDimitry Andric 
1009349cc55cSDimitry Andric   /// Install PHI values into the live-in array for each block, according to
1010349cc55cSDimitry Andric   /// the IDF of each register.
1011349cc55cSDimitry Andric   void placeMLocPHIs(MachineFunction &MF,
1012349cc55cSDimitry Andric                      SmallPtrSetImpl<MachineBasicBlock *> &AllBlocks,
1013*81ad6265SDimitry Andric                      FuncValueTable &MInLocs,
1014349cc55cSDimitry Andric                      SmallVectorImpl<MLocTransferMap> &MLocTransfer);
1015349cc55cSDimitry Andric 
10161fd87a68SDimitry Andric   /// Propagate variable values to blocks in the common case where there's
10171fd87a68SDimitry Andric   /// only one value assigned to the variable. This function has better
10181fd87a68SDimitry Andric   /// performance as it doesn't have to find the dominance frontier between
10191fd87a68SDimitry Andric   /// different assignments.
10201fd87a68SDimitry Andric   void placePHIsForSingleVarDefinition(
10211fd87a68SDimitry Andric           const SmallPtrSetImpl<MachineBasicBlock *> &InScopeBlocks,
10221fd87a68SDimitry Andric           MachineBasicBlock *MBB, SmallVectorImpl<VLocTracker> &AllTheVLocs,
10231fd87a68SDimitry Andric           const DebugVariable &Var, LiveInsT &Output);
10241fd87a68SDimitry Andric 
1025349cc55cSDimitry Andric   /// Calculate the iterated-dominance-frontier for a set of defs, using the
1026349cc55cSDimitry Andric   /// existing LLVM facilities for this. Works for a single "value" or
1027349cc55cSDimitry Andric   /// machine/variable location.
1028349cc55cSDimitry Andric   /// \p AllBlocks Set of blocks where we might consume the value.
1029349cc55cSDimitry Andric   /// \p DefBlocks Set of blocks where the value/location is defined.
1030349cc55cSDimitry Andric   /// \p PHIBlocks Output set of blocks where PHIs must be placed.
1031349cc55cSDimitry Andric   void BlockPHIPlacement(const SmallPtrSetImpl<MachineBasicBlock *> &AllBlocks,
1032349cc55cSDimitry Andric                          const SmallPtrSetImpl<MachineBasicBlock *> &DefBlocks,
1033349cc55cSDimitry Andric                          SmallVectorImpl<MachineBasicBlock *> &PHIBlocks);
1034349cc55cSDimitry Andric 
1035349cc55cSDimitry Andric   /// Perform a control flow join (lattice value meet) of the values in machine
1036349cc55cSDimitry Andric   /// locations at \p MBB. Follows the algorithm described in the file-comment,
1037349cc55cSDimitry Andric   /// reading live-outs of predecessors from \p OutLocs, the current live ins
1038349cc55cSDimitry Andric   /// from \p InLocs, and assigning the newly computed live ins back into
1039349cc55cSDimitry Andric   /// \p InLocs. \returns two bools -- the first indicates whether a change
1040349cc55cSDimitry Andric   /// was made, the second whether a lattice downgrade occurred. If the latter
1041349cc55cSDimitry Andric   /// is true, revisiting this block is necessary.
1042349cc55cSDimitry Andric   bool mlocJoin(MachineBasicBlock &MBB,
1043349cc55cSDimitry Andric                 SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
1044*81ad6265SDimitry Andric                 FuncValueTable &OutLocs, ValueTable &InLocs);
1045349cc55cSDimitry Andric 
10461fd87a68SDimitry Andric   /// Produce a set of blocks that are in the current lexical scope. This means
10471fd87a68SDimitry Andric   /// those blocks that contain instructions "in" the scope, blocks where
10481fd87a68SDimitry Andric   /// assignments to variables in scope occur, and artificial blocks that are
10491fd87a68SDimitry Andric   /// successors to any of the earlier blocks. See https://llvm.org/PR48091 for
10501fd87a68SDimitry Andric   /// more commentry on what "in scope" means.
10511fd87a68SDimitry Andric   /// \p DILoc A location in the scope that we're fetching blocks for.
10521fd87a68SDimitry Andric   /// \p Output Set to put in-scope-blocks into.
10531fd87a68SDimitry Andric   /// \p AssignBlocks Blocks known to contain assignments of variables in scope.
10541fd87a68SDimitry Andric   void
10551fd87a68SDimitry Andric   getBlocksForScope(const DILocation *DILoc,
10561fd87a68SDimitry Andric                     SmallPtrSetImpl<const MachineBasicBlock *> &Output,
10571fd87a68SDimitry Andric                     const SmallPtrSetImpl<MachineBasicBlock *> &AssignBlocks);
10581fd87a68SDimitry Andric 
1059349cc55cSDimitry Andric   /// Solve the variable value dataflow problem, for a single lexical scope.
1060349cc55cSDimitry Andric   /// Uses the algorithm from the file comment to resolve control flow joins
1061349cc55cSDimitry Andric   /// using PHI placement and value propagation. Reads the locations of machine
1062349cc55cSDimitry Andric   /// values from the \p MInLocs and \p MOutLocs arrays (see buildMLocValueMap)
1063349cc55cSDimitry Andric   /// and reads the variable values transfer function from \p AllTheVlocs.
1064349cc55cSDimitry Andric   /// Live-in and Live-out variable values are stored locally, with the live-ins
1065349cc55cSDimitry Andric   /// permanently stored to \p Output once a fixedpoint is reached.
1066349cc55cSDimitry Andric   /// \p VarsWeCareAbout contains a collection of the variables in \p Scope
1067349cc55cSDimitry Andric   /// that we should be tracking.
1068349cc55cSDimitry Andric   /// \p AssignBlocks contains the set of blocks that aren't in \p DILoc's
1069349cc55cSDimitry Andric   /// scope, but which do contain DBG_VALUEs, which VarLocBasedImpl tracks
1070349cc55cSDimitry Andric   /// locations through.
1071349cc55cSDimitry Andric   void buildVLocValueMap(const DILocation *DILoc,
1072349cc55cSDimitry Andric                          const SmallSet<DebugVariable, 4> &VarsWeCareAbout,
1073349cc55cSDimitry Andric                          SmallPtrSetImpl<MachineBasicBlock *> &AssignBlocks,
1074*81ad6265SDimitry Andric                          LiveInsT &Output, FuncValueTable &MOutLocs,
1075*81ad6265SDimitry Andric                          FuncValueTable &MInLocs,
1076349cc55cSDimitry Andric                          SmallVectorImpl<VLocTracker> &AllTheVLocs);
1077349cc55cSDimitry Andric 
1078349cc55cSDimitry Andric   /// Attempt to eliminate un-necessary PHIs on entry to a block. Examines the
1079349cc55cSDimitry Andric   /// live-in values coming from predecessors live-outs, and replaces any PHIs
1080349cc55cSDimitry Andric   /// already present in this blocks live-ins with a live-through value if the
1081349cc55cSDimitry Andric   /// PHI isn't needed.
1082349cc55cSDimitry Andric   /// \p LiveIn Old live-in value, overwritten with new one if live-in changes.
1083349cc55cSDimitry Andric   /// \returns true if any live-ins change value, either from value propagation
1084349cc55cSDimitry Andric   ///          or PHI elimination.
1085349cc55cSDimitry Andric   bool vlocJoin(MachineBasicBlock &MBB, LiveIdxT &VLOCOutLocs,
1086349cc55cSDimitry Andric                 SmallPtrSet<const MachineBasicBlock *, 8> &BlocksToExplore,
1087349cc55cSDimitry Andric                 DbgValue &LiveIn);
1088349cc55cSDimitry Andric 
1089349cc55cSDimitry Andric   /// For the given block and live-outs feeding into it, try to find a
1090349cc55cSDimitry Andric   /// machine location where all the variable values join together.
1091349cc55cSDimitry Andric   /// \returns Value ID of a machine PHI if an appropriate one is available.
1092349cc55cSDimitry Andric   Optional<ValueIDNum>
1093349cc55cSDimitry Andric   pickVPHILoc(const MachineBasicBlock &MBB, const DebugVariable &Var,
1094*81ad6265SDimitry Andric               const LiveIdxT &LiveOuts, FuncValueTable &MOutLocs,
1095349cc55cSDimitry Andric               const SmallVectorImpl<const MachineBasicBlock *> &BlockOrders);
1096349cc55cSDimitry Andric 
10971fd87a68SDimitry Andric   /// Take collections of DBG_VALUE instructions stored in TTracker, and
10981fd87a68SDimitry Andric   /// install them into their output blocks. Preserves a stable order of
10991fd87a68SDimitry Andric   /// DBG_VALUEs produced (which would otherwise cause nondeterminism) through
11001fd87a68SDimitry Andric   /// the AllVarsNumbering order.
11011fd87a68SDimitry Andric   bool emitTransfers(DenseMap<DebugVariable, unsigned> &AllVarsNumbering);
11021fd87a68SDimitry Andric 
1103349cc55cSDimitry Andric   /// Boilerplate computation of some initial sets, artifical blocks and
1104349cc55cSDimitry Andric   /// RPOT block ordering.
1105349cc55cSDimitry Andric   void initialSetup(MachineFunction &MF);
1106349cc55cSDimitry Andric 
1107d56accc7SDimitry Andric   /// Produce a map of the last lexical scope that uses a block, using the
1108d56accc7SDimitry Andric   /// scopes DFSOut number. Mapping is block-number to DFSOut.
1109d56accc7SDimitry Andric   /// \p EjectionMap Pre-allocated vector in which to install the built ma.
1110d56accc7SDimitry Andric   /// \p ScopeToDILocation Mapping of LexicalScopes to their DILocations.
1111d56accc7SDimitry Andric   /// \p AssignBlocks Map of blocks where assignments happen for a scope.
1112d56accc7SDimitry Andric   void makeDepthFirstEjectionMap(SmallVectorImpl<unsigned> &EjectionMap,
1113d56accc7SDimitry Andric                                  const ScopeToDILocT &ScopeToDILocation,
1114d56accc7SDimitry Andric                                  ScopeToAssignBlocksT &AssignBlocks);
1115d56accc7SDimitry Andric 
1116d56accc7SDimitry Andric   /// When determining per-block variable values and emitting to DBG_VALUEs,
1117d56accc7SDimitry Andric   /// this function explores by lexical scope depth. Doing so means that per
1118d56accc7SDimitry Andric   /// block information can be fully computed before exploration finishes,
1119d56accc7SDimitry Andric   /// allowing us to emit it and free data structures earlier than otherwise.
1120d56accc7SDimitry Andric   /// It's also good for locality.
1121d56accc7SDimitry Andric   bool depthFirstVLocAndEmit(
1122d56accc7SDimitry Andric       unsigned MaxNumBlocks, const ScopeToDILocT &ScopeToDILocation,
1123d56accc7SDimitry Andric       const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToBlocks,
1124*81ad6265SDimitry Andric       LiveInsT &Output, FuncValueTable &MOutLocs, FuncValueTable &MInLocs,
1125d56accc7SDimitry Andric       SmallVectorImpl<VLocTracker> &AllTheVLocs, MachineFunction &MF,
1126d56accc7SDimitry Andric       DenseMap<DebugVariable, unsigned> &AllVarsNumbering,
1127d56accc7SDimitry Andric       const TargetPassConfig &TPC);
1128d56accc7SDimitry Andric 
1129349cc55cSDimitry Andric   bool ExtendRanges(MachineFunction &MF, MachineDominatorTree *DomTree,
1130349cc55cSDimitry Andric                     TargetPassConfig *TPC, unsigned InputBBLimit,
1131349cc55cSDimitry Andric                     unsigned InputDbgValLimit) override;
1132349cc55cSDimitry Andric 
1133349cc55cSDimitry Andric public:
1134349cc55cSDimitry Andric   /// Default construct and initialize the pass.
1135349cc55cSDimitry Andric   InstrRefBasedLDV();
1136349cc55cSDimitry Andric 
1137349cc55cSDimitry Andric   LLVM_DUMP_METHOD
1138349cc55cSDimitry Andric   void dump_mloc_transfer(const MLocTransferMap &mloc_transfer) const;
1139349cc55cSDimitry Andric 
1140349cc55cSDimitry Andric   bool isCalleeSaved(LocIdx L) const;
1141349cc55cSDimitry Andric 
1142349cc55cSDimitry Andric   bool hasFoldedStackStore(const MachineInstr &MI) {
1143349cc55cSDimitry Andric     // Instruction must have a memory operand that's a stack slot, and isn't
1144349cc55cSDimitry Andric     // aliased, meaning it's a spill from regalloc instead of a variable.
1145349cc55cSDimitry Andric     // If it's aliased, we can't guarantee its value.
1146349cc55cSDimitry Andric     if (!MI.hasOneMemOperand())
1147349cc55cSDimitry Andric       return false;
1148349cc55cSDimitry Andric     auto *MemOperand = *MI.memoperands_begin();
1149349cc55cSDimitry Andric     return MemOperand->isStore() &&
1150349cc55cSDimitry Andric            MemOperand->getPseudoValue() &&
1151349cc55cSDimitry Andric            MemOperand->getPseudoValue()->kind() == PseudoSourceValue::FixedStack
1152349cc55cSDimitry Andric            && !MemOperand->getPseudoValue()->isAliased(MFI);
1153349cc55cSDimitry Andric   }
1154349cc55cSDimitry Andric 
1155349cc55cSDimitry Andric   Optional<LocIdx> findLocationForMemOperand(const MachineInstr &MI);
1156349cc55cSDimitry Andric };
1157349cc55cSDimitry Andric 
1158349cc55cSDimitry Andric } // namespace LiveDebugValues
1159349cc55cSDimitry Andric 
1160349cc55cSDimitry Andric namespace llvm {
1161349cc55cSDimitry Andric using namespace LiveDebugValues;
1162349cc55cSDimitry Andric 
1163349cc55cSDimitry Andric template <> struct DenseMapInfo<LocIdx> {
1164349cc55cSDimitry Andric   static inline LocIdx getEmptyKey() { return LocIdx::MakeIllegalLoc(); }
1165349cc55cSDimitry Andric   static inline LocIdx getTombstoneKey() { return LocIdx::MakeTombstoneLoc(); }
1166349cc55cSDimitry Andric 
1167349cc55cSDimitry Andric   static unsigned getHashValue(const LocIdx &Loc) { return Loc.asU64(); }
1168349cc55cSDimitry Andric 
1169349cc55cSDimitry Andric   static bool isEqual(const LocIdx &A, const LocIdx &B) { return A == B; }
1170349cc55cSDimitry Andric };
1171349cc55cSDimitry Andric 
1172349cc55cSDimitry Andric template <> struct DenseMapInfo<ValueIDNum> {
1173349cc55cSDimitry Andric   static inline ValueIDNum getEmptyKey() { return ValueIDNum::EmptyValue; }
1174349cc55cSDimitry Andric   static inline ValueIDNum getTombstoneKey() {
1175349cc55cSDimitry Andric     return ValueIDNum::TombstoneValue;
1176349cc55cSDimitry Andric   }
1177349cc55cSDimitry Andric 
117804eeddc0SDimitry Andric   static unsigned getHashValue(const ValueIDNum &Val) {
117904eeddc0SDimitry Andric     return hash_value(Val.asU64());
118004eeddc0SDimitry Andric   }
1181349cc55cSDimitry Andric 
1182349cc55cSDimitry Andric   static bool isEqual(const ValueIDNum &A, const ValueIDNum &B) {
1183349cc55cSDimitry Andric     return A == B;
1184349cc55cSDimitry Andric   }
1185349cc55cSDimitry Andric };
1186349cc55cSDimitry Andric 
1187349cc55cSDimitry Andric } // end namespace llvm
1188349cc55cSDimitry Andric 
1189349cc55cSDimitry Andric #endif /* LLVM_LIB_CODEGEN_LIVEDEBUGVALUES_INSTRREFBASEDLDV_H */
1190