Skip to content

Commit

Permalink
[DebugInfo] LiveDebugValues: move DBG_VALUE creation into VarLoc class
Browse files Browse the repository at this point in the history
Rather than having a mixture of location-state shared between DBG_VALUEs
and VarLoc objects in LiveDebugValues, this patch makes VarLoc the
master record of variable locations. The refactoring means that the
transfer of locations from one place to another is always a performed by
an operation on an existing VarLoc, that produces another transferred
VarLoc. DBG_VALUEs are only created at the end of LiveDebugValues, once
all locations are known. As a plus, there is now only one method where
DBG_VALUEs can be created.

The test case added covers a circumstance that is now impossible to
express in LiveDebugValues: if an already-indirect DBG_VALUE is spilt,
previously it would have been restored-from-spill as a direct DBG_VALUE.
We now don't lose this information along the way, as VarLocs always
refer back to the "original" non-transfer DBG_VALUE, and we can always
work out whether a location was "originally" indirect.

Differential Revision: https://reviews.llvm.org/D67398

llvm-svn: 373727
  • Loading branch information
jmorse committed Oct 4, 2019
1 parent 90cfbf3 commit 61800a7
Show file tree
Hide file tree
Showing 2 changed files with 277 additions and 108 deletions.
244 changes: 137 additions & 107 deletions llvm/lib/CodeGen/LiveDebugValues.cpp
Expand Up @@ -219,8 +219,7 @@ class LiveDebugValues : public MachineFunctionPass {
const ConstantInt *CImm;
} Loc;

VarLoc(const MachineInstr &MI, LexicalScopes &LS,
VarLocKind K = InvalidKind)
VarLoc(const MachineInstr &MI, LexicalScopes &LS)
: Var(MI), Expr(MI.getDebugExpression()), MI(MI),
UVS(MI.getDebugLoc(), LS) {
static_assert((sizeof(Loc) == sizeof(uint64_t)),
Expand All @@ -244,18 +243,77 @@ class LiveDebugValues : public MachineFunctionPass {
"entry values must be register locations");
}

/// The constructor for spill locations.
VarLoc(const MachineInstr &MI, unsigned SpillBase, int SpillOffset,
LexicalScopes &LS, const MachineInstr &OrigMI)
: Var(MI), Expr(MI.getDebugExpression()), MI(OrigMI),
UVS(MI.getDebugLoc(), LS) {
assert(MI.isDebugValue() && "not a DBG_VALUE");
assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE");
Kind = SpillLocKind;
Loc.SpillLocation = {SpillBase, SpillOffset};
/// Take the variable and machine-location in DBG_VALUE MI, and build an
/// entry location using the given expression.
static VarLoc CreateEntryLoc(const MachineInstr &MI, LexicalScopes &LS,
const DIExpression *EntryExpr) {
VarLoc VL(MI, LS);
VL.Kind = EntryValueKind;
VL.Expr = EntryExpr;
return VL;
}

/// Copy the register location in DBG_VALUE MI, updating the register to
/// be NewReg.
static VarLoc CreateCopyLoc(const MachineInstr &MI, LexicalScopes &LS,
unsigned NewReg) {
VarLoc VL(MI, LS);
assert(VL.Kind == RegisterKind);
VL.Loc.RegNo = NewReg;
return VL;
}

/// 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,
int SpillOffset, LexicalScopes &LS) {
VarLoc VL(MI, LS);
assert(VL.Kind == RegisterKind);
VL.Kind = SpillLocKind;
VL.Loc.SpillLocation = {SpillBase, SpillOffset};
return VL;
}

// Is the Loc field a constant or constant object?
/// Create a DBG_VALUE representing this VarLoc in the given function.
/// Copies variable-specific information such as DILocalVariable and
/// inlining information from the original DBG_VALUE instruction, which may
/// have been several transfers ago.
MachineInstr *BuildDbgValue(MachineFunction &MF) const {
const DebugLoc &DbgLoc = MI.getDebugLoc();
bool Indirect = MI.isIndirectDebugValue();
const auto &IID = MI.getDesc();
const DILocalVariable *Var = MI.getDebugVariable();
const DIExpression *DIExpr = MI.getDebugExpression();

switch (Kind) {
case EntryValueKind:
// An entry value is a register location -- but with an updated
// expression.
return BuildMI(MF, DbgLoc, IID, Indirect, Loc.RegNo, 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 *SpillExpr = DIExpression::prepend(
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.getOperand(0);
return BuildMI(MF, DbgLoc, IID, Indirect, MO, Var, DIExpr);
}
case InvalidKind:
llvm_unreachable("Tried to produce DBG_VALUE for invalid VarLoc");
}
}

/// Is the Loc field a constant or constant object?
bool isConstant() const { return Kind == ImmediateKind; }

/// If this variable is described by a register, return it,
Expand All @@ -271,7 +329,31 @@ class LiveDebugValues : public MachineFunctionPass {
bool dominates(MachineBasicBlock &MBB) const { return UVS.dominates(&MBB); }

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void dump() const { MI.dump(); }
// TRI can be null.
void dump(const TargetRegisterInfo *TRI, raw_ostream &Out = dbgs()) const {
dbgs() << "VarLoc(";
switch (Kind) {
case RegisterKind:
case EntryValueKind:
dbgs() << printReg(Loc.RegNo, TRI);
break;
case SpillLocKind:
dbgs() << printReg(Loc.SpillLocation.SpillBase, TRI);
dbgs() << "[" << Loc.SpillLocation.SpillOffset << "]";
break;
case ImmediateKind:
dbgs() << Loc.Immediate;
break;
case InvalidKind:
llvm_unreachable("Invalid VarLoc in dump method");
}

dbgs() << ", \"" << Var.getVar()->getName() << "\", " << *Expr << ", ";
if (Var.getInlinedAt())
dbgs() << "!" << Var.getInlinedAt()->getMetadataID() << ")\n";
else
dbgs() << "(null))\n";
}
#endif

bool operator==(const VarLoc &Other) const {
Expand All @@ -291,8 +373,8 @@ class LiveDebugValues : public MachineFunctionPass {
using VarLocSet = SparseBitVector<>;
using VarLocInMBB = SmallDenseMap<const MachineBasicBlock *, VarLocSet>;
struct TransferDebugPair {
MachineInstr *TransferInst;
MachineInstr *DebugInst;
MachineInstr *TransferInst; /// Instruction where this transfer occurs.
unsigned LocationID; /// Location number for the transfer dest.
};
using TransferMap = SmallVector<TransferDebugPair, 4>;

Expand Down Expand Up @@ -561,7 +643,7 @@ void LiveDebugValues::printVarLocInMBB(const MachineFunction &MF,
const VarLoc &VL = VarLocIDs[VLL];
Out << " Var: " << VL.Var.getVar()->getName();
Out << " MI: ";
VL.dump();
VL.dump(TRI, Out);
}
}
Out << "\n";
Expand Down Expand Up @@ -624,7 +706,6 @@ void LiveDebugValues::emitEntryValues(MachineInstr &MI,
TransferMap &Transfers,
DebugParamMap &DebugEntryVals,
SparseBitVector<> &KillSet) {
MachineFunction *MF = MI.getParent()->getParent();
for (unsigned ID : KillSet) {
if (!VarLocIDs[ID].Var.getVar()->isParameter())
continue;
Expand All @@ -639,20 +720,12 @@ void LiveDebugValues::emitEntryValues(MachineInstr &MI,
auto ParamDebugInstr = DebugEntryVals[CurrDebugInstr->getDebugVariable()];
DIExpression *NewExpr = DIExpression::prepend(
ParamDebugInstr->getDebugExpression(), DIExpression::EntryValue);
MachineInstr *EntryValDbgMI =
BuildMI(*MF, ParamDebugInstr->getDebugLoc(), ParamDebugInstr->getDesc(),
ParamDebugInstr->isIndirectDebugValue(),
ParamDebugInstr->getOperand(0).getReg(),
ParamDebugInstr->getDebugVariable(), NewExpr);

if (ParamDebugInstr->isIndirectDebugValue())
EntryValDbgMI->getOperand(1).setImm(
ParamDebugInstr->getOperand(1).getImm());

Transfers.push_back({&MI, EntryValDbgMI});
VarLoc VL(*EntryValDbgMI, LS);
unsigned EntryValLocID = VarLocIDs.insert(VL);
OpenRanges.insert(EntryValLocID, VL.Var);

VarLoc EntryLoc = VarLoc::CreateEntryLoc(*ParamDebugInstr, LS, NewExpr);

unsigned EntryValLocID = VarLocIDs.insert(EntryLoc);
Transfers.push_back({&MI, EntryValLocID});
OpenRanges.insert(EntryValLocID, EntryLoc.Var);
}
}

Expand All @@ -666,21 +739,19 @@ void LiveDebugValues::insertTransferDebugPair(
VarLocMap &VarLocIDs, unsigned OldVarID, TransferKind Kind,
unsigned NewReg) {
const MachineInstr *DebugInstr = &VarLocIDs[OldVarID].MI;
MachineFunction *MF = MI.getParent()->getParent();
MachineInstr *NewDebugInstr;

auto ProcessVarLoc = [&MI, &OpenRanges, &Transfers, &DebugInstr,
&VarLocIDs](VarLoc &VL, MachineInstr *NewDebugInstr) {
&VarLocIDs](VarLoc &VL) {
unsigned LocId = VarLocIDs.insert(VL);

// Close this variable's previous location range.
DebugVariable V(*DebugInstr);
OpenRanges.erase(V);

// Record the new location as an open range, and a postponed transfer
// inserting a DBG_VALUE for this location.
OpenRanges.insert(LocId, VL.Var);
// The newly created DBG_VALUE instruction NewDebugInstr must be inserted
// after MI. Keep track of the pairing.
TransferDebugPair MIP = {&MI, NewDebugInstr};
TransferDebugPair MIP = {&MI, LocId};
Transfers.push_back(MIP);
};

Expand All @@ -692,37 +763,25 @@ void LiveDebugValues::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.
NewDebugInstr = BuildMI(
*MF, DebugInstr->getDebugLoc(), DebugInstr->getDesc(),
DebugInstr->isIndirectDebugValue(), NewReg,
DebugInstr->getDebugVariable(), DebugInstr->getDebugExpression());
if (DebugInstr->isIndirectDebugValue())
NewDebugInstr->getOperand(1).setImm(DebugInstr->getOperand(1).getImm());
VarLoc VL(*NewDebugInstr, LS);
ProcessVarLoc(VL, NewDebugInstr);
LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for register copy: ";
NewDebugInstr->print(dbgs(), /*IsStandalone*/false,
/*SkipOpers*/false, /*SkipDebugLoc*/false,
/*AddNewLine*/true, TII));
VarLoc VL = VarLoc::CreateCopyLoc(*DebugInstr, LS, NewReg);
ProcessVarLoc(VL);
LLVM_DEBUG({
dbgs() << "Creating VarLoc for register copy:";
VL.dump(TRI);
});
return;
}
case TransferKind::TransferSpill: {
// Create a DBG_VALUE instruction to describe the Var in its spilled
// location.
VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI);
auto *SpillExpr = DIExpression::prepend(DebugInstr->getDebugExpression(),
DIExpression::ApplyOffset,
SpillLocation.SpillOffset);
NewDebugInstr = BuildMI(
*MF, DebugInstr->getDebugLoc(), DebugInstr->getDesc(), true,
SpillLocation.SpillBase, DebugInstr->getDebugVariable(), SpillExpr);
VarLoc VL(*NewDebugInstr, SpillLocation.SpillBase,
SpillLocation.SpillOffset, LS, *DebugInstr);
ProcessVarLoc(VL, NewDebugInstr);
LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for spill: ";
NewDebugInstr->print(dbgs(), /*IsStandalone*/false,
/*SkipOpers*/false, /*SkipDebugLoc*/false,
/*AddNewLine*/true, TII));
VarLoc VL = VarLoc::CreateSpillLoc(*DebugInstr, SpillLocation.SpillBase,
SpillLocation.SpillOffset, LS);
ProcessVarLoc(VL);
LLVM_DEBUG({
dbgs() << "Creating VarLoc for spill:";
VL.dump(TRI);
});
return;
}
case TransferKind::TransferRestore: {
Expand All @@ -732,15 +791,12 @@ void LiveDebugValues::insertTransferDebugPair(
DIBuilder DIB(*const_cast<Function &>(MF->getFunction()).getParent());
// DebugInstr refers to the pre-spill location, therefore we can reuse
// its expression.
NewDebugInstr = BuildMI(
*MF, DebugInstr->getDebugLoc(), DebugInstr->getDesc(), false, NewReg,
DebugInstr->getDebugVariable(), DebugInstr->getDebugExpression());
VarLoc VL(*NewDebugInstr, LS);
ProcessVarLoc(VL, NewDebugInstr);
LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for register restore: ";
NewDebugInstr->print(dbgs(), /*IsStandalone*/false,
/*SkipOpers*/false, /*SkipDebugLoc*/false,
/*AddNewLine*/true, TII));
VarLoc VL = VarLoc::CreateCopyLoc(*DebugInstr, LS, NewReg);
ProcessVarLoc(VL);
LLVM_DEBUG({
dbgs() << "Creating VarLoc for restore:";
VL.dump(TRI);
});
return;
}
}
Expand Down Expand Up @@ -895,11 +951,9 @@ void LiveDebugValues::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);
MachineInstr *NewDebugInstr =
BuildMI(*MF, VL.MI.getDebugLoc(), VL.MI.getDesc(),
VL.MI.isIndirectDebugValue(), 0, // $noreg
VL.MI.getDebugVariable(), VL.MI.getDebugExpression());
Transfers.push_back({&MI, NewDebugInstr});
VarLoc UndefVL = VarLoc::CreateCopyLoc(VL.MI, LS, 0);
unsigned UndefLocID = VarLocIDs.insert(UndefVL);
Transfers.push_back({&MI, UndefLocID});
}
}
OpenRanges.erase(KillSet, VarLocIDs);
Expand Down Expand Up @@ -990,7 +1044,7 @@ bool LiveDebugValues::transferTerminator(MachineBasicBlock *CurMBB,
: OpenRanges.getVarLocs()) {
// Copy OpenRanges to OutLocs, if not already present.
dbgs() << "Add to OutLocs in MBB #" << CurMBB->getNumber() << ": ";
VarLocIDs[ID].dump();
VarLocIDs[ID].dump(TRI);
});
VarLocSet &VLS = OutLocs[CurMBB];
Changed = VLS != OpenRanges.getVarLocs();
Expand Down Expand Up @@ -1192,35 +1246,9 @@ void LiveDebugValues::flushPendingLocs(VarLocInMBB &PendingInLocs,
// 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[ID];
const MachineInstr *DebugInstr = &DiffIt.MI;
MachineInstr *MI = nullptr;

if (DiffIt.isConstant()) {
MachineOperand MO(DebugInstr->getOperand(0));
MI = BuildMI(MBB, MBB.instr_begin(), DebugInstr->getDebugLoc(),
DebugInstr->getDesc(), false, MO,
DebugInstr->getDebugVariable(),
DebugInstr->getDebugExpression());
} else {
auto *DebugExpr = DebugInstr->getDebugExpression();
Register Reg = DebugInstr->getOperand(0).getReg();
bool IsIndirect = DebugInstr->isIndirectDebugValue();

if (DiffIt.Kind == VarLoc::SpillLocKind) {
// This is is a spilt location; DebugInstr refers to the unspilt
// location. We need to rebuild the spilt location expression and
// point the DBG_VALUE at the frame register.
DebugExpr = DIExpression::prepend(
DebugInstr->getDebugExpression(), DIExpression::ApplyOffset,
DiffIt.Loc.SpillLocation.SpillOffset);
Reg = TRI->getFrameRegister(*DebugInstr->getMF());
IsIndirect = true;
}
MachineInstr *MI = DiffIt.BuildDbgValue(*MBB.getParent());
MBB.insert(MBB.instr_begin(), MI);

MI = BuildMI(MBB, MBB.instr_begin(), DebugInstr->getDebugLoc(),
DebugInstr->getDesc(), IsIndirect, Reg,
DebugInstr->getDebugVariable(), DebugExpr);
}
(void)MI;
LLVM_DEBUG(dbgs() << "Inserted: "; MI->dump(););
}
Expand Down Expand Up @@ -1381,8 +1409,10 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {

// Add any DBG_VALUE instructions created by location transfers.
for (auto &TR : Transfers) {
auto *MBB = TR.TransferInst->getParent();
MBB->insertAfterBundle(TR.TransferInst->getIterator(), TR.DebugInst);
MachineBasicBlock *MBB = TR.TransferInst->getParent();
const VarLoc &VL = VarLocIDs[TR.LocationID];
MachineInstr *MI = VL.BuildDbgValue(MF);
MBB->insertAfterBundle(TR.TransferInst->getIterator(), MI);
}
Transfers.clear();

Expand Down

0 comments on commit 61800a7

Please sign in to comment.