1af732203SDimitry Andric //===- VarLocBasedImpl.cpp - Tracking Debug Value MIs with VarLoc class----===//
2af732203SDimitry Andric //
3af732203SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4af732203SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5af732203SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6af732203SDimitry Andric //
7af732203SDimitry Andric //===----------------------------------------------------------------------===//
8af732203SDimitry Andric ///
9af732203SDimitry Andric /// \file VarLocBasedImpl.cpp
10af732203SDimitry Andric ///
11af732203SDimitry Andric /// LiveDebugValues is an optimistic "available expressions" dataflow
12af732203SDimitry Andric /// algorithm. The set of expressions is the set of machine locations
13af732203SDimitry Andric /// (registers, spill slots, constants) that a variable fragment might be
14af732203SDimitry Andric /// located, qualified by a DIExpression and indirect-ness flag, while each
15af732203SDimitry Andric /// variable is identified by a DebugVariable object. The availability of an
16af732203SDimitry Andric /// expression begins when a DBG_VALUE instruction specifies the location of a
17af732203SDimitry Andric /// DebugVariable, and continues until that location is clobbered or
18af732203SDimitry Andric /// re-specified by a different DBG_VALUE for the same DebugVariable.
19af732203SDimitry Andric ///
20af732203SDimitry Andric /// The output of LiveDebugValues is additional DBG_VALUE instructions,
21af732203SDimitry Andric /// placed to extend variable locations as far they're available. This file
22af732203SDimitry Andric /// and the VarLocBasedLDV class is an implementation that explicitly tracks
23af732203SDimitry Andric /// locations, using the VarLoc class.
24af732203SDimitry Andric ///
25af732203SDimitry Andric /// The canonical "available expressions" problem doesn't have expression
26af732203SDimitry Andric /// clobbering, instead when a variable is re-assigned, any expressions using
27af732203SDimitry Andric /// that variable get invalidated. LiveDebugValues can map onto "available
28af732203SDimitry Andric /// expressions" by having every register represented by a variable, which is
29af732203SDimitry Andric /// used in an expression that becomes available at a DBG_VALUE instruction.
30af732203SDimitry Andric /// When the register is clobbered, its variable is effectively reassigned, and
31af732203SDimitry Andric /// expressions computed from it become unavailable. A similar construct is
32af732203SDimitry Andric /// needed when a DebugVariable has its location re-specified, to invalidate
33af732203SDimitry Andric /// all other locations for that DebugVariable.
34af732203SDimitry Andric ///
35af732203SDimitry Andric /// Using the dataflow analysis to compute the available expressions, we create
36af732203SDimitry Andric /// a DBG_VALUE at the beginning of each block where the expression is
37af732203SDimitry Andric /// live-in. This propagates variable locations into every basic block where
38af732203SDimitry Andric /// the location can be determined, rather than only having DBG_VALUEs in blocks
39af732203SDimitry Andric /// where locations are specified due to an assignment or some optimization.
40af732203SDimitry Andric /// Movements of values between registers and spill slots are annotated with
41af732203SDimitry Andric /// DBG_VALUEs too to track variable values bewteen locations. All this allows
42af732203SDimitry Andric /// DbgEntityHistoryCalculator to focus on only the locations within individual
43af732203SDimitry Andric /// blocks, facilitating testing and improving modularity.
44af732203SDimitry Andric ///
45af732203SDimitry Andric /// We follow an optimisic dataflow approach, with this lattice:
46af732203SDimitry Andric ///
47af732203SDimitry Andric /// \verbatim
48af732203SDimitry Andric /// ┬ "Unknown"
49af732203SDimitry Andric /// |
50af732203SDimitry Andric /// v
51af732203SDimitry Andric /// True
52af732203SDimitry Andric /// |
53af732203SDimitry Andric /// v
54af732203SDimitry Andric /// ⊥ False
55af732203SDimitry Andric /// \endverbatim With "True" signifying that the expression is available (and
56af732203SDimitry Andric /// thus a DebugVariable's location is the corresponding register), while
57af732203SDimitry Andric /// "False" signifies that the expression is unavailable. "Unknown"s never
58af732203SDimitry Andric /// survive to the end of the analysis (see below).
59af732203SDimitry Andric ///
60af732203SDimitry Andric /// Formally, all DebugVariable locations that are live-out of a block are
61af732203SDimitry Andric /// initialized to \top. A blocks live-in values take the meet of the lattice
62af732203SDimitry Andric /// value for every predecessors live-outs, except for the entry block, where
63af732203SDimitry Andric /// all live-ins are \bot. The usual dataflow propagation occurs: the transfer
64af732203SDimitry Andric /// function for a block assigns an expression for a DebugVariable to be "True"
65af732203SDimitry Andric /// if a DBG_VALUE in the block specifies it; "False" if the location is
66af732203SDimitry Andric /// clobbered; or the live-in value if it is unaffected by the block. We
67af732203SDimitry Andric /// visit each block in reverse post order until a fixedpoint is reached. The
68af732203SDimitry Andric /// solution produced is maximal.
69af732203SDimitry Andric ///
70af732203SDimitry Andric /// Intuitively, we start by assuming that every expression / variable location
71af732203SDimitry Andric /// is at least "True", and then propagate "False" from the entry block and any
72af732203SDimitry Andric /// clobbers until there are no more changes to make. This gives us an accurate
73af732203SDimitry Andric /// solution because all incorrect locations will have a "False" propagated into
74af732203SDimitry Andric /// them. It also gives us a solution that copes well with loops by assuming
75af732203SDimitry Andric /// that variable locations are live-through every loop, and then removing those
76af732203SDimitry Andric /// that are not through dataflow.
77af732203SDimitry Andric ///
78af732203SDimitry Andric /// Within LiveDebugValues: each variable location is represented by a
79*5f7ddb14SDimitry Andric /// VarLoc object that identifies the source variable, the set of
80*5f7ddb14SDimitry Andric /// machine-locations that currently describe it (a single location for
81*5f7ddb14SDimitry Andric /// DBG_VALUE or multiple for DBG_VALUE_LIST), and the DBG_VALUE inst that
82*5f7ddb14SDimitry Andric /// specifies the location. Each VarLoc is indexed in the (function-scope) \p
83*5f7ddb14SDimitry Andric /// VarLocMap, giving each VarLoc a set of unique indexes, each of which
84*5f7ddb14SDimitry Andric /// corresponds to one of the VarLoc's machine-locations and can be used to
85*5f7ddb14SDimitry Andric /// lookup the VarLoc in the VarLocMap. Rather than operate directly on machine
86*5f7ddb14SDimitry Andric /// locations, the dataflow analysis in this pass identifies locations by their
87*5f7ddb14SDimitry Andric /// indices in the VarLocMap, meaning all the variable locations in a block can
88*5f7ddb14SDimitry Andric /// be described by a sparse vector of VarLocMap indicies.
89af732203SDimitry Andric ///
90af732203SDimitry Andric /// All the storage for the dataflow analysis is local to the ExtendRanges
91af732203SDimitry Andric /// method and passed down to helper methods. "OutLocs" and "InLocs" record the
92af732203SDimitry Andric /// in and out lattice values for each block. "OpenRanges" maintains a list of
93af732203SDimitry Andric /// variable locations and, with the "process" method, evaluates the transfer
94*5f7ddb14SDimitry Andric /// function of each block. "flushPendingLocs" installs debug value instructions
95*5f7ddb14SDimitry Andric /// for each live-in location at the start of blocks, while "Transfers" records
96af732203SDimitry Andric /// transfers of values between machine-locations.
97af732203SDimitry Andric ///
98af732203SDimitry Andric /// We avoid explicitly representing the "Unknown" (\top) lattice value in the
99af732203SDimitry Andric /// implementation. Instead, unvisited blocks implicitly have all lattice
100af732203SDimitry Andric /// values set as "Unknown". After being visited, there will be path back to
101af732203SDimitry Andric /// the entry block where the lattice value is "False", and as the transfer
102af732203SDimitry Andric /// function cannot make new "Unknown" locations, there are no scenarios where
103af732203SDimitry Andric /// a block can have an "Unknown" location after being visited. Similarly, we
104af732203SDimitry Andric /// don't enumerate all possible variable locations before exploring the
105af732203SDimitry Andric /// function: when a new location is discovered, all blocks previously explored
106af732203SDimitry Andric /// were implicitly "False" but unrecorded, and become explicitly "False" when
107af732203SDimitry Andric /// a new VarLoc is created with its bit not set in predecessor InLocs or
108af732203SDimitry Andric /// OutLocs.
109af732203SDimitry Andric ///
110af732203SDimitry Andric //===----------------------------------------------------------------------===//
111af732203SDimitry Andric
112af732203SDimitry Andric #include "LiveDebugValues.h"
113af732203SDimitry Andric
114af732203SDimitry Andric #include "llvm/ADT/CoalescingBitVector.h"
115af732203SDimitry Andric #include "llvm/ADT/DenseMap.h"
116af732203SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
117af732203SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
118af732203SDimitry Andric #include "llvm/ADT/SmallSet.h"
119af732203SDimitry Andric #include "llvm/ADT/SmallVector.h"
120af732203SDimitry Andric #include "llvm/ADT/Statistic.h"
121af732203SDimitry Andric #include "llvm/ADT/UniqueVector.h"
122af732203SDimitry Andric #include "llvm/CodeGen/LexicalScopes.h"
123af732203SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
124af732203SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
125af732203SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
126af732203SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
127af732203SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
128af732203SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
129af732203SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
130af732203SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
131af732203SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h"
132af732203SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h"
133af732203SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
134af732203SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
135af732203SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
136af732203SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
137af732203SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
138af732203SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
139af732203SDimitry Andric #include "llvm/Config/llvm-config.h"
140af732203SDimitry Andric #include "llvm/IR/DIBuilder.h"
141af732203SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
142af732203SDimitry Andric #include "llvm/IR/DebugLoc.h"
143af732203SDimitry Andric #include "llvm/IR/Function.h"
144af732203SDimitry Andric #include "llvm/IR/Module.h"
145af732203SDimitry Andric #include "llvm/InitializePasses.h"
146af732203SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
147af732203SDimitry Andric #include "llvm/Pass.h"
148af732203SDimitry Andric #include "llvm/Support/Casting.h"
149af732203SDimitry Andric #include "llvm/Support/Compiler.h"
150af732203SDimitry Andric #include "llvm/Support/Debug.h"
151af732203SDimitry Andric #include "llvm/Support/TypeSize.h"
152af732203SDimitry Andric #include "llvm/Support/raw_ostream.h"
153af732203SDimitry Andric #include "llvm/Target/TargetMachine.h"
154af732203SDimitry Andric #include <algorithm>
155af732203SDimitry Andric #include <cassert>
156af732203SDimitry Andric #include <cstdint>
157af732203SDimitry Andric #include <functional>
158af732203SDimitry Andric #include <queue>
159af732203SDimitry Andric #include <tuple>
160af732203SDimitry Andric #include <utility>
161af732203SDimitry Andric #include <vector>
162af732203SDimitry Andric
163af732203SDimitry Andric using namespace llvm;
164af732203SDimitry Andric
165af732203SDimitry Andric #define DEBUG_TYPE "livedebugvalues"
166af732203SDimitry Andric
167af732203SDimitry Andric STATISTIC(NumInserted, "Number of DBG_VALUE instructions inserted");
168af732203SDimitry Andric
169af732203SDimitry Andric // Options to prevent pathological compile-time behavior. If InputBBLimit and
170af732203SDimitry Andric // InputDbgValueLimit are both exceeded, range extension is disabled.
171af732203SDimitry Andric static cl::opt<unsigned> InputBBLimit(
172af732203SDimitry Andric "livedebugvalues-input-bb-limit",
173af732203SDimitry Andric cl::desc("Maximum input basic blocks before DBG_VALUE limit applies"),
174af732203SDimitry Andric cl::init(10000), cl::Hidden);
175af732203SDimitry Andric static cl::opt<unsigned> InputDbgValueLimit(
176af732203SDimitry Andric "livedebugvalues-input-dbg-value-limit",
177af732203SDimitry Andric cl::desc(
178af732203SDimitry Andric "Maximum input DBG_VALUE insts supported by debug range extension"),
179af732203SDimitry Andric cl::init(50000), cl::Hidden);
180af732203SDimitry Andric
181af732203SDimitry Andric /// If \p Op is a stack or frame register return true, otherwise return false.
182af732203SDimitry Andric /// This is used to avoid basing the debug entry values on the registers, since
183af732203SDimitry Andric /// we do not support it at the moment.
isRegOtherThanSPAndFP(const MachineOperand & Op,const MachineInstr & MI,const TargetRegisterInfo * TRI)184af732203SDimitry Andric static bool isRegOtherThanSPAndFP(const MachineOperand &Op,
185af732203SDimitry Andric const MachineInstr &MI,
186af732203SDimitry Andric const TargetRegisterInfo *TRI) {
187af732203SDimitry Andric if (!Op.isReg())
188af732203SDimitry Andric return false;
189af732203SDimitry Andric
190af732203SDimitry Andric const MachineFunction *MF = MI.getParent()->getParent();
191af732203SDimitry Andric const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
192af732203SDimitry Andric Register SP = TLI->getStackPointerRegisterToSaveRestore();
193af732203SDimitry Andric Register FP = TRI->getFrameRegister(*MF);
194af732203SDimitry Andric Register Reg = Op.getReg();
195af732203SDimitry Andric
196af732203SDimitry Andric return Reg && Reg != SP && Reg != FP;
197af732203SDimitry Andric }
198af732203SDimitry Andric
199af732203SDimitry Andric namespace {
200af732203SDimitry Andric
201af732203SDimitry Andric // Max out the number of statically allocated elements in DefinedRegsSet, as
202af732203SDimitry Andric // this prevents fallback to std::set::count() operations.
203af732203SDimitry Andric using DefinedRegsSet = SmallSet<Register, 32>;
204af732203SDimitry Andric
205*5f7ddb14SDimitry Andric // The IDs in this set correspond to MachineLocs in VarLocs, as well as VarLocs
206*5f7ddb14SDimitry Andric // that represent Entry Values; every VarLoc in the set will also appear
207*5f7ddb14SDimitry Andric // exactly once at Location=0.
208*5f7ddb14SDimitry Andric // As a result, each VarLoc may appear more than once in this "set", but each
209*5f7ddb14SDimitry Andric // range corresponding to a Reg, SpillLoc, or EntryValue type will still be a
210*5f7ddb14SDimitry Andric // "true" set (i.e. each VarLoc may appear only once), and the range Location=0
211*5f7ddb14SDimitry Andric // is the set of all VarLocs.
212af732203SDimitry Andric using VarLocSet = CoalescingBitVector<uint64_t>;
213af732203SDimitry Andric
214af732203SDimitry Andric /// A type-checked pair of {Register Location (or 0), Index}, used to index
215af732203SDimitry Andric /// into a \ref VarLocMap. This can be efficiently converted to a 64-bit int
216af732203SDimitry Andric /// for insertion into a \ref VarLocSet, and efficiently converted back. The
217af732203SDimitry Andric /// type-checker helps ensure that the conversions aren't lossy.
218af732203SDimitry Andric ///
219af732203SDimitry Andric /// Why encode a location /into/ the VarLocMap index? This makes it possible
220af732203SDimitry Andric /// to find the open VarLocs killed by a register def very quickly. This is a
221af732203SDimitry Andric /// performance-critical operation for LiveDebugValues.
222af732203SDimitry Andric struct LocIndex {
223af732203SDimitry Andric using u32_location_t = uint32_t;
224af732203SDimitry Andric using u32_index_t = uint32_t;
225af732203SDimitry Andric
226af732203SDimitry Andric u32_location_t Location; // Physical registers live in the range [1;2^30) (see
227af732203SDimitry Andric // \ref MCRegister), so we have plenty of range left
228af732203SDimitry Andric // here to encode non-register locations.
229af732203SDimitry Andric u32_index_t Index;
230af732203SDimitry Andric
231*5f7ddb14SDimitry Andric /// The location that has an entry for every VarLoc in the map.
232*5f7ddb14SDimitry Andric static constexpr u32_location_t kUniversalLocation = 0;
233*5f7ddb14SDimitry Andric
234*5f7ddb14SDimitry Andric /// The first location that is reserved for VarLocs with locations of kind
235*5f7ddb14SDimitry Andric /// RegisterKind.
236*5f7ddb14SDimitry Andric static constexpr u32_location_t kFirstRegLocation = 1;
237*5f7ddb14SDimitry Andric
238*5f7ddb14SDimitry Andric /// The first location greater than 0 that is not reserved for VarLocs with
239*5f7ddb14SDimitry Andric /// locations of kind RegisterKind.
240af732203SDimitry Andric static constexpr u32_location_t kFirstInvalidRegLocation = 1 << 30;
241af732203SDimitry Andric
242*5f7ddb14SDimitry Andric /// A special location reserved for VarLocs with locations of kind
243*5f7ddb14SDimitry Andric /// SpillLocKind.
244af732203SDimitry Andric static constexpr u32_location_t kSpillLocation = kFirstInvalidRegLocation;
245af732203SDimitry Andric
246af732203SDimitry Andric /// A special location reserved for VarLocs of kind EntryValueBackupKind and
247af732203SDimitry Andric /// EntryValueCopyBackupKind.
248af732203SDimitry Andric static constexpr u32_location_t kEntryValueBackupLocation =
249af732203SDimitry Andric kFirstInvalidRegLocation + 1;
250af732203SDimitry Andric
LocIndex__anon9749acf60111::LocIndex251af732203SDimitry Andric LocIndex(u32_location_t Location, u32_index_t Index)
252af732203SDimitry Andric : Location(Location), Index(Index) {}
253af732203SDimitry Andric
getAsRawInteger__anon9749acf60111::LocIndex254af732203SDimitry Andric uint64_t getAsRawInteger() const {
255af732203SDimitry Andric return (static_cast<uint64_t>(Location) << 32) | Index;
256af732203SDimitry Andric }
257af732203SDimitry Andric
fromRawInteger__anon9749acf60111::LocIndex258af732203SDimitry Andric template<typename IntT> static LocIndex fromRawInteger(IntT ID) {
259af732203SDimitry Andric static_assert(std::is_unsigned<IntT>::value &&
260af732203SDimitry Andric sizeof(ID) == sizeof(uint64_t),
261af732203SDimitry Andric "Cannot convert raw integer to LocIndex");
262af732203SDimitry Andric return {static_cast<u32_location_t>(ID >> 32),
263af732203SDimitry Andric static_cast<u32_index_t>(ID)};
264af732203SDimitry Andric }
265af732203SDimitry Andric
266af732203SDimitry Andric /// Get the start of the interval reserved for VarLocs of kind RegisterKind
267af732203SDimitry Andric /// which reside in \p Reg. The end is at rawIndexForReg(Reg+1)-1.
rawIndexForReg__anon9749acf60111::LocIndex268*5f7ddb14SDimitry Andric static uint64_t rawIndexForReg(Register Reg) {
269af732203SDimitry Andric return LocIndex(Reg, 0).getAsRawInteger();
270af732203SDimitry Andric }
271af732203SDimitry Andric
272af732203SDimitry Andric /// Return a range covering all set indices in the interval reserved for
273af732203SDimitry Andric /// \p Location in \p Set.
indexRangeForLocation__anon9749acf60111::LocIndex274af732203SDimitry Andric static auto indexRangeForLocation(const VarLocSet &Set,
275af732203SDimitry Andric u32_location_t Location) {
276af732203SDimitry Andric uint64_t Start = LocIndex(Location, 0).getAsRawInteger();
277af732203SDimitry Andric uint64_t End = LocIndex(Location + 1, 0).getAsRawInteger();
278af732203SDimitry Andric return Set.half_open_range(Start, End);
279af732203SDimitry Andric }
280af732203SDimitry Andric };
281af732203SDimitry Andric
282*5f7ddb14SDimitry Andric // Simple Set for storing all the VarLoc Indices at a Location bucket.
283*5f7ddb14SDimitry Andric using VarLocsInRange = SmallSet<LocIndex::u32_index_t, 32>;
284*5f7ddb14SDimitry Andric // Vector of all `LocIndex`s for a given VarLoc; the same Location should not
285*5f7ddb14SDimitry Andric // appear in any two of these, as each VarLoc appears at most once in any
286*5f7ddb14SDimitry Andric // Location bucket.
287*5f7ddb14SDimitry Andric using LocIndices = SmallVector<LocIndex, 2>;
288*5f7ddb14SDimitry Andric
289af732203SDimitry Andric class VarLocBasedLDV : public LDVImpl {
290af732203SDimitry Andric private:
291af732203SDimitry Andric const TargetRegisterInfo *TRI;
292af732203SDimitry Andric const TargetInstrInfo *TII;
293af732203SDimitry Andric const TargetFrameLowering *TFI;
294af732203SDimitry Andric TargetPassConfig *TPC;
295af732203SDimitry Andric BitVector CalleeSavedRegs;
296af732203SDimitry Andric LexicalScopes LS;
297af732203SDimitry Andric VarLocSet::Allocator Alloc;
298af732203SDimitry Andric
299af732203SDimitry Andric enum struct TransferKind { TransferCopy, TransferSpill, TransferRestore };
300af732203SDimitry Andric
301af732203SDimitry Andric using FragmentInfo = DIExpression::FragmentInfo;
302af732203SDimitry Andric using OptFragmentInfo = Optional<DIExpression::FragmentInfo>;
303af732203SDimitry Andric
304af732203SDimitry Andric /// A pair of debug variable and value location.
305af732203SDimitry Andric struct VarLoc {
306af732203SDimitry Andric // The location at which a spilled variable resides. It consists of a
307af732203SDimitry Andric // register and an offset.
308af732203SDimitry Andric struct SpillLoc {
309af732203SDimitry Andric unsigned SpillBase;
310af732203SDimitry Andric StackOffset SpillOffset;
operator ==__anon9749acf60111::VarLocBasedLDV::VarLoc::SpillLoc311af732203SDimitry Andric bool operator==(const SpillLoc &Other) const {
312af732203SDimitry Andric return SpillBase == Other.SpillBase && SpillOffset == Other.SpillOffset;
313af732203SDimitry Andric }
operator !=__anon9749acf60111::VarLocBasedLDV::VarLoc::SpillLoc314af732203SDimitry Andric bool operator!=(const SpillLoc &Other) const {
315af732203SDimitry Andric return !(*this == Other);
316af732203SDimitry Andric }
317af732203SDimitry Andric };
318af732203SDimitry Andric
319af732203SDimitry Andric /// Identity of the variable at this location.
320af732203SDimitry Andric const DebugVariable Var;
321af732203SDimitry Andric
322af732203SDimitry Andric /// The expression applied to this location.
323af732203SDimitry Andric const DIExpression *Expr;
324af732203SDimitry Andric
325af732203SDimitry Andric /// DBG_VALUE to clone var/expr information from if this location
326af732203SDimitry Andric /// is moved.
327af732203SDimitry Andric const MachineInstr &MI;
328af732203SDimitry Andric
329*5f7ddb14SDimitry Andric enum class MachineLocKind {
330af732203SDimitry Andric InvalidKind = 0,
331af732203SDimitry Andric RegisterKind,
332af732203SDimitry Andric SpillLocKind,
333*5f7ddb14SDimitry Andric ImmediateKind
334*5f7ddb14SDimitry Andric };
335*5f7ddb14SDimitry Andric
336*5f7ddb14SDimitry Andric enum class EntryValueLocKind {
337*5f7ddb14SDimitry Andric NonEntryValueKind = 0,
338af732203SDimitry Andric EntryValueKind,
339af732203SDimitry Andric EntryValueBackupKind,
340af732203SDimitry Andric EntryValueCopyBackupKind
341*5f7ddb14SDimitry Andric } EVKind;
342af732203SDimitry Andric
343af732203SDimitry Andric /// The value location. Stored separately to avoid repeatedly
344af732203SDimitry Andric /// extracting it from MI.
345*5f7ddb14SDimitry Andric union MachineLocValue {
346af732203SDimitry Andric uint64_t RegNo;
347af732203SDimitry Andric SpillLoc SpillLocation;
348af732203SDimitry Andric uint64_t Hash;
349af732203SDimitry Andric int64_t Immediate;
350af732203SDimitry Andric const ConstantFP *FPImm;
351af732203SDimitry Andric const ConstantInt *CImm;
MachineLocValue()352*5f7ddb14SDimitry Andric MachineLocValue() : Hash(0) {}
353*5f7ddb14SDimitry Andric };
354*5f7ddb14SDimitry Andric
355*5f7ddb14SDimitry Andric /// A single machine location; its Kind is either a register, spill
356*5f7ddb14SDimitry Andric /// location, or immediate value.
357*5f7ddb14SDimitry Andric /// If the VarLoc is not a NonEntryValueKind, then it will use only a
358*5f7ddb14SDimitry Andric /// single MachineLoc of RegisterKind.
359*5f7ddb14SDimitry Andric struct MachineLoc {
360*5f7ddb14SDimitry Andric MachineLocKind Kind;
361*5f7ddb14SDimitry Andric MachineLocValue Value;
operator ==__anon9749acf60111::VarLocBasedLDV::VarLoc::MachineLoc362*5f7ddb14SDimitry Andric bool operator==(const MachineLoc &Other) const {
363*5f7ddb14SDimitry Andric if (Kind != Other.Kind)
364*5f7ddb14SDimitry Andric return false;
365*5f7ddb14SDimitry Andric switch (Kind) {
366*5f7ddb14SDimitry Andric case MachineLocKind::SpillLocKind:
367*5f7ddb14SDimitry Andric return Value.SpillLocation == Other.Value.SpillLocation;
368*5f7ddb14SDimitry Andric case MachineLocKind::RegisterKind:
369*5f7ddb14SDimitry Andric case MachineLocKind::ImmediateKind:
370*5f7ddb14SDimitry Andric return Value.Hash == Other.Value.Hash;
371*5f7ddb14SDimitry Andric default:
372*5f7ddb14SDimitry Andric llvm_unreachable("Invalid kind");
373*5f7ddb14SDimitry Andric }
374*5f7ddb14SDimitry Andric }
operator <__anon9749acf60111::VarLocBasedLDV::VarLoc::MachineLoc375*5f7ddb14SDimitry Andric bool operator<(const MachineLoc &Other) const {
376*5f7ddb14SDimitry Andric switch (Kind) {
377*5f7ddb14SDimitry Andric case MachineLocKind::SpillLocKind:
378*5f7ddb14SDimitry Andric return std::make_tuple(
379*5f7ddb14SDimitry Andric Kind, Value.SpillLocation.SpillBase,
380*5f7ddb14SDimitry Andric Value.SpillLocation.SpillOffset.getFixed(),
381*5f7ddb14SDimitry Andric Value.SpillLocation.SpillOffset.getScalable()) <
382*5f7ddb14SDimitry Andric std::make_tuple(
383*5f7ddb14SDimitry Andric Other.Kind, Other.Value.SpillLocation.SpillBase,
384*5f7ddb14SDimitry Andric Other.Value.SpillLocation.SpillOffset.getFixed(),
385*5f7ddb14SDimitry Andric Other.Value.SpillLocation.SpillOffset.getScalable());
386*5f7ddb14SDimitry Andric case MachineLocKind::RegisterKind:
387*5f7ddb14SDimitry Andric case MachineLocKind::ImmediateKind:
388*5f7ddb14SDimitry Andric return std::tie(Kind, Value.Hash) <
389*5f7ddb14SDimitry Andric std::tie(Other.Kind, Other.Value.Hash);
390*5f7ddb14SDimitry Andric default:
391*5f7ddb14SDimitry Andric llvm_unreachable("Invalid kind");
392*5f7ddb14SDimitry Andric }
393*5f7ddb14SDimitry Andric }
394*5f7ddb14SDimitry Andric };
395*5f7ddb14SDimitry Andric
396*5f7ddb14SDimitry Andric /// The set of machine locations used to determine the variable's value, in
397*5f7ddb14SDimitry Andric /// conjunction with Expr. Initially populated with MI's debug operands,
398*5f7ddb14SDimitry Andric /// but may be transformed independently afterwards.
399*5f7ddb14SDimitry Andric SmallVector<MachineLoc, 8> Locs;
400*5f7ddb14SDimitry Andric /// Used to map the index of each location in Locs back to the index of its
401*5f7ddb14SDimitry Andric /// original debug operand in MI. Used when multiple location operands are
402*5f7ddb14SDimitry Andric /// coalesced and the original MI's operands need to be accessed while
403*5f7ddb14SDimitry Andric /// emitting a debug value.
404*5f7ddb14SDimitry Andric SmallVector<unsigned, 8> OrigLocMap;
405af732203SDimitry Andric
VarLoc__anon9749acf60111::VarLocBasedLDV::VarLoc406af732203SDimitry Andric VarLoc(const MachineInstr &MI, LexicalScopes &LS)
407af732203SDimitry Andric : Var(MI.getDebugVariable(), MI.getDebugExpression(),
408af732203SDimitry Andric MI.getDebugLoc()->getInlinedAt()),
409*5f7ddb14SDimitry Andric Expr(MI.getDebugExpression()), MI(MI),
410*5f7ddb14SDimitry Andric EVKind(EntryValueLocKind::NonEntryValueKind) {
411af732203SDimitry Andric assert(MI.isDebugValue() && "not a DBG_VALUE");
412*5f7ddb14SDimitry Andric assert((MI.isDebugValueList() || MI.getNumOperands() == 4) &&
413*5f7ddb14SDimitry Andric "malformed DBG_VALUE");
414*5f7ddb14SDimitry Andric for (const MachineOperand &Op : MI.debug_operands()) {
415*5f7ddb14SDimitry Andric MachineLoc ML = GetLocForOp(Op);
416*5f7ddb14SDimitry Andric auto It = find(Locs, ML);
417*5f7ddb14SDimitry Andric if (It == Locs.end()) {
418*5f7ddb14SDimitry Andric Locs.push_back(ML);
419*5f7ddb14SDimitry Andric OrigLocMap.push_back(MI.getDebugOperandIndex(&Op));
420*5f7ddb14SDimitry Andric } else {
421*5f7ddb14SDimitry Andric // ML duplicates an element in Locs; replace references to Op
422*5f7ddb14SDimitry Andric // with references to the duplicating element.
423*5f7ddb14SDimitry Andric unsigned OpIdx = Locs.size();
424*5f7ddb14SDimitry Andric unsigned DuplicatingIdx = std::distance(Locs.begin(), It);
425*5f7ddb14SDimitry Andric Expr = DIExpression::replaceArg(Expr, OpIdx, DuplicatingIdx);
426*5f7ddb14SDimitry Andric }
427af732203SDimitry Andric }
428af732203SDimitry Andric
429*5f7ddb14SDimitry Andric // We create the debug entry values from the factory functions rather
430*5f7ddb14SDimitry Andric // than from this ctor.
431*5f7ddb14SDimitry Andric assert(EVKind != EntryValueLocKind::EntryValueKind &&
432*5f7ddb14SDimitry Andric !isEntryBackupLoc());
433*5f7ddb14SDimitry Andric }
434*5f7ddb14SDimitry Andric
GetLocForOp__anon9749acf60111::VarLocBasedLDV::VarLoc435*5f7ddb14SDimitry Andric static MachineLoc GetLocForOp(const MachineOperand &Op) {
436*5f7ddb14SDimitry Andric MachineLocKind Kind;
437*5f7ddb14SDimitry Andric MachineLocValue Loc;
438*5f7ddb14SDimitry Andric if (Op.isReg()) {
439*5f7ddb14SDimitry Andric Kind = MachineLocKind::RegisterKind;
440*5f7ddb14SDimitry Andric Loc.RegNo = Op.getReg();
441*5f7ddb14SDimitry Andric } else if (Op.isImm()) {
442*5f7ddb14SDimitry Andric Kind = MachineLocKind::ImmediateKind;
443*5f7ddb14SDimitry Andric Loc.Immediate = Op.getImm();
444*5f7ddb14SDimitry Andric } else if (Op.isFPImm()) {
445*5f7ddb14SDimitry Andric Kind = MachineLocKind::ImmediateKind;
446*5f7ddb14SDimitry Andric Loc.FPImm = Op.getFPImm();
447*5f7ddb14SDimitry Andric } else if (Op.isCImm()) {
448*5f7ddb14SDimitry Andric Kind = MachineLocKind::ImmediateKind;
449*5f7ddb14SDimitry Andric Loc.CImm = Op.getCImm();
450*5f7ddb14SDimitry Andric } else
451*5f7ddb14SDimitry Andric llvm_unreachable("Invalid Op kind for MachineLoc.");
452*5f7ddb14SDimitry Andric return {Kind, Loc};
453af732203SDimitry Andric }
454af732203SDimitry Andric
455af732203SDimitry Andric /// Take the variable and machine-location in DBG_VALUE MI, and build an
456af732203SDimitry Andric /// entry location using the given expression.
CreateEntryLoc__anon9749acf60111::VarLocBasedLDV::VarLoc457af732203SDimitry Andric static VarLoc CreateEntryLoc(const MachineInstr &MI, LexicalScopes &LS,
458af732203SDimitry Andric const DIExpression *EntryExpr, Register Reg) {
459af732203SDimitry Andric VarLoc VL(MI, LS);
460*5f7ddb14SDimitry Andric assert(VL.Locs.size() == 1 &&
461*5f7ddb14SDimitry Andric VL.Locs[0].Kind == MachineLocKind::RegisterKind);
462*5f7ddb14SDimitry Andric VL.EVKind = EntryValueLocKind::EntryValueKind;
463af732203SDimitry Andric VL.Expr = EntryExpr;
464*5f7ddb14SDimitry Andric VL.Locs[0].Value.RegNo = Reg;
465af732203SDimitry Andric return VL;
466af732203SDimitry Andric }
467af732203SDimitry Andric
468af732203SDimitry Andric /// Take the variable and machine-location from the DBG_VALUE (from the
469af732203SDimitry Andric /// function entry), and build an entry value backup location. The backup
470af732203SDimitry Andric /// location will turn into the normal location if the backup is valid at
471af732203SDimitry Andric /// the time of the primary location clobbering.
CreateEntryBackupLoc__anon9749acf60111::VarLocBasedLDV::VarLoc472af732203SDimitry Andric static VarLoc CreateEntryBackupLoc(const MachineInstr &MI,
473af732203SDimitry Andric LexicalScopes &LS,
474af732203SDimitry Andric const DIExpression *EntryExpr) {
475af732203SDimitry Andric VarLoc VL(MI, LS);
476*5f7ddb14SDimitry Andric assert(VL.Locs.size() == 1 &&
477*5f7ddb14SDimitry Andric VL.Locs[0].Kind == MachineLocKind::RegisterKind);
478*5f7ddb14SDimitry Andric VL.EVKind = EntryValueLocKind::EntryValueBackupKind;
479af732203SDimitry Andric VL.Expr = EntryExpr;
480af732203SDimitry Andric return VL;
481af732203SDimitry Andric }
482af732203SDimitry Andric
483af732203SDimitry Andric /// Take the variable and machine-location from the DBG_VALUE (from the
484af732203SDimitry Andric /// function entry), and build a copy of an entry value backup location by
485af732203SDimitry Andric /// setting the register location to NewReg.
CreateEntryCopyBackupLoc__anon9749acf60111::VarLocBasedLDV::VarLoc486af732203SDimitry Andric static VarLoc CreateEntryCopyBackupLoc(const MachineInstr &MI,
487af732203SDimitry Andric LexicalScopes &LS,
488af732203SDimitry Andric const DIExpression *EntryExpr,
489af732203SDimitry Andric Register NewReg) {
490af732203SDimitry Andric VarLoc VL(MI, LS);
491*5f7ddb14SDimitry Andric assert(VL.Locs.size() == 1 &&
492*5f7ddb14SDimitry Andric VL.Locs[0].Kind == MachineLocKind::RegisterKind);
493*5f7ddb14SDimitry Andric VL.EVKind = EntryValueLocKind::EntryValueCopyBackupKind;
494af732203SDimitry Andric VL.Expr = EntryExpr;
495*5f7ddb14SDimitry Andric VL.Locs[0].Value.RegNo = NewReg;
496af732203SDimitry Andric return VL;
497af732203SDimitry Andric }
498af732203SDimitry Andric
499af732203SDimitry Andric /// Copy the register location in DBG_VALUE MI, updating the register to
500af732203SDimitry Andric /// be NewReg.
CreateCopyLoc__anon9749acf60111::VarLocBasedLDV::VarLoc501*5f7ddb14SDimitry Andric static VarLoc CreateCopyLoc(const VarLoc &OldVL, const MachineLoc &OldML,
502af732203SDimitry Andric Register NewReg) {
503*5f7ddb14SDimitry Andric VarLoc VL = OldVL;
504*5f7ddb14SDimitry Andric for (size_t I = 0, E = VL.Locs.size(); I < E; ++I)
505*5f7ddb14SDimitry Andric if (VL.Locs[I] == OldML) {
506*5f7ddb14SDimitry Andric VL.Locs[I].Kind = MachineLocKind::RegisterKind;
507*5f7ddb14SDimitry Andric VL.Locs[I].Value.RegNo = NewReg;
508af732203SDimitry Andric return VL;
509af732203SDimitry Andric }
510*5f7ddb14SDimitry Andric llvm_unreachable("Should have found OldML in new VarLoc.");
511*5f7ddb14SDimitry Andric }
512af732203SDimitry Andric
513*5f7ddb14SDimitry Andric /// Take the variable described by DBG_VALUE* MI, and create a VarLoc
514af732203SDimitry Andric /// locating it in the specified spill location.
CreateSpillLoc__anon9749acf60111::VarLocBasedLDV::VarLoc515*5f7ddb14SDimitry Andric static VarLoc CreateSpillLoc(const VarLoc &OldVL, const MachineLoc &OldML,
516*5f7ddb14SDimitry Andric unsigned SpillBase, StackOffset SpillOffset) {
517*5f7ddb14SDimitry Andric VarLoc VL = OldVL;
518*5f7ddb14SDimitry Andric for (int I = 0, E = VL.Locs.size(); I < E; ++I)
519*5f7ddb14SDimitry Andric if (VL.Locs[I] == OldML) {
520*5f7ddb14SDimitry Andric VL.Locs[I].Kind = MachineLocKind::SpillLocKind;
521*5f7ddb14SDimitry Andric VL.Locs[I].Value.SpillLocation = {SpillBase, SpillOffset};
522af732203SDimitry Andric return VL;
523af732203SDimitry Andric }
524*5f7ddb14SDimitry Andric llvm_unreachable("Should have found OldML in new VarLoc.");
525*5f7ddb14SDimitry Andric }
526af732203SDimitry Andric
527af732203SDimitry Andric /// Create a DBG_VALUE representing this VarLoc in the given function.
528af732203SDimitry Andric /// Copies variable-specific information such as DILocalVariable and
529af732203SDimitry Andric /// inlining information from the original DBG_VALUE instruction, which may
530af732203SDimitry Andric /// have been several transfers ago.
BuildDbgValue__anon9749acf60111::VarLocBasedLDV::VarLoc531af732203SDimitry Andric MachineInstr *BuildDbgValue(MachineFunction &MF) const {
532*5f7ddb14SDimitry Andric assert(!isEntryBackupLoc() &&
533*5f7ddb14SDimitry Andric "Tried to produce DBG_VALUE for backup VarLoc");
534af732203SDimitry Andric const DebugLoc &DbgLoc = MI.getDebugLoc();
535af732203SDimitry Andric bool Indirect = MI.isIndirectDebugValue();
536af732203SDimitry Andric const auto &IID = MI.getDesc();
537af732203SDimitry Andric const DILocalVariable *Var = MI.getDebugVariable();
538af732203SDimitry Andric NumInserted++;
539af732203SDimitry Andric
540*5f7ddb14SDimitry Andric const DIExpression *DIExpr = Expr;
541*5f7ddb14SDimitry Andric SmallVector<MachineOperand, 8> MOs;
542*5f7ddb14SDimitry Andric for (unsigned I = 0, E = Locs.size(); I < E; ++I) {
543*5f7ddb14SDimitry Andric MachineLocKind LocKind = Locs[I].Kind;
544*5f7ddb14SDimitry Andric MachineLocValue Loc = Locs[I].Value;
545*5f7ddb14SDimitry Andric const MachineOperand &Orig = MI.getDebugOperand(OrigLocMap[I]);
546*5f7ddb14SDimitry Andric switch (LocKind) {
547*5f7ddb14SDimitry Andric case MachineLocKind::RegisterKind:
548af732203SDimitry Andric // An entry value is a register location -- but with an updated
549*5f7ddb14SDimitry Andric // expression. The register location of such DBG_VALUE is always the
550*5f7ddb14SDimitry Andric // one from the entry DBG_VALUE, it does not matter if the entry value
551*5f7ddb14SDimitry Andric // was copied in to another register due to some optimizations.
552*5f7ddb14SDimitry Andric // Non-entry value register locations are like the source
553*5f7ddb14SDimitry Andric // DBG_VALUE, but with the register number from this VarLoc.
554*5f7ddb14SDimitry Andric MOs.push_back(MachineOperand::CreateReg(
555*5f7ddb14SDimitry Andric EVKind == EntryValueLocKind::EntryValueKind ? Orig.getReg()
556*5f7ddb14SDimitry Andric : Register(Loc.RegNo),
557*5f7ddb14SDimitry Andric false));
558*5f7ddb14SDimitry Andric MOs.back().setIsDebug();
559*5f7ddb14SDimitry Andric break;
560*5f7ddb14SDimitry Andric case MachineLocKind::SpillLocKind: {
561af732203SDimitry Andric // Spills are indirect DBG_VALUEs, with a base register and offset.
562af732203SDimitry Andric // Use the original DBG_VALUEs expression to build the spilt location
563af732203SDimitry Andric // on top of. FIXME: spill locations created before this pass runs
564af732203SDimitry Andric // are not recognized, and not handled here.
565af732203SDimitry Andric unsigned Base = Loc.SpillLocation.SpillBase;
566*5f7ddb14SDimitry Andric auto *TRI = MF.getSubtarget().getRegisterInfo();
567*5f7ddb14SDimitry Andric if (MI.isNonListDebugValue()) {
568*5f7ddb14SDimitry Andric DIExpr =
569*5f7ddb14SDimitry Andric TRI->prependOffsetExpression(DIExpr, DIExpression::ApplyOffset,
570*5f7ddb14SDimitry Andric Loc.SpillLocation.SpillOffset);
571*5f7ddb14SDimitry Andric Indirect = true;
572*5f7ddb14SDimitry Andric } else {
573*5f7ddb14SDimitry Andric SmallVector<uint64_t, 4> Ops;
574*5f7ddb14SDimitry Andric TRI->getOffsetOpcodes(Loc.SpillLocation.SpillOffset, Ops);
575*5f7ddb14SDimitry Andric Ops.push_back(dwarf::DW_OP_deref);
576*5f7ddb14SDimitry Andric DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, I);
577af732203SDimitry Andric }
578*5f7ddb14SDimitry Andric MOs.push_back(MachineOperand::CreateReg(Base, false));
579*5f7ddb14SDimitry Andric MOs.back().setIsDebug();
580*5f7ddb14SDimitry Andric break;
581af732203SDimitry Andric }
582*5f7ddb14SDimitry Andric case MachineLocKind::ImmediateKind: {
583*5f7ddb14SDimitry Andric MOs.push_back(Orig);
584*5f7ddb14SDimitry Andric break;
585af732203SDimitry Andric }
586*5f7ddb14SDimitry Andric case MachineLocKind::InvalidKind:
587*5f7ddb14SDimitry Andric llvm_unreachable("Tried to produce DBG_VALUE for invalid VarLoc");
588*5f7ddb14SDimitry Andric }
589*5f7ddb14SDimitry Andric }
590*5f7ddb14SDimitry Andric return BuildMI(MF, DbgLoc, IID, Indirect, MOs, Var, DIExpr);
591af732203SDimitry Andric }
592af732203SDimitry Andric
593af732203SDimitry Andric /// Is the Loc field a constant or constant object?
isConstant__anon9749acf60111::VarLocBasedLDV::VarLoc594*5f7ddb14SDimitry Andric bool isConstant(MachineLocKind Kind) const {
595*5f7ddb14SDimitry Andric return Kind == MachineLocKind::ImmediateKind;
596*5f7ddb14SDimitry Andric }
597af732203SDimitry Andric
598af732203SDimitry Andric /// Check if the Loc field is an entry backup location.
isEntryBackupLoc__anon9749acf60111::VarLocBasedLDV::VarLoc599af732203SDimitry Andric bool isEntryBackupLoc() const {
600*5f7ddb14SDimitry Andric return EVKind == EntryValueLocKind::EntryValueBackupKind ||
601*5f7ddb14SDimitry Andric EVKind == EntryValueLocKind::EntryValueCopyBackupKind;
602af732203SDimitry Andric }
603af732203SDimitry Andric
604*5f7ddb14SDimitry Andric /// If this variable is described by register \p Reg holding the entry
605*5f7ddb14SDimitry Andric /// value, return true.
isEntryValueBackupReg__anon9749acf60111::VarLocBasedLDV::VarLoc606*5f7ddb14SDimitry Andric bool isEntryValueBackupReg(Register Reg) const {
607*5f7ddb14SDimitry Andric return EVKind == EntryValueLocKind::EntryValueBackupKind && usesReg(Reg);
608af732203SDimitry Andric }
609af732203SDimitry Andric
610*5f7ddb14SDimitry Andric /// If this variable is described by register \p Reg holding a copy of the
611*5f7ddb14SDimitry Andric /// entry value, return true.
isEntryValueCopyBackupReg__anon9749acf60111::VarLocBasedLDV::VarLoc612*5f7ddb14SDimitry Andric bool isEntryValueCopyBackupReg(Register Reg) const {
613*5f7ddb14SDimitry Andric return EVKind == EntryValueLocKind::EntryValueCopyBackupKind &&
614*5f7ddb14SDimitry Andric usesReg(Reg);
615af732203SDimitry Andric }
616af732203SDimitry Andric
617*5f7ddb14SDimitry Andric /// If this variable is described in whole or part by \p Reg, return true.
usesReg__anon9749acf60111::VarLocBasedLDV::VarLoc618*5f7ddb14SDimitry Andric bool usesReg(Register Reg) const {
619*5f7ddb14SDimitry Andric MachineLoc RegML;
620*5f7ddb14SDimitry Andric RegML.Kind = MachineLocKind::RegisterKind;
621*5f7ddb14SDimitry Andric RegML.Value.RegNo = Reg;
622*5f7ddb14SDimitry Andric return is_contained(Locs, RegML);
623*5f7ddb14SDimitry Andric }
624*5f7ddb14SDimitry Andric
625*5f7ddb14SDimitry Andric /// If this variable is described in whole or part by \p Reg, return true.
getRegIdx__anon9749acf60111::VarLocBasedLDV::VarLoc626*5f7ddb14SDimitry Andric unsigned getRegIdx(Register Reg) const {
627*5f7ddb14SDimitry Andric for (unsigned Idx = 0; Idx < Locs.size(); ++Idx)
628*5f7ddb14SDimitry Andric if (Locs[Idx].Kind == MachineLocKind::RegisterKind &&
629*5f7ddb14SDimitry Andric Locs[Idx].Value.RegNo == Reg)
630*5f7ddb14SDimitry Andric return Idx;
631*5f7ddb14SDimitry Andric llvm_unreachable("Could not find given Reg in Locs");
632*5f7ddb14SDimitry Andric }
633*5f7ddb14SDimitry Andric
634*5f7ddb14SDimitry Andric /// If this variable is described in whole or part by 1 or more registers,
635*5f7ddb14SDimitry Andric /// add each of them to \p Regs and return true.
getDescribingRegs__anon9749acf60111::VarLocBasedLDV::VarLoc636*5f7ddb14SDimitry Andric bool getDescribingRegs(SmallVectorImpl<uint32_t> &Regs) const {
637*5f7ddb14SDimitry Andric bool AnyRegs = false;
638*5f7ddb14SDimitry Andric for (auto Loc : Locs)
639*5f7ddb14SDimitry Andric if (Loc.Kind == MachineLocKind::RegisterKind) {
640*5f7ddb14SDimitry Andric Regs.push_back(Loc.Value.RegNo);
641*5f7ddb14SDimitry Andric AnyRegs = true;
642*5f7ddb14SDimitry Andric }
643*5f7ddb14SDimitry Andric return AnyRegs;
644*5f7ddb14SDimitry Andric }
645*5f7ddb14SDimitry Andric
containsSpillLocs__anon9749acf60111::VarLocBasedLDV::VarLoc646*5f7ddb14SDimitry Andric bool containsSpillLocs() const {
647*5f7ddb14SDimitry Andric return any_of(Locs, [](VarLoc::MachineLoc ML) {
648*5f7ddb14SDimitry Andric return ML.Kind == VarLoc::MachineLocKind::SpillLocKind;
649*5f7ddb14SDimitry Andric });
650*5f7ddb14SDimitry Andric }
651*5f7ddb14SDimitry Andric
652*5f7ddb14SDimitry Andric /// If this variable is described in whole or part by \p SpillLocation,
653*5f7ddb14SDimitry Andric /// return true.
usesSpillLoc__anon9749acf60111::VarLocBasedLDV::VarLoc654*5f7ddb14SDimitry Andric bool usesSpillLoc(SpillLoc SpillLocation) const {
655*5f7ddb14SDimitry Andric MachineLoc SpillML;
656*5f7ddb14SDimitry Andric SpillML.Kind = MachineLocKind::SpillLocKind;
657*5f7ddb14SDimitry Andric SpillML.Value.SpillLocation = SpillLocation;
658*5f7ddb14SDimitry Andric return is_contained(Locs, SpillML);
659*5f7ddb14SDimitry Andric }
660*5f7ddb14SDimitry Andric
661*5f7ddb14SDimitry Andric /// If this variable is described in whole or part by \p SpillLocation,
662*5f7ddb14SDimitry Andric /// return the index .
getSpillLocIdx__anon9749acf60111::VarLocBasedLDV::VarLoc663*5f7ddb14SDimitry Andric unsigned getSpillLocIdx(SpillLoc SpillLocation) const {
664*5f7ddb14SDimitry Andric for (unsigned Idx = 0; Idx < Locs.size(); ++Idx)
665*5f7ddb14SDimitry Andric if (Locs[Idx].Kind == MachineLocKind::SpillLocKind &&
666*5f7ddb14SDimitry Andric Locs[Idx].Value.SpillLocation == SpillLocation)
667*5f7ddb14SDimitry Andric return Idx;
668*5f7ddb14SDimitry Andric llvm_unreachable("Could not find given SpillLoc in Locs");
669af732203SDimitry Andric }
670af732203SDimitry Andric
671af732203SDimitry Andric /// Determine whether the lexical scope of this value's debug location
672af732203SDimitry Andric /// dominates MBB.
dominates__anon9749acf60111::VarLocBasedLDV::VarLoc673af732203SDimitry Andric bool dominates(LexicalScopes &LS, MachineBasicBlock &MBB) const {
674af732203SDimitry Andric return LS.dominates(MI.getDebugLoc().get(), &MBB);
675af732203SDimitry Andric }
676af732203SDimitry Andric
677af732203SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
678af732203SDimitry Andric // TRI can be null.
dump__anon9749acf60111::VarLocBasedLDV::VarLoc679af732203SDimitry Andric void dump(const TargetRegisterInfo *TRI, raw_ostream &Out = dbgs()) const {
680af732203SDimitry Andric Out << "VarLoc(";
681*5f7ddb14SDimitry Andric for (const MachineLoc &MLoc : Locs) {
682*5f7ddb14SDimitry Andric if (Locs.begin() != &MLoc)
683*5f7ddb14SDimitry Andric Out << ", ";
684*5f7ddb14SDimitry Andric switch (MLoc.Kind) {
685*5f7ddb14SDimitry Andric case MachineLocKind::RegisterKind:
686*5f7ddb14SDimitry Andric Out << printReg(MLoc.Value.RegNo, TRI);
687af732203SDimitry Andric break;
688*5f7ddb14SDimitry Andric case MachineLocKind::SpillLocKind:
689*5f7ddb14SDimitry Andric Out << printReg(MLoc.Value.SpillLocation.SpillBase, TRI);
690*5f7ddb14SDimitry Andric Out << "[" << MLoc.Value.SpillLocation.SpillOffset.getFixed() << " + "
691*5f7ddb14SDimitry Andric << MLoc.Value.SpillLocation.SpillOffset.getScalable()
692*5f7ddb14SDimitry Andric << "x vscale"
693af732203SDimitry Andric << "]";
694af732203SDimitry Andric break;
695*5f7ddb14SDimitry Andric case MachineLocKind::ImmediateKind:
696*5f7ddb14SDimitry Andric Out << MLoc.Value.Immediate;
697af732203SDimitry Andric break;
698*5f7ddb14SDimitry Andric case MachineLocKind::InvalidKind:
699af732203SDimitry Andric llvm_unreachable("Invalid VarLoc in dump method");
700af732203SDimitry Andric }
701*5f7ddb14SDimitry Andric }
702af732203SDimitry Andric
703af732203SDimitry Andric Out << ", \"" << Var.getVariable()->getName() << "\", " << *Expr << ", ";
704af732203SDimitry Andric if (Var.getInlinedAt())
705af732203SDimitry Andric Out << "!" << Var.getInlinedAt()->getMetadataID() << ")\n";
706af732203SDimitry Andric else
707af732203SDimitry Andric Out << "(null))";
708af732203SDimitry Andric
709af732203SDimitry Andric if (isEntryBackupLoc())
710af732203SDimitry Andric Out << " (backup loc)\n";
711af732203SDimitry Andric else
712af732203SDimitry Andric Out << "\n";
713af732203SDimitry Andric }
714af732203SDimitry Andric #endif
715af732203SDimitry Andric
operator ==__anon9749acf60111::VarLocBasedLDV::VarLoc716af732203SDimitry Andric bool operator==(const VarLoc &Other) const {
717*5f7ddb14SDimitry Andric return std::tie(EVKind, Var, Expr, Locs) ==
718*5f7ddb14SDimitry Andric std::tie(Other.EVKind, Other.Var, Other.Expr, Other.Locs);
719af732203SDimitry Andric }
720af732203SDimitry Andric
721af732203SDimitry Andric /// This operator guarantees that VarLocs are sorted by Variable first.
operator <__anon9749acf60111::VarLocBasedLDV::VarLoc722af732203SDimitry Andric bool operator<(const VarLoc &Other) const {
723*5f7ddb14SDimitry Andric return std::tie(Var, EVKind, Locs, Expr) <
724*5f7ddb14SDimitry Andric std::tie(Other.Var, Other.EVKind, Other.Locs, Other.Expr);
725af732203SDimitry Andric }
726af732203SDimitry Andric };
727af732203SDimitry Andric
728*5f7ddb14SDimitry Andric #ifndef NDEBUG
729*5f7ddb14SDimitry Andric using VarVec = SmallVector<VarLoc, 32>;
730*5f7ddb14SDimitry Andric #endif
731*5f7ddb14SDimitry Andric
732af732203SDimitry Andric /// VarLocMap is used for two things:
733*5f7ddb14SDimitry Andric /// 1) Assigning LocIndices to a VarLoc. The LocIndices can be used to
734af732203SDimitry Andric /// virtually insert a VarLoc into a VarLocSet.
735af732203SDimitry Andric /// 2) Given a LocIndex, look up the unique associated VarLoc.
736af732203SDimitry Andric class VarLocMap {
737af732203SDimitry Andric /// Map a VarLoc to an index within the vector reserved for its location
738af732203SDimitry Andric /// within Loc2Vars.
739*5f7ddb14SDimitry Andric std::map<VarLoc, LocIndices> Var2Indices;
740af732203SDimitry Andric
741af732203SDimitry Andric /// Map a location to a vector which holds VarLocs which live in that
742af732203SDimitry Andric /// location.
743af732203SDimitry Andric SmallDenseMap<LocIndex::u32_location_t, std::vector<VarLoc>> Loc2Vars;
744af732203SDimitry Andric
745*5f7ddb14SDimitry Andric public:
746*5f7ddb14SDimitry Andric /// Retrieve LocIndices for \p VL.
insert(const VarLoc & VL)747*5f7ddb14SDimitry Andric LocIndices insert(const VarLoc &VL) {
748*5f7ddb14SDimitry Andric LocIndices &Indices = Var2Indices[VL];
749*5f7ddb14SDimitry Andric // If Indices is not empty, VL is already in the map.
750*5f7ddb14SDimitry Andric if (!Indices.empty())
751*5f7ddb14SDimitry Andric return Indices;
752*5f7ddb14SDimitry Andric SmallVector<LocIndex::u32_location_t, 4> Locations;
753*5f7ddb14SDimitry Andric // LocIndices are determined by EVKind and MLs; each Register has a
754*5f7ddb14SDimitry Andric // unique location, while all SpillLocs use a single bucket, and any EV
755*5f7ddb14SDimitry Andric // VarLocs use only the Backup bucket or none at all (except the
756*5f7ddb14SDimitry Andric // compulsory entry at the universal location index). LocIndices will
757*5f7ddb14SDimitry Andric // always have an index at the universal location index as the last index.
758*5f7ddb14SDimitry Andric if (VL.EVKind == VarLoc::EntryValueLocKind::NonEntryValueKind) {
759*5f7ddb14SDimitry Andric VL.getDescribingRegs(Locations);
760*5f7ddb14SDimitry Andric assert(all_of(Locations,
761*5f7ddb14SDimitry Andric [](auto RegNo) {
762*5f7ddb14SDimitry Andric return RegNo < LocIndex::kFirstInvalidRegLocation;
763*5f7ddb14SDimitry Andric }) &&
764af732203SDimitry Andric "Physreg out of range?");
765*5f7ddb14SDimitry Andric if (VL.containsSpillLocs()) {
766*5f7ddb14SDimitry Andric LocIndex::u32_location_t Loc = LocIndex::kSpillLocation;
767*5f7ddb14SDimitry Andric Locations.push_back(Loc);
768af732203SDimitry Andric }
769*5f7ddb14SDimitry Andric } else if (VL.EVKind != VarLoc::EntryValueLocKind::EntryValueKind) {
770*5f7ddb14SDimitry Andric LocIndex::u32_location_t Loc = LocIndex::kEntryValueBackupLocation;
771*5f7ddb14SDimitry Andric Locations.push_back(Loc);
772*5f7ddb14SDimitry Andric }
773*5f7ddb14SDimitry Andric Locations.push_back(LocIndex::kUniversalLocation);
774*5f7ddb14SDimitry Andric for (LocIndex::u32_location_t Location : Locations) {
775*5f7ddb14SDimitry Andric auto &Vars = Loc2Vars[Location];
776*5f7ddb14SDimitry Andric Indices.push_back(
777*5f7ddb14SDimitry Andric {Location, static_cast<LocIndex::u32_index_t>(Vars.size())});
778*5f7ddb14SDimitry Andric Vars.push_back(VL);
779*5f7ddb14SDimitry Andric }
780*5f7ddb14SDimitry Andric return Indices;
781af732203SDimitry Andric }
782af732203SDimitry Andric
getAllIndices(const VarLoc & VL) const783*5f7ddb14SDimitry Andric LocIndices getAllIndices(const VarLoc &VL) const {
784*5f7ddb14SDimitry Andric auto IndIt = Var2Indices.find(VL);
785*5f7ddb14SDimitry Andric assert(IndIt != Var2Indices.end() && "VarLoc not tracked");
786*5f7ddb14SDimitry Andric return IndIt->second;
787af732203SDimitry Andric }
788af732203SDimitry Andric
789af732203SDimitry Andric /// Retrieve the unique VarLoc associated with \p ID.
operator [](LocIndex ID) const790af732203SDimitry Andric const VarLoc &operator[](LocIndex ID) const {
791af732203SDimitry Andric auto LocIt = Loc2Vars.find(ID.Location);
792af732203SDimitry Andric assert(LocIt != Loc2Vars.end() && "Location not tracked");
793af732203SDimitry Andric return LocIt->second[ID.Index];
794af732203SDimitry Andric }
795af732203SDimitry Andric };
796af732203SDimitry Andric
797af732203SDimitry Andric using VarLocInMBB =
798af732203SDimitry Andric SmallDenseMap<const MachineBasicBlock *, std::unique_ptr<VarLocSet>>;
799af732203SDimitry Andric struct TransferDebugPair {
800af732203SDimitry Andric MachineInstr *TransferInst; ///< Instruction where this transfer occurs.
801af732203SDimitry Andric LocIndex LocationID; ///< Location number for the transfer dest.
802af732203SDimitry Andric };
803af732203SDimitry Andric using TransferMap = SmallVector<TransferDebugPair, 4>;
804af732203SDimitry Andric
805af732203SDimitry Andric // Types for recording sets of variable fragments that overlap. For a given
806af732203SDimitry Andric // local variable, we record all other fragments of that variable that could
807af732203SDimitry Andric // overlap it, to reduce search time.
808af732203SDimitry Andric using FragmentOfVar =
809af732203SDimitry Andric std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;
810af732203SDimitry Andric using OverlapMap =
811af732203SDimitry Andric DenseMap<FragmentOfVar, SmallVector<DIExpression::FragmentInfo, 1>>;
812af732203SDimitry Andric
813af732203SDimitry Andric // Helper while building OverlapMap, a map of all fragments seen for a given
814af732203SDimitry Andric // DILocalVariable.
815af732203SDimitry Andric using VarToFragments =
816af732203SDimitry Andric DenseMap<const DILocalVariable *, SmallSet<FragmentInfo, 4>>;
817af732203SDimitry Andric
818*5f7ddb14SDimitry Andric /// Collects all VarLocs from \p CollectFrom. Each unique VarLoc is added
819*5f7ddb14SDimitry Andric /// to \p Collected once, in order of insertion into \p VarLocIDs.
820*5f7ddb14SDimitry Andric static void collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
821*5f7ddb14SDimitry Andric const VarLocSet &CollectFrom,
822*5f7ddb14SDimitry Andric const VarLocMap &VarLocIDs);
823*5f7ddb14SDimitry Andric
824*5f7ddb14SDimitry Andric /// Get the registers which are used by VarLocs of kind RegisterKind tracked
825*5f7ddb14SDimitry Andric /// by \p CollectFrom.
826*5f7ddb14SDimitry Andric void getUsedRegs(const VarLocSet &CollectFrom,
827*5f7ddb14SDimitry Andric SmallVectorImpl<Register> &UsedRegs) const;
828*5f7ddb14SDimitry Andric
829af732203SDimitry Andric /// This holds the working set of currently open ranges. For fast
830af732203SDimitry Andric /// access, this is done both as a set of VarLocIDs, and a map of
831af732203SDimitry Andric /// DebugVariable to recent VarLocID. Note that a DBG_VALUE ends all
832af732203SDimitry Andric /// previous open ranges for the same variable. In addition, we keep
833af732203SDimitry Andric /// two different maps (Vars/EntryValuesBackupVars), so erase/insert
834af732203SDimitry Andric /// methods act differently depending on whether a VarLoc is primary
835af732203SDimitry Andric /// location or backup one. In the case the VarLoc is backup location
836af732203SDimitry Andric /// we will erase/insert from the EntryValuesBackupVars map, otherwise
837af732203SDimitry Andric /// we perform the operation on the Vars.
838af732203SDimitry Andric class OpenRangesSet {
839*5f7ddb14SDimitry Andric VarLocSet::Allocator &Alloc;
840af732203SDimitry Andric VarLocSet VarLocs;
841af732203SDimitry Andric // Map the DebugVariable to recent primary location ID.
842*5f7ddb14SDimitry Andric SmallDenseMap<DebugVariable, LocIndices, 8> Vars;
843af732203SDimitry Andric // Map the DebugVariable to recent backup location ID.
844*5f7ddb14SDimitry Andric SmallDenseMap<DebugVariable, LocIndices, 8> EntryValuesBackupVars;
845af732203SDimitry Andric OverlapMap &OverlappingFragments;
846af732203SDimitry Andric
847af732203SDimitry Andric public:
OpenRangesSet(VarLocSet::Allocator & Alloc,OverlapMap & _OLapMap)848af732203SDimitry Andric OpenRangesSet(VarLocSet::Allocator &Alloc, OverlapMap &_OLapMap)
849*5f7ddb14SDimitry Andric : Alloc(Alloc), VarLocs(Alloc), OverlappingFragments(_OLapMap) {}
850af732203SDimitry Andric
getVarLocs() const851af732203SDimitry Andric const VarLocSet &getVarLocs() const { return VarLocs; }
852af732203SDimitry Andric
853*5f7ddb14SDimitry Andric // Fetches all VarLocs in \p VarLocIDs and inserts them into \p Collected.
854*5f7ddb14SDimitry Andric // This method is needed to get every VarLoc once, as each VarLoc may have
855*5f7ddb14SDimitry Andric // multiple indices in a VarLocMap (corresponding to each applicable
856*5f7ddb14SDimitry Andric // location), but all VarLocs appear exactly once at the universal location
857*5f7ddb14SDimitry Andric // index.
getUniqueVarLocs(SmallVectorImpl<VarLoc> & Collected,const VarLocMap & VarLocIDs) const858*5f7ddb14SDimitry Andric void getUniqueVarLocs(SmallVectorImpl<VarLoc> &Collected,
859*5f7ddb14SDimitry Andric const VarLocMap &VarLocIDs) const {
860*5f7ddb14SDimitry Andric collectAllVarLocs(Collected, VarLocs, VarLocIDs);
861*5f7ddb14SDimitry Andric }
862*5f7ddb14SDimitry Andric
863af732203SDimitry Andric /// Terminate all open ranges for VL.Var by removing it from the set.
864af732203SDimitry Andric void erase(const VarLoc &VL);
865af732203SDimitry Andric
866*5f7ddb14SDimitry Andric /// Terminate all open ranges listed as indices in \c KillSet with
867*5f7ddb14SDimitry Andric /// \c Location by removing them from the set.
868*5f7ddb14SDimitry Andric void erase(const VarLocsInRange &KillSet, const VarLocMap &VarLocIDs,
869*5f7ddb14SDimitry Andric LocIndex::u32_location_t Location);
870af732203SDimitry Andric
871af732203SDimitry Andric /// Insert a new range into the set.
872*5f7ddb14SDimitry Andric void insert(LocIndices VarLocIDs, const VarLoc &VL);
873af732203SDimitry Andric
874af732203SDimitry Andric /// Insert a set of ranges.
875*5f7ddb14SDimitry Andric void insertFromLocSet(const VarLocSet &ToLoad, const VarLocMap &Map);
876af732203SDimitry Andric
877*5f7ddb14SDimitry Andric llvm::Optional<LocIndices> getEntryValueBackup(DebugVariable Var);
878af732203SDimitry Andric
879af732203SDimitry Andric /// Empty the set.
clear()880af732203SDimitry Andric void clear() {
881af732203SDimitry Andric VarLocs.clear();
882af732203SDimitry Andric Vars.clear();
883af732203SDimitry Andric EntryValuesBackupVars.clear();
884af732203SDimitry Andric }
885af732203SDimitry Andric
886af732203SDimitry Andric /// Return whether the set is empty or not.
empty() const887af732203SDimitry Andric bool empty() const {
888af732203SDimitry Andric assert(Vars.empty() == EntryValuesBackupVars.empty() &&
889af732203SDimitry Andric Vars.empty() == VarLocs.empty() &&
890af732203SDimitry Andric "open ranges are inconsistent");
891af732203SDimitry Andric return VarLocs.empty();
892af732203SDimitry Andric }
893af732203SDimitry Andric
894af732203SDimitry Andric /// Get an empty range of VarLoc IDs.
getEmptyVarLocRange() const895af732203SDimitry Andric auto getEmptyVarLocRange() const {
896af732203SDimitry Andric return iterator_range<VarLocSet::const_iterator>(getVarLocs().end(),
897af732203SDimitry Andric getVarLocs().end());
898af732203SDimitry Andric }
899af732203SDimitry Andric
900*5f7ddb14SDimitry Andric /// Get all set IDs for VarLocs with MLs of kind RegisterKind in \p Reg.
getRegisterVarLocs(Register Reg) const901af732203SDimitry Andric auto getRegisterVarLocs(Register Reg) const {
902af732203SDimitry Andric return LocIndex::indexRangeForLocation(getVarLocs(), Reg);
903af732203SDimitry Andric }
904af732203SDimitry Andric
905*5f7ddb14SDimitry Andric /// Get all set IDs for VarLocs with MLs of kind SpillLocKind.
getSpillVarLocs() const906af732203SDimitry Andric auto getSpillVarLocs() const {
907af732203SDimitry Andric return LocIndex::indexRangeForLocation(getVarLocs(),
908af732203SDimitry Andric LocIndex::kSpillLocation);
909af732203SDimitry Andric }
910af732203SDimitry Andric
911*5f7ddb14SDimitry Andric /// Get all set IDs for VarLocs of EVKind EntryValueBackupKind or
912af732203SDimitry Andric /// EntryValueCopyBackupKind.
getEntryValueBackupVarLocs() const913af732203SDimitry Andric auto getEntryValueBackupVarLocs() const {
914af732203SDimitry Andric return LocIndex::indexRangeForLocation(
915af732203SDimitry Andric getVarLocs(), LocIndex::kEntryValueBackupLocation);
916af732203SDimitry Andric }
917af732203SDimitry Andric };
918af732203SDimitry Andric
919*5f7ddb14SDimitry Andric /// Collect all VarLoc IDs from \p CollectFrom for VarLocs with MLs of kind
920*5f7ddb14SDimitry Andric /// RegisterKind which are located in any reg in \p Regs. The IDs for each
921*5f7ddb14SDimitry Andric /// VarLoc correspond to entries in the universal location bucket, which every
922*5f7ddb14SDimitry Andric /// VarLoc has exactly 1 entry for. Insert collected IDs into \p Collected.
923*5f7ddb14SDimitry Andric static void collectIDsForRegs(VarLocsInRange &Collected,
924*5f7ddb14SDimitry Andric const DefinedRegsSet &Regs,
925*5f7ddb14SDimitry Andric const VarLocSet &CollectFrom,
926*5f7ddb14SDimitry Andric const VarLocMap &VarLocIDs);
927af732203SDimitry Andric
getVarLocsInMBB(const MachineBasicBlock * MBB,VarLocInMBB & Locs)928af732203SDimitry Andric VarLocSet &getVarLocsInMBB(const MachineBasicBlock *MBB, VarLocInMBB &Locs) {
929af732203SDimitry Andric std::unique_ptr<VarLocSet> &VLS = Locs[MBB];
930af732203SDimitry Andric if (!VLS)
931af732203SDimitry Andric VLS = std::make_unique<VarLocSet>(Alloc);
932af732203SDimitry Andric return *VLS.get();
933af732203SDimitry Andric }
934af732203SDimitry Andric
getVarLocsInMBB(const MachineBasicBlock * MBB,const VarLocInMBB & Locs) const935af732203SDimitry Andric const VarLocSet &getVarLocsInMBB(const MachineBasicBlock *MBB,
936af732203SDimitry Andric const VarLocInMBB &Locs) const {
937af732203SDimitry Andric auto It = Locs.find(MBB);
938af732203SDimitry Andric assert(It != Locs.end() && "MBB not in map");
939af732203SDimitry Andric return *It->second.get();
940af732203SDimitry Andric }
941af732203SDimitry Andric
942af732203SDimitry Andric /// Tests whether this instruction is a spill to a stack location.
943af732203SDimitry Andric bool isSpillInstruction(const MachineInstr &MI, MachineFunction *MF);
944af732203SDimitry Andric
945af732203SDimitry Andric /// Decide if @MI is a spill instruction and return true if it is. We use 2
946af732203SDimitry Andric /// criteria to make this decision:
947af732203SDimitry Andric /// - Is this instruction a store to a spill slot?
948af732203SDimitry Andric /// - Is there a register operand that is both used and killed?
949af732203SDimitry Andric /// TODO: Store optimization can fold spills into other stores (including
950af732203SDimitry Andric /// other spills). We do not handle this yet (more than one memory operand).
951af732203SDimitry Andric bool isLocationSpill(const MachineInstr &MI, MachineFunction *MF,
952af732203SDimitry Andric Register &Reg);
953af732203SDimitry Andric
954af732203SDimitry Andric /// Returns true if the given machine instruction is a debug value which we
955af732203SDimitry Andric /// can emit entry values for.
956af732203SDimitry Andric ///
957af732203SDimitry Andric /// Currently, we generate debug entry values only for parameters that are
958af732203SDimitry Andric /// unmodified throughout the function and located in a register.
959af732203SDimitry Andric bool isEntryValueCandidate(const MachineInstr &MI,
960af732203SDimitry Andric const DefinedRegsSet &Regs) const;
961af732203SDimitry Andric
962af732203SDimitry Andric /// If a given instruction is identified as a spill, return the spill location
963af732203SDimitry Andric /// and set \p Reg to the spilled register.
964af732203SDimitry Andric Optional<VarLoc::SpillLoc> isRestoreInstruction(const MachineInstr &MI,
965af732203SDimitry Andric MachineFunction *MF,
966af732203SDimitry Andric Register &Reg);
967af732203SDimitry Andric /// Given a spill instruction, extract the register and offset used to
968af732203SDimitry Andric /// address the spill location in a target independent way.
969af732203SDimitry Andric VarLoc::SpillLoc extractSpillBaseRegAndOffset(const MachineInstr &MI);
970af732203SDimitry Andric void insertTransferDebugPair(MachineInstr &MI, OpenRangesSet &OpenRanges,
971af732203SDimitry Andric TransferMap &Transfers, VarLocMap &VarLocIDs,
972af732203SDimitry Andric LocIndex OldVarID, TransferKind Kind,
973*5f7ddb14SDimitry Andric const VarLoc::MachineLoc &OldLoc,
974af732203SDimitry Andric Register NewReg = Register());
975af732203SDimitry Andric
976af732203SDimitry Andric void transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges,
977af732203SDimitry Andric VarLocMap &VarLocIDs);
978af732203SDimitry Andric void transferSpillOrRestoreInst(MachineInstr &MI, OpenRangesSet &OpenRanges,
979af732203SDimitry Andric VarLocMap &VarLocIDs, TransferMap &Transfers);
980af732203SDimitry Andric bool removeEntryValue(const MachineInstr &MI, OpenRangesSet &OpenRanges,
981af732203SDimitry Andric VarLocMap &VarLocIDs, const VarLoc &EntryVL);
982af732203SDimitry Andric void emitEntryValues(MachineInstr &MI, OpenRangesSet &OpenRanges,
983af732203SDimitry Andric VarLocMap &VarLocIDs, TransferMap &Transfers,
984*5f7ddb14SDimitry Andric VarLocsInRange &KillSet);
985af732203SDimitry Andric void recordEntryValue(const MachineInstr &MI,
986af732203SDimitry Andric const DefinedRegsSet &DefinedRegs,
987af732203SDimitry Andric OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs);
988af732203SDimitry Andric void transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges,
989af732203SDimitry Andric VarLocMap &VarLocIDs, TransferMap &Transfers);
990af732203SDimitry Andric void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges,
991af732203SDimitry Andric VarLocMap &VarLocIDs, TransferMap &Transfers);
992af732203SDimitry Andric bool transferTerminator(MachineBasicBlock *MBB, OpenRangesSet &OpenRanges,
993af732203SDimitry Andric VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs);
994af732203SDimitry Andric
995af732203SDimitry Andric void process(MachineInstr &MI, OpenRangesSet &OpenRanges,
996af732203SDimitry Andric VarLocMap &VarLocIDs, TransferMap &Transfers);
997af732203SDimitry Andric
998af732203SDimitry Andric void accumulateFragmentMap(MachineInstr &MI, VarToFragments &SeenFragments,
999af732203SDimitry Andric OverlapMap &OLapMap);
1000af732203SDimitry Andric
1001af732203SDimitry Andric bool join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
1002af732203SDimitry Andric const VarLocMap &VarLocIDs,
1003af732203SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
1004af732203SDimitry Andric SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks);
1005af732203SDimitry Andric
1006af732203SDimitry Andric /// Create DBG_VALUE insts for inlocs that have been propagated but
1007af732203SDimitry Andric /// had their instruction creation deferred.
1008af732203SDimitry Andric void flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs);
1009af732203SDimitry Andric
1010af732203SDimitry Andric bool ExtendRanges(MachineFunction &MF, TargetPassConfig *TPC) override;
1011af732203SDimitry Andric
1012af732203SDimitry Andric public:
1013af732203SDimitry Andric /// Default construct and initialize the pass.
1014af732203SDimitry Andric VarLocBasedLDV();
1015af732203SDimitry Andric
1016af732203SDimitry Andric ~VarLocBasedLDV();
1017af732203SDimitry Andric
1018af732203SDimitry Andric /// Print to ostream with a message.
1019af732203SDimitry Andric void printVarLocInMBB(const MachineFunction &MF, const VarLocInMBB &V,
1020af732203SDimitry Andric const VarLocMap &VarLocIDs, const char *msg,
1021af732203SDimitry Andric raw_ostream &Out) const;
1022af732203SDimitry Andric };
1023af732203SDimitry Andric
1024af732203SDimitry Andric } // end anonymous namespace
1025af732203SDimitry Andric
1026af732203SDimitry Andric //===----------------------------------------------------------------------===//
1027af732203SDimitry Andric // Implementation
1028af732203SDimitry Andric //===----------------------------------------------------------------------===//
1029af732203SDimitry Andric
VarLocBasedLDV()1030af732203SDimitry Andric VarLocBasedLDV::VarLocBasedLDV() { }
1031af732203SDimitry Andric
~VarLocBasedLDV()1032af732203SDimitry Andric VarLocBasedLDV::~VarLocBasedLDV() { }
1033af732203SDimitry Andric
1034af732203SDimitry Andric /// Erase a variable from the set of open ranges, and additionally erase any
1035af732203SDimitry Andric /// fragments that may overlap it. If the VarLoc is a backup location, erase
1036af732203SDimitry Andric /// the variable from the EntryValuesBackupVars set, indicating we should stop
1037af732203SDimitry Andric /// tracking its backup entry location. Otherwise, if the VarLoc is primary
1038af732203SDimitry Andric /// location, erase the variable from the Vars set.
erase(const VarLoc & VL)1039af732203SDimitry Andric void VarLocBasedLDV::OpenRangesSet::erase(const VarLoc &VL) {
1040af732203SDimitry Andric // Erasure helper.
1041af732203SDimitry Andric auto DoErase = [VL, this](DebugVariable VarToErase) {
1042af732203SDimitry Andric auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1043af732203SDimitry Andric auto It = EraseFrom->find(VarToErase);
1044af732203SDimitry Andric if (It != EraseFrom->end()) {
1045*5f7ddb14SDimitry Andric LocIndices IDs = It->second;
1046*5f7ddb14SDimitry Andric for (LocIndex ID : IDs)
1047af732203SDimitry Andric VarLocs.reset(ID.getAsRawInteger());
1048af732203SDimitry Andric EraseFrom->erase(It);
1049af732203SDimitry Andric }
1050af732203SDimitry Andric };
1051af732203SDimitry Andric
1052af732203SDimitry Andric DebugVariable Var = VL.Var;
1053af732203SDimitry Andric
1054af732203SDimitry Andric // Erase the variable/fragment that ends here.
1055af732203SDimitry Andric DoErase(Var);
1056af732203SDimitry Andric
1057af732203SDimitry Andric // Extract the fragment. Interpret an empty fragment as one that covers all
1058af732203SDimitry Andric // possible bits.
1059af732203SDimitry Andric FragmentInfo ThisFragment = Var.getFragmentOrDefault();
1060af732203SDimitry Andric
1061af732203SDimitry Andric // There may be fragments that overlap the designated fragment. Look them up
1062af732203SDimitry Andric // in the pre-computed overlap map, and erase them too.
1063af732203SDimitry Andric auto MapIt = OverlappingFragments.find({Var.getVariable(), ThisFragment});
1064af732203SDimitry Andric if (MapIt != OverlappingFragments.end()) {
1065af732203SDimitry Andric for (auto Fragment : MapIt->second) {
1066af732203SDimitry Andric VarLocBasedLDV::OptFragmentInfo FragmentHolder;
1067af732203SDimitry Andric if (!DebugVariable::isDefaultFragment(Fragment))
1068af732203SDimitry Andric FragmentHolder = VarLocBasedLDV::OptFragmentInfo(Fragment);
1069af732203SDimitry Andric DoErase({Var.getVariable(), FragmentHolder, Var.getInlinedAt()});
1070af732203SDimitry Andric }
1071af732203SDimitry Andric }
1072af732203SDimitry Andric }
1073af732203SDimitry Andric
erase(const VarLocsInRange & KillSet,const VarLocMap & VarLocIDs,LocIndex::u32_location_t Location)1074*5f7ddb14SDimitry Andric void VarLocBasedLDV::OpenRangesSet::erase(const VarLocsInRange &KillSet,
1075*5f7ddb14SDimitry Andric const VarLocMap &VarLocIDs,
1076*5f7ddb14SDimitry Andric LocIndex::u32_location_t Location) {
1077*5f7ddb14SDimitry Andric VarLocSet RemoveSet(Alloc);
1078*5f7ddb14SDimitry Andric for (LocIndex::u32_index_t ID : KillSet) {
1079*5f7ddb14SDimitry Andric const VarLoc &VL = VarLocIDs[LocIndex(Location, ID)];
1080*5f7ddb14SDimitry Andric auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1081*5f7ddb14SDimitry Andric EraseFrom->erase(VL.Var);
1082*5f7ddb14SDimitry Andric LocIndices VLI = VarLocIDs.getAllIndices(VL);
1083*5f7ddb14SDimitry Andric for (LocIndex ID : VLI)
1084*5f7ddb14SDimitry Andric RemoveSet.set(ID.getAsRawInteger());
1085*5f7ddb14SDimitry Andric }
1086*5f7ddb14SDimitry Andric VarLocs.intersectWithComplement(RemoveSet);
1087*5f7ddb14SDimitry Andric }
1088*5f7ddb14SDimitry Andric
insertFromLocSet(const VarLocSet & ToLoad,const VarLocMap & Map)1089*5f7ddb14SDimitry Andric void VarLocBasedLDV::OpenRangesSet::insertFromLocSet(const VarLocSet &ToLoad,
1090*5f7ddb14SDimitry Andric const VarLocMap &Map) {
1091*5f7ddb14SDimitry Andric VarLocsInRange UniqueVarLocIDs;
1092*5f7ddb14SDimitry Andric DefinedRegsSet Regs;
1093*5f7ddb14SDimitry Andric Regs.insert(LocIndex::kUniversalLocation);
1094*5f7ddb14SDimitry Andric collectIDsForRegs(UniqueVarLocIDs, Regs, ToLoad, Map);
1095*5f7ddb14SDimitry Andric for (uint64_t ID : UniqueVarLocIDs) {
1096*5f7ddb14SDimitry Andric LocIndex Idx = LocIndex::fromRawInteger(ID);
1097*5f7ddb14SDimitry Andric const VarLoc &VarL = Map[Idx];
1098*5f7ddb14SDimitry Andric const LocIndices Indices = Map.getAllIndices(VarL);
1099*5f7ddb14SDimitry Andric insert(Indices, VarL);
1100af732203SDimitry Andric }
1101af732203SDimitry Andric }
1102af732203SDimitry Andric
insert(LocIndices VarLocIDs,const VarLoc & VL)1103*5f7ddb14SDimitry Andric void VarLocBasedLDV::OpenRangesSet::insert(LocIndices VarLocIDs,
1104af732203SDimitry Andric const VarLoc &VL) {
1105af732203SDimitry Andric auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1106*5f7ddb14SDimitry Andric for (LocIndex ID : VarLocIDs)
1107*5f7ddb14SDimitry Andric VarLocs.set(ID.getAsRawInteger());
1108*5f7ddb14SDimitry Andric InsertInto->insert({VL.Var, VarLocIDs});
1109af732203SDimitry Andric }
1110af732203SDimitry Andric
1111af732203SDimitry Andric /// Return the Loc ID of an entry value backup location, if it exists for the
1112af732203SDimitry Andric /// variable.
1113*5f7ddb14SDimitry Andric llvm::Optional<LocIndices>
getEntryValueBackup(DebugVariable Var)1114af732203SDimitry Andric VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(DebugVariable Var) {
1115af732203SDimitry Andric auto It = EntryValuesBackupVars.find(Var);
1116af732203SDimitry Andric if (It != EntryValuesBackupVars.end())
1117af732203SDimitry Andric return It->second;
1118af732203SDimitry Andric
1119af732203SDimitry Andric return llvm::None;
1120af732203SDimitry Andric }
1121af732203SDimitry Andric
collectIDsForRegs(VarLocsInRange & Collected,const DefinedRegsSet & Regs,const VarLocSet & CollectFrom,const VarLocMap & VarLocIDs)1122*5f7ddb14SDimitry Andric void VarLocBasedLDV::collectIDsForRegs(VarLocsInRange &Collected,
1123af732203SDimitry Andric const DefinedRegsSet &Regs,
1124*5f7ddb14SDimitry Andric const VarLocSet &CollectFrom,
1125*5f7ddb14SDimitry Andric const VarLocMap &VarLocIDs) {
1126af732203SDimitry Andric assert(!Regs.empty() && "Nothing to collect");
1127*5f7ddb14SDimitry Andric SmallVector<Register, 32> SortedRegs;
1128*5f7ddb14SDimitry Andric append_range(SortedRegs, Regs);
1129af732203SDimitry Andric array_pod_sort(SortedRegs.begin(), SortedRegs.end());
1130af732203SDimitry Andric auto It = CollectFrom.find(LocIndex::rawIndexForReg(SortedRegs.front()));
1131af732203SDimitry Andric auto End = CollectFrom.end();
1132*5f7ddb14SDimitry Andric for (Register Reg : SortedRegs) {
1133*5f7ddb14SDimitry Andric // The half-open interval [FirstIndexForReg, FirstInvalidIndex) contains
1134*5f7ddb14SDimitry Andric // all possible VarLoc IDs for VarLocs with MLs of kind RegisterKind which
1135*5f7ddb14SDimitry Andric // live in Reg.
1136af732203SDimitry Andric uint64_t FirstIndexForReg = LocIndex::rawIndexForReg(Reg);
1137af732203SDimitry Andric uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(Reg + 1);
1138af732203SDimitry Andric It.advanceToLowerBound(FirstIndexForReg);
1139af732203SDimitry Andric
1140af732203SDimitry Andric // Iterate through that half-open interval and collect all the set IDs.
1141*5f7ddb14SDimitry Andric for (; It != End && *It < FirstInvalidIndex; ++It) {
1142*5f7ddb14SDimitry Andric LocIndex ItIdx = LocIndex::fromRawInteger(*It);
1143*5f7ddb14SDimitry Andric const VarLoc &VL = VarLocIDs[ItIdx];
1144*5f7ddb14SDimitry Andric LocIndices LI = VarLocIDs.getAllIndices(VL);
1145*5f7ddb14SDimitry Andric // For now, the back index is always the universal location index.
1146*5f7ddb14SDimitry Andric assert(LI.back().Location == LocIndex::kUniversalLocation &&
1147*5f7ddb14SDimitry Andric "Unexpected order of LocIndices for VarLoc; was it inserted into "
1148*5f7ddb14SDimitry Andric "the VarLocMap correctly?");
1149*5f7ddb14SDimitry Andric Collected.insert(LI.back().Index);
1150*5f7ddb14SDimitry Andric }
1151af732203SDimitry Andric
1152af732203SDimitry Andric if (It == End)
1153af732203SDimitry Andric return;
1154af732203SDimitry Andric }
1155af732203SDimitry Andric }
1156af732203SDimitry Andric
getUsedRegs(const VarLocSet & CollectFrom,SmallVectorImpl<Register> & UsedRegs) const1157af732203SDimitry Andric void VarLocBasedLDV::getUsedRegs(const VarLocSet &CollectFrom,
1158*5f7ddb14SDimitry Andric SmallVectorImpl<Register> &UsedRegs) const {
1159af732203SDimitry Andric // All register-based VarLocs are assigned indices greater than or equal to
1160af732203SDimitry Andric // FirstRegIndex.
1161*5f7ddb14SDimitry Andric uint64_t FirstRegIndex =
1162*5f7ddb14SDimitry Andric LocIndex::rawIndexForReg(LocIndex::kFirstRegLocation);
1163af732203SDimitry Andric uint64_t FirstInvalidIndex =
1164af732203SDimitry Andric LocIndex::rawIndexForReg(LocIndex::kFirstInvalidRegLocation);
1165af732203SDimitry Andric for (auto It = CollectFrom.find(FirstRegIndex),
1166af732203SDimitry Andric End = CollectFrom.find(FirstInvalidIndex);
1167af732203SDimitry Andric It != End;) {
1168af732203SDimitry Andric // We found a VarLoc ID for a VarLoc that lives in a register. Figure out
1169af732203SDimitry Andric // which register and add it to UsedRegs.
1170af732203SDimitry Andric uint32_t FoundReg = LocIndex::fromRawInteger(*It).Location;
1171af732203SDimitry Andric assert((UsedRegs.empty() || FoundReg != UsedRegs.back()) &&
1172af732203SDimitry Andric "Duplicate used reg");
1173af732203SDimitry Andric UsedRegs.push_back(FoundReg);
1174af732203SDimitry Andric
1175af732203SDimitry Andric // Skip to the next /set/ register. Note that this finds a lower bound, so
1176af732203SDimitry Andric // even if there aren't any VarLocs living in `FoundReg+1`, we're still
1177af732203SDimitry Andric // guaranteed to move on to the next register (or to end()).
1178af732203SDimitry Andric uint64_t NextRegIndex = LocIndex::rawIndexForReg(FoundReg + 1);
1179af732203SDimitry Andric It.advanceToLowerBound(NextRegIndex);
1180af732203SDimitry Andric }
1181af732203SDimitry Andric }
1182af732203SDimitry Andric
1183af732203SDimitry Andric //===----------------------------------------------------------------------===//
1184af732203SDimitry Andric // Debug Range Extension Implementation
1185af732203SDimitry Andric //===----------------------------------------------------------------------===//
1186af732203SDimitry Andric
1187af732203SDimitry Andric #ifndef NDEBUG
printVarLocInMBB(const MachineFunction & MF,const VarLocInMBB & V,const VarLocMap & VarLocIDs,const char * msg,raw_ostream & Out) const1188af732203SDimitry Andric void VarLocBasedLDV::printVarLocInMBB(const MachineFunction &MF,
1189af732203SDimitry Andric const VarLocInMBB &V,
1190af732203SDimitry Andric const VarLocMap &VarLocIDs,
1191af732203SDimitry Andric const char *msg,
1192af732203SDimitry Andric raw_ostream &Out) const {
1193af732203SDimitry Andric Out << '\n' << msg << '\n';
1194af732203SDimitry Andric for (const MachineBasicBlock &BB : MF) {
1195af732203SDimitry Andric if (!V.count(&BB))
1196af732203SDimitry Andric continue;
1197af732203SDimitry Andric const VarLocSet &L = getVarLocsInMBB(&BB, V);
1198af732203SDimitry Andric if (L.empty())
1199af732203SDimitry Andric continue;
1200*5f7ddb14SDimitry Andric SmallVector<VarLoc, 32> VarLocs;
1201*5f7ddb14SDimitry Andric collectAllVarLocs(VarLocs, L, VarLocIDs);
1202af732203SDimitry Andric Out << "MBB: " << BB.getNumber() << ":\n";
1203*5f7ddb14SDimitry Andric for (const VarLoc &VL : VarLocs) {
1204af732203SDimitry Andric Out << " Var: " << VL.Var.getVariable()->getName();
1205af732203SDimitry Andric Out << " MI: ";
1206af732203SDimitry Andric VL.dump(TRI, Out);
1207af732203SDimitry Andric }
1208af732203SDimitry Andric }
1209af732203SDimitry Andric Out << "\n";
1210af732203SDimitry Andric }
1211af732203SDimitry Andric #endif
1212af732203SDimitry Andric
1213af732203SDimitry Andric VarLocBasedLDV::VarLoc::SpillLoc
extractSpillBaseRegAndOffset(const MachineInstr & MI)1214af732203SDimitry Andric VarLocBasedLDV::extractSpillBaseRegAndOffset(const MachineInstr &MI) {
1215af732203SDimitry Andric assert(MI.hasOneMemOperand() &&
1216af732203SDimitry Andric "Spill instruction does not have exactly one memory operand?");
1217af732203SDimitry Andric auto MMOI = MI.memoperands_begin();
1218af732203SDimitry Andric const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
1219af732203SDimitry Andric assert(PVal->kind() == PseudoSourceValue::FixedStack &&
1220af732203SDimitry Andric "Inconsistent memory operand in spill instruction");
1221af732203SDimitry Andric int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
1222af732203SDimitry Andric const MachineBasicBlock *MBB = MI.getParent();
1223af732203SDimitry Andric Register Reg;
1224af732203SDimitry Andric StackOffset Offset = TFI->getFrameIndexReference(*MBB->getParent(), FI, Reg);
1225af732203SDimitry Andric return {Reg, Offset};
1226af732203SDimitry Andric }
1227af732203SDimitry Andric
1228af732203SDimitry Andric /// Try to salvage the debug entry value if we encounter a new debug value
1229af732203SDimitry Andric /// describing the same parameter, otherwise stop tracking the value. Return
1230af732203SDimitry Andric /// true if we should stop tracking the entry value, otherwise return false.
removeEntryValue(const MachineInstr & MI,OpenRangesSet & OpenRanges,VarLocMap & VarLocIDs,const VarLoc & EntryVL)1231af732203SDimitry Andric bool VarLocBasedLDV::removeEntryValue(const MachineInstr &MI,
1232af732203SDimitry Andric OpenRangesSet &OpenRanges,
1233af732203SDimitry Andric VarLocMap &VarLocIDs,
1234af732203SDimitry Andric const VarLoc &EntryVL) {
1235af732203SDimitry Andric // Skip the DBG_VALUE which is the debug entry value itself.
1236af732203SDimitry Andric if (MI.isIdenticalTo(EntryVL.MI))
1237af732203SDimitry Andric return false;
1238af732203SDimitry Andric
1239af732203SDimitry Andric // If the parameter's location is not register location, we can not track
1240af732203SDimitry Andric // the entry value any more. In addition, if the debug expression from the
1241af732203SDimitry Andric // DBG_VALUE is not empty, we can assume the parameter's value has changed
1242af732203SDimitry Andric // indicating that we should stop tracking its entry value as well.
1243af732203SDimitry Andric if (!MI.getDebugOperand(0).isReg() ||
1244af732203SDimitry Andric MI.getDebugExpression()->getNumElements() != 0)
1245af732203SDimitry Andric return true;
1246af732203SDimitry Andric
1247af732203SDimitry Andric // If the DBG_VALUE comes from a copy instruction that copies the entry value,
1248af732203SDimitry Andric // it means the parameter's value has not changed and we should be able to use
1249af732203SDimitry Andric // its entry value.
1250af732203SDimitry Andric Register Reg = MI.getDebugOperand(0).getReg();
1251af732203SDimitry Andric auto I = std::next(MI.getReverseIterator());
1252af732203SDimitry Andric const MachineOperand *SrcRegOp, *DestRegOp;
1253af732203SDimitry Andric if (I != MI.getParent()->rend()) {
1254*5f7ddb14SDimitry Andric
1255af732203SDimitry Andric // TODO: Try to keep tracking of an entry value if we encounter a propagated
1256af732203SDimitry Andric // DBG_VALUE describing the copy of the entry value. (Propagated entry value
1257af732203SDimitry Andric // does not indicate the parameter modification.)
1258af732203SDimitry Andric auto DestSrc = TII->isCopyInstr(*I);
1259af732203SDimitry Andric if (!DestSrc)
1260af732203SDimitry Andric return true;
1261af732203SDimitry Andric
1262af732203SDimitry Andric SrcRegOp = DestSrc->Source;
1263af732203SDimitry Andric DestRegOp = DestSrc->Destination;
1264af732203SDimitry Andric if (Reg != DestRegOp->getReg())
1265af732203SDimitry Andric return true;
1266af732203SDimitry Andric
1267af732203SDimitry Andric for (uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1268af732203SDimitry Andric const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(ID)];
1269*5f7ddb14SDimitry Andric if (VL.isEntryValueCopyBackupReg(Reg) &&
1270*5f7ddb14SDimitry Andric // Entry Values should not be variadic.
1271af732203SDimitry Andric VL.MI.getDebugOperand(0).getReg() == SrcRegOp->getReg())
1272af732203SDimitry Andric return false;
1273af732203SDimitry Andric }
1274af732203SDimitry Andric }
1275af732203SDimitry Andric
1276af732203SDimitry Andric return true;
1277af732203SDimitry Andric }
1278af732203SDimitry Andric
1279af732203SDimitry Andric /// End all previous ranges related to @MI and start a new range from @MI
1280af732203SDimitry Andric /// if it is a DBG_VALUE instr.
transferDebugValue(const MachineInstr & MI,OpenRangesSet & OpenRanges,VarLocMap & VarLocIDs)1281af732203SDimitry Andric void VarLocBasedLDV::transferDebugValue(const MachineInstr &MI,
1282af732203SDimitry Andric OpenRangesSet &OpenRanges,
1283af732203SDimitry Andric VarLocMap &VarLocIDs) {
1284af732203SDimitry Andric if (!MI.isDebugValue())
1285af732203SDimitry Andric return;
1286af732203SDimitry Andric const DILocalVariable *Var = MI.getDebugVariable();
1287af732203SDimitry Andric const DIExpression *Expr = MI.getDebugExpression();
1288af732203SDimitry Andric const DILocation *DebugLoc = MI.getDebugLoc();
1289af732203SDimitry Andric const DILocation *InlinedAt = DebugLoc->getInlinedAt();
1290af732203SDimitry Andric assert(Var->isValidLocationForIntrinsic(DebugLoc) &&
1291af732203SDimitry Andric "Expected inlined-at fields to agree");
1292af732203SDimitry Andric
1293af732203SDimitry Andric DebugVariable V(Var, Expr, InlinedAt);
1294af732203SDimitry Andric
1295af732203SDimitry Andric // Check if this DBG_VALUE indicates a parameter's value changing.
1296af732203SDimitry Andric // If that is the case, we should stop tracking its entry value.
1297af732203SDimitry Andric auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);
1298af732203SDimitry Andric if (Var->isParameter() && EntryValBackupID) {
1299*5f7ddb14SDimitry Andric const VarLoc &EntryVL = VarLocIDs[EntryValBackupID->back()];
1300af732203SDimitry Andric if (removeEntryValue(MI, OpenRanges, VarLocIDs, EntryVL)) {
1301af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Deleting a DBG entry value because of: ";
1302af732203SDimitry Andric MI.print(dbgs(), /*IsStandalone*/ false,
1303af732203SDimitry Andric /*SkipOpers*/ false, /*SkipDebugLoc*/ false,
1304af732203SDimitry Andric /*AddNewLine*/ true, TII));
1305af732203SDimitry Andric OpenRanges.erase(EntryVL);
1306af732203SDimitry Andric }
1307af732203SDimitry Andric }
1308af732203SDimitry Andric
1309*5f7ddb14SDimitry Andric if (all_of(MI.debug_operands(), [](const MachineOperand &MO) {
1310*5f7ddb14SDimitry Andric return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||
1311*5f7ddb14SDimitry Andric MO.isCImm();
1312*5f7ddb14SDimitry Andric })) {
1313af732203SDimitry Andric // Use normal VarLoc constructor for registers and immediates.
1314af732203SDimitry Andric VarLoc VL(MI, LS);
1315af732203SDimitry Andric // End all previous ranges of VL.Var.
1316af732203SDimitry Andric OpenRanges.erase(VL);
1317af732203SDimitry Andric
1318*5f7ddb14SDimitry Andric LocIndices IDs = VarLocIDs.insert(VL);
1319af732203SDimitry Andric // Add the VarLoc to OpenRanges from this DBG_VALUE.
1320*5f7ddb14SDimitry Andric OpenRanges.insert(IDs, VL);
1321*5f7ddb14SDimitry Andric } else if (MI.memoperands().size() > 0) {
1322af732203SDimitry Andric llvm_unreachable("DBG_VALUE with mem operand encountered after regalloc?");
1323af732203SDimitry Andric } else {
1324af732203SDimitry Andric // This must be an undefined location. If it has an open range, erase it.
1325*5f7ddb14SDimitry Andric assert(MI.isUndefDebugValue() &&
1326af732203SDimitry Andric "Unexpected non-undef DBG_VALUE encountered");
1327af732203SDimitry Andric VarLoc VL(MI, LS);
1328af732203SDimitry Andric OpenRanges.erase(VL);
1329af732203SDimitry Andric }
1330af732203SDimitry Andric }
1331af732203SDimitry Andric
1332*5f7ddb14SDimitry Andric // This should be removed later, doesn't fit the new design.
collectAllVarLocs(SmallVectorImpl<VarLoc> & Collected,const VarLocSet & CollectFrom,const VarLocMap & VarLocIDs)1333*5f7ddb14SDimitry Andric void VarLocBasedLDV::collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
1334*5f7ddb14SDimitry Andric const VarLocSet &CollectFrom,
1335*5f7ddb14SDimitry Andric const VarLocMap &VarLocIDs) {
1336*5f7ddb14SDimitry Andric // The half-open interval [FirstIndexForReg, FirstInvalidIndex) contains all
1337*5f7ddb14SDimitry Andric // possible VarLoc IDs for VarLocs with MLs of kind RegisterKind which live
1338*5f7ddb14SDimitry Andric // in Reg.
1339*5f7ddb14SDimitry Andric uint64_t FirstIndex = LocIndex::rawIndexForReg(LocIndex::kUniversalLocation);
1340*5f7ddb14SDimitry Andric uint64_t FirstInvalidIndex =
1341*5f7ddb14SDimitry Andric LocIndex::rawIndexForReg(LocIndex::kUniversalLocation + 1);
1342*5f7ddb14SDimitry Andric // Iterate through that half-open interval and collect all the set IDs.
1343*5f7ddb14SDimitry Andric for (auto It = CollectFrom.find(FirstIndex), End = CollectFrom.end();
1344*5f7ddb14SDimitry Andric It != End && *It < FirstInvalidIndex; ++It) {
1345*5f7ddb14SDimitry Andric LocIndex RegIdx = LocIndex::fromRawInteger(*It);
1346*5f7ddb14SDimitry Andric Collected.push_back(VarLocIDs[RegIdx]);
1347*5f7ddb14SDimitry Andric }
1348*5f7ddb14SDimitry Andric }
1349*5f7ddb14SDimitry Andric
1350af732203SDimitry Andric /// Turn the entry value backup locations into primary locations.
emitEntryValues(MachineInstr & MI,OpenRangesSet & OpenRanges,VarLocMap & VarLocIDs,TransferMap & Transfers,VarLocsInRange & KillSet)1351af732203SDimitry Andric void VarLocBasedLDV::emitEntryValues(MachineInstr &MI,
1352af732203SDimitry Andric OpenRangesSet &OpenRanges,
1353af732203SDimitry Andric VarLocMap &VarLocIDs,
1354af732203SDimitry Andric TransferMap &Transfers,
1355*5f7ddb14SDimitry Andric VarLocsInRange &KillSet) {
1356af732203SDimitry Andric // Do not insert entry value locations after a terminator.
1357af732203SDimitry Andric if (MI.isTerminator())
1358af732203SDimitry Andric return;
1359af732203SDimitry Andric
1360*5f7ddb14SDimitry Andric for (uint32_t ID : KillSet) {
1361*5f7ddb14SDimitry Andric // The KillSet IDs are indices for the universal location bucket.
1362*5f7ddb14SDimitry Andric LocIndex Idx = LocIndex(LocIndex::kUniversalLocation, ID);
1363af732203SDimitry Andric const VarLoc &VL = VarLocIDs[Idx];
1364af732203SDimitry Andric if (!VL.Var.getVariable()->isParameter())
1365af732203SDimitry Andric continue;
1366af732203SDimitry Andric
1367af732203SDimitry Andric auto DebugVar = VL.Var;
1368*5f7ddb14SDimitry Andric Optional<LocIndices> EntryValBackupIDs =
1369af732203SDimitry Andric OpenRanges.getEntryValueBackup(DebugVar);
1370af732203SDimitry Andric
1371af732203SDimitry Andric // If the parameter has the entry value backup, it means we should
1372af732203SDimitry Andric // be able to use its entry value.
1373*5f7ddb14SDimitry Andric if (!EntryValBackupIDs)
1374af732203SDimitry Andric continue;
1375af732203SDimitry Andric
1376*5f7ddb14SDimitry Andric const VarLoc &EntryVL = VarLocIDs[EntryValBackupIDs->back()];
1377*5f7ddb14SDimitry Andric VarLoc EntryLoc = VarLoc::CreateEntryLoc(EntryVL.MI, LS, EntryVL.Expr,
1378*5f7ddb14SDimitry Andric EntryVL.Locs[0].Value.RegNo);
1379*5f7ddb14SDimitry Andric LocIndices EntryValueIDs = VarLocIDs.insert(EntryLoc);
1380*5f7ddb14SDimitry Andric Transfers.push_back({&MI, EntryValueIDs.back()});
1381*5f7ddb14SDimitry Andric OpenRanges.insert(EntryValueIDs, EntryLoc);
1382af732203SDimitry Andric }
1383af732203SDimitry Andric }
1384af732203SDimitry Andric
1385af732203SDimitry Andric /// Create new TransferDebugPair and insert it in \p Transfers. The VarLoc
1386af732203SDimitry Andric /// with \p OldVarID should be deleted form \p OpenRanges and replaced with
1387af732203SDimitry Andric /// new VarLoc. If \p NewReg is different than default zero value then the
1388af732203SDimitry Andric /// new location will be register location created by the copy like instruction,
1389af732203SDimitry Andric /// otherwise it is variable's location on the stack.
insertTransferDebugPair(MachineInstr & MI,OpenRangesSet & OpenRanges,TransferMap & Transfers,VarLocMap & VarLocIDs,LocIndex OldVarID,TransferKind Kind,const VarLoc::MachineLoc & OldLoc,Register NewReg)1390af732203SDimitry Andric void VarLocBasedLDV::insertTransferDebugPair(
1391af732203SDimitry Andric MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
1392af732203SDimitry Andric VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind,
1393*5f7ddb14SDimitry Andric const VarLoc::MachineLoc &OldLoc, Register NewReg) {
1394*5f7ddb14SDimitry Andric const VarLoc &OldVarLoc = VarLocIDs[OldVarID];
1395af732203SDimitry Andric
1396af732203SDimitry Andric auto ProcessVarLoc = [&MI, &OpenRanges, &Transfers, &VarLocIDs](VarLoc &VL) {
1397*5f7ddb14SDimitry Andric LocIndices LocIds = VarLocIDs.insert(VL);
1398af732203SDimitry Andric
1399af732203SDimitry Andric // Close this variable's previous location range.
1400af732203SDimitry Andric OpenRanges.erase(VL);
1401af732203SDimitry Andric
1402af732203SDimitry Andric // Record the new location as an open range, and a postponed transfer
1403af732203SDimitry Andric // inserting a DBG_VALUE for this location.
1404*5f7ddb14SDimitry Andric OpenRanges.insert(LocIds, VL);
1405af732203SDimitry Andric assert(!MI.isTerminator() && "Cannot insert DBG_VALUE after terminator");
1406*5f7ddb14SDimitry Andric TransferDebugPair MIP = {&MI, LocIds.back()};
1407af732203SDimitry Andric Transfers.push_back(MIP);
1408af732203SDimitry Andric };
1409af732203SDimitry Andric
1410af732203SDimitry Andric // End all previous ranges of VL.Var.
1411af732203SDimitry Andric OpenRanges.erase(VarLocIDs[OldVarID]);
1412af732203SDimitry Andric switch (Kind) {
1413af732203SDimitry Andric case TransferKind::TransferCopy: {
1414af732203SDimitry Andric assert(NewReg &&
1415af732203SDimitry Andric "No register supplied when handling a copy of a debug value");
1416af732203SDimitry Andric // Create a DBG_VALUE instruction to describe the Var in its new
1417af732203SDimitry Andric // register location.
1418*5f7ddb14SDimitry Andric VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1419af732203SDimitry Andric ProcessVarLoc(VL);
1420af732203SDimitry Andric LLVM_DEBUG({
1421af732203SDimitry Andric dbgs() << "Creating VarLoc for register copy:";
1422af732203SDimitry Andric VL.dump(TRI);
1423af732203SDimitry Andric });
1424af732203SDimitry Andric return;
1425af732203SDimitry Andric }
1426af732203SDimitry Andric case TransferKind::TransferSpill: {
1427af732203SDimitry Andric // Create a DBG_VALUE instruction to describe the Var in its spilled
1428af732203SDimitry Andric // location.
1429af732203SDimitry Andric VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI);
1430*5f7ddb14SDimitry Andric VarLoc VL = VarLoc::CreateSpillLoc(
1431*5f7ddb14SDimitry Andric OldVarLoc, OldLoc, SpillLocation.SpillBase, SpillLocation.SpillOffset);
1432af732203SDimitry Andric ProcessVarLoc(VL);
1433af732203SDimitry Andric LLVM_DEBUG({
1434af732203SDimitry Andric dbgs() << "Creating VarLoc for spill:";
1435af732203SDimitry Andric VL.dump(TRI);
1436af732203SDimitry Andric });
1437af732203SDimitry Andric return;
1438af732203SDimitry Andric }
1439af732203SDimitry Andric case TransferKind::TransferRestore: {
1440af732203SDimitry Andric assert(NewReg &&
1441af732203SDimitry Andric "No register supplied when handling a restore of a debug value");
1442af732203SDimitry Andric // DebugInstr refers to the pre-spill location, therefore we can reuse
1443af732203SDimitry Andric // its expression.
1444*5f7ddb14SDimitry Andric VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1445af732203SDimitry Andric ProcessVarLoc(VL);
1446af732203SDimitry Andric LLVM_DEBUG({
1447af732203SDimitry Andric dbgs() << "Creating VarLoc for restore:";
1448af732203SDimitry Andric VL.dump(TRI);
1449af732203SDimitry Andric });
1450af732203SDimitry Andric return;
1451af732203SDimitry Andric }
1452af732203SDimitry Andric }
1453af732203SDimitry Andric llvm_unreachable("Invalid transfer kind");
1454af732203SDimitry Andric }
1455af732203SDimitry Andric
1456af732203SDimitry Andric /// A definition of a register may mark the end of a range.
transferRegisterDef(MachineInstr & MI,OpenRangesSet & OpenRanges,VarLocMap & VarLocIDs,TransferMap & Transfers)1457af732203SDimitry Andric void VarLocBasedLDV::transferRegisterDef(
1458af732203SDimitry Andric MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,
1459af732203SDimitry Andric TransferMap &Transfers) {
1460af732203SDimitry Andric
1461af732203SDimitry Andric // Meta Instructions do not affect the debug liveness of any register they
1462af732203SDimitry Andric // define.
1463af732203SDimitry Andric if (MI.isMetaInstruction())
1464af732203SDimitry Andric return;
1465af732203SDimitry Andric
1466af732203SDimitry Andric MachineFunction *MF = MI.getMF();
1467af732203SDimitry Andric const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
1468af732203SDimitry Andric Register SP = TLI->getStackPointerRegisterToSaveRestore();
1469af732203SDimitry Andric
1470af732203SDimitry Andric // Find the regs killed by MI, and find regmasks of preserved regs.
1471af732203SDimitry Andric DefinedRegsSet DeadRegs;
1472af732203SDimitry Andric SmallVector<const uint32_t *, 4> RegMasks;
1473af732203SDimitry Andric for (const MachineOperand &MO : MI.operands()) {
1474af732203SDimitry Andric // Determine whether the operand is a register def.
1475af732203SDimitry Andric if (MO.isReg() && MO.isDef() && MO.getReg() &&
1476af732203SDimitry Andric Register::isPhysicalRegister(MO.getReg()) &&
1477af732203SDimitry Andric !(MI.isCall() && MO.getReg() == SP)) {
1478af732203SDimitry Andric // Remove ranges of all aliased registers.
1479af732203SDimitry Andric for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)
1480af732203SDimitry Andric // FIXME: Can we break out of this loop early if no insertion occurs?
1481af732203SDimitry Andric DeadRegs.insert(*RAI);
1482af732203SDimitry Andric } else if (MO.isRegMask()) {
1483af732203SDimitry Andric RegMasks.push_back(MO.getRegMask());
1484af732203SDimitry Andric }
1485af732203SDimitry Andric }
1486af732203SDimitry Andric
1487af732203SDimitry Andric // Erase VarLocs which reside in one of the dead registers. For performance
1488af732203SDimitry Andric // reasons, it's critical to not iterate over the full set of open VarLocs.
1489af732203SDimitry Andric // Iterate over the set of dying/used regs instead.
1490af732203SDimitry Andric if (!RegMasks.empty()) {
1491*5f7ddb14SDimitry Andric SmallVector<Register, 32> UsedRegs;
1492af732203SDimitry Andric getUsedRegs(OpenRanges.getVarLocs(), UsedRegs);
1493*5f7ddb14SDimitry Andric for (Register Reg : UsedRegs) {
1494af732203SDimitry Andric // Remove ranges of all clobbered registers. Register masks don't usually
1495af732203SDimitry Andric // list SP as preserved. Assume that call instructions never clobber SP,
1496af732203SDimitry Andric // because some backends (e.g., AArch64) never list SP in the regmask.
1497af732203SDimitry Andric // While the debug info may be off for an instruction or two around
1498af732203SDimitry Andric // callee-cleanup calls, transferring the DEBUG_VALUE across the call is
1499af732203SDimitry Andric // still a better user experience.
1500af732203SDimitry Andric if (Reg == SP)
1501af732203SDimitry Andric continue;
1502af732203SDimitry Andric bool AnyRegMaskKillsReg =
1503af732203SDimitry Andric any_of(RegMasks, [Reg](const uint32_t *RegMask) {
1504af732203SDimitry Andric return MachineOperand::clobbersPhysReg(RegMask, Reg);
1505af732203SDimitry Andric });
1506af732203SDimitry Andric if (AnyRegMaskKillsReg)
1507af732203SDimitry Andric DeadRegs.insert(Reg);
1508af732203SDimitry Andric }
1509af732203SDimitry Andric }
1510af732203SDimitry Andric
1511af732203SDimitry Andric if (DeadRegs.empty())
1512af732203SDimitry Andric return;
1513af732203SDimitry Andric
1514*5f7ddb14SDimitry Andric VarLocsInRange KillSet;
1515*5f7ddb14SDimitry Andric collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs(), VarLocIDs);
1516*5f7ddb14SDimitry Andric OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kUniversalLocation);
1517af732203SDimitry Andric
1518af732203SDimitry Andric if (TPC) {
1519af732203SDimitry Andric auto &TM = TPC->getTM<TargetMachine>();
1520af732203SDimitry Andric if (TM.Options.ShouldEmitDebugEntryValues())
1521af732203SDimitry Andric emitEntryValues(MI, OpenRanges, VarLocIDs, Transfers, KillSet);
1522af732203SDimitry Andric }
1523af732203SDimitry Andric }
1524af732203SDimitry Andric
isSpillInstruction(const MachineInstr & MI,MachineFunction * MF)1525af732203SDimitry Andric bool VarLocBasedLDV::isSpillInstruction(const MachineInstr &MI,
1526af732203SDimitry Andric MachineFunction *MF) {
1527af732203SDimitry Andric // TODO: Handle multiple stores folded into one.
1528af732203SDimitry Andric if (!MI.hasOneMemOperand())
1529af732203SDimitry Andric return false;
1530af732203SDimitry Andric
1531af732203SDimitry Andric if (!MI.getSpillSize(TII) && !MI.getFoldedSpillSize(TII))
1532af732203SDimitry Andric return false; // This is not a spill instruction, since no valid size was
1533af732203SDimitry Andric // returned from either function.
1534af732203SDimitry Andric
1535af732203SDimitry Andric return true;
1536af732203SDimitry Andric }
1537af732203SDimitry Andric
isLocationSpill(const MachineInstr & MI,MachineFunction * MF,Register & Reg)1538af732203SDimitry Andric bool VarLocBasedLDV::isLocationSpill(const MachineInstr &MI,
1539af732203SDimitry Andric MachineFunction *MF, Register &Reg) {
1540af732203SDimitry Andric if (!isSpillInstruction(MI, MF))
1541af732203SDimitry Andric return false;
1542af732203SDimitry Andric
1543af732203SDimitry Andric auto isKilledReg = [&](const MachineOperand MO, Register &Reg) {
1544af732203SDimitry Andric if (!MO.isReg() || !MO.isUse()) {
1545af732203SDimitry Andric Reg = 0;
1546af732203SDimitry Andric return false;
1547af732203SDimitry Andric }
1548af732203SDimitry Andric Reg = MO.getReg();
1549af732203SDimitry Andric return MO.isKill();
1550af732203SDimitry Andric };
1551af732203SDimitry Andric
1552af732203SDimitry Andric for (const MachineOperand &MO : MI.operands()) {
1553af732203SDimitry Andric // In a spill instruction generated by the InlineSpiller the spilled
1554af732203SDimitry Andric // register has its kill flag set.
1555af732203SDimitry Andric if (isKilledReg(MO, Reg))
1556af732203SDimitry Andric return true;
1557af732203SDimitry Andric if (Reg != 0) {
1558af732203SDimitry Andric // Check whether next instruction kills the spilled register.
1559af732203SDimitry Andric // FIXME: Current solution does not cover search for killed register in
1560af732203SDimitry Andric // bundles and instructions further down the chain.
1561af732203SDimitry Andric auto NextI = std::next(MI.getIterator());
1562af732203SDimitry Andric // Skip next instruction that points to basic block end iterator.
1563af732203SDimitry Andric if (MI.getParent()->end() == NextI)
1564af732203SDimitry Andric continue;
1565af732203SDimitry Andric Register RegNext;
1566af732203SDimitry Andric for (const MachineOperand &MONext : NextI->operands()) {
1567af732203SDimitry Andric // Return true if we came across the register from the
1568af732203SDimitry Andric // previous spill instruction that is killed in NextI.
1569af732203SDimitry Andric if (isKilledReg(MONext, RegNext) && RegNext == Reg)
1570af732203SDimitry Andric return true;
1571af732203SDimitry Andric }
1572af732203SDimitry Andric }
1573af732203SDimitry Andric }
1574af732203SDimitry Andric // Return false if we didn't find spilled register.
1575af732203SDimitry Andric return false;
1576af732203SDimitry Andric }
1577af732203SDimitry Andric
1578af732203SDimitry Andric Optional<VarLocBasedLDV::VarLoc::SpillLoc>
isRestoreInstruction(const MachineInstr & MI,MachineFunction * MF,Register & Reg)1579af732203SDimitry Andric VarLocBasedLDV::isRestoreInstruction(const MachineInstr &MI,
1580af732203SDimitry Andric MachineFunction *MF, Register &Reg) {
1581af732203SDimitry Andric if (!MI.hasOneMemOperand())
1582af732203SDimitry Andric return None;
1583af732203SDimitry Andric
1584af732203SDimitry Andric // FIXME: Handle folded restore instructions with more than one memory
1585af732203SDimitry Andric // operand.
1586af732203SDimitry Andric if (MI.getRestoreSize(TII)) {
1587af732203SDimitry Andric Reg = MI.getOperand(0).getReg();
1588af732203SDimitry Andric return extractSpillBaseRegAndOffset(MI);
1589af732203SDimitry Andric }
1590af732203SDimitry Andric return None;
1591af732203SDimitry Andric }
1592af732203SDimitry Andric
1593af732203SDimitry Andric /// A spilled register may indicate that we have to end the current range of
1594af732203SDimitry Andric /// a variable and create a new one for the spill location.
1595af732203SDimitry Andric /// A restored register may indicate the reverse situation.
1596af732203SDimitry Andric /// We don't want to insert any instructions in process(), so we just create
1597af732203SDimitry Andric /// the DBG_VALUE without inserting it and keep track of it in \p Transfers.
1598af732203SDimitry Andric /// It will be inserted into the BB when we're done iterating over the
1599af732203SDimitry Andric /// instructions.
transferSpillOrRestoreInst(MachineInstr & MI,OpenRangesSet & OpenRanges,VarLocMap & VarLocIDs,TransferMap & Transfers)1600af732203SDimitry Andric void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI,
1601af732203SDimitry Andric OpenRangesSet &OpenRanges,
1602af732203SDimitry Andric VarLocMap &VarLocIDs,
1603af732203SDimitry Andric TransferMap &Transfers) {
1604af732203SDimitry Andric MachineFunction *MF = MI.getMF();
1605af732203SDimitry Andric TransferKind TKind;
1606af732203SDimitry Andric Register Reg;
1607af732203SDimitry Andric Optional<VarLoc::SpillLoc> Loc;
1608af732203SDimitry Andric
1609af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Examining instruction: "; MI.dump(););
1610af732203SDimitry Andric
1611af732203SDimitry Andric // First, if there are any DBG_VALUEs pointing at a spill slot that is
1612af732203SDimitry Andric // written to, then close the variable location. The value in memory
1613af732203SDimitry Andric // will have changed.
1614*5f7ddb14SDimitry Andric VarLocsInRange KillSet;
1615af732203SDimitry Andric if (isSpillInstruction(MI, MF)) {
1616af732203SDimitry Andric Loc = extractSpillBaseRegAndOffset(MI);
1617af732203SDimitry Andric for (uint64_t ID : OpenRanges.getSpillVarLocs()) {
1618af732203SDimitry Andric LocIndex Idx = LocIndex::fromRawInteger(ID);
1619af732203SDimitry Andric const VarLoc &VL = VarLocIDs[Idx];
1620*5f7ddb14SDimitry Andric assert(VL.containsSpillLocs() && "Broken VarLocSet?");
1621*5f7ddb14SDimitry Andric if (VL.usesSpillLoc(*Loc)) {
1622af732203SDimitry Andric // This location is overwritten by the current instruction -- terminate
1623af732203SDimitry Andric // the open range, and insert an explicit DBG_VALUE $noreg.
1624af732203SDimitry Andric //
1625af732203SDimitry Andric // Doing this at a later stage would require re-interpreting all
1626af732203SDimitry Andric // DBG_VALUes and DIExpressions to identify whether they point at
1627af732203SDimitry Andric // memory, and then analysing all memory writes to see if they
1628af732203SDimitry Andric // overwrite that memory, which is expensive.
1629af732203SDimitry Andric //
1630af732203SDimitry Andric // At this stage, we already know which DBG_VALUEs are for spills and
1631af732203SDimitry Andric // where they are located; it's best to fix handle overwrites now.
1632*5f7ddb14SDimitry Andric KillSet.insert(ID);
1633*5f7ddb14SDimitry Andric unsigned SpillLocIdx = VL.getSpillLocIdx(*Loc);
1634*5f7ddb14SDimitry Andric VarLoc::MachineLoc OldLoc = VL.Locs[SpillLocIdx];
1635*5f7ddb14SDimitry Andric VarLoc UndefVL = VarLoc::CreateCopyLoc(VL, OldLoc, 0);
1636*5f7ddb14SDimitry Andric LocIndices UndefLocIDs = VarLocIDs.insert(UndefVL);
1637*5f7ddb14SDimitry Andric Transfers.push_back({&MI, UndefLocIDs.back()});
1638af732203SDimitry Andric }
1639af732203SDimitry Andric }
1640*5f7ddb14SDimitry Andric OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kSpillLocation);
1641af732203SDimitry Andric }
1642af732203SDimitry Andric
1643af732203SDimitry Andric // Try to recognise spill and restore instructions that may create a new
1644af732203SDimitry Andric // variable location.
1645af732203SDimitry Andric if (isLocationSpill(MI, MF, Reg)) {
1646af732203SDimitry Andric TKind = TransferKind::TransferSpill;
1647af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Recognized as spill: "; MI.dump(););
1648af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Register: " << Reg << " " << printReg(Reg, TRI)
1649af732203SDimitry Andric << "\n");
1650af732203SDimitry Andric } else {
1651af732203SDimitry Andric if (!(Loc = isRestoreInstruction(MI, MF, Reg)))
1652af732203SDimitry Andric return;
1653af732203SDimitry Andric TKind = TransferKind::TransferRestore;
1654af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Recognized as restore: "; MI.dump(););
1655af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Register: " << Reg << " " << printReg(Reg, TRI)
1656af732203SDimitry Andric << "\n");
1657af732203SDimitry Andric }
1658af732203SDimitry Andric // Check if the register or spill location is the location of a debug value.
1659af732203SDimitry Andric auto TransferCandidates = OpenRanges.getEmptyVarLocRange();
1660af732203SDimitry Andric if (TKind == TransferKind::TransferSpill)
1661af732203SDimitry Andric TransferCandidates = OpenRanges.getRegisterVarLocs(Reg);
1662af732203SDimitry Andric else if (TKind == TransferKind::TransferRestore)
1663af732203SDimitry Andric TransferCandidates = OpenRanges.getSpillVarLocs();
1664af732203SDimitry Andric for (uint64_t ID : TransferCandidates) {
1665af732203SDimitry Andric LocIndex Idx = LocIndex::fromRawInteger(ID);
1666af732203SDimitry Andric const VarLoc &VL = VarLocIDs[Idx];
1667*5f7ddb14SDimitry Andric unsigned LocIdx;
1668af732203SDimitry Andric if (TKind == TransferKind::TransferSpill) {
1669*5f7ddb14SDimitry Andric assert(VL.usesReg(Reg) && "Broken VarLocSet?");
1670af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Spilling Register " << printReg(Reg, TRI) << '('
1671af732203SDimitry Andric << VL.Var.getVariable()->getName() << ")\n");
1672*5f7ddb14SDimitry Andric LocIdx = VL.getRegIdx(Reg);
1673af732203SDimitry Andric } else {
1674*5f7ddb14SDimitry Andric assert(TKind == TransferKind::TransferRestore && VL.containsSpillLocs() &&
1675*5f7ddb14SDimitry Andric "Broken VarLocSet?");
1676*5f7ddb14SDimitry Andric if (!VL.usesSpillLoc(*Loc))
1677af732203SDimitry Andric // The spill location is not the location of a debug value.
1678af732203SDimitry Andric continue;
1679af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Restoring Register " << printReg(Reg, TRI) << '('
1680af732203SDimitry Andric << VL.Var.getVariable()->getName() << ")\n");
1681*5f7ddb14SDimitry Andric LocIdx = VL.getSpillLocIdx(*Loc);
1682af732203SDimitry Andric }
1683*5f7ddb14SDimitry Andric VarLoc::MachineLoc MLoc = VL.Locs[LocIdx];
1684af732203SDimitry Andric insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, Idx, TKind,
1685*5f7ddb14SDimitry Andric MLoc, Reg);
1686af732203SDimitry Andric // FIXME: A comment should explain why it's correct to return early here,
1687af732203SDimitry Andric // if that is in fact correct.
1688af732203SDimitry Andric return;
1689af732203SDimitry Andric }
1690af732203SDimitry Andric }
1691af732203SDimitry Andric
1692af732203SDimitry Andric /// If \p MI is a register copy instruction, that copies a previously tracked
1693af732203SDimitry Andric /// value from one register to another register that is callee saved, we
1694af732203SDimitry Andric /// create new DBG_VALUE instruction described with copy destination register.
transferRegisterCopy(MachineInstr & MI,OpenRangesSet & OpenRanges,VarLocMap & VarLocIDs,TransferMap & Transfers)1695af732203SDimitry Andric void VarLocBasedLDV::transferRegisterCopy(MachineInstr &MI,
1696af732203SDimitry Andric OpenRangesSet &OpenRanges,
1697af732203SDimitry Andric VarLocMap &VarLocIDs,
1698af732203SDimitry Andric TransferMap &Transfers) {
1699af732203SDimitry Andric auto DestSrc = TII->isCopyInstr(MI);
1700af732203SDimitry Andric if (!DestSrc)
1701af732203SDimitry Andric return;
1702af732203SDimitry Andric
1703af732203SDimitry Andric const MachineOperand *DestRegOp = DestSrc->Destination;
1704af732203SDimitry Andric const MachineOperand *SrcRegOp = DestSrc->Source;
1705af732203SDimitry Andric
1706af732203SDimitry Andric if (!DestRegOp->isDef())
1707af732203SDimitry Andric return;
1708af732203SDimitry Andric
1709af732203SDimitry Andric auto isCalleeSavedReg = [&](Register Reg) {
1710af732203SDimitry Andric for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI)
1711af732203SDimitry Andric if (CalleeSavedRegs.test(*RAI))
1712af732203SDimitry Andric return true;
1713af732203SDimitry Andric return false;
1714af732203SDimitry Andric };
1715af732203SDimitry Andric
1716af732203SDimitry Andric Register SrcReg = SrcRegOp->getReg();
1717af732203SDimitry Andric Register DestReg = DestRegOp->getReg();
1718af732203SDimitry Andric
1719af732203SDimitry Andric // We want to recognize instructions where destination register is callee
1720af732203SDimitry Andric // saved register. If register that could be clobbered by the call is
1721af732203SDimitry Andric // included, there would be a great chance that it is going to be clobbered
1722af732203SDimitry Andric // soon. It is more likely that previous register location, which is callee
1723af732203SDimitry Andric // saved, is going to stay unclobbered longer, even if it is killed.
1724af732203SDimitry Andric if (!isCalleeSavedReg(DestReg))
1725af732203SDimitry Andric return;
1726af732203SDimitry Andric
1727af732203SDimitry Andric // Remember an entry value movement. If we encounter a new debug value of
1728af732203SDimitry Andric // a parameter describing only a moving of the value around, rather then
1729af732203SDimitry Andric // modifying it, we are still able to use the entry value if needed.
1730af732203SDimitry Andric if (isRegOtherThanSPAndFP(*DestRegOp, MI, TRI)) {
1731af732203SDimitry Andric for (uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1732af732203SDimitry Andric LocIndex Idx = LocIndex::fromRawInteger(ID);
1733af732203SDimitry Andric const VarLoc &VL = VarLocIDs[Idx];
1734*5f7ddb14SDimitry Andric if (VL.isEntryValueBackupReg(SrcReg)) {
1735af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Copy of the entry value: "; MI.dump(););
1736af732203SDimitry Andric VarLoc EntryValLocCopyBackup =
1737af732203SDimitry Andric VarLoc::CreateEntryCopyBackupLoc(VL.MI, LS, VL.Expr, DestReg);
1738af732203SDimitry Andric // Stop tracking the original entry value.
1739af732203SDimitry Andric OpenRanges.erase(VL);
1740af732203SDimitry Andric
1741af732203SDimitry Andric // Start tracking the entry value copy.
1742*5f7ddb14SDimitry Andric LocIndices EntryValCopyLocIDs = VarLocIDs.insert(EntryValLocCopyBackup);
1743*5f7ddb14SDimitry Andric OpenRanges.insert(EntryValCopyLocIDs, EntryValLocCopyBackup);
1744af732203SDimitry Andric break;
1745af732203SDimitry Andric }
1746af732203SDimitry Andric }
1747af732203SDimitry Andric }
1748af732203SDimitry Andric
1749af732203SDimitry Andric if (!SrcRegOp->isKill())
1750af732203SDimitry Andric return;
1751af732203SDimitry Andric
1752af732203SDimitry Andric for (uint64_t ID : OpenRanges.getRegisterVarLocs(SrcReg)) {
1753af732203SDimitry Andric LocIndex Idx = LocIndex::fromRawInteger(ID);
1754*5f7ddb14SDimitry Andric assert(VarLocIDs[Idx].usesReg(SrcReg) && "Broken VarLocSet?");
1755*5f7ddb14SDimitry Andric VarLoc::MachineLocValue Loc;
1756*5f7ddb14SDimitry Andric Loc.RegNo = SrcReg;
1757*5f7ddb14SDimitry Andric VarLoc::MachineLoc MLoc{VarLoc::MachineLocKind::RegisterKind, Loc};
1758af732203SDimitry Andric insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, Idx,
1759*5f7ddb14SDimitry Andric TransferKind::TransferCopy, MLoc, DestReg);
1760af732203SDimitry Andric // FIXME: A comment should explain why it's correct to return early here,
1761af732203SDimitry Andric // if that is in fact correct.
1762af732203SDimitry Andric return;
1763af732203SDimitry Andric }
1764af732203SDimitry Andric }
1765af732203SDimitry Andric
1766af732203SDimitry Andric /// Terminate all open ranges at the end of the current basic block.
transferTerminator(MachineBasicBlock * CurMBB,OpenRangesSet & OpenRanges,VarLocInMBB & OutLocs,const VarLocMap & VarLocIDs)1767af732203SDimitry Andric bool VarLocBasedLDV::transferTerminator(MachineBasicBlock *CurMBB,
1768af732203SDimitry Andric OpenRangesSet &OpenRanges,
1769af732203SDimitry Andric VarLocInMBB &OutLocs,
1770af732203SDimitry Andric const VarLocMap &VarLocIDs) {
1771af732203SDimitry Andric bool Changed = false;
1772*5f7ddb14SDimitry Andric LLVM_DEBUG({
1773*5f7ddb14SDimitry Andric VarVec VarLocs;
1774*5f7ddb14SDimitry Andric OpenRanges.getUniqueVarLocs(VarLocs, VarLocIDs);
1775*5f7ddb14SDimitry Andric for (VarLoc &VL : VarLocs) {
1776af732203SDimitry Andric // Copy OpenRanges to OutLocs, if not already present.
1777af732203SDimitry Andric dbgs() << "Add to OutLocs in MBB #" << CurMBB->getNumber() << ": ";
1778*5f7ddb14SDimitry Andric VL.dump(TRI);
1779*5f7ddb14SDimitry Andric }
1780af732203SDimitry Andric });
1781af732203SDimitry Andric VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);
1782af732203SDimitry Andric Changed = VLS != OpenRanges.getVarLocs();
1783af732203SDimitry Andric // New OutLocs set may be different due to spill, restore or register
1784af732203SDimitry Andric // copy instruction processing.
1785af732203SDimitry Andric if (Changed)
1786af732203SDimitry Andric VLS = OpenRanges.getVarLocs();
1787af732203SDimitry Andric OpenRanges.clear();
1788af732203SDimitry Andric return Changed;
1789af732203SDimitry Andric }
1790af732203SDimitry Andric
1791af732203SDimitry Andric /// Accumulate a mapping between each DILocalVariable fragment and other
1792af732203SDimitry Andric /// fragments of that DILocalVariable which overlap. This reduces work during
1793af732203SDimitry Andric /// the data-flow stage from "Find any overlapping fragments" to "Check if the
1794af732203SDimitry Andric /// known-to-overlap fragments are present".
1795af732203SDimitry Andric /// \param MI A previously unprocessed DEBUG_VALUE instruction to analyze for
1796af732203SDimitry Andric /// fragment usage.
1797af732203SDimitry Andric /// \param SeenFragments Map from DILocalVariable to all fragments of that
1798af732203SDimitry Andric /// Variable which are known to exist.
1799af732203SDimitry Andric /// \param OverlappingFragments The overlap map being constructed, from one
1800af732203SDimitry Andric /// Var/Fragment pair to a vector of fragments known to overlap.
accumulateFragmentMap(MachineInstr & MI,VarToFragments & SeenFragments,OverlapMap & OverlappingFragments)1801af732203SDimitry Andric void VarLocBasedLDV::accumulateFragmentMap(MachineInstr &MI,
1802af732203SDimitry Andric VarToFragments &SeenFragments,
1803af732203SDimitry Andric OverlapMap &OverlappingFragments) {
1804af732203SDimitry Andric DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(),
1805af732203SDimitry Andric MI.getDebugLoc()->getInlinedAt());
1806af732203SDimitry Andric FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
1807af732203SDimitry Andric
1808af732203SDimitry Andric // If this is the first sighting of this variable, then we are guaranteed
1809af732203SDimitry Andric // there are currently no overlapping fragments either. Initialize the set
1810af732203SDimitry Andric // of seen fragments, record no overlaps for the current one, and return.
1811af732203SDimitry Andric auto SeenIt = SeenFragments.find(MIVar.getVariable());
1812af732203SDimitry Andric if (SeenIt == SeenFragments.end()) {
1813af732203SDimitry Andric SmallSet<FragmentInfo, 4> OneFragment;
1814af732203SDimitry Andric OneFragment.insert(ThisFragment);
1815af732203SDimitry Andric SeenFragments.insert({MIVar.getVariable(), OneFragment});
1816af732203SDimitry Andric
1817af732203SDimitry Andric OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
1818af732203SDimitry Andric return;
1819af732203SDimitry Andric }
1820af732203SDimitry Andric
1821af732203SDimitry Andric // If this particular Variable/Fragment pair already exists in the overlap
1822af732203SDimitry Andric // map, it has already been accounted for.
1823af732203SDimitry Andric auto IsInOLapMap =
1824af732203SDimitry Andric OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
1825af732203SDimitry Andric if (!IsInOLapMap.second)
1826af732203SDimitry Andric return;
1827af732203SDimitry Andric
1828af732203SDimitry Andric auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
1829af732203SDimitry Andric auto &AllSeenFragments = SeenIt->second;
1830af732203SDimitry Andric
1831af732203SDimitry Andric // Otherwise, examine all other seen fragments for this variable, with "this"
1832af732203SDimitry Andric // fragment being a previously unseen fragment. Record any pair of
1833af732203SDimitry Andric // overlapping fragments.
1834af732203SDimitry Andric for (auto &ASeenFragment : AllSeenFragments) {
1835af732203SDimitry Andric // Does this previously seen fragment overlap?
1836af732203SDimitry Andric if (DIExpression::fragmentsOverlap(ThisFragment, ASeenFragment)) {
1837af732203SDimitry Andric // Yes: Mark the current fragment as being overlapped.
1838af732203SDimitry Andric ThisFragmentsOverlaps.push_back(ASeenFragment);
1839af732203SDimitry Andric // Mark the previously seen fragment as being overlapped by the current
1840af732203SDimitry Andric // one.
1841af732203SDimitry Andric auto ASeenFragmentsOverlaps =
1842af732203SDimitry Andric OverlappingFragments.find({MIVar.getVariable(), ASeenFragment});
1843af732203SDimitry Andric assert(ASeenFragmentsOverlaps != OverlappingFragments.end() &&
1844af732203SDimitry Andric "Previously seen var fragment has no vector of overlaps");
1845af732203SDimitry Andric ASeenFragmentsOverlaps->second.push_back(ThisFragment);
1846af732203SDimitry Andric }
1847af732203SDimitry Andric }
1848af732203SDimitry Andric
1849af732203SDimitry Andric AllSeenFragments.insert(ThisFragment);
1850af732203SDimitry Andric }
1851af732203SDimitry Andric
1852af732203SDimitry Andric /// This routine creates OpenRanges.
process(MachineInstr & MI,OpenRangesSet & OpenRanges,VarLocMap & VarLocIDs,TransferMap & Transfers)1853af732203SDimitry Andric void VarLocBasedLDV::process(MachineInstr &MI, OpenRangesSet &OpenRanges,
1854af732203SDimitry Andric VarLocMap &VarLocIDs, TransferMap &Transfers) {
1855af732203SDimitry Andric transferDebugValue(MI, OpenRanges, VarLocIDs);
1856af732203SDimitry Andric transferRegisterDef(MI, OpenRanges, VarLocIDs, Transfers);
1857af732203SDimitry Andric transferRegisterCopy(MI, OpenRanges, VarLocIDs, Transfers);
1858af732203SDimitry Andric transferSpillOrRestoreInst(MI, OpenRanges, VarLocIDs, Transfers);
1859af732203SDimitry Andric }
1860af732203SDimitry Andric
1861af732203SDimitry Andric /// This routine joins the analysis results of all incoming edges in @MBB by
1862af732203SDimitry Andric /// inserting a new DBG_VALUE instruction at the start of the @MBB - if the same
1863af732203SDimitry Andric /// source variable in all the predecessors of @MBB reside in the same location.
join(MachineBasicBlock & MBB,VarLocInMBB & OutLocs,VarLocInMBB & InLocs,const VarLocMap & VarLocIDs,SmallPtrSet<const MachineBasicBlock *,16> & Visited,SmallPtrSetImpl<const MachineBasicBlock * > & ArtificialBlocks)1864af732203SDimitry Andric bool VarLocBasedLDV::join(
1865af732203SDimitry Andric MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
1866af732203SDimitry Andric const VarLocMap &VarLocIDs,
1867af732203SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
1868af732203SDimitry Andric SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks) {
1869af732203SDimitry Andric LLVM_DEBUG(dbgs() << "join MBB: " << MBB.getNumber() << "\n");
1870af732203SDimitry Andric
1871af732203SDimitry Andric VarLocSet InLocsT(Alloc); // Temporary incoming locations.
1872af732203SDimitry Andric
1873af732203SDimitry Andric // For all predecessors of this MBB, find the set of VarLocs that
1874af732203SDimitry Andric // can be joined.
1875af732203SDimitry Andric int NumVisited = 0;
1876af732203SDimitry Andric for (auto p : MBB.predecessors()) {
1877af732203SDimitry Andric // Ignore backedges if we have not visited the predecessor yet. As the
1878af732203SDimitry Andric // predecessor hasn't yet had locations propagated into it, most locations
1879af732203SDimitry Andric // will not yet be valid, so treat them as all being uninitialized and
1880af732203SDimitry Andric // potentially valid. If a location guessed to be correct here is
1881af732203SDimitry Andric // invalidated later, we will remove it when we revisit this block.
1882af732203SDimitry Andric if (!Visited.count(p)) {
1883af732203SDimitry Andric LLVM_DEBUG(dbgs() << " ignoring unvisited pred MBB: " << p->getNumber()
1884af732203SDimitry Andric << "\n");
1885af732203SDimitry Andric continue;
1886af732203SDimitry Andric }
1887af732203SDimitry Andric auto OL = OutLocs.find(p);
1888af732203SDimitry Andric // Join is null in case of empty OutLocs from any of the pred.
1889af732203SDimitry Andric if (OL == OutLocs.end())
1890af732203SDimitry Andric return false;
1891af732203SDimitry Andric
1892af732203SDimitry Andric // Just copy over the Out locs to incoming locs for the first visited
1893af732203SDimitry Andric // predecessor, and for all other predecessors join the Out locs.
1894af732203SDimitry Andric VarLocSet &OutLocVLS = *OL->second.get();
1895af732203SDimitry Andric if (!NumVisited)
1896af732203SDimitry Andric InLocsT = OutLocVLS;
1897af732203SDimitry Andric else
1898af732203SDimitry Andric InLocsT &= OutLocVLS;
1899af732203SDimitry Andric
1900af732203SDimitry Andric LLVM_DEBUG({
1901af732203SDimitry Andric if (!InLocsT.empty()) {
1902*5f7ddb14SDimitry Andric VarVec VarLocs;
1903*5f7ddb14SDimitry Andric collectAllVarLocs(VarLocs, InLocsT, VarLocIDs);
1904*5f7ddb14SDimitry Andric for (const VarLoc &VL : VarLocs)
1905af732203SDimitry Andric dbgs() << " gathered candidate incoming var: "
1906*5f7ddb14SDimitry Andric << VL.Var.getVariable()->getName() << "\n";
1907af732203SDimitry Andric }
1908af732203SDimitry Andric });
1909af732203SDimitry Andric
1910af732203SDimitry Andric NumVisited++;
1911af732203SDimitry Andric }
1912af732203SDimitry Andric
1913af732203SDimitry Andric // Filter out DBG_VALUES that are out of scope.
1914af732203SDimitry Andric VarLocSet KillSet(Alloc);
1915af732203SDimitry Andric bool IsArtificial = ArtificialBlocks.count(&MBB);
1916af732203SDimitry Andric if (!IsArtificial) {
1917af732203SDimitry Andric for (uint64_t ID : InLocsT) {
1918af732203SDimitry Andric LocIndex Idx = LocIndex::fromRawInteger(ID);
1919af732203SDimitry Andric if (!VarLocIDs[Idx].dominates(LS, MBB)) {
1920af732203SDimitry Andric KillSet.set(ID);
1921af732203SDimitry Andric LLVM_DEBUG({
1922af732203SDimitry Andric auto Name = VarLocIDs[Idx].Var.getVariable()->getName();
1923af732203SDimitry Andric dbgs() << " killing " << Name << ", it doesn't dominate MBB\n";
1924af732203SDimitry Andric });
1925af732203SDimitry Andric }
1926af732203SDimitry Andric }
1927af732203SDimitry Andric }
1928af732203SDimitry Andric InLocsT.intersectWithComplement(KillSet);
1929af732203SDimitry Andric
1930af732203SDimitry Andric // As we are processing blocks in reverse post-order we
1931af732203SDimitry Andric // should have processed at least one predecessor, unless it
1932af732203SDimitry Andric // is the entry block which has no predecessor.
1933af732203SDimitry Andric assert((NumVisited || MBB.pred_empty()) &&
1934af732203SDimitry Andric "Should have processed at least one predecessor");
1935af732203SDimitry Andric
1936af732203SDimitry Andric VarLocSet &ILS = getVarLocsInMBB(&MBB, InLocs);
1937af732203SDimitry Andric bool Changed = false;
1938af732203SDimitry Andric if (ILS != InLocsT) {
1939af732203SDimitry Andric ILS = InLocsT;
1940af732203SDimitry Andric Changed = true;
1941af732203SDimitry Andric }
1942af732203SDimitry Andric
1943af732203SDimitry Andric return Changed;
1944af732203SDimitry Andric }
1945af732203SDimitry Andric
flushPendingLocs(VarLocInMBB & PendingInLocs,VarLocMap & VarLocIDs)1946af732203SDimitry Andric void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs,
1947af732203SDimitry Andric VarLocMap &VarLocIDs) {
1948af732203SDimitry Andric // PendingInLocs records all locations propagated into blocks, which have
1949af732203SDimitry Andric // not had DBG_VALUE insts created. Go through and create those insts now.
1950af732203SDimitry Andric for (auto &Iter : PendingInLocs) {
1951af732203SDimitry Andric // Map is keyed on a constant pointer, unwrap it so we can insert insts.
1952af732203SDimitry Andric auto &MBB = const_cast<MachineBasicBlock &>(*Iter.first);
1953af732203SDimitry Andric VarLocSet &Pending = *Iter.second.get();
1954af732203SDimitry Andric
1955*5f7ddb14SDimitry Andric SmallVector<VarLoc, 32> VarLocs;
1956*5f7ddb14SDimitry Andric collectAllVarLocs(VarLocs, Pending, VarLocIDs);
1957*5f7ddb14SDimitry Andric
1958*5f7ddb14SDimitry Andric for (VarLoc DiffIt : VarLocs) {
1959af732203SDimitry Andric // The ID location is live-in to MBB -- work out what kind of machine
1960af732203SDimitry Andric // location it is and create a DBG_VALUE.
1961af732203SDimitry Andric if (DiffIt.isEntryBackupLoc())
1962af732203SDimitry Andric continue;
1963af732203SDimitry Andric MachineInstr *MI = DiffIt.BuildDbgValue(*MBB.getParent());
1964af732203SDimitry Andric MBB.insert(MBB.instr_begin(), MI);
1965af732203SDimitry Andric
1966af732203SDimitry Andric (void)MI;
1967af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Inserted: "; MI->dump(););
1968af732203SDimitry Andric }
1969af732203SDimitry Andric }
1970af732203SDimitry Andric }
1971af732203SDimitry Andric
isEntryValueCandidate(const MachineInstr & MI,const DefinedRegsSet & DefinedRegs) const1972af732203SDimitry Andric bool VarLocBasedLDV::isEntryValueCandidate(
1973af732203SDimitry Andric const MachineInstr &MI, const DefinedRegsSet &DefinedRegs) const {
1974af732203SDimitry Andric assert(MI.isDebugValue() && "This must be DBG_VALUE.");
1975af732203SDimitry Andric
1976af732203SDimitry Andric // TODO: Add support for local variables that are expressed in terms of
1977af732203SDimitry Andric // parameters entry values.
1978af732203SDimitry Andric // TODO: Add support for modified arguments that can be expressed
1979af732203SDimitry Andric // by using its entry value.
1980af732203SDimitry Andric auto *DIVar = MI.getDebugVariable();
1981af732203SDimitry Andric if (!DIVar->isParameter())
1982af732203SDimitry Andric return false;
1983af732203SDimitry Andric
1984af732203SDimitry Andric // Do not consider parameters that belong to an inlined function.
1985af732203SDimitry Andric if (MI.getDebugLoc()->getInlinedAt())
1986af732203SDimitry Andric return false;
1987af732203SDimitry Andric
1988af732203SDimitry Andric // Only consider parameters that are described using registers. Parameters
1989af732203SDimitry Andric // that are passed on the stack are not yet supported, so ignore debug
1990af732203SDimitry Andric // values that are described by the frame or stack pointer.
1991af732203SDimitry Andric if (!isRegOtherThanSPAndFP(MI.getDebugOperand(0), MI, TRI))
1992af732203SDimitry Andric return false;
1993af732203SDimitry Andric
1994af732203SDimitry Andric // If a parameter's value has been propagated from the caller, then the
1995af732203SDimitry Andric // parameter's DBG_VALUE may be described using a register defined by some
1996af732203SDimitry Andric // instruction in the entry block, in which case we shouldn't create an
1997af732203SDimitry Andric // entry value.
1998af732203SDimitry Andric if (DefinedRegs.count(MI.getDebugOperand(0).getReg()))
1999af732203SDimitry Andric return false;
2000af732203SDimitry Andric
2001af732203SDimitry Andric // TODO: Add support for parameters that have a pre-existing debug expressions
2002af732203SDimitry Andric // (e.g. fragments).
2003af732203SDimitry Andric if (MI.getDebugExpression()->getNumElements() > 0)
2004af732203SDimitry Andric return false;
2005af732203SDimitry Andric
2006af732203SDimitry Andric return true;
2007af732203SDimitry Andric }
2008af732203SDimitry Andric
2009af732203SDimitry Andric /// Collect all register defines (including aliases) for the given instruction.
collectRegDefs(const MachineInstr & MI,DefinedRegsSet & Regs,const TargetRegisterInfo * TRI)2010af732203SDimitry Andric static void collectRegDefs(const MachineInstr &MI, DefinedRegsSet &Regs,
2011af732203SDimitry Andric const TargetRegisterInfo *TRI) {
2012af732203SDimitry Andric for (const MachineOperand &MO : MI.operands())
2013af732203SDimitry Andric if (MO.isReg() && MO.isDef() && MO.getReg())
2014af732203SDimitry Andric for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI)
2015af732203SDimitry Andric Regs.insert(*AI);
2016af732203SDimitry Andric }
2017af732203SDimitry Andric
2018af732203SDimitry Andric /// This routine records the entry values of function parameters. The values
2019af732203SDimitry Andric /// could be used as backup values. If we loose the track of some unmodified
2020af732203SDimitry Andric /// parameters, the backup values will be used as a primary locations.
recordEntryValue(const MachineInstr & MI,const DefinedRegsSet & DefinedRegs,OpenRangesSet & OpenRanges,VarLocMap & VarLocIDs)2021af732203SDimitry Andric void VarLocBasedLDV::recordEntryValue(const MachineInstr &MI,
2022af732203SDimitry Andric const DefinedRegsSet &DefinedRegs,
2023af732203SDimitry Andric OpenRangesSet &OpenRanges,
2024af732203SDimitry Andric VarLocMap &VarLocIDs) {
2025af732203SDimitry Andric if (TPC) {
2026af732203SDimitry Andric auto &TM = TPC->getTM<TargetMachine>();
2027af732203SDimitry Andric if (!TM.Options.ShouldEmitDebugEntryValues())
2028af732203SDimitry Andric return;
2029af732203SDimitry Andric }
2030af732203SDimitry Andric
2031af732203SDimitry Andric DebugVariable V(MI.getDebugVariable(), MI.getDebugExpression(),
2032af732203SDimitry Andric MI.getDebugLoc()->getInlinedAt());
2033af732203SDimitry Andric
2034af732203SDimitry Andric if (!isEntryValueCandidate(MI, DefinedRegs) ||
2035af732203SDimitry Andric OpenRanges.getEntryValueBackup(V))
2036af732203SDimitry Andric return;
2037af732203SDimitry Andric
2038af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Creating the backup entry location: "; MI.dump(););
2039af732203SDimitry Andric
2040af732203SDimitry Andric // Create the entry value and use it as a backup location until it is
2041af732203SDimitry Andric // valid. It is valid until a parameter is not changed.
2042af732203SDimitry Andric DIExpression *NewExpr =
2043af732203SDimitry Andric DIExpression::prepend(MI.getDebugExpression(), DIExpression::EntryValue);
2044af732203SDimitry Andric VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(MI, LS, NewExpr);
2045*5f7ddb14SDimitry Andric LocIndices EntryValLocIDs = VarLocIDs.insert(EntryValLocAsBackup);
2046*5f7ddb14SDimitry Andric OpenRanges.insert(EntryValLocIDs, EntryValLocAsBackup);
2047af732203SDimitry Andric }
2048af732203SDimitry Andric
2049af732203SDimitry Andric /// Calculate the liveness information for the given machine function and
2050af732203SDimitry Andric /// extend ranges across basic blocks.
ExtendRanges(MachineFunction & MF,TargetPassConfig * TPC)2051af732203SDimitry Andric bool VarLocBasedLDV::ExtendRanges(MachineFunction &MF, TargetPassConfig *TPC) {
2052af732203SDimitry Andric LLVM_DEBUG(dbgs() << "\nDebug Range Extension\n");
2053af732203SDimitry Andric
2054af732203SDimitry Andric if (!MF.getFunction().getSubprogram())
2055af732203SDimitry Andric // VarLocBaseLDV will already have removed all DBG_VALUEs.
2056af732203SDimitry Andric return false;
2057af732203SDimitry Andric
2058af732203SDimitry Andric // Skip functions from NoDebug compilation units.
2059af732203SDimitry Andric if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
2060af732203SDimitry Andric DICompileUnit::NoDebug)
2061af732203SDimitry Andric return false;
2062af732203SDimitry Andric
2063af732203SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo();
2064af732203SDimitry Andric TII = MF.getSubtarget().getInstrInfo();
2065af732203SDimitry Andric TFI = MF.getSubtarget().getFrameLowering();
2066af732203SDimitry Andric TFI->getCalleeSaves(MF, CalleeSavedRegs);
2067af732203SDimitry Andric this->TPC = TPC;
2068af732203SDimitry Andric LS.initialize(MF);
2069af732203SDimitry Andric
2070af732203SDimitry Andric bool Changed = false;
2071af732203SDimitry Andric bool OLChanged = false;
2072af732203SDimitry Andric bool MBBJoined = false;
2073af732203SDimitry Andric
2074af732203SDimitry Andric VarLocMap VarLocIDs; // Map VarLoc<>unique ID for use in bitvectors.
2075af732203SDimitry Andric OverlapMap OverlapFragments; // Map of overlapping variable fragments.
2076af732203SDimitry Andric OpenRangesSet OpenRanges(Alloc, OverlapFragments);
2077af732203SDimitry Andric // Ranges that are open until end of bb.
2078af732203SDimitry Andric VarLocInMBB OutLocs; // Ranges that exist beyond bb.
2079af732203SDimitry Andric VarLocInMBB InLocs; // Ranges that are incoming after joining.
2080af732203SDimitry Andric TransferMap Transfers; // DBG_VALUEs associated with transfers (such as
2081af732203SDimitry Andric // spills, copies and restores).
2082af732203SDimitry Andric
2083af732203SDimitry Andric VarToFragments SeenFragments;
2084af732203SDimitry Andric
2085af732203SDimitry Andric // Blocks which are artificial, i.e. blocks which exclusively contain
2086af732203SDimitry Andric // instructions without locations, or with line 0 locations.
2087af732203SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 16> ArtificialBlocks;
2088af732203SDimitry Andric
2089af732203SDimitry Andric DenseMap<unsigned int, MachineBasicBlock *> OrderToBB;
2090af732203SDimitry Andric DenseMap<MachineBasicBlock *, unsigned int> BBToOrder;
2091af732203SDimitry Andric std::priority_queue<unsigned int, std::vector<unsigned int>,
2092af732203SDimitry Andric std::greater<unsigned int>>
2093af732203SDimitry Andric Worklist;
2094af732203SDimitry Andric std::priority_queue<unsigned int, std::vector<unsigned int>,
2095af732203SDimitry Andric std::greater<unsigned int>>
2096af732203SDimitry Andric Pending;
2097af732203SDimitry Andric
2098af732203SDimitry Andric // Set of register defines that are seen when traversing the entry block
2099af732203SDimitry Andric // looking for debug entry value candidates.
2100af732203SDimitry Andric DefinedRegsSet DefinedRegs;
2101af732203SDimitry Andric
2102af732203SDimitry Andric // Only in the case of entry MBB collect DBG_VALUEs representing
2103af732203SDimitry Andric // function parameters in order to generate debug entry values for them.
2104af732203SDimitry Andric MachineBasicBlock &First_MBB = *(MF.begin());
2105af732203SDimitry Andric for (auto &MI : First_MBB) {
2106af732203SDimitry Andric collectRegDefs(MI, DefinedRegs, TRI);
2107af732203SDimitry Andric if (MI.isDebugValue())
2108af732203SDimitry Andric recordEntryValue(MI, DefinedRegs, OpenRanges, VarLocIDs);
2109af732203SDimitry Andric }
2110af732203SDimitry Andric
2111af732203SDimitry Andric // Initialize per-block structures and scan for fragment overlaps.
2112af732203SDimitry Andric for (auto &MBB : MF)
2113af732203SDimitry Andric for (auto &MI : MBB)
2114af732203SDimitry Andric if (MI.isDebugValue())
2115af732203SDimitry Andric accumulateFragmentMap(MI, SeenFragments, OverlapFragments);
2116af732203SDimitry Andric
2117af732203SDimitry Andric auto hasNonArtificialLocation = [](const MachineInstr &MI) -> bool {
2118af732203SDimitry Andric if (const DebugLoc &DL = MI.getDebugLoc())
2119af732203SDimitry Andric return DL.getLine() != 0;
2120af732203SDimitry Andric return false;
2121af732203SDimitry Andric };
2122af732203SDimitry Andric for (auto &MBB : MF)
2123af732203SDimitry Andric if (none_of(MBB.instrs(), hasNonArtificialLocation))
2124af732203SDimitry Andric ArtificialBlocks.insert(&MBB);
2125af732203SDimitry Andric
2126af732203SDimitry Andric LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2127af732203SDimitry Andric "OutLocs after initialization", dbgs()));
2128af732203SDimitry Andric
2129af732203SDimitry Andric ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
2130af732203SDimitry Andric unsigned int RPONumber = 0;
2131*5f7ddb14SDimitry Andric for (MachineBasicBlock *MBB : RPOT) {
2132*5f7ddb14SDimitry Andric OrderToBB[RPONumber] = MBB;
2133*5f7ddb14SDimitry Andric BBToOrder[MBB] = RPONumber;
2134af732203SDimitry Andric Worklist.push(RPONumber);
2135af732203SDimitry Andric ++RPONumber;
2136af732203SDimitry Andric }
2137af732203SDimitry Andric
2138af732203SDimitry Andric if (RPONumber > InputBBLimit) {
2139af732203SDimitry Andric unsigned NumInputDbgValues = 0;
2140af732203SDimitry Andric for (auto &MBB : MF)
2141af732203SDimitry Andric for (auto &MI : MBB)
2142af732203SDimitry Andric if (MI.isDebugValue())
2143af732203SDimitry Andric ++NumInputDbgValues;
2144af732203SDimitry Andric if (NumInputDbgValues > InputDbgValueLimit) {
2145af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Disabling VarLocBasedLDV: " << MF.getName()
2146af732203SDimitry Andric << " has " << RPONumber << " basic blocks and "
2147af732203SDimitry Andric << NumInputDbgValues
2148af732203SDimitry Andric << " input DBG_VALUEs, exceeding limits.\n");
2149af732203SDimitry Andric return false;
2150af732203SDimitry Andric }
2151af732203SDimitry Andric }
2152af732203SDimitry Andric
2153af732203SDimitry Andric // This is a standard "union of predecessor outs" dataflow problem.
2154af732203SDimitry Andric // To solve it, we perform join() and process() using the two worklist method
2155af732203SDimitry Andric // until the ranges converge.
2156af732203SDimitry Andric // Ranges have converged when both worklists are empty.
2157af732203SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2158af732203SDimitry Andric while (!Worklist.empty() || !Pending.empty()) {
2159af732203SDimitry Andric // We track what is on the pending worklist to avoid inserting the same
2160af732203SDimitry Andric // thing twice. We could avoid this with a custom priority queue, but this
2161af732203SDimitry Andric // is probably not worth it.
2162af732203SDimitry Andric SmallPtrSet<MachineBasicBlock *, 16> OnPending;
2163af732203SDimitry Andric LLVM_DEBUG(dbgs() << "Processing Worklist\n");
2164af732203SDimitry Andric while (!Worklist.empty()) {
2165af732203SDimitry Andric MachineBasicBlock *MBB = OrderToBB[Worklist.top()];
2166af732203SDimitry Andric Worklist.pop();
2167af732203SDimitry Andric MBBJoined = join(*MBB, OutLocs, InLocs, VarLocIDs, Visited,
2168af732203SDimitry Andric ArtificialBlocks);
2169af732203SDimitry Andric MBBJoined |= Visited.insert(MBB).second;
2170af732203SDimitry Andric if (MBBJoined) {
2171af732203SDimitry Andric MBBJoined = false;
2172af732203SDimitry Andric Changed = true;
2173af732203SDimitry Andric // Now that we have started to extend ranges across BBs we need to
2174af732203SDimitry Andric // examine spill, copy and restore instructions to see whether they
2175af732203SDimitry Andric // operate with registers that correspond to user variables.
2176af732203SDimitry Andric // First load any pending inlocs.
2177af732203SDimitry Andric OpenRanges.insertFromLocSet(getVarLocsInMBB(MBB, InLocs), VarLocIDs);
2178af732203SDimitry Andric for (auto &MI : *MBB)
2179af732203SDimitry Andric process(MI, OpenRanges, VarLocIDs, Transfers);
2180af732203SDimitry Andric OLChanged |= transferTerminator(MBB, OpenRanges, OutLocs, VarLocIDs);
2181af732203SDimitry Andric
2182af732203SDimitry Andric LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2183af732203SDimitry Andric "OutLocs after propagating", dbgs()));
2184af732203SDimitry Andric LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
2185af732203SDimitry Andric "InLocs after propagating", dbgs()));
2186af732203SDimitry Andric
2187af732203SDimitry Andric if (OLChanged) {
2188af732203SDimitry Andric OLChanged = false;
2189af732203SDimitry Andric for (auto s : MBB->successors())
2190af732203SDimitry Andric if (OnPending.insert(s).second) {
2191af732203SDimitry Andric Pending.push(BBToOrder[s]);
2192af732203SDimitry Andric }
2193af732203SDimitry Andric }
2194af732203SDimitry Andric }
2195af732203SDimitry Andric }
2196af732203SDimitry Andric Worklist.swap(Pending);
2197af732203SDimitry Andric // At this point, pending must be empty, since it was just the empty
2198af732203SDimitry Andric // worklist
2199af732203SDimitry Andric assert(Pending.empty() && "Pending should be empty");
2200af732203SDimitry Andric }
2201af732203SDimitry Andric
2202af732203SDimitry Andric // Add any DBG_VALUE instructions created by location transfers.
2203af732203SDimitry Andric for (auto &TR : Transfers) {
2204af732203SDimitry Andric assert(!TR.TransferInst->isTerminator() &&
2205af732203SDimitry Andric "Cannot insert DBG_VALUE after terminator");
2206af732203SDimitry Andric MachineBasicBlock *MBB = TR.TransferInst->getParent();
2207af732203SDimitry Andric const VarLoc &VL = VarLocIDs[TR.LocationID];
2208af732203SDimitry Andric MachineInstr *MI = VL.BuildDbgValue(MF);
2209af732203SDimitry Andric MBB->insertAfterBundle(TR.TransferInst->getIterator(), MI);
2210af732203SDimitry Andric }
2211af732203SDimitry Andric Transfers.clear();
2212af732203SDimitry Andric
2213af732203SDimitry Andric // Deferred inlocs will not have had any DBG_VALUE insts created; do
2214af732203SDimitry Andric // that now.
2215af732203SDimitry Andric flushPendingLocs(InLocs, VarLocIDs);
2216af732203SDimitry Andric
2217af732203SDimitry Andric LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "Final OutLocs", dbgs()));
2218af732203SDimitry Andric LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs, "Final InLocs", dbgs()));
2219af732203SDimitry Andric return Changed;
2220af732203SDimitry Andric }
2221af732203SDimitry Andric
2222af732203SDimitry Andric LDVImpl *
makeVarLocBasedLiveDebugValues()2223af732203SDimitry Andric llvm::makeVarLocBasedLiveDebugValues()
2224af732203SDimitry Andric {
2225af732203SDimitry Andric return new VarLocBasedLDV();
2226af732203SDimitry Andric }
2227