summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/LiveDebugValues
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/CodeGen/LiveDebugValues
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/CodeGen/LiveDebugValues')
-rw-r--r--llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp911
-rw-r--r--llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp10
-rw-r--r--llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h5
-rw-r--r--llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp906
4 files changed, 1397 insertions, 435 deletions
diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
index 18ffe8ba0669..dc9907058340 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
@@ -148,6 +148,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -160,6 +161,7 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
@@ -184,6 +186,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/TypeSize.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/Utils/SSAUpdaterImpl.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
@@ -199,23 +203,16 @@
using namespace llvm;
+// SSAUpdaterImple sets DEBUG_TYPE, change it.
+#undef DEBUG_TYPE
#define DEBUG_TYPE "livedebugvalues"
-STATISTIC(NumInserted, "Number of DBG_VALUE instructions inserted");
-STATISTIC(NumRemoved, "Number of DBG_VALUE instructions removed");
-
// Act more like the VarLoc implementation, by propagating some locations too
// far and ignoring some transfers.
static cl::opt<bool> EmulateOldLDV("emulate-old-livedebugvalues", cl::Hidden,
cl::desc("Act like old LiveDebugValues did"),
cl::init(false));
-// Rely on isStoreToStackSlotPostFE and similar to observe all stack spills.
-static cl::opt<bool>
- ObserveAllStackops("observe-all-stack-ops", cl::Hidden,
- cl::desc("Allow non-kill spill and restores"),
- cl::init(false));
-
namespace {
// The location at which a spilled value resides. It consists of a register and
@@ -959,25 +956,27 @@ public:
class TransferTracker {
public:
const TargetInstrInfo *TII;
+ const TargetLowering *TLI;
/// This machine location tracker is assumed to always contain the up-to-date
/// value mapping for all machine locations. TransferTracker only reads
/// information from it. (XXX make it const?)
MLocTracker *MTracker;
MachineFunction &MF;
+ bool ShouldEmitDebugEntryValues;
/// Record of all changes in variable locations at a block position. Awkwardly
/// we allow inserting either before or after the point: MBB != nullptr
/// indicates it's before, otherwise after.
struct Transfer {
- MachineBasicBlock::iterator Pos; /// Position to insert DBG_VALUes
- MachineBasicBlock *MBB; /// non-null if we should insert after.
+ MachineBasicBlock::instr_iterator Pos; /// Position to insert DBG_VALUes
+ MachineBasicBlock *MBB; /// non-null if we should insert after.
SmallVector<MachineInstr *, 4> Insts; /// Vector of DBG_VALUEs to insert.
};
- typedef struct {
+ struct LocAndProperties {
LocIdx Loc;
DbgValueProperties Properties;
- } LocAndProperties;
+ };
/// Collection of transfers (DBG_VALUEs) to be inserted.
SmallVector<Transfer, 32> Transfers;
@@ -1027,9 +1026,13 @@ public:
TransferTracker(const TargetInstrInfo *TII, MLocTracker *MTracker,
MachineFunction &MF, const TargetRegisterInfo &TRI,
- const BitVector &CalleeSavedRegs)
+ const BitVector &CalleeSavedRegs, const TargetPassConfig &TPC)
: TII(TII), MTracker(MTracker), MF(MF), TRI(TRI),
- CalleeSavedRegs(CalleeSavedRegs) {}
+ CalleeSavedRegs(CalleeSavedRegs) {
+ TLI = MF.getSubtarget().getTargetLowering();
+ auto &TM = TPC.getTM<TargetMachine>();
+ ShouldEmitDebugEntryValues = TM.Options.ShouldEmitDebugEntryValues();
+ }
/// Load object with live-in variable values. \p mlocs contains the live-in
/// values in each machine location, while \p vlocs the live-in variable
@@ -1097,6 +1100,8 @@ public:
// use-before-def to be resolved as we step through the block.
if (Num.getBlock() == (unsigned)MBB.getNumber() && !Num.isPHI())
addUseBeforeDef(Var.first, Var.second.Properties, Num);
+ else
+ recoverAsEntryValue(Var.first, Var.second.Properties, Num);
continue;
}
@@ -1152,10 +1157,73 @@ public:
/// Helper to move created DBG_VALUEs into Transfers collection.
void flushDbgValues(MachineBasicBlock::iterator Pos, MachineBasicBlock *MBB) {
- if (PendingDbgValues.size() > 0) {
- Transfers.push_back({Pos, MBB, PendingDbgValues});
- PendingDbgValues.clear();
- }
+ if (PendingDbgValues.size() == 0)
+ return;
+
+ // Pick out the instruction start position.
+ MachineBasicBlock::instr_iterator BundleStart;
+ if (MBB && Pos == MBB->begin())
+ BundleStart = MBB->instr_begin();
+ else
+ BundleStart = getBundleStart(Pos->getIterator());
+
+ Transfers.push_back({BundleStart, MBB, PendingDbgValues});
+ PendingDbgValues.clear();
+ }
+
+ bool isEntryValueVariable(const DebugVariable &Var,
+ const DIExpression *Expr) const {
+ if (!Var.getVariable()->isParameter())
+ return false;
+
+ if (Var.getInlinedAt())
+ return false;
+
+ if (Expr->getNumElements() > 0)
+ return false;
+
+ return true;
+ }
+
+ bool isEntryValueValue(const ValueIDNum &Val) const {
+ // Must be in entry block (block number zero), and be a PHI / live-in value.
+ if (Val.getBlock() || !Val.isPHI())
+ return false;
+
+ // Entry values must enter in a register.
+ if (MTracker->isSpill(Val.getLoc()))
+ return false;
+
+ Register SP = TLI->getStackPointerRegisterToSaveRestore();
+ Register FP = TRI.getFrameRegister(MF);
+ Register Reg = MTracker->LocIdxToLocID[Val.getLoc()];
+ return Reg != SP && Reg != FP;
+ }
+
+ bool recoverAsEntryValue(const DebugVariable &Var, DbgValueProperties &Prop,
+ const ValueIDNum &Num) {
+ // Is this variable location a candidate to be an entry value. First,
+ // should we be trying this at all?
+ if (!ShouldEmitDebugEntryValues)
+ return false;
+
+ // Is the variable appropriate for entry values (i.e., is a parameter).
+ if (!isEntryValueVariable(Var, Prop.DIExpr))
+ return false;
+
+ // Is the value assigned to this variable still the entry value?
+ if (!isEntryValueValue(Num))
+ return false;
+
+ // Emit a variable location using an entry value expression.
+ DIExpression *NewExpr =
+ DIExpression::prepend(Prop.DIExpr, DIExpression::EntryValue);
+ Register Reg = MTracker->LocIdxToLocID[Num.getLoc()];
+ MachineOperand MO = MachineOperand::CreateReg(Reg, false);
+ MO.setIsDebug(true);
+
+ PendingDbgValues.push_back(emitMOLoc(MO, Var, {NewExpr, Prop.Indirect}));
+ return true;
}
/// Change a variable value after encountering a DBG_VALUE inside a block.
@@ -1224,26 +1292,70 @@ public:
}
}
- /// Explicitly terminate variable locations based on \p mloc. Creates undef
- /// DBG_VALUEs for any variables that were located there, and clears
- /// #ActiveMLoc / #ActiveVLoc tracking information for that location.
- void clobberMloc(LocIdx MLoc, MachineBasicBlock::iterator Pos) {
- assert(MTracker->isSpill(MLoc));
+ /// Account for a location \p mloc being clobbered. Examine the variable
+ /// locations that will be terminated: and try to recover them by using
+ /// another location. Optionally, given \p MakeUndef, emit a DBG_VALUE to
+ /// explicitly terminate a location if it can't be recovered.
+ void clobberMloc(LocIdx MLoc, MachineBasicBlock::iterator Pos,
+ bool MakeUndef = true) {
auto ActiveMLocIt = ActiveMLocs.find(MLoc);
if (ActiveMLocIt == ActiveMLocs.end())
return;
+ // What was the old variable value?
+ ValueIDNum OldValue = VarLocs[MLoc.asU64()];
VarLocs[MLoc.asU64()] = ValueIDNum::EmptyValue;
+ // Examine the remaining variable locations: if we can find the same value
+ // again, we can recover the location.
+ Optional<LocIdx> NewLoc = None;
+ for (auto Loc : MTracker->locations())
+ if (Loc.Value == OldValue)
+ NewLoc = Loc.Idx;
+
+ // If there is no location, and we weren't asked to make the variable
+ // explicitly undef, then stop here.
+ if (!NewLoc && !MakeUndef) {
+ // Try and recover a few more locations with entry values.
+ for (auto &Var : ActiveMLocIt->second) {
+ auto &Prop = ActiveVLocs.find(Var)->second.Properties;
+ recoverAsEntryValue(Var, Prop, OldValue);
+ }
+ flushDbgValues(Pos, nullptr);
+ return;
+ }
+
+ // Examine all the variables based on this location.
+ DenseSet<DebugVariable> NewMLocs;
for (auto &Var : ActiveMLocIt->second) {
auto ActiveVLocIt = ActiveVLocs.find(Var);
- // Create an undef. We can't feed in a nullptr DIExpression alas,
- // so use the variables last expression. Pass None as the location.
+ // Re-state the variable location: if there's no replacement then NewLoc
+ // is None and a $noreg DBG_VALUE will be created. Otherwise, a DBG_VALUE
+ // identifying the alternative location will be emitted.
const DIExpression *Expr = ActiveVLocIt->second.Properties.DIExpr;
DbgValueProperties Properties(Expr, false);
- PendingDbgValues.push_back(MTracker->emitLoc(None, Var, Properties));
- ActiveVLocs.erase(ActiveVLocIt);
+ PendingDbgValues.push_back(MTracker->emitLoc(NewLoc, Var, Properties));
+
+ // Update machine locations <=> variable locations maps. Defer updating
+ // ActiveMLocs to avoid invalidaing the ActiveMLocIt iterator.
+ if (!NewLoc) {
+ ActiveVLocs.erase(ActiveVLocIt);
+ } else {
+ ActiveVLocIt->second.Loc = *NewLoc;
+ NewMLocs.insert(Var);
+ }
}
+
+ // Commit any deferred ActiveMLoc changes.
+ if (!NewMLocs.empty())
+ for (auto &Var : NewMLocs)
+ ActiveMLocs[*NewLoc].insert(Var);
+
+ // We lazily track what locations have which values; if we've found a new
+ // location for the clobbered value, remember it.
+ if (NewLoc)
+ VarLocs[NewLoc->asU64()] = OldValue;
+
flushDbgValues(Pos, nullptr);
ActiveMLocIt->second.clear();
@@ -1332,6 +1444,7 @@ private:
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
const TargetFrameLowering *TFI;
+ const MachineFrameInfo *MFI;
BitVector CalleeSavedRegs;
LexicalScopes LS;
TargetPassConfig *TPC;
@@ -1372,6 +1485,23 @@ private:
/// instruction numbers in DBG_INSTR_REFs into machine value numbers.
std::map<uint64_t, InstAndNum> DebugInstrNumToInstr;
+ /// Record of where we observed a DBG_PHI instruction.
+ class DebugPHIRecord {
+ public:
+ uint64_t InstrNum; ///< Instruction number of this DBG_PHI.
+ MachineBasicBlock *MBB; ///< Block where DBG_PHI occurred.
+ ValueIDNum ValueRead; ///< The value number read by the DBG_PHI.
+ LocIdx ReadLoc; ///< Register/Stack location the DBG_PHI reads.
+
+ operator unsigned() const { return InstrNum; }
+ };
+
+ /// Map from instruction numbers defined by DBG_PHIs to a record of what that
+ /// DBG_PHI read and where. Populated and edited during the machine value
+ /// location problem -- we use LLVMs SSA Updater to fix changes by
+ /// optimizations that destroy PHI instructions.
+ SmallVector<DebugPHIRecord, 32> DebugPHINumToValue;
+
// Map of overlapping variable fragments.
OverlapMap OverlapFragments;
VarToFragments SeenFragments;
@@ -1398,7 +1528,8 @@ private:
SpillLoc extractSpillBaseRegAndOffset(const MachineInstr &MI);
/// Observe a single instruction while stepping through a block.
- void process(MachineInstr &MI);
+ void process(MachineInstr &MI, ValueIDNum **MLiveOuts = nullptr,
+ ValueIDNum **MLiveIns = nullptr);
/// Examines whether \p MI is a DBG_VALUE and notifies trackers.
/// \returns true if MI was recognized and processed.
@@ -1406,7 +1537,13 @@ private:
/// Examines whether \p MI is a DBG_INSTR_REF and notifies trackers.
/// \returns true if MI was recognized and processed.
- bool transferDebugInstrRef(MachineInstr &MI);
+ bool transferDebugInstrRef(MachineInstr &MI, ValueIDNum **MLiveOuts,
+ ValueIDNum **MLiveIns);
+
+ /// Stores value-information about where this PHI occurred, and what
+ /// instruction number is associated with it.
+ /// \returns true if MI was recognized and processed.
+ bool transferDebugPHI(MachineInstr &MI);
/// Examines whether \p MI is copy instruction, and notifies trackers.
/// \returns true if MI was recognized and processed.
@@ -1425,6 +1562,18 @@ private:
void accumulateFragmentMap(MachineInstr &MI);
+ /// Determine the machine value number referred to by (potentially several)
+ /// DBG_PHI instructions. Block duplication and tail folding can duplicate
+ /// DBG_PHIs, shifting the position where values in registers merge, and
+ /// forming another mini-ssa problem to solve.
+ /// \p Here the position of a DBG_INSTR_REF seeking a machine value number
+ /// \p InstrNum Debug instruction number defined by DBG_PHI instructions.
+ /// \returns The machine value number at position Here, or None.
+ Optional<ValueIDNum> resolveDbgPHIs(MachineFunction &MF,
+ ValueIDNum **MLiveOuts,
+ ValueIDNum **MLiveIns, MachineInstr &Here,
+ uint64_t InstrNum);
+
/// Step through the function, recording register definitions and movements
/// in an MLocTracker. Convert the observations into a per-block transfer
/// function in \p MLocTransfer, suitable for using with the machine value
@@ -1527,8 +1676,9 @@ private:
/// right now "order of appearence in function, when explored in RPO", so
/// that we can compare explictly against VarLocBasedImpl.
void emitLocations(MachineFunction &MF, LiveInsT SavedLiveIns,
- ValueIDNum **MInLocs,
- DenseMap<DebugVariable, unsigned> &AllVarsNumbering);
+ ValueIDNum **MOutLocs, ValueIDNum **MInLocs,
+ DenseMap<DebugVariable, unsigned> &AllVarsNumbering,
+ const TargetPassConfig &TPC);
/// Boilerplate computation of some initial sets, artifical blocks and
/// RPOT block ordering.
@@ -1640,7 +1790,9 @@ bool InstrRefBasedLDV::transferDebugValue(const MachineInstr &MI) {
return true;
}
-bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI) {
+bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI,
+ ValueIDNum **MLiveOuts,
+ ValueIDNum **MLiveIns) {
if (!MI.isDebugRef())
return false;
@@ -1669,12 +1821,22 @@ bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI) {
// Various optimizations may have happened to the value during codegen,
// recorded in the value substitution table. Apply any substitutions to
- // the instruction / operand number in this DBG_INSTR_REF.
- auto Sub = MF.DebugValueSubstitutions.find(std::make_pair(InstNo, OpNo));
- while (Sub != MF.DebugValueSubstitutions.end()) {
- InstNo = Sub->second.first;
- OpNo = Sub->second.second;
- Sub = MF.DebugValueSubstitutions.find(std::make_pair(InstNo, OpNo));
+ // the instruction / operand number in this DBG_INSTR_REF, and collect
+ // any subregister extractions performed during optimization.
+
+ // Create dummy substitution with Src set, for lookup.
+ auto SoughtSub =
+ MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0);
+
+ SmallVector<unsigned, 4> SeenSubregs;
+ auto LowerBoundIt = llvm::lower_bound(MF.DebugValueSubstitutions, SoughtSub);
+ while (LowerBoundIt != MF.DebugValueSubstitutions.end() &&
+ LowerBoundIt->Src == SoughtSub.Src) {
+ std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
+ SoughtSub.Src = LowerBoundIt->Dest;
+ if (unsigned Subreg = LowerBoundIt->Subreg)
+ SeenSubregs.push_back(Subreg);
+ LowerBoundIt = llvm::lower_bound(MF.DebugValueSubstitutions, SoughtSub);
}
// Default machine value number is <None> -- if no instruction defines
@@ -1682,8 +1844,10 @@ bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI) {
Optional<ValueIDNum> NewID = None;
// Try to lookup the instruction number, and find the machine value number
- // that it defines.
+ // that it defines. It could be an instruction, or a PHI.
auto InstrIt = DebugInstrNumToInstr.find(InstNo);
+ auto PHIIt = std::lower_bound(DebugPHINumToValue.begin(),
+ DebugPHINumToValue.end(), InstNo);
if (InstrIt != DebugInstrNumToInstr.end()) {
const MachineInstr &TargetInstr = *InstrIt->second.first;
uint64_t BlockNo = TargetInstr.getParent()->getNumber();
@@ -1698,6 +1862,82 @@ bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI) {
unsigned LocID = MTracker->getLocID(MO.getReg(), false);
LocIdx L = MTracker->LocIDToLocIdx[LocID];
NewID = ValueIDNum(BlockNo, InstrIt->second.second, L);
+ } else if (PHIIt != DebugPHINumToValue.end() && PHIIt->InstrNum == InstNo) {
+ // It's actually a PHI value. Which value it is might not be obvious, use
+ // the resolver helper to find out.
+ NewID = resolveDbgPHIs(*MI.getParent()->getParent(), MLiveOuts, MLiveIns,
+ MI, InstNo);
+ }
+
+ // Apply any subregister extractions, in reverse. We might have seen code
+ // like this:
+ // CALL64 @foo, implicit-def $rax
+ // %0:gr64 = COPY $rax
+ // %1:gr32 = COPY %0.sub_32bit
+ // %2:gr16 = COPY %1.sub_16bit
+ // %3:gr8 = COPY %2.sub_8bit
+ // In which case each copy would have been recorded as a substitution with
+ // a subregister qualifier. Apply those qualifiers now.
+ if (NewID && !SeenSubregs.empty()) {
+ unsigned Offset = 0;
+ unsigned Size = 0;
+
+ // Look at each subregister that we passed through, and progressively
+ // narrow in, accumulating any offsets that occur. Substitutions should
+ // only ever be the same or narrower width than what they read from;
+ // iterate in reverse order so that we go from wide to small.
+ for (unsigned Subreg : reverse(SeenSubregs)) {
+ unsigned ThisSize = TRI->getSubRegIdxSize(Subreg);
+ unsigned ThisOffset = TRI->getSubRegIdxOffset(Subreg);
+ Offset += ThisOffset;
+ Size = (Size == 0) ? ThisSize : std::min(Size, ThisSize);
+ }
+
+ // If that worked, look for an appropriate subregister with the register
+ // where the define happens. Don't look at values that were defined during
+ // a stack write: we can't currently express register locations within
+ // spills.
+ LocIdx L = NewID->getLoc();
+ if (NewID && !MTracker->isSpill(L)) {
+ // Find the register class for the register where this def happened.
+ // FIXME: no index for this?
+ Register Reg = MTracker->LocIdxToLocID[L];
+ const TargetRegisterClass *TRC = nullptr;
+ for (auto *TRCI : TRI->regclasses())
+ if (TRCI->contains(Reg))
+ TRC = TRCI;
+ assert(TRC && "Couldn't find target register class?");
+
+ // If the register we have isn't the right size or in the right place,
+ // Try to find a subregister inside it.
+ unsigned MainRegSize = TRI->getRegSizeInBits(*TRC);
+ if (Size != MainRegSize || Offset) {
+ // Enumerate all subregisters, searching.
+ Register NewReg = 0;
+ for (MCSubRegIterator SRI(Reg, TRI, false); SRI.isValid(); ++SRI) {
+ unsigned Subreg = TRI->getSubRegIndex(Reg, *SRI);
+ unsigned SubregSize = TRI->getSubRegIdxSize(Subreg);
+ unsigned SubregOffset = TRI->getSubRegIdxOffset(Subreg);
+ if (SubregSize == Size && SubregOffset == Offset) {
+ NewReg = *SRI;
+ break;
+ }
+ }
+
+ // If we didn't find anything: there's no way to express our value.
+ if (!NewReg) {
+ NewID = None;
+ } else {
+ // Re-state the value as being defined within the subregister
+ // that we found.
+ LocIdx NewLoc = MTracker->lookupOrTrackRegister(NewReg);
+ NewID = ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
+ }
+ }
+ } else {
+ // If we can't handle subregisters, unset the new value.
+ NewID = None;
+ }
}
// We, we have a value number or None. Tell the variable value tracker about
@@ -1752,6 +1992,55 @@ bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI) {
MachineInstr *DbgMI = MTracker->emitLoc(FoundLoc, V, Properties);
TTracker->PendingDbgValues.push_back(DbgMI);
TTracker->flushDbgValues(MI.getIterator(), nullptr);
+ return true;
+}
+
+bool InstrRefBasedLDV::transferDebugPHI(MachineInstr &MI) {
+ if (!MI.isDebugPHI())
+ return false;
+
+ // Analyse these only when solving the machine value location problem.
+ if (VTracker || TTracker)
+ return true;
+
+ // First operand is the value location, either a stack slot or register.
+ // Second is the debug instruction number of the original PHI.
+ const MachineOperand &MO = MI.getOperand(0);
+ unsigned InstrNum = MI.getOperand(1).getImm();
+
+ if (MO.isReg()) {
+ // The value is whatever's currently in the register. Read and record it,
+ // to be analysed later.
+ Register Reg = MO.getReg();
+ ValueIDNum Num = MTracker->readReg(Reg);
+ auto PHIRec = DebugPHIRecord(
+ {InstrNum, MI.getParent(), Num, MTracker->lookupOrTrackRegister(Reg)});
+ DebugPHINumToValue.push_back(PHIRec);
+ } else {
+ // The value is whatever's in this stack slot.
+ assert(MO.isFI());
+ unsigned FI = MO.getIndex();
+
+ // If the stack slot is dead, then this was optimized away.
+ // FIXME: stack slot colouring should account for slots that get merged.
+ if (MFI->isDeadObjectIndex(FI))
+ return true;
+
+ // Identify this spill slot.
+ Register Base;
+ StackOffset Offs = TFI->getFrameIndexReference(*MI.getMF(), FI, Base);
+ SpillLoc SL = {Base, Offs};
+ Optional<ValueIDNum> Num = MTracker->readSpill(SL);
+
+ if (!Num)
+ // Nothing ever writes to this slot. Curious, but nothing we can do.
+ return true;
+
+ // Record this DBG_PHI for later analysis.
+ auto DbgPHI = DebugPHIRecord(
+ {InstrNum, MI.getParent(), *Num, *MTracker->getSpillMLoc(SL)});
+ DebugPHINumToValue.push_back(DbgPHI);
+ }
return true;
}
@@ -1803,6 +2092,32 @@ void InstrRefBasedLDV::transferRegisterDef(MachineInstr &MI) {
for (auto *MO : RegMaskPtrs)
MTracker->writeRegMask(MO, CurBB, CurInst);
+
+ if (!TTracker)
+ return;
+
+ // When committing variable values to locations: tell transfer tracker that
+ // we've clobbered things. It may be able to recover the variable from a
+ // different location.
+
+ // Inform TTracker about any direct clobbers.
+ for (uint32_t DeadReg : DeadRegs) {
+ LocIdx Loc = MTracker->lookupOrTrackRegister(DeadReg);
+ TTracker->clobberMloc(Loc, MI.getIterator(), false);
+ }
+
+ // Look for any clobbers performed by a register mask. Only test locations
+ // that are actually being tracked.
+ for (auto L : MTracker->locations()) {
+ // Stack locations can't be clobbered by regmasks.
+ if (MTracker->isSpill(L.Idx))
+ continue;
+
+ Register Reg = MTracker->LocIdxToLocID[L.Idx];
+ for (auto *MO : RegMaskPtrs)
+ if (MO->clobbersPhysReg(Reg))
+ TTracker->clobberMloc(L.Idx, MI.getIterator(), false);
+ }
}
void InstrRefBasedLDV::performCopy(Register SrcRegNum, Register DstRegNum) {
@@ -1871,47 +2186,9 @@ bool InstrRefBasedLDV::isLocationSpill(const MachineInstr &MI,
if (!isSpillInstruction(MI, MF))
return false;
- // XXX FIXME: On x86, isStoreToStackSlotPostFE returns '1' instead of an
- // actual register number.
- if (ObserveAllStackops) {
- int FI;
- Reg = TII->isStoreToStackSlotPostFE(MI, FI);
- return Reg != 0;
- }
-
- auto isKilledReg = [&](const MachineOperand MO, unsigned &Reg) {
- if (!MO.isReg() || !MO.isUse()) {
- Reg = 0;
- return false;
- }
- Reg = MO.getReg();
- return MO.isKill();
- };
-
- for (const MachineOperand &MO : MI.operands()) {
- // In a spill instruction generated by the InlineSpiller the spilled
- // register has its kill flag set.
- if (isKilledReg(MO, Reg))
- return true;
- if (Reg != 0) {
- // Check whether next instruction kills the spilled register.
- // FIXME: Current solution does not cover search for killed register in
- // bundles and instructions further down the chain.
- auto NextI = std::next(MI.getIterator());
- // Skip next instruction that points to basic block end iterator.
- if (MI.getParent()->end() == NextI)
- continue;
- unsigned RegNext;
- for (const MachineOperand &MONext : NextI->operands()) {
- // Return true if we came across the register from the
- // previous spill instruction that is killed in NextI.
- if (isKilledReg(MONext, RegNext) && RegNext == Reg)
- return true;
- }
- }
- }
- // Return false if we didn't find spilled register.
- return false;
+ int FI;
+ Reg = TII->isStoreToStackSlotPostFE(MI, FI);
+ return Reg != 0;
}
Optional<SpillLoc>
@@ -1950,8 +2227,12 @@ bool InstrRefBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI) {
if (TTracker) {
Optional<LocIdx> MLoc = MTracker->getSpillMLoc(*Loc);
- if (MLoc)
+ if (MLoc) {
+ // Un-set this location before clobbering, so that we don't salvage
+ // the variable location back to the same place.
+ MTracker->setMLoc(*MLoc, ValueIDNum::EmptyValue);
TTracker->clobberMloc(*MLoc, MI.getIterator());
+ }
}
}
@@ -2066,6 +2347,15 @@ bool InstrRefBasedLDV::transferRegisterCopy(MachineInstr &MI) {
if (EmulateOldLDV && SrcReg != DestReg)
MTracker->defReg(SrcReg, CurBB, CurInst);
+ // Finally, the copy might have clobbered variables based on the destination
+ // register. Tell TTracker about it, in case a backup location exists.
+ if (TTracker) {
+ for (MCRegAliasIterator RAI(DestReg, TRI, true); RAI.isValid(); ++RAI) {
+ LocIdx ClobberedLoc = MTracker->getRegMLoc(*RAI);
+ TTracker->clobberMloc(ClobberedLoc, MI.getIterator(), false);
+ }
+ }
+
return true;
}
@@ -2124,13 +2414,16 @@ void InstrRefBasedLDV::accumulateFragmentMap(MachineInstr &MI) {
AllSeenFragments.insert(ThisFragment);
}
-void InstrRefBasedLDV::process(MachineInstr &MI) {
+void InstrRefBasedLDV::process(MachineInstr &MI, ValueIDNum **MLiveOuts,
+ ValueIDNum **MLiveIns) {
// Try to interpret an MI as a debug or transfer instruction. Only if it's
// none of these should we interpret it's register defs as new value
// definitions.
if (transferDebugValue(MI))
return;
- if (transferDebugInstrRef(MI))
+ if (transferDebugInstrRef(MI, MLiveOuts, MLiveIns))
+ return;
+ if (transferDebugPHI(MI))
return;
if (transferRegisterCopy(MI))
return;
@@ -2641,9 +2934,7 @@ std::tuple<bool, bool> InstrRefBasedLDV::vlocJoin(
auto &ILS = *ILSIt->second;
// Order predecessors by RPOT order, for exploring them in that order.
- SmallVector<MachineBasicBlock *, 8> BlockOrders;
- for (auto p : MBB.predecessors())
- BlockOrders.push_back(p);
+ SmallVector<MachineBasicBlock *, 8> BlockOrders(MBB.predecessors());
auto Cmp = [&](MachineBasicBlock *A, MachineBasicBlock *B) {
return BBToOrder[A] < BBToOrder[B];
@@ -3128,9 +3419,10 @@ void InstrRefBasedLDV::dump_mloc_transfer(
#endif
void InstrRefBasedLDV::emitLocations(
- MachineFunction &MF, LiveInsT SavedLiveIns, ValueIDNum **MInLocs,
- DenseMap<DebugVariable, unsigned> &AllVarsNumbering) {
- TTracker = new TransferTracker(TII, MTracker, MF, *TRI, CalleeSavedRegs);
+ MachineFunction &MF, LiveInsT SavedLiveIns, ValueIDNum **MOutLocs,
+ ValueIDNum **MInLocs, DenseMap<DebugVariable, unsigned> &AllVarsNumbering,
+ const TargetPassConfig &TPC) {
+ TTracker = new TransferTracker(TII, MTracker, MF, *TRI, CalleeSavedRegs, TPC);
unsigned NumLocs = MTracker->getNumLocs();
// For each block, load in the machine value locations and variable value
@@ -3146,7 +3438,7 @@ void InstrRefBasedLDV::emitLocations(
CurBB = bbnum;
CurInst = 1;
for (auto &MI : MBB) {
- process(MI);
+ process(MI, MOutLocs, MInLocs);
TTracker->checkInstForNewValues(CurInst, MI.getIterator());
++CurInst;
}
@@ -3178,9 +3470,14 @@ void InstrRefBasedLDV::emitLocations(
MBB.insert(P.Pos, MI);
}
} else {
+ // Terminators, like tail calls, can clobber things. Don't try and place
+ // transfers after them.
+ if (P.Pos->isTerminator())
+ continue;
+
MachineBasicBlock &MBB = *P.Pos->getParent();
for (auto *MI : P.Insts) {
- MBB.insertAfter(P.Pos, MI);
+ MBB.insertAfterBundle(P.Pos, MI);
}
}
}
@@ -3201,12 +3498,27 @@ void InstrRefBasedLDV::initialSetup(MachineFunction &MF) {
// Compute mappings of block <=> RPO order.
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
unsigned int RPONumber = 0;
- for (auto RI = RPOT.begin(), RE = RPOT.end(); RI != RE; ++RI) {
- OrderToBB[RPONumber] = *RI;
- BBToOrder[*RI] = RPONumber;
- BBNumToRPO[(*RI)->getNumber()] = RPONumber;
+ for (MachineBasicBlock *MBB : RPOT) {
+ OrderToBB[RPONumber] = MBB;
+ BBToOrder[MBB] = RPONumber;
+ BBNumToRPO[MBB->getNumber()] = RPONumber;
++RPONumber;
}
+
+ // Order value substitutions by their "source" operand pair, for quick lookup.
+ llvm::sort(MF.DebugValueSubstitutions);
+
+#ifdef EXPENSIVE_CHECKS
+ // As an expensive check, test whether there are any duplicate substitution
+ // sources in the collection.
+ if (MF.DebugValueSubstitutions.size() > 2) {
+ for (auto It = MF.DebugValueSubstitutions.begin();
+ It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
+ assert(It->Src != std::next(It)->Src && "Duplicate variable location "
+ "substitution seen");
+ }
+ }
+#endif
}
/// Calculate the liveness information for the given machine function and
@@ -3224,6 +3536,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
TII = MF.getSubtarget().getInstrInfo();
TFI = MF.getSubtarget().getFrameLowering();
TFI->getCalleeSaves(MF, CalleeSavedRegs);
+ MFI = &MF.getFrameInfo();
LS.initialize(MF);
MTracker =
@@ -3266,6 +3579,21 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
// dataflow problem.
mlocDataflow(MInLocs, MOutLocs, MLocTransfer);
+ // Patch up debug phi numbers, turning unknown block-live-in values into
+ // either live-through machine values, or PHIs.
+ for (auto &DBG_PHI : DebugPHINumToValue) {
+ // Identify unresolved block-live-ins.
+ ValueIDNum &Num = DBG_PHI.ValueRead;
+ if (!Num.isPHI())
+ continue;
+
+ unsigned BlockNo = Num.getBlock();
+ LocIdx LocNo = Num.getLoc();
+ Num = MInLocs[BlockNo][LocNo.asU64()];
+ }
+ // Later, we'll be looking up ranges of instruction numbers.
+ llvm::sort(DebugPHINumToValue);
+
// Walk back through each block / instruction, collecting DBG_VALUE
// instructions and recording what machine value their operands refer to.
for (auto &OrderPair : OrderToBB) {
@@ -3276,7 +3604,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
MTracker->loadFromArray(MInLocs[CurBB], CurBB);
CurInst = 1;
for (auto &MI : MBB) {
- process(MI);
+ process(MI, MOutLocs, MInLocs);
++CurInst;
}
MTracker->reset();
@@ -3331,7 +3659,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
// Using the computed value locations and variable values for each block,
// create the DBG_VALUE instructions representing the extended variable
// locations.
- emitLocations(MF, SavedLiveIns, MInLocs, AllVarsNumbering);
+ emitLocations(MF, SavedLiveIns, MOutLocs, MInLocs, AllVarsNumbering, *TPC);
for (int Idx = 0; Idx < MaxNumBlocks; ++Idx) {
delete[] MOutLocs[Idx];
@@ -3354,6 +3682,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
BBToOrder.clear();
BBNumToRPO.clear();
DebugInstrNumToInstr.clear();
+ DebugPHINumToValue.clear();
return Changed;
}
@@ -3361,3 +3690,389 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
LDVImpl *llvm::makeInstrRefBasedLiveDebugValues() {
return new InstrRefBasedLDV();
}
+
+namespace {
+class LDVSSABlock;
+class LDVSSAUpdater;
+
+// Pick a type to identify incoming block values as we construct SSA. We
+// can't use anything more robust than an integer unfortunately, as SSAUpdater
+// expects to zero-initialize the type.
+typedef uint64_t BlockValueNum;
+
+/// Represents an SSA PHI node for the SSA updater class. Contains the block
+/// this PHI is in, the value number it would have, and the expected incoming
+/// values from parent blocks.
+class LDVSSAPhi {
+public:
+ SmallVector<std::pair<LDVSSABlock *, BlockValueNum>, 4> IncomingValues;
+ LDVSSABlock *ParentBlock;
+ BlockValueNum PHIValNum;
+ LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
+ : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
+
+ LDVSSABlock *getParent() { return ParentBlock; }
+};
+
+/// Thin wrapper around a block predecessor iterator. Only difference from a
+/// normal block iterator is that it dereferences to an LDVSSABlock.
+class LDVSSABlockIterator {
+public:
+ MachineBasicBlock::pred_iterator PredIt;
+ LDVSSAUpdater &Updater;
+
+ LDVSSABlockIterator(MachineBasicBlock::pred_iterator PredIt,
+ LDVSSAUpdater &Updater)
+ : PredIt(PredIt), Updater(Updater) {}
+
+ bool operator!=(const LDVSSABlockIterator &OtherIt) const {
+ return OtherIt.PredIt != PredIt;
+ }
+
+ LDVSSABlockIterator &operator++() {
+ ++PredIt;
+ return *this;
+ }
+
+ LDVSSABlock *operator*();
+};
+
+/// Thin wrapper around a block for SSA Updater interface. Necessary because
+/// we need to track the PHI value(s) that we may have observed as necessary
+/// in this block.
+class LDVSSABlock {
+public:
+ MachineBasicBlock &BB;
+ LDVSSAUpdater &Updater;
+ using PHIListT = SmallVector<LDVSSAPhi, 1>;
+ /// List of PHIs in this block. There should only ever be one.
+ PHIListT PHIList;
+
+ LDVSSABlock(MachineBasicBlock &BB, LDVSSAUpdater &Updater)
+ : BB(BB), Updater(Updater) {}
+
+ LDVSSABlockIterator succ_begin() {
+ return LDVSSABlockIterator(BB.succ_begin(), Updater);
+ }
+
+ LDVSSABlockIterator succ_end() {
+ return LDVSSABlockIterator(BB.succ_end(), Updater);
+ }
+
+ /// SSAUpdater has requested a PHI: create that within this block record.
+ LDVSSAPhi *newPHI(BlockValueNum Value) {
+ PHIList.emplace_back(Value, this);
+ return &PHIList.back();
+ }
+
+ /// SSAUpdater wishes to know what PHIs already exist in this block.
+ PHIListT &phis() { return PHIList; }
+};
+
+/// Utility class for the SSAUpdater interface: tracks blocks, PHIs and values
+/// while SSAUpdater is exploring the CFG. It's passed as a handle / baton to
+// SSAUpdaterTraits<LDVSSAUpdater>.
+class LDVSSAUpdater {
+public:
+ /// Map of value numbers to PHI records.
+ DenseMap<BlockValueNum, LDVSSAPhi *> PHIs;
+ /// Map of which blocks generate Undef values -- blocks that are not
+ /// dominated by any Def.
+ DenseMap<MachineBasicBlock *, BlockValueNum> UndefMap;
+ /// Map of machine blocks to our own records of them.
+ DenseMap<MachineBasicBlock *, LDVSSABlock *> BlockMap;
+ /// Machine location where any PHI must occur.
+ LocIdx Loc;
+ /// Table of live-in machine value numbers for blocks / locations.
+ ValueIDNum **MLiveIns;
+
+ LDVSSAUpdater(LocIdx L, ValueIDNum **MLiveIns) : Loc(L), MLiveIns(MLiveIns) {}
+
+ void reset() {
+ for (auto &Block : BlockMap)
+ delete Block.second;
+
+ PHIs.clear();
+ UndefMap.clear();
+ BlockMap.clear();
+ }
+
+ ~LDVSSAUpdater() { reset(); }
+
+ /// For a given MBB, create a wrapper block for it. Stores it in the
+ /// LDVSSAUpdater block map.
+ LDVSSABlock *getSSALDVBlock(MachineBasicBlock *BB) {
+ auto it = BlockMap.find(BB);
+ if (it == BlockMap.end()) {
+ BlockMap[BB] = new LDVSSABlock(*BB, *this);
+ it = BlockMap.find(BB);
+ }
+ return it->second;
+ }
+
+ /// Find the live-in value number for the given block. Looks up the value at
+ /// the PHI location on entry.
+ BlockValueNum getValue(LDVSSABlock *LDVBB) {
+ return MLiveIns[LDVBB->BB.getNumber()][Loc.asU64()].asU64();
+ }
+};
+
+LDVSSABlock *LDVSSABlockIterator::operator*() {
+ return Updater.getSSALDVBlock(*PredIt);
+}
+
+#ifndef NDEBUG
+
+raw_ostream &operator<<(raw_ostream &out, const LDVSSAPhi &PHI) {
+ out << "SSALDVPHI " << PHI.PHIValNum;
+ return out;
+}
+
+#endif
+
+} // namespace
+
+namespace llvm {
+
+/// Template specialization to give SSAUpdater access to CFG and value
+/// information. SSAUpdater calls methods in these traits, passing in the
+/// LDVSSAUpdater object, to learn about blocks and the values they define.
+/// It also provides methods to create PHI nodes and track them.
+template <> class SSAUpdaterTraits<LDVSSAUpdater> {
+public:
+ using BlkT = LDVSSABlock;
+ using ValT = BlockValueNum;
+ using PhiT = LDVSSAPhi;
+ using BlkSucc_iterator = LDVSSABlockIterator;
+
+ // Methods to access block successors -- dereferencing to our wrapper class.
+ static BlkSucc_iterator BlkSucc_begin(BlkT *BB) { return BB->succ_begin(); }
+ static BlkSucc_iterator BlkSucc_end(BlkT *BB) { return BB->succ_end(); }
+
+ /// Iterator for PHI operands.
+ class PHI_iterator {
+ private:
+ LDVSSAPhi *PHI;
+ unsigned Idx;
+
+ public:
+ explicit PHI_iterator(LDVSSAPhi *P) // begin iterator
+ : PHI(P), Idx(0) {}
+ PHI_iterator(LDVSSAPhi *P, bool) // end iterator
+ : PHI(P), Idx(PHI->IncomingValues.size()) {}
+
+ PHI_iterator &operator++() {
+ Idx++;
+ return *this;
+ }
+ bool operator==(const PHI_iterator &X) const { return Idx == X.Idx; }
+ bool operator!=(const PHI_iterator &X) const { return !operator==(X); }
+
+ BlockValueNum getIncomingValue() { return PHI->IncomingValues[Idx].second; }
+
+ LDVSSABlock *getIncomingBlock() { return PHI->IncomingValues[Idx].first; }
+ };
+
+ static inline PHI_iterator PHI_begin(PhiT *PHI) { return PHI_iterator(PHI); }
+
+ static inline PHI_iterator PHI_end(PhiT *PHI) {
+ return PHI_iterator(PHI, true);
+ }
+
+ /// FindPredecessorBlocks - Put the predecessors of BB into the Preds
+ /// vector.
+ static void FindPredecessorBlocks(LDVSSABlock *BB,
+ SmallVectorImpl<LDVSSABlock *> *Preds) {
+ for (MachineBasicBlock::pred_iterator PI = BB->BB.pred_begin(),
+ E = BB->BB.pred_end();
+ PI != E; ++PI)
+ Preds->push_back(BB->Updater.getSSALDVBlock(*PI));
+ }
+
+ /// GetUndefVal - Normally creates an IMPLICIT_DEF instruction with a new
+ /// register. For LiveDebugValues, represents a block identified as not having
+ /// any DBG_PHI predecessors.
+ static BlockValueNum GetUndefVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
+ // Create a value number for this block -- it needs to be unique and in the
+ // "undef" collection, so that we know it's not real. Use a number
+ // representing a PHI into this block.
+ BlockValueNum Num = ValueIDNum(BB->BB.getNumber(), 0, Updater->Loc).asU64();
+ Updater->UndefMap[&BB->BB] = Num;
+ return Num;
+ }
+
+ /// CreateEmptyPHI - Create a (representation of a) PHI in the given block.
+ /// SSAUpdater will populate it with information about incoming values. The
+ /// value number of this PHI is whatever the machine value number problem
+ /// solution determined it to be. This includes non-phi values if SSAUpdater
+ /// tries to create a PHI where the incoming values are identical.
+ static BlockValueNum CreateEmptyPHI(LDVSSABlock *BB, unsigned NumPreds,
+ LDVSSAUpdater *Updater) {
+ BlockValueNum PHIValNum = Updater->getValue(BB);
+ LDVSSAPhi *PHI = BB->newPHI(PHIValNum);
+ Updater->PHIs[PHIValNum] = PHI;
+ return PHIValNum;
+ }
+
+ /// AddPHIOperand - Add the specified value as an operand of the PHI for
+ /// the specified predecessor block.
+ static void AddPHIOperand(LDVSSAPhi *PHI, BlockValueNum Val, LDVSSABlock *Pred) {
+ PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
+ }
+
+ /// ValueIsPHI - Check if the instruction that defines the specified value
+ /// is a PHI instruction.
+ static LDVSSAPhi *ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
+ auto PHIIt = Updater->PHIs.find(Val);
+ if (PHIIt == Updater->PHIs.end())
+ return nullptr;
+ return PHIIt->second;
+ }
+
+ /// ValueIsNewPHI - Like ValueIsPHI but also check if the PHI has no source
+ /// operands, i.e., it was just added.
+ static LDVSSAPhi *ValueIsNewPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
+ LDVSSAPhi *PHI = ValueIsPHI(Val, Updater);
+ if (PHI && PHI->IncomingValues.size() == 0)
+ return PHI;
+ return nullptr;
+ }
+
+ /// GetPHIValue - For the specified PHI instruction, return the value
+ /// that it defines.
+ static BlockValueNum GetPHIValue(LDVSSAPhi *PHI) { return PHI->PHIValNum; }
+};
+
+} // end namespace llvm
+
+Optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs(MachineFunction &MF,
+ ValueIDNum **MLiveOuts,
+ ValueIDNum **MLiveIns,
+ MachineInstr &Here,
+ uint64_t InstrNum) {
+ // Pick out records of DBG_PHI instructions that have been observed. If there
+ // are none, then we cannot compute a value number.
+ auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
+ DebugPHINumToValue.end(), InstrNum);
+ auto LowerIt = RangePair.first;
+ auto UpperIt = RangePair.second;
+
+ // No DBG_PHI means there can be no location.
+ if (LowerIt == UpperIt)
+ return None;
+
+ // If there's only one DBG_PHI, then that is our value number.
+ if (std::distance(LowerIt, UpperIt) == 1)
+ return LowerIt->ValueRead;
+
+ auto DBGPHIRange = make_range(LowerIt, UpperIt);
+
+ // Pick out the location (physreg, slot) where any PHIs must occur. It's
+ // technically possible for us to merge values in different registers in each
+ // block, but highly unlikely that LLVM will generate such code after register
+ // allocation.
+ LocIdx Loc = LowerIt->ReadLoc;
+
+ // We have several DBG_PHIs, and a use position (the Here inst). All each
+ // DBG_PHI does is identify a value at a program position. We can treat each
+ // DBG_PHI like it's a Def of a value, and the use position is a Use of a
+ // value, just like SSA. We use the bulk-standard LLVM SSA updater class to
+ // determine which Def is used at the Use, and any PHIs that happen along
+ // the way.
+ // Adapted LLVM SSA Updater:
+ LDVSSAUpdater Updater(Loc, MLiveIns);
+ // Map of which Def or PHI is the current value in each block.
+ DenseMap<LDVSSABlock *, BlockValueNum> AvailableValues;
+ // Set of PHIs that we have created along the way.
+ SmallVector<LDVSSAPhi *, 8> CreatedPHIs;
+
+ // Each existing DBG_PHI is a Def'd value under this model. Record these Defs
+ // for the SSAUpdater.
+ for (const auto &DBG_PHI : DBGPHIRange) {
+ LDVSSABlock *Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
+ const ValueIDNum &Num = DBG_PHI.ValueRead;
+ AvailableValues.insert(std::make_pair(Block, Num.asU64()));
+ }
+
+ LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.getParent());
+ const auto &AvailIt = AvailableValues.find(HereBlock);
+ if (AvailIt != AvailableValues.end()) {
+ // Actually, we already know what the value is -- the Use is in the same
+ // block as the Def.
+ return ValueIDNum::fromU64(AvailIt->second);
+ }
+
+ // Otherwise, we must use the SSA Updater. It will identify the value number
+ // that we are to use, and the PHIs that must happen along the way.
+ SSAUpdaterImpl<LDVSSAUpdater> Impl(&Updater, &AvailableValues, &CreatedPHIs);
+ BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.getParent()));
+ ValueIDNum Result = ValueIDNum::fromU64(ResultInt);
+
+ // We have the number for a PHI, or possibly live-through value, to be used
+ // at this Use. There are a number of things we have to check about it though:
+ // * Does any PHI use an 'Undef' (like an IMPLICIT_DEF) value? If so, this
+ // Use was not completely dominated by DBG_PHIs and we should abort.
+ // * Are the Defs or PHIs clobbered in a block? SSAUpdater isn't aware that
+ // we've left SSA form. Validate that the inputs to each PHI are the
+ // expected values.
+ // * Is a PHI we've created actually a merging of values, or are all the
+ // predecessor values the same, leading to a non-PHI machine value number?
+ // (SSAUpdater doesn't know that either). Remap validated PHIs into the
+ // the ValidatedValues collection below to sort this out.
+ DenseMap<LDVSSABlock *, ValueIDNum> ValidatedValues;
+
+ // Define all the input DBG_PHI values in ValidatedValues.
+ for (const auto &DBG_PHI : DBGPHIRange) {
+ LDVSSABlock *Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
+ const ValueIDNum &Num = DBG_PHI.ValueRead;
+ ValidatedValues.insert(std::make_pair(Block, Num));
+ }
+
+ // Sort PHIs to validate into RPO-order.
+ SmallVector<LDVSSAPhi *, 8> SortedPHIs;
+ for (auto &PHI : CreatedPHIs)
+ SortedPHIs.push_back(PHI);
+
+ std::sort(
+ SortedPHIs.begin(), SortedPHIs.end(), [&](LDVSSAPhi *A, LDVSSAPhi *B) {
+ return BBToOrder[&A->getParent()->BB] < BBToOrder[&B->getParent()->BB];
+ });
+
+ for (auto &PHI : SortedPHIs) {
+ ValueIDNum ThisBlockValueNum =
+ MLiveIns[PHI->ParentBlock->BB.getNumber()][Loc.asU64()];
+
+ // Are all these things actually defined?
+ for (auto &PHIIt : PHI->IncomingValues) {
+ // Any undef input means DBG_PHIs didn't dominate the use point.
+ if (Updater.UndefMap.find(&PHIIt.first->BB) != Updater.UndefMap.end())
+ return None;
+
+ ValueIDNum ValueToCheck;
+ ValueIDNum *BlockLiveOuts = MLiveOuts[PHIIt.first->BB.getNumber()];
+
+ auto VVal = ValidatedValues.find(PHIIt.first);
+ if (VVal == ValidatedValues.end()) {
+ // We cross a loop, and this is a backedge. LLVMs tail duplication
+ // happens so late that DBG_PHI instructions should not be able to
+ // migrate into loops -- meaning we can only be live-through this
+ // loop.
+ ValueToCheck = ThisBlockValueNum;
+ } else {
+ // Does the block have as a live-out, in the location we're examining,
+ // the value that we expect? If not, it's been moved or clobbered.
+ ValueToCheck = VVal->second;
+ }
+
+ if (BlockLiveOuts[Loc.asU64()] != ValueToCheck)
+ return None;
+ }
+
+ // Record this value as validated.
+ ValidatedValues.insert({PHI->ParentBlock, ThisBlockValueNum});
+ }
+
+ // All the PHIs are valid: we can return what the SSAUpdater said our value
+ // number was.
+ return Result;
+}
diff --git a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp
index 770c46ec8436..38e803d1abb5 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp
@@ -14,6 +14,7 @@
#include "llvm/CodeGen/Passes.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachine.h"
/// \file LiveDebugValues.cpp
@@ -33,6 +34,12 @@
using namespace llvm;
+static cl::opt<bool>
+ ForceInstrRefLDV("force-instr-ref-livedebugvalues", cl::Hidden,
+ cl::desc("Use instruction-ref based LiveDebugValues with "
+ "normal DBG_VALUE inputs"),
+ cl::init(false));
+
/// Generic LiveDebugValues pass. Calls through to VarLocBasedLDV or
/// InstrRefBasedLDV to perform location propagation, via the LDVImpl
/// base class.
@@ -87,6 +94,9 @@ bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) {
InstrRefBased = TM.Options.ValueTrackingVariableLocations;
}
+ // Allow the user to force selection of InstrRef LDV.
+ InstrRefBased |= ForceInstrRefLDV;
+
if (InstrRefBased)
TheImpl = llvm::makeInstrRefBasedLiveDebugValues();
else
diff --git a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h
index 6b05bc68d74d..9c910f180b9f 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h
+++ b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h
@@ -6,6 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIB_CODEGEN_LIVEDEBUGVALUES_LIVEDEBUGVALUES_H
+#define LLVM_LIB_CODEGEN_LIVEDEBUGVALUES_LIVEDEBUGVALUES_H
+
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -30,3 +33,5 @@ public:
extern LDVImpl *makeVarLocBasedLiveDebugValues();
extern LDVImpl *makeInstrRefBasedLiveDebugValues();
} // namespace llvm
+
+#endif // LLVM_LIB_CODEGEN_LIVEDEBUGVALUES_LIVEDEBUGVALUES_H
diff --git a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp
index e2daa46fe6b9..1e6d65c18953 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp
@@ -76,20 +76,23 @@
/// that are not through dataflow.
///
/// Within LiveDebugValues: each variable location is represented by a
-/// VarLoc object that identifies the source variable, its current
-/// machine-location, and the DBG_VALUE inst that specifies the location. Each
-/// VarLoc is indexed in the (function-scope) \p VarLocMap, giving each VarLoc a
-/// unique index. Rather than operate directly on machine locations, the
-/// dataflow analysis in this pass identifies locations by their index in the
-/// VarLocMap, meaning all the variable locations in a block can be described
-/// by a sparse vector of VarLocMap indicies.
+/// VarLoc object that identifies the source variable, the set of
+/// machine-locations that currently describe it (a single location for
+/// DBG_VALUE or multiple for DBG_VALUE_LIST), and the DBG_VALUE inst that
+/// specifies the location. Each VarLoc is indexed in the (function-scope) \p
+/// VarLocMap, giving each VarLoc a set of unique indexes, each of which
+/// corresponds to one of the VarLoc's machine-locations and can be used to
+/// lookup the VarLoc in the VarLocMap. Rather than operate directly on machine
+/// locations, the dataflow analysis in this pass identifies locations by their
+/// indices in the VarLocMap, meaning all the variable locations in a block can
+/// be described by a sparse vector of VarLocMap indicies.
///
/// All the storage for the dataflow analysis is local to the ExtendRanges
/// method and passed down to helper methods. "OutLocs" and "InLocs" record the
/// in and out lattice values for each block. "OpenRanges" maintains a list of
/// variable locations and, with the "process" method, evaluates the transfer
-/// function of each block. "flushPendingLocs" installs DBG_VALUEs for each
-/// live-in location at the start of blocks, while "Transfers" records
+/// function of each block. "flushPendingLocs" installs debug value instructions
+/// for each live-in location at the start of blocks, while "Transfers" records
/// transfers of values between machine-locations.
///
/// We avoid explicitly representing the "Unknown" (\top) lattice value in the
@@ -175,17 +178,6 @@ static cl::opt<unsigned> InputDbgValueLimit(
"Maximum input DBG_VALUE insts supported by debug range extension"),
cl::init(50000), cl::Hidden);
-// If @MI is a DBG_VALUE with debug value described by a defined
-// register, returns the number of this register. In the other case, returns 0.
-static Register isDbgValueDescribedByReg(const MachineInstr &MI) {
- assert(MI.isDebugValue() && "expected a DBG_VALUE");
- assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE");
- // If location of variable is described using a register (directly
- // or indirectly), this register is always a first operand.
- return MI.getDebugOperand(0).isReg() ? MI.getDebugOperand(0).getReg()
- : Register();
-}
-
/// If \p Op is a stack or frame register return true, otherwise return false.
/// This is used to avoid basing the debug entry values on the registers, since
/// we do not support it at the moment.
@@ -210,6 +202,13 @@ namespace {
// this prevents fallback to std::set::count() operations.
using DefinedRegsSet = SmallSet<Register, 32>;
+// The IDs in this set correspond to MachineLocs in VarLocs, as well as VarLocs
+// that represent Entry Values; every VarLoc in the set will also appear
+// exactly once at Location=0.
+// As a result, each VarLoc may appear more than once in this "set", but each
+// range corresponding to a Reg, SpillLoc, or EntryValue type will still be a
+// "true" set (i.e. each VarLoc may appear only once), and the range Location=0
+// is the set of all VarLocs.
using VarLocSet = CoalescingBitVector<uint64_t>;
/// A type-checked pair of {Register Location (or 0), Index}, used to index
@@ -229,11 +228,19 @@ struct LocIndex {
// here to encode non-register locations.
u32_index_t Index;
- /// The first location greater than 0 that is not reserved for VarLocs of
- /// kind RegisterKind.
+ /// The location that has an entry for every VarLoc in the map.
+ static constexpr u32_location_t kUniversalLocation = 0;
+
+ /// The first location that is reserved for VarLocs with locations of kind
+ /// RegisterKind.
+ static constexpr u32_location_t kFirstRegLocation = 1;
+
+ /// The first location greater than 0 that is not reserved for VarLocs with
+ /// locations of kind RegisterKind.
static constexpr u32_location_t kFirstInvalidRegLocation = 1 << 30;
- /// A special location reserved for VarLocs of kind SpillLocKind.
+ /// A special location reserved for VarLocs with locations of kind
+ /// SpillLocKind.
static constexpr u32_location_t kSpillLocation = kFirstInvalidRegLocation;
/// A special location reserved for VarLocs of kind EntryValueBackupKind and
@@ -258,7 +265,7 @@ struct LocIndex {
/// Get the start of the interval reserved for VarLocs of kind RegisterKind
/// which reside in \p Reg. The end is at rawIndexForReg(Reg+1)-1.
- static uint64_t rawIndexForReg(uint32_t Reg) {
+ static uint64_t rawIndexForReg(Register Reg) {
return LocIndex(Reg, 0).getAsRawInteger();
}
@@ -272,6 +279,13 @@ struct LocIndex {
}
};
+// Simple Set for storing all the VarLoc Indices at a Location bucket.
+using VarLocsInRange = SmallSet<LocIndex::u32_index_t, 32>;
+// Vector of all `LocIndex`s for a given VarLoc; the same Location should not
+// appear in any two of these, as each VarLoc appears at most once in any
+// Location bucket.
+using LocIndices = SmallVector<LocIndex, 2>;
+
class VarLocBasedLDV : public LDVImpl {
private:
const TargetRegisterInfo *TRI;
@@ -312,51 +326,130 @@ private:
/// is moved.
const MachineInstr &MI;
- enum VarLocKind {
+ enum class MachineLocKind {
InvalidKind = 0,
RegisterKind,
SpillLocKind,
- ImmediateKind,
+ ImmediateKind
+ };
+
+ enum class EntryValueLocKind {
+ NonEntryValueKind = 0,
EntryValueKind,
EntryValueBackupKind,
EntryValueCopyBackupKind
- } Kind = InvalidKind;
+ } EVKind;
/// The value location. Stored separately to avoid repeatedly
/// extracting it from MI.
- union LocUnion {
+ union MachineLocValue {
uint64_t RegNo;
SpillLoc SpillLocation;
uint64_t Hash;
int64_t Immediate;
const ConstantFP *FPImm;
const ConstantInt *CImm;
- LocUnion() : Hash(0) {}
- } Loc;
+ MachineLocValue() : Hash(0) {}
+ };
+
+ /// A single machine location; its Kind is either a register, spill
+ /// location, or immediate value.
+ /// If the VarLoc is not a NonEntryValueKind, then it will use only a
+ /// single MachineLoc of RegisterKind.
+ struct MachineLoc {
+ MachineLocKind Kind;
+ MachineLocValue Value;
+ bool operator==(const MachineLoc &Other) const {
+ if (Kind != Other.Kind)
+ return false;
+ switch (Kind) {
+ case MachineLocKind::SpillLocKind:
+ return Value.SpillLocation == Other.Value.SpillLocation;
+ case MachineLocKind::RegisterKind:
+ case MachineLocKind::ImmediateKind:
+ return Value.Hash == Other.Value.Hash;
+ default:
+ llvm_unreachable("Invalid kind");
+ }
+ }
+ bool operator<(const MachineLoc &Other) const {
+ switch (Kind) {
+ case MachineLocKind::SpillLocKind:
+ return std::make_tuple(
+ Kind, Value.SpillLocation.SpillBase,
+ Value.SpillLocation.SpillOffset.getFixed(),
+ Value.SpillLocation.SpillOffset.getScalable()) <
+ std::make_tuple(
+ Other.Kind, Other.Value.SpillLocation.SpillBase,
+ Other.Value.SpillLocation.SpillOffset.getFixed(),
+ Other.Value.SpillLocation.SpillOffset.getScalable());
+ case MachineLocKind::RegisterKind:
+ case MachineLocKind::ImmediateKind:
+ return std::tie(Kind, Value.Hash) <
+ std::tie(Other.Kind, Other.Value.Hash);
+ default:
+ llvm_unreachable("Invalid kind");
+ }
+ }
+ };
+
+ /// The set of machine locations used to determine the variable's value, in
+ /// conjunction with Expr. Initially populated with MI's debug operands,
+ /// but may be transformed independently afterwards.
+ SmallVector<MachineLoc, 8> Locs;
+ /// Used to map the index of each location in Locs back to the index of its
+ /// original debug operand in MI. Used when multiple location operands are
+ /// coalesced and the original MI's operands need to be accessed while
+ /// emitting a debug value.
+ SmallVector<unsigned, 8> OrigLocMap;
VarLoc(const MachineInstr &MI, LexicalScopes &LS)
: Var(MI.getDebugVariable(), MI.getDebugExpression(),
MI.getDebugLoc()->getInlinedAt()),
- Expr(MI.getDebugExpression()), MI(MI) {
+ Expr(MI.getDebugExpression()), MI(MI),
+ EVKind(EntryValueLocKind::NonEntryValueKind) {
assert(MI.isDebugValue() && "not a DBG_VALUE");
- assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE");
- if (int RegNo = isDbgValueDescribedByReg(MI)) {
- Kind = RegisterKind;
- Loc.RegNo = RegNo;
- } else if (MI.getDebugOperand(0).isImm()) {
- Kind = ImmediateKind;
- Loc.Immediate = MI.getDebugOperand(0).getImm();
- } else if (MI.getDebugOperand(0).isFPImm()) {
- Kind = ImmediateKind;
- Loc.FPImm = MI.getDebugOperand(0).getFPImm();
- } else if (MI.getDebugOperand(0).isCImm()) {
- Kind = ImmediateKind;
- Loc.CImm = MI.getDebugOperand(0).getCImm();
+ assert((MI.isDebugValueList() || MI.getNumOperands() == 4) &&
+ "malformed DBG_VALUE");
+ for (const MachineOperand &Op : MI.debug_operands()) {
+ MachineLoc ML = GetLocForOp(Op);
+ auto It = find(Locs, ML);
+ if (It == Locs.end()) {
+ Locs.push_back(ML);
+ OrigLocMap.push_back(MI.getDebugOperandIndex(&Op));
+ } else {
+ // ML duplicates an element in Locs; replace references to Op
+ // with references to the duplicating element.
+ unsigned OpIdx = Locs.size();
+ unsigned DuplicatingIdx = std::distance(Locs.begin(), It);
+ Expr = DIExpression::replaceArg(Expr, OpIdx, DuplicatingIdx);
+ }
}
- // We create the debug entry values from the factory functions rather than
- // from this ctor.
- assert(Kind != EntryValueKind && !isEntryBackupLoc());
+ // We create the debug entry values from the factory functions rather
+ // than from this ctor.
+ assert(EVKind != EntryValueLocKind::EntryValueKind &&
+ !isEntryBackupLoc());
+ }
+
+ static MachineLoc GetLocForOp(const MachineOperand &Op) {
+ MachineLocKind Kind;
+ MachineLocValue Loc;
+ if (Op.isReg()) {
+ Kind = MachineLocKind::RegisterKind;
+ Loc.RegNo = Op.getReg();
+ } else if (Op.isImm()) {
+ Kind = MachineLocKind::ImmediateKind;
+ Loc.Immediate = Op.getImm();
+ } else if (Op.isFPImm()) {
+ Kind = MachineLocKind::ImmediateKind;
+ Loc.FPImm = Op.getFPImm();
+ } else if (Op.isCImm()) {
+ Kind = MachineLocKind::ImmediateKind;
+ Loc.CImm = Op.getCImm();
+ } else
+ llvm_unreachable("Invalid Op kind for MachineLoc.");
+ return {Kind, Loc};
}
/// Take the variable and machine-location in DBG_VALUE MI, and build an
@@ -364,10 +457,11 @@ private:
static VarLoc CreateEntryLoc(const MachineInstr &MI, LexicalScopes &LS,
const DIExpression *EntryExpr, Register Reg) {
VarLoc VL(MI, LS);
- assert(VL.Kind == RegisterKind);
- VL.Kind = EntryValueKind;
+ assert(VL.Locs.size() == 1 &&
+ VL.Locs[0].Kind == MachineLocKind::RegisterKind);
+ VL.EVKind = EntryValueLocKind::EntryValueKind;
VL.Expr = EntryExpr;
- VL.Loc.RegNo = Reg;
+ VL.Locs[0].Value.RegNo = Reg;
return VL;
}
@@ -379,8 +473,9 @@ private:
LexicalScopes &LS,
const DIExpression *EntryExpr) {
VarLoc VL(MI, LS);
- assert(VL.Kind == RegisterKind);
- VL.Kind = EntryValueBackupKind;
+ assert(VL.Locs.size() == 1 &&
+ VL.Locs[0].Kind == MachineLocKind::RegisterKind);
+ VL.EVKind = EntryValueLocKind::EntryValueBackupKind;
VL.Expr = EntryExpr;
return VL;
}
@@ -393,32 +488,40 @@ private:
const DIExpression *EntryExpr,
Register NewReg) {
VarLoc VL(MI, LS);
- assert(VL.Kind == RegisterKind);
- VL.Kind = EntryValueCopyBackupKind;
+ assert(VL.Locs.size() == 1 &&
+ VL.Locs[0].Kind == MachineLocKind::RegisterKind);
+ VL.EVKind = EntryValueLocKind::EntryValueCopyBackupKind;
VL.Expr = EntryExpr;
- VL.Loc.RegNo = NewReg;
+ VL.Locs[0].Value.RegNo = NewReg;
return VL;
}
/// Copy the register location in DBG_VALUE MI, updating the register to
/// be NewReg.
- static VarLoc CreateCopyLoc(const MachineInstr &MI, LexicalScopes &LS,
+ static VarLoc CreateCopyLoc(const VarLoc &OldVL, const MachineLoc &OldML,
Register NewReg) {
- VarLoc VL(MI, LS);
- assert(VL.Kind == RegisterKind);
- VL.Loc.RegNo = NewReg;
- return VL;
+ VarLoc VL = OldVL;
+ for (size_t I = 0, E = VL.Locs.size(); I < E; ++I)
+ if (VL.Locs[I] == OldML) {
+ VL.Locs[I].Kind = MachineLocKind::RegisterKind;
+ VL.Locs[I].Value.RegNo = NewReg;
+ return VL;
+ }
+ llvm_unreachable("Should have found OldML in new VarLoc.");
}
- /// Take the variable described by DBG_VALUE MI, and create a VarLoc
+ /// Take the variable described by DBG_VALUE* MI, and create a VarLoc
/// locating it in the specified spill location.
- static VarLoc CreateSpillLoc(const MachineInstr &MI, unsigned SpillBase,
- StackOffset SpillOffset, LexicalScopes &LS) {
- VarLoc VL(MI, LS);
- assert(VL.Kind == RegisterKind);
- VL.Kind = SpillLocKind;
- VL.Loc.SpillLocation = {SpillBase, SpillOffset};
- return VL;
+ static VarLoc CreateSpillLoc(const VarLoc &OldVL, const MachineLoc &OldML,
+ unsigned SpillBase, StackOffset SpillOffset) {
+ VarLoc VL = OldVL;
+ for (int I = 0, E = VL.Locs.size(); I < E; ++I)
+ if (VL.Locs[I] == OldML) {
+ VL.Locs[I].Kind = MachineLocKind::SpillLocKind;
+ VL.Locs[I].Value.SpillLocation = {SpillBase, SpillOffset};
+ return VL;
+ }
+ llvm_unreachable("Should have found OldML in new VarLoc.");
}
/// Create a DBG_VALUE representing this VarLoc in the given function.
@@ -426,79 +529,143 @@ private:
/// inlining information from the original DBG_VALUE instruction, which may
/// have been several transfers ago.
MachineInstr *BuildDbgValue(MachineFunction &MF) const {
+ assert(!isEntryBackupLoc() &&
+ "Tried to produce DBG_VALUE for backup VarLoc");
const DebugLoc &DbgLoc = MI.getDebugLoc();
bool Indirect = MI.isIndirectDebugValue();
const auto &IID = MI.getDesc();
const DILocalVariable *Var = MI.getDebugVariable();
- const DIExpression *DIExpr = MI.getDebugExpression();
NumInserted++;
- switch (Kind) {
- case EntryValueKind:
- // An entry value is a register location -- but with an updated
- // expression. The register location of such DBG_VALUE is always the one
- // from the entry DBG_VALUE, it does not matter if the entry value was
- // copied in to another register due to some optimizations.
- return BuildMI(MF, DbgLoc, IID, Indirect,
- MI.getDebugOperand(0).getReg(), Var, Expr);
- case RegisterKind:
- // Register locations are like the source DBG_VALUE, but with the
- // register number from this VarLoc.
- return BuildMI(MF, DbgLoc, IID, Indirect, Loc.RegNo, Var, DIExpr);
- case SpillLocKind: {
- // Spills are indirect DBG_VALUEs, with a base register and offset.
- // Use the original DBG_VALUEs expression to build the spilt location
- // on top of. FIXME: spill locations created before this pass runs
- // are not recognized, and not handled here.
- auto *TRI = MF.getSubtarget().getRegisterInfo();
- auto *SpillExpr = TRI->prependOffsetExpression(
- DIExpr, DIExpression::ApplyOffset, Loc.SpillLocation.SpillOffset);
- unsigned Base = Loc.SpillLocation.SpillBase;
- return BuildMI(MF, DbgLoc, IID, true, Base, Var, SpillExpr);
- }
- case ImmediateKind: {
- MachineOperand MO = MI.getDebugOperand(0);
- return BuildMI(MF, DbgLoc, IID, Indirect, MO, Var, DIExpr);
- }
- case EntryValueBackupKind:
- case EntryValueCopyBackupKind:
- case InvalidKind:
- llvm_unreachable(
- "Tried to produce DBG_VALUE for invalid or backup VarLoc");
+ const DIExpression *DIExpr = Expr;
+ SmallVector<MachineOperand, 8> MOs;
+ for (unsigned I = 0, E = Locs.size(); I < E; ++I) {
+ MachineLocKind LocKind = Locs[I].Kind;
+ MachineLocValue Loc = Locs[I].Value;
+ const MachineOperand &Orig = MI.getDebugOperand(OrigLocMap[I]);
+ switch (LocKind) {
+ case MachineLocKind::RegisterKind:
+ // An entry value is a register location -- but with an updated
+ // expression. The register location of such DBG_VALUE is always the
+ // one from the entry DBG_VALUE, it does not matter if the entry value
+ // was copied in to another register due to some optimizations.
+ // Non-entry value register locations are like the source
+ // DBG_VALUE, but with the register number from this VarLoc.
+ MOs.push_back(MachineOperand::CreateReg(
+ EVKind == EntryValueLocKind::EntryValueKind ? Orig.getReg()
+ : Register(Loc.RegNo),
+ false));
+ MOs.back().setIsDebug();
+ break;
+ case MachineLocKind::SpillLocKind: {
+ // Spills are indirect DBG_VALUEs, with a base register and offset.
+ // Use the original DBG_VALUEs expression to build the spilt location
+ // on top of. FIXME: spill locations created before this pass runs
+ // are not recognized, and not handled here.
+ unsigned Base = Loc.SpillLocation.SpillBase;
+ auto *TRI = MF.getSubtarget().getRegisterInfo();
+ if (MI.isNonListDebugValue()) {
+ DIExpr =
+ TRI->prependOffsetExpression(DIExpr, DIExpression::ApplyOffset,
+ Loc.SpillLocation.SpillOffset);
+ Indirect = true;
+ } else {
+ SmallVector<uint64_t, 4> Ops;
+ TRI->getOffsetOpcodes(Loc.SpillLocation.SpillOffset, Ops);
+ Ops.push_back(dwarf::DW_OP_deref);
+ DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, I);
+ }
+ MOs.push_back(MachineOperand::CreateReg(Base, false));
+ MOs.back().setIsDebug();
+ break;
+ }
+ case MachineLocKind::ImmediateKind: {
+ MOs.push_back(Orig);
+ break;
+ }
+ case MachineLocKind::InvalidKind:
+ llvm_unreachable("Tried to produce DBG_VALUE for invalid VarLoc");
+ }
}
- llvm_unreachable("Unrecognized VarLocBasedLDV.VarLoc.Kind enum");
+ return BuildMI(MF, DbgLoc, IID, Indirect, MOs, Var, DIExpr);
}
/// Is the Loc field a constant or constant object?
- bool isConstant() const { return Kind == ImmediateKind; }
+ bool isConstant(MachineLocKind Kind) const {
+ return Kind == MachineLocKind::ImmediateKind;
+ }
/// Check if the Loc field is an entry backup location.
bool isEntryBackupLoc() const {
- return Kind == EntryValueBackupKind || Kind == EntryValueCopyBackupKind;
+ return EVKind == EntryValueLocKind::EntryValueBackupKind ||
+ EVKind == EntryValueLocKind::EntryValueCopyBackupKind;
}
- /// If this variable is described by a register holding the entry value,
- /// return it, otherwise return 0.
- unsigned getEntryValueBackupReg() const {
- if (Kind == EntryValueBackupKind)
- return Loc.RegNo;
- return 0;
+ /// If this variable is described by register \p Reg holding the entry
+ /// value, return true.
+ bool isEntryValueBackupReg(Register Reg) const {
+ return EVKind == EntryValueLocKind::EntryValueBackupKind && usesReg(Reg);
}
- /// If this variable is described by a register holding the copy of the
- /// entry value, return it, otherwise return 0.
- unsigned getEntryValueCopyBackupReg() const {
- if (Kind == EntryValueCopyBackupKind)
- return Loc.RegNo;
- return 0;
+ /// If this variable is described by register \p Reg holding a copy of the
+ /// entry value, return true.
+ bool isEntryValueCopyBackupReg(Register Reg) const {
+ return EVKind == EntryValueLocKind::EntryValueCopyBackupKind &&
+ usesReg(Reg);
}
- /// If this variable is described by a register, return it,
- /// otherwise return 0.
- unsigned isDescribedByReg() const {
- if (Kind == RegisterKind)
- return Loc.RegNo;
- return 0;
+ /// If this variable is described in whole or part by \p Reg, return true.
+ bool usesReg(Register Reg) const {
+ MachineLoc RegML;
+ RegML.Kind = MachineLocKind::RegisterKind;
+ RegML.Value.RegNo = Reg;
+ return is_contained(Locs, RegML);
+ }
+
+ /// If this variable is described in whole or part by \p Reg, return true.
+ unsigned getRegIdx(Register Reg) const {
+ for (unsigned Idx = 0; Idx < Locs.size(); ++Idx)
+ if (Locs[Idx].Kind == MachineLocKind::RegisterKind &&
+ Locs[Idx].Value.RegNo == Reg)
+ return Idx;
+ llvm_unreachable("Could not find given Reg in Locs");
+ }
+
+ /// If this variable is described in whole or part by 1 or more registers,
+ /// add each of them to \p Regs and return true.
+ bool getDescribingRegs(SmallVectorImpl<uint32_t> &Regs) const {
+ bool AnyRegs = false;
+ for (auto Loc : Locs)
+ if (Loc.Kind == MachineLocKind::RegisterKind) {
+ Regs.push_back(Loc.Value.RegNo);
+ AnyRegs = true;
+ }
+ return AnyRegs;
+ }
+
+ bool containsSpillLocs() const {
+ return any_of(Locs, [](VarLoc::MachineLoc ML) {
+ return ML.Kind == VarLoc::MachineLocKind::SpillLocKind;
+ });
+ }
+
+ /// If this variable is described in whole or part by \p SpillLocation,
+ /// return true.
+ bool usesSpillLoc(SpillLoc SpillLocation) const {
+ MachineLoc SpillML;
+ SpillML.Kind = MachineLocKind::SpillLocKind;
+ SpillML.Value.SpillLocation = SpillLocation;
+ return is_contained(Locs, SpillML);
+ }
+
+ /// If this variable is described in whole or part by \p SpillLocation,
+ /// return the index .
+ unsigned getSpillLocIdx(SpillLoc SpillLocation) const {
+ for (unsigned Idx = 0; Idx < Locs.size(); ++Idx)
+ if (Locs[Idx].Kind == MachineLocKind::SpillLocKind &&
+ Locs[Idx].Value.SpillLocation == SpillLocation)
+ return Idx;
+ llvm_unreachable("Could not find given SpillLoc in Locs");
}
/// Determine whether the lexical scope of this value's debug location
@@ -511,24 +678,26 @@ private:
// TRI can be null.
void dump(const TargetRegisterInfo *TRI, raw_ostream &Out = dbgs()) const {
Out << "VarLoc(";
- switch (Kind) {
- case RegisterKind:
- case EntryValueKind:
- case EntryValueBackupKind:
- case EntryValueCopyBackupKind:
- Out << printReg(Loc.RegNo, TRI);
- break;
- case SpillLocKind:
- Out << printReg(Loc.SpillLocation.SpillBase, TRI);
- Out << "[" << Loc.SpillLocation.SpillOffset.getFixed() << " + "
- << Loc.SpillLocation.SpillOffset.getScalable() << "x vscale"
- << "]";
- break;
- case ImmediateKind:
- Out << Loc.Immediate;
- break;
- case InvalidKind:
- llvm_unreachable("Invalid VarLoc in dump method");
+ for (const MachineLoc &MLoc : Locs) {
+ if (Locs.begin() != &MLoc)
+ Out << ", ";
+ switch (MLoc.Kind) {
+ case MachineLocKind::RegisterKind:
+ Out << printReg(MLoc.Value.RegNo, TRI);
+ break;
+ case MachineLocKind::SpillLocKind:
+ Out << printReg(MLoc.Value.SpillLocation.SpillBase, TRI);
+ Out << "[" << MLoc.Value.SpillLocation.SpillOffset.getFixed() << " + "
+ << MLoc.Value.SpillLocation.SpillOffset.getScalable()
+ << "x vscale"
+ << "]";
+ break;
+ case MachineLocKind::ImmediateKind:
+ Out << MLoc.Value.Immediate;
+ break;
+ case MachineLocKind::InvalidKind:
+ llvm_unreachable("Invalid VarLoc in dump method");
+ }
}
Out << ", \"" << Var.getVariable()->getName() << "\", " << *Expr << ", ";
@@ -545,90 +714,76 @@ private:
#endif
bool operator==(const VarLoc &Other) const {
- if (Kind != Other.Kind || !(Var == Other.Var) || Expr != Other.Expr)
- return false;
-
- switch (Kind) {
- case SpillLocKind:
- return Loc.SpillLocation == Other.Loc.SpillLocation;
- case RegisterKind:
- case ImmediateKind:
- case EntryValueKind:
- case EntryValueBackupKind:
- case EntryValueCopyBackupKind:
- return Loc.Hash == Other.Loc.Hash;
- default:
- llvm_unreachable("Invalid kind");
- }
+ return std::tie(EVKind, Var, Expr, Locs) ==
+ std::tie(Other.EVKind, Other.Var, Other.Expr, Other.Locs);
}
/// This operator guarantees that VarLocs are sorted by Variable first.
bool operator<(const VarLoc &Other) const {
- switch (Kind) {
- case SpillLocKind:
- return std::make_tuple(Var, Kind, Loc.SpillLocation.SpillBase,
- Loc.SpillLocation.SpillOffset.getFixed(),
- Loc.SpillLocation.SpillOffset.getScalable(),
- Expr) <
- std::make_tuple(
- Other.Var, Other.Kind, Other.Loc.SpillLocation.SpillBase,
- Other.Loc.SpillLocation.SpillOffset.getFixed(),
- Other.Loc.SpillLocation.SpillOffset.getScalable(),
- Other.Expr);
- case RegisterKind:
- case ImmediateKind:
- case EntryValueKind:
- case EntryValueBackupKind:
- case EntryValueCopyBackupKind:
- return std::tie(Var, Kind, Loc.Hash, Expr) <
- std::tie(Other.Var, Other.Kind, Other.Loc.Hash, Other.Expr);
- default:
- llvm_unreachable("Invalid kind");
- }
+ return std::tie(Var, EVKind, Locs, Expr) <
+ std::tie(Other.Var, Other.EVKind, Other.Locs, Other.Expr);
}
};
+#ifndef NDEBUG
+ using VarVec = SmallVector<VarLoc, 32>;
+#endif
+
/// VarLocMap is used for two things:
- /// 1) Assigning a unique LocIndex to a VarLoc. This LocIndex can be used to
+ /// 1) Assigning LocIndices to a VarLoc. The LocIndices can be used to
/// virtually insert a VarLoc into a VarLocSet.
/// 2) Given a LocIndex, look up the unique associated VarLoc.
class VarLocMap {
/// Map a VarLoc to an index within the vector reserved for its location
/// within Loc2Vars.
- std::map<VarLoc, LocIndex::u32_index_t> Var2Index;
+ std::map<VarLoc, LocIndices> Var2Indices;
/// Map a location to a vector which holds VarLocs which live in that
/// location.
SmallDenseMap<LocIndex::u32_location_t, std::vector<VarLoc>> Loc2Vars;
- /// Determine the 32-bit location reserved for \p VL, based on its kind.
- static LocIndex::u32_location_t getLocationForVar(const VarLoc &VL) {
- switch (VL.Kind) {
- case VarLoc::RegisterKind:
- assert((VL.Loc.RegNo < LocIndex::kFirstInvalidRegLocation) &&
+ public:
+ /// Retrieve LocIndices for \p VL.
+ LocIndices insert(const VarLoc &VL) {
+ LocIndices &Indices = Var2Indices[VL];
+ // If Indices is not empty, VL is already in the map.
+ if (!Indices.empty())
+ return Indices;
+ SmallVector<LocIndex::u32_location_t, 4> Locations;
+ // LocIndices are determined by EVKind and MLs; each Register has a
+ // unique location, while all SpillLocs use a single bucket, and any EV
+ // VarLocs use only the Backup bucket or none at all (except the
+ // compulsory entry at the universal location index). LocIndices will
+ // always have an index at the universal location index as the last index.
+ if (VL.EVKind == VarLoc::EntryValueLocKind::NonEntryValueKind) {
+ VL.getDescribingRegs(Locations);
+ assert(all_of(Locations,
+ [](auto RegNo) {
+ return RegNo < LocIndex::kFirstInvalidRegLocation;
+ }) &&
"Physreg out of range?");
- return VL.Loc.RegNo;
- case VarLoc::SpillLocKind:
- return LocIndex::kSpillLocation;
- case VarLoc::EntryValueBackupKind:
- case VarLoc::EntryValueCopyBackupKind:
- return LocIndex::kEntryValueBackupLocation;
- default:
- return 0;
+ if (VL.containsSpillLocs()) {
+ LocIndex::u32_location_t Loc = LocIndex::kSpillLocation;
+ Locations.push_back(Loc);
+ }
+ } else if (VL.EVKind != VarLoc::EntryValueLocKind::EntryValueKind) {
+ LocIndex::u32_location_t Loc = LocIndex::kEntryValueBackupLocation;
+ Locations.push_back(Loc);
}
- }
-
- public:
- /// Retrieve a unique LocIndex for \p VL.
- LocIndex insert(const VarLoc &VL) {
- LocIndex::u32_location_t Location = getLocationForVar(VL);
- LocIndex::u32_index_t &Index = Var2Index[VL];
- if (!Index) {
+ Locations.push_back(LocIndex::kUniversalLocation);
+ for (LocIndex::u32_location_t Location : Locations) {
auto &Vars = Loc2Vars[Location];
+ Indices.push_back(
+ {Location, static_cast<LocIndex::u32_index_t>(Vars.size())});
Vars.push_back(VL);
- Index = Vars.size();
}
- return {Location, Index - 1};
+ return Indices;
+ }
+
+ LocIndices getAllIndices(const VarLoc &VL) const {
+ auto IndIt = Var2Indices.find(VL);
+ assert(IndIt != Var2Indices.end() && "VarLoc not tracked");
+ return IndIt->second;
}
/// Retrieve the unique VarLoc associated with \p ID.
@@ -660,6 +815,17 @@ private:
using VarToFragments =
DenseMap<const DILocalVariable *, SmallSet<FragmentInfo, 4>>;
+ /// Collects all VarLocs from \p CollectFrom. Each unique VarLoc is added
+ /// to \p Collected once, in order of insertion into \p VarLocIDs.
+ static void collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
+ const VarLocSet &CollectFrom,
+ const VarLocMap &VarLocIDs);
+
+ /// Get the registers which are used by VarLocs of kind RegisterKind tracked
+ /// by \p CollectFrom.
+ void getUsedRegs(const VarLocSet &CollectFrom,
+ SmallVectorImpl<Register> &UsedRegs) const;
+
/// This holds the working set of currently open ranges. For fast
/// access, this is done both as a set of VarLocIDs, and a map of
/// DebugVariable to recent VarLocID. Note that a DBG_VALUE ends all
@@ -670,39 +836,45 @@ private:
/// we will erase/insert from the EntryValuesBackupVars map, otherwise
/// we perform the operation on the Vars.
class OpenRangesSet {
+ VarLocSet::Allocator &Alloc;
VarLocSet VarLocs;
// Map the DebugVariable to recent primary location ID.
- SmallDenseMap<DebugVariable, LocIndex, 8> Vars;
+ SmallDenseMap<DebugVariable, LocIndices, 8> Vars;
// Map the DebugVariable to recent backup location ID.
- SmallDenseMap<DebugVariable, LocIndex, 8> EntryValuesBackupVars;
+ SmallDenseMap<DebugVariable, LocIndices, 8> EntryValuesBackupVars;
OverlapMap &OverlappingFragments;
public:
OpenRangesSet(VarLocSet::Allocator &Alloc, OverlapMap &_OLapMap)
- : VarLocs(Alloc), OverlappingFragments(_OLapMap) {}
+ : Alloc(Alloc), VarLocs(Alloc), OverlappingFragments(_OLapMap) {}
const VarLocSet &getVarLocs() const { return VarLocs; }
+ // Fetches all VarLocs in \p VarLocIDs and inserts them into \p Collected.
+ // This method is needed to get every VarLoc once, as each VarLoc may have
+ // multiple indices in a VarLocMap (corresponding to each applicable
+ // location), but all VarLocs appear exactly once at the universal location
+ // index.
+ void getUniqueVarLocs(SmallVectorImpl<VarLoc> &Collected,
+ const VarLocMap &VarLocIDs) const {
+ collectAllVarLocs(Collected, VarLocs, VarLocIDs);
+ }
+
/// Terminate all open ranges for VL.Var by removing it from the set.
void erase(const VarLoc &VL);
- /// Terminate all open ranges listed in \c KillSet by removing
- /// them from the set.
- void erase(const VarLocSet &KillSet, const VarLocMap &VarLocIDs);
+ /// Terminate all open ranges listed as indices in \c KillSet with
+ /// \c Location by removing them from the set.
+ void erase(const VarLocsInRange &KillSet, const VarLocMap &VarLocIDs,
+ LocIndex::u32_location_t Location);
/// Insert a new range into the set.
- void insert(LocIndex VarLocID, const VarLoc &VL);
+ void insert(LocIndices VarLocIDs, const VarLoc &VL);
/// Insert a set of ranges.
- void insertFromLocSet(const VarLocSet &ToLoad, const VarLocMap &Map) {
- for (uint64_t ID : ToLoad) {
- LocIndex Idx = LocIndex::fromRawInteger(ID);
- const VarLoc &VarL = Map[Idx];
- insert(Idx, VarL);
- }
- }
+ void insertFromLocSet(const VarLocSet &ToLoad, const VarLocMap &Map);
- llvm::Optional<LocIndex> getEntryValueBackup(DebugVariable Var);
+ llvm::Optional<LocIndices> getEntryValueBackup(DebugVariable Var);
/// Empty the set.
void clear() {
@@ -725,18 +897,18 @@ private:
getVarLocs().end());
}
- /// Get all set IDs for VarLocs of kind RegisterKind in \p Reg.
+ /// Get all set IDs for VarLocs with MLs of kind RegisterKind in \p Reg.
auto getRegisterVarLocs(Register Reg) const {
return LocIndex::indexRangeForLocation(getVarLocs(), Reg);
}
- /// Get all set IDs for VarLocs of kind SpillLocKind.
+ /// Get all set IDs for VarLocs with MLs of kind SpillLocKind.
auto getSpillVarLocs() const {
return LocIndex::indexRangeForLocation(getVarLocs(),
LocIndex::kSpillLocation);
}
- /// Get all set IDs for VarLocs of kind EntryValueBackupKind or
+ /// Get all set IDs for VarLocs of EVKind EntryValueBackupKind or
/// EntryValueCopyBackupKind.
auto getEntryValueBackupVarLocs() const {
return LocIndex::indexRangeForLocation(
@@ -744,16 +916,14 @@ private:
}
};
- /// Collect all VarLoc IDs from \p CollectFrom for VarLocs of kind
- /// RegisterKind which are located in any reg in \p Regs. Insert collected IDs
- /// into \p Collected.
- void collectIDsForRegs(VarLocSet &Collected, const DefinedRegsSet &Regs,
- const VarLocSet &CollectFrom) const;
-
- /// Get the registers which are used by VarLocs of kind RegisterKind tracked
- /// by \p CollectFrom.
- void getUsedRegs(const VarLocSet &CollectFrom,
- SmallVectorImpl<uint32_t> &UsedRegs) const;
+ /// Collect all VarLoc IDs from \p CollectFrom for VarLocs with MLs of kind
+ /// RegisterKind which are located in any reg in \p Regs. The IDs for each
+ /// VarLoc correspond to entries in the universal location bucket, which every
+ /// VarLoc has exactly 1 entry for. Insert collected IDs into \p Collected.
+ static void collectIDsForRegs(VarLocsInRange &Collected,
+ const DefinedRegsSet &Regs,
+ const VarLocSet &CollectFrom,
+ const VarLocMap &VarLocIDs);
VarLocSet &getVarLocsInMBB(const MachineBasicBlock *MBB, VarLocInMBB &Locs) {
std::unique_ptr<VarLocSet> &VLS = Locs[MBB];
@@ -800,6 +970,7 @@ private:
void insertTransferDebugPair(MachineInstr &MI, OpenRangesSet &OpenRanges,
TransferMap &Transfers, VarLocMap &VarLocIDs,
LocIndex OldVarID, TransferKind Kind,
+ const VarLoc::MachineLoc &OldLoc,
Register NewReg = Register());
void transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges,
@@ -810,7 +981,7 @@ private:
VarLocMap &VarLocIDs, const VarLoc &EntryVL);
void emitEntryValues(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs, TransferMap &Transfers,
- VarLocSet &KillSet);
+ VarLocsInRange &KillSet);
void recordEntryValue(const MachineInstr &MI,
const DefinedRegsSet &DefinedRegs,
OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs);
@@ -871,8 +1042,9 @@ void VarLocBasedLDV::OpenRangesSet::erase(const VarLoc &VL) {
auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
auto It = EraseFrom->find(VarToErase);
if (It != EraseFrom->end()) {
- LocIndex ID = It->second;
- VarLocs.reset(ID.getAsRawInteger());
+ LocIndices IDs = It->second;
+ for (LocIndex ID : IDs)
+ VarLocs.reset(ID.getAsRawInteger());
EraseFrom->erase(It);
}
};
@@ -899,26 +1071,46 @@ void VarLocBasedLDV::OpenRangesSet::erase(const VarLoc &VL) {
}
}
-void VarLocBasedLDV::OpenRangesSet::erase(const VarLocSet &KillSet,
- const VarLocMap &VarLocIDs) {
- VarLocs.intersectWithComplement(KillSet);
- for (uint64_t ID : KillSet) {
- const VarLoc *VL = &VarLocIDs[LocIndex::fromRawInteger(ID)];
- auto *EraseFrom = VL->isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
- EraseFrom->erase(VL->Var);
+void VarLocBasedLDV::OpenRangesSet::erase(const VarLocsInRange &KillSet,
+ const VarLocMap &VarLocIDs,
+ LocIndex::u32_location_t Location) {
+ VarLocSet RemoveSet(Alloc);
+ for (LocIndex::u32_index_t ID : KillSet) {
+ const VarLoc &VL = VarLocIDs[LocIndex(Location, ID)];
+ auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
+ EraseFrom->erase(VL.Var);
+ LocIndices VLI = VarLocIDs.getAllIndices(VL);
+ for (LocIndex ID : VLI)
+ RemoveSet.set(ID.getAsRawInteger());
+ }
+ VarLocs.intersectWithComplement(RemoveSet);
+}
+
+void VarLocBasedLDV::OpenRangesSet::insertFromLocSet(const VarLocSet &ToLoad,
+ const VarLocMap &Map) {
+ VarLocsInRange UniqueVarLocIDs;
+ DefinedRegsSet Regs;
+ Regs.insert(LocIndex::kUniversalLocation);
+ collectIDsForRegs(UniqueVarLocIDs, Regs, ToLoad, Map);
+ for (uint64_t ID : UniqueVarLocIDs) {
+ LocIndex Idx = LocIndex::fromRawInteger(ID);
+ const VarLoc &VarL = Map[Idx];
+ const LocIndices Indices = Map.getAllIndices(VarL);
+ insert(Indices, VarL);
}
}
-void VarLocBasedLDV::OpenRangesSet::insert(LocIndex VarLocID,
- const VarLoc &VL) {
+void VarLocBasedLDV::OpenRangesSet::insert(LocIndices VarLocIDs,
+ const VarLoc &VL) {
auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
- VarLocs.set(VarLocID.getAsRawInteger());
- InsertInto->insert({VL.Var, VarLocID});
+ for (LocIndex ID : VarLocIDs)
+ VarLocs.set(ID.getAsRawInteger());
+ InsertInto->insert({VL.Var, VarLocIDs});
}
/// Return the Loc ID of an entry value backup location, if it exists for the
/// variable.
-llvm::Optional<LocIndex>
+llvm::Optional<LocIndices>
VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(DebugVariable Var) {
auto It = EntryValuesBackupVars.find(Var);
if (It != EntryValuesBackupVars.end())
@@ -927,26 +1119,35 @@ VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(DebugVariable Var) {
return llvm::None;
}
-void VarLocBasedLDV::collectIDsForRegs(VarLocSet &Collected,
- const DefinedRegsSet &Regs,
- const VarLocSet &CollectFrom) const {
+void VarLocBasedLDV::collectIDsForRegs(VarLocsInRange &Collected,
+ const DefinedRegsSet &Regs,
+ const VarLocSet &CollectFrom,
+ const VarLocMap &VarLocIDs) {
assert(!Regs.empty() && "Nothing to collect");
- SmallVector<uint32_t, 32> SortedRegs;
- for (Register Reg : Regs)
- SortedRegs.push_back(Reg);
+ SmallVector<Register, 32> SortedRegs;
+ append_range(SortedRegs, Regs);
array_pod_sort(SortedRegs.begin(), SortedRegs.end());
auto It = CollectFrom.find(LocIndex::rawIndexForReg(SortedRegs.front()));
auto End = CollectFrom.end();
- for (uint32_t Reg : SortedRegs) {
- // The half-open interval [FirstIndexForReg, FirstInvalidIndex) contains all
- // possible VarLoc IDs for VarLocs of kind RegisterKind which live in Reg.
+ for (Register Reg : SortedRegs) {
+ // The half-open interval [FirstIndexForReg, FirstInvalidIndex) contains
+ // all possible VarLoc IDs for VarLocs with MLs of kind RegisterKind which
+ // live in Reg.
uint64_t FirstIndexForReg = LocIndex::rawIndexForReg(Reg);
uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(Reg + 1);
It.advanceToLowerBound(FirstIndexForReg);
// Iterate through that half-open interval and collect all the set IDs.
- for (; It != End && *It < FirstInvalidIndex; ++It)
- Collected.set(*It);
+ for (; It != End && *It < FirstInvalidIndex; ++It) {
+ LocIndex ItIdx = LocIndex::fromRawInteger(*It);
+ const VarLoc &VL = VarLocIDs[ItIdx];
+ LocIndices LI = VarLocIDs.getAllIndices(VL);
+ // For now, the back index is always the universal location index.
+ assert(LI.back().Location == LocIndex::kUniversalLocation &&
+ "Unexpected order of LocIndices for VarLoc; was it inserted into "
+ "the VarLocMap correctly?");
+ Collected.insert(LI.back().Index);
+ }
if (It == End)
return;
@@ -954,10 +1155,11 @@ void VarLocBasedLDV::collectIDsForRegs(VarLocSet &Collected,
}
void VarLocBasedLDV::getUsedRegs(const VarLocSet &CollectFrom,
- SmallVectorImpl<uint32_t> &UsedRegs) const {
+ SmallVectorImpl<Register> &UsedRegs) const {
// All register-based VarLocs are assigned indices greater than or equal to
// FirstRegIndex.
- uint64_t FirstRegIndex = LocIndex::rawIndexForReg(1);
+ uint64_t FirstRegIndex =
+ LocIndex::rawIndexForReg(LocIndex::kFirstRegLocation);
uint64_t FirstInvalidIndex =
LocIndex::rawIndexForReg(LocIndex::kFirstInvalidRegLocation);
for (auto It = CollectFrom.find(FirstRegIndex),
@@ -995,9 +1197,10 @@ void VarLocBasedLDV::printVarLocInMBB(const MachineFunction &MF,
const VarLocSet &L = getVarLocsInMBB(&BB, V);
if (L.empty())
continue;
+ SmallVector<VarLoc, 32> VarLocs;
+ collectAllVarLocs(VarLocs, L, VarLocIDs);
Out << "MBB: " << BB.getNumber() << ":\n";
- for (uint64_t VLL : L) {
- const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(VLL)];
+ for (const VarLoc &VL : VarLocs) {
Out << " Var: " << VL.Var.getVariable()->getName();
Out << " MI: ";
VL.dump(TRI, Out);
@@ -1044,11 +1247,11 @@ bool VarLocBasedLDV::removeEntryValue(const MachineInstr &MI,
// If the DBG_VALUE comes from a copy instruction that copies the entry value,
// it means the parameter's value has not changed and we should be able to use
// its entry value.
- bool TrySalvageEntryValue = false;
Register Reg = MI.getDebugOperand(0).getReg();
auto I = std::next(MI.getReverseIterator());
const MachineOperand *SrcRegOp, *DestRegOp;
if (I != MI.getParent()->rend()) {
+
// TODO: Try to keep tracking of an entry value if we encounter a propagated
// DBG_VALUE describing the copy of the entry value. (Propagated entry value
// does not indicate the parameter modification.)
@@ -1060,13 +1263,11 @@ bool VarLocBasedLDV::removeEntryValue(const MachineInstr &MI,
DestRegOp = DestSrc->Destination;
if (Reg != DestRegOp->getReg())
return true;
- TrySalvageEntryValue = true;
- }
- if (TrySalvageEntryValue) {
for (uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(ID)];
- if (VL.getEntryValueCopyBackupReg() == Reg &&
+ if (VL.isEntryValueCopyBackupReg(Reg) &&
+ // Entry Values should not be variadic.
VL.MI.getDebugOperand(0).getReg() == SrcRegOp->getReg())
return false;
}
@@ -1095,7 +1296,7 @@ void VarLocBasedLDV::transferDebugValue(const MachineInstr &MI,
// If that is the case, we should stop tracking its entry value.
auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);
if (Var->isParameter() && EntryValBackupID) {
- const VarLoc &EntryVL = VarLocIDs[*EntryValBackupID];
+ const VarLoc &EntryVL = VarLocIDs[EntryValBackupID->back()];
if (removeEntryValue(MI, OpenRanges, VarLocIDs, EntryVL)) {
LLVM_DEBUG(dbgs() << "Deleting a DBG entry value because of: ";
MI.print(dbgs(), /*IsStandalone*/ false,
@@ -1105,59 +1306,79 @@ void VarLocBasedLDV::transferDebugValue(const MachineInstr &MI,
}
}
- if (isDbgValueDescribedByReg(MI) || MI.getDebugOperand(0).isImm() ||
- MI.getDebugOperand(0).isFPImm() || MI.getDebugOperand(0).isCImm()) {
+ if (all_of(MI.debug_operands(), [](const MachineOperand &MO) {
+ return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||
+ MO.isCImm();
+ })) {
// Use normal VarLoc constructor for registers and immediates.
VarLoc VL(MI, LS);
// End all previous ranges of VL.Var.
OpenRanges.erase(VL);
- LocIndex ID = VarLocIDs.insert(VL);
+ LocIndices IDs = VarLocIDs.insert(VL);
// Add the VarLoc to OpenRanges from this DBG_VALUE.
- OpenRanges.insert(ID, VL);
- } else if (MI.hasOneMemOperand()) {
+ OpenRanges.insert(IDs, VL);
+ } else if (MI.memoperands().size() > 0) {
llvm_unreachable("DBG_VALUE with mem operand encountered after regalloc?");
} else {
// This must be an undefined location. If it has an open range, erase it.
- assert(MI.getDebugOperand(0).isReg() &&
- MI.getDebugOperand(0).getReg() == 0 &&
+ assert(MI.isUndefDebugValue() &&
"Unexpected non-undef DBG_VALUE encountered");
VarLoc VL(MI, LS);
OpenRanges.erase(VL);
}
}
+// This should be removed later, doesn't fit the new design.
+void VarLocBasedLDV::collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
+ const VarLocSet &CollectFrom,
+ const VarLocMap &VarLocIDs) {
+ // The half-open interval [FirstIndexForReg, FirstInvalidIndex) contains all
+ // possible VarLoc IDs for VarLocs with MLs of kind RegisterKind which live
+ // in Reg.
+ uint64_t FirstIndex = LocIndex::rawIndexForReg(LocIndex::kUniversalLocation);
+ uint64_t FirstInvalidIndex =
+ LocIndex::rawIndexForReg(LocIndex::kUniversalLocation + 1);
+ // Iterate through that half-open interval and collect all the set IDs.
+ for (auto It = CollectFrom.find(FirstIndex), End = CollectFrom.end();
+ It != End && *It < FirstInvalidIndex; ++It) {
+ LocIndex RegIdx = LocIndex::fromRawInteger(*It);
+ Collected.push_back(VarLocIDs[RegIdx]);
+ }
+}
+
/// Turn the entry value backup locations into primary locations.
void VarLocBasedLDV::emitEntryValues(MachineInstr &MI,
- OpenRangesSet &OpenRanges,
- VarLocMap &VarLocIDs,
- TransferMap &Transfers,
- VarLocSet &KillSet) {
+ OpenRangesSet &OpenRanges,
+ VarLocMap &VarLocIDs,
+ TransferMap &Transfers,
+ VarLocsInRange &KillSet) {
// Do not insert entry value locations after a terminator.
if (MI.isTerminator())
return;
- for (uint64_t ID : KillSet) {
- LocIndex Idx = LocIndex::fromRawInteger(ID);
+ for (uint32_t ID : KillSet) {
+ // The KillSet IDs are indices for the universal location bucket.
+ LocIndex Idx = LocIndex(LocIndex::kUniversalLocation, ID);
const VarLoc &VL = VarLocIDs[Idx];
if (!VL.Var.getVariable()->isParameter())
continue;
auto DebugVar = VL.Var;
- Optional<LocIndex> EntryValBackupID =
+ Optional<LocIndices> EntryValBackupIDs =
OpenRanges.getEntryValueBackup(DebugVar);
// If the parameter has the entry value backup, it means we should
// be able to use its entry value.
- if (!EntryValBackupID)
+ if (!EntryValBackupIDs)
continue;
- const VarLoc &EntryVL = VarLocIDs[*EntryValBackupID];
- VarLoc EntryLoc =
- VarLoc::CreateEntryLoc(EntryVL.MI, LS, EntryVL.Expr, EntryVL.Loc.RegNo);
- LocIndex EntryValueID = VarLocIDs.insert(EntryLoc);
- Transfers.push_back({&MI, EntryValueID});
- OpenRanges.insert(EntryValueID, EntryLoc);
+ const VarLoc &EntryVL = VarLocIDs[EntryValBackupIDs->back()];
+ VarLoc EntryLoc = VarLoc::CreateEntryLoc(EntryVL.MI, LS, EntryVL.Expr,
+ EntryVL.Locs[0].Value.RegNo);
+ LocIndices EntryValueIDs = VarLocIDs.insert(EntryLoc);
+ Transfers.push_back({&MI, EntryValueIDs.back()});
+ OpenRanges.insert(EntryValueIDs, EntryLoc);
}
}
@@ -1169,20 +1390,20 @@ void VarLocBasedLDV::emitEntryValues(MachineInstr &MI,
void VarLocBasedLDV::insertTransferDebugPair(
MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind,
- Register NewReg) {
- const MachineInstr *DebugInstr = &VarLocIDs[OldVarID].MI;
+ const VarLoc::MachineLoc &OldLoc, Register NewReg) {
+ const VarLoc &OldVarLoc = VarLocIDs[OldVarID];
auto ProcessVarLoc = [&MI, &OpenRanges, &Transfers, &VarLocIDs](VarLoc &VL) {
- LocIndex LocId = VarLocIDs.insert(VL);
+ LocIndices LocIds = VarLocIDs.insert(VL);
// Close this variable's previous location range.
OpenRanges.erase(VL);
// Record the new location as an open range, and a postponed transfer
// inserting a DBG_VALUE for this location.
- OpenRanges.insert(LocId, VL);
+ OpenRanges.insert(LocIds, VL);
assert(!MI.isTerminator() && "Cannot insert DBG_VALUE after terminator");
- TransferDebugPair MIP = {&MI, LocId};
+ TransferDebugPair MIP = {&MI, LocIds.back()};
Transfers.push_back(MIP);
};
@@ -1194,7 +1415,7 @@ void VarLocBasedLDV::insertTransferDebugPair(
"No register supplied when handling a copy of a debug value");
// Create a DBG_VALUE instruction to describe the Var in its new
// register location.
- VarLoc VL = VarLoc::CreateCopyLoc(*DebugInstr, LS, NewReg);
+ VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
ProcessVarLoc(VL);
LLVM_DEBUG({
dbgs() << "Creating VarLoc for register copy:";
@@ -1206,8 +1427,8 @@ void VarLocBasedLDV::insertTransferDebugPair(
// Create a DBG_VALUE instruction to describe the Var in its spilled
// location.
VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI);
- VarLoc VL = VarLoc::CreateSpillLoc(*DebugInstr, SpillLocation.SpillBase,
- SpillLocation.SpillOffset, LS);
+ VarLoc VL = VarLoc::CreateSpillLoc(
+ OldVarLoc, OldLoc, SpillLocation.SpillBase, SpillLocation.SpillOffset);
ProcessVarLoc(VL);
LLVM_DEBUG({
dbgs() << "Creating VarLoc for spill:";
@@ -1220,7 +1441,7 @@ void VarLocBasedLDV::insertTransferDebugPair(
"No register supplied when handling a restore of a debug value");
// DebugInstr refers to the pre-spill location, therefore we can reuse
// its expression.
- VarLoc VL = VarLoc::CreateCopyLoc(*DebugInstr, LS, NewReg);
+ VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
ProcessVarLoc(VL);
LLVM_DEBUG({
dbgs() << "Creating VarLoc for restore:";
@@ -1267,9 +1488,9 @@ void VarLocBasedLDV::transferRegisterDef(
// reasons, it's critical to not iterate over the full set of open VarLocs.
// Iterate over the set of dying/used regs instead.
if (!RegMasks.empty()) {
- SmallVector<uint32_t, 32> UsedRegs;
+ SmallVector<Register, 32> UsedRegs;
getUsedRegs(OpenRanges.getVarLocs(), UsedRegs);
- for (uint32_t Reg : UsedRegs) {
+ for (Register Reg : UsedRegs) {
// Remove ranges of all clobbered registers. Register masks don't usually
// list SP as preserved. Assume that call instructions never clobber SP,
// because some backends (e.g., AArch64) never list SP in the regmask.
@@ -1290,9 +1511,9 @@ void VarLocBasedLDV::transferRegisterDef(
if (DeadRegs.empty())
return;
- VarLocSet KillSet(Alloc);
- collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs());
- OpenRanges.erase(KillSet, VarLocIDs);
+ VarLocsInRange KillSet;
+ collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs(), VarLocIDs);
+ OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kUniversalLocation);
if (TPC) {
auto &TM = TPC->getTM<TargetMachine>();
@@ -1390,14 +1611,14 @@ void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI,
// First, if there are any DBG_VALUEs pointing at a spill slot that is
// written to, then close the variable location. The value in memory
// will have changed.
- VarLocSet KillSet(Alloc);
+ VarLocsInRange KillSet;
if (isSpillInstruction(MI, MF)) {
Loc = extractSpillBaseRegAndOffset(MI);
for (uint64_t ID : OpenRanges.getSpillVarLocs()) {
LocIndex Idx = LocIndex::fromRawInteger(ID);
const VarLoc &VL = VarLocIDs[Idx];
- assert(VL.Kind == VarLoc::SpillLocKind && "Broken VarLocSet?");
- if (VL.Loc.SpillLocation == *Loc) {
+ assert(VL.containsSpillLocs() && "Broken VarLocSet?");
+ if (VL.usesSpillLoc(*Loc)) {
// This location is overwritten by the current instruction -- terminate
// the open range, and insert an explicit DBG_VALUE $noreg.
//
@@ -1408,13 +1629,15 @@ void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI,
//
// At this stage, we already know which DBG_VALUEs are for spills and
// where they are located; it's best to fix handle overwrites now.
- KillSet.set(ID);
- VarLoc UndefVL = VarLoc::CreateCopyLoc(VL.MI, LS, 0);
- LocIndex UndefLocID = VarLocIDs.insert(UndefVL);
- Transfers.push_back({&MI, UndefLocID});
+ KillSet.insert(ID);
+ unsigned SpillLocIdx = VL.getSpillLocIdx(*Loc);
+ VarLoc::MachineLoc OldLoc = VL.Locs[SpillLocIdx];
+ VarLoc UndefVL = VarLoc::CreateCopyLoc(VL, OldLoc, 0);
+ LocIndices UndefLocIDs = VarLocIDs.insert(UndefVL);
+ Transfers.push_back({&MI, UndefLocIDs.back()});
}
}
- OpenRanges.erase(KillSet, VarLocIDs);
+ OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kSpillLocation);
}
// Try to recognise spill and restore instructions that may create a new
@@ -1441,21 +1664,25 @@ void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI,
for (uint64_t ID : TransferCandidates) {
LocIndex Idx = LocIndex::fromRawInteger(ID);
const VarLoc &VL = VarLocIDs[Idx];
+ unsigned LocIdx;
if (TKind == TransferKind::TransferSpill) {
- assert(VL.isDescribedByReg() == Reg && "Broken VarLocSet?");
+ assert(VL.usesReg(Reg) && "Broken VarLocSet?");
LLVM_DEBUG(dbgs() << "Spilling Register " << printReg(Reg, TRI) << '('
<< VL.Var.getVariable()->getName() << ")\n");
+ LocIdx = VL.getRegIdx(Reg);
} else {
- assert(TKind == TransferKind::TransferRestore &&
- VL.Kind == VarLoc::SpillLocKind && "Broken VarLocSet?");
- if (VL.Loc.SpillLocation != *Loc)
+ assert(TKind == TransferKind::TransferRestore && VL.containsSpillLocs() &&
+ "Broken VarLocSet?");
+ if (!VL.usesSpillLoc(*Loc))
// The spill location is not the location of a debug value.
continue;
LLVM_DEBUG(dbgs() << "Restoring Register " << printReg(Reg, TRI) << '('
<< VL.Var.getVariable()->getName() << ")\n");
+ LocIdx = VL.getSpillLocIdx(*Loc);
}
+ VarLoc::MachineLoc MLoc = VL.Locs[LocIdx];
insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, Idx, TKind,
- Reg);
+ MLoc, Reg);
// FIXME: A comment should explain why it's correct to return early here,
// if that is in fact correct.
return;
@@ -1504,17 +1731,16 @@ void VarLocBasedLDV::transferRegisterCopy(MachineInstr &MI,
for (uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
LocIndex Idx = LocIndex::fromRawInteger(ID);
const VarLoc &VL = VarLocIDs[Idx];
- if (VL.getEntryValueBackupReg() == SrcReg) {
+ if (VL.isEntryValueBackupReg(SrcReg)) {
LLVM_DEBUG(dbgs() << "Copy of the entry value: "; MI.dump(););
VarLoc EntryValLocCopyBackup =
VarLoc::CreateEntryCopyBackupLoc(VL.MI, LS, VL.Expr, DestReg);
-
// Stop tracking the original entry value.
OpenRanges.erase(VL);
// Start tracking the entry value copy.
- LocIndex EntryValCopyLocID = VarLocIDs.insert(EntryValLocCopyBackup);
- OpenRanges.insert(EntryValCopyLocID, EntryValLocCopyBackup);
+ LocIndices EntryValCopyLocIDs = VarLocIDs.insert(EntryValLocCopyBackup);
+ OpenRanges.insert(EntryValCopyLocIDs, EntryValLocCopyBackup);
break;
}
}
@@ -1525,9 +1751,12 @@ void VarLocBasedLDV::transferRegisterCopy(MachineInstr &MI,
for (uint64_t ID : OpenRanges.getRegisterVarLocs(SrcReg)) {
LocIndex Idx = LocIndex::fromRawInteger(ID);
- assert(VarLocIDs[Idx].isDescribedByReg() == SrcReg && "Broken VarLocSet?");
+ assert(VarLocIDs[Idx].usesReg(SrcReg) && "Broken VarLocSet?");
+ VarLoc::MachineLocValue Loc;
+ Loc.RegNo = SrcReg;
+ VarLoc::MachineLoc MLoc{VarLoc::MachineLocKind::RegisterKind, Loc};
insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, Idx,
- TransferKind::TransferCopy, DestReg);
+ TransferKind::TransferCopy, MLoc, DestReg);
// FIXME: A comment should explain why it's correct to return early here,
// if that is in fact correct.
return;
@@ -1540,12 +1769,14 @@ bool VarLocBasedLDV::transferTerminator(MachineBasicBlock *CurMBB,
VarLocInMBB &OutLocs,
const VarLocMap &VarLocIDs) {
bool Changed = false;
-
- LLVM_DEBUG(for (uint64_t ID
- : OpenRanges.getVarLocs()) {
- // Copy OpenRanges to OutLocs, if not already present.
- dbgs() << "Add to OutLocs in MBB #" << CurMBB->getNumber() << ": ";
- VarLocIDs[LocIndex::fromRawInteger(ID)].dump(TRI);
+ LLVM_DEBUG({
+ VarVec VarLocs;
+ OpenRanges.getUniqueVarLocs(VarLocs, VarLocIDs);
+ for (VarLoc &VL : VarLocs) {
+ // Copy OpenRanges to OutLocs, if not already present.
+ dbgs() << "Add to OutLocs in MBB #" << CurMBB->getNumber() << ": ";
+ VL.dump(TRI);
+ }
});
VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);
Changed = VLS != OpenRanges.getVarLocs();
@@ -1668,12 +1899,11 @@ bool VarLocBasedLDV::join(
LLVM_DEBUG({
if (!InLocsT.empty()) {
- for (uint64_t ID : InLocsT)
+ VarVec VarLocs;
+ collectAllVarLocs(VarLocs, InLocsT, VarLocIDs);
+ for (const VarLoc &VL : VarLocs)
dbgs() << " gathered candidate incoming var: "
- << VarLocIDs[LocIndex::fromRawInteger(ID)]
- .Var.getVariable()
- ->getName()
- << "\n";
+ << VL.Var.getVariable()->getName() << "\n";
}
});
@@ -1722,10 +1952,12 @@ void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs,
auto &MBB = const_cast<MachineBasicBlock &>(*Iter.first);
VarLocSet &Pending = *Iter.second.get();
- for (uint64_t ID : Pending) {
+ SmallVector<VarLoc, 32> VarLocs;
+ collectAllVarLocs(VarLocs, Pending, VarLocIDs);
+
+ for (VarLoc DiffIt : VarLocs) {
// The ID location is live-in to MBB -- work out what kind of machine
// location it is and create a DBG_VALUE.
- const VarLoc &DiffIt = VarLocIDs[LocIndex::fromRawInteger(ID)];
if (DiffIt.isEntryBackupLoc())
continue;
MachineInstr *MI = DiffIt.BuildDbgValue(*MBB.getParent());
@@ -1810,8 +2042,8 @@ void VarLocBasedLDV::recordEntryValue(const MachineInstr &MI,
DIExpression *NewExpr =
DIExpression::prepend(MI.getDebugExpression(), DIExpression::EntryValue);
VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(MI, LS, NewExpr);
- LocIndex EntryValLocID = VarLocIDs.insert(EntryValLocAsBackup);
- OpenRanges.insert(EntryValLocID, EntryValLocAsBackup);
+ LocIndices EntryValLocIDs = VarLocIDs.insert(EntryValLocAsBackup);
+ OpenRanges.insert(EntryValLocIDs, EntryValLocAsBackup);
}
/// Calculate the liveness information for the given machine function and
@@ -1896,9 +2128,9 @@ bool VarLocBasedLDV::ExtendRanges(MachineFunction &MF, TargetPassConfig *TPC) {
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
unsigned int RPONumber = 0;
- for (auto RI = RPOT.begin(), RE = RPOT.end(); RI != RE; ++RI) {
- OrderToBB[RPONumber] = *RI;
- BBToOrder[*RI] = RPONumber;
+ for (MachineBasicBlock *MBB : RPOT) {
+ OrderToBB[RPONumber] = MBB;
+ BBToOrder[MBB] = RPONumber;
Worklist.push(RPONumber);
++RPONumber;
}