summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
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/InstrRefBasedImpl.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp')
-rw-r--r--llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp911
1 files changed, 813 insertions, 98 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;
+}