[LiveDebugValues] Tracking copying value between registers

During the execution of long functions or functions that have a lot of
inlined code it could come to the situation where tracked value could be
transferred from one register to another. The transfer is recognized only if
destination register is a callee saved register and if source register is
killed. We do not salvage caller-saved registers since there is a great
chance that killed register would outlive it.

Patch by Nikola Prica.

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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336978 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Petar Jovanovic
2018-07-13 08:24:26 +00:00
parent 1b59f048c7
commit b76c453971
4 changed files with 702 additions and 49 deletions
+124 -49
View File
@@ -40,6 +40,7 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
@@ -82,6 +83,7 @@ private:
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
const TargetFrameLowering *TFI;
BitVector CalleeSavedRegs;
LexicalScopes LS;
/// Keeps track of lexical scopes associated with a user value's source
@@ -179,11 +181,11 @@ private:
using VarLocMap = UniqueVector<VarLoc>;
using VarLocSet = SparseBitVector<>;
using VarLocInMBB = SmallDenseMap<const MachineBasicBlock *, VarLocSet>;
struct SpillDebugPair {
MachineInstr *SpillInst;
struct TransferDebugPair {
MachineInstr *TransferInst;
MachineInstr *DebugInst;
};
using SpillMap = SmallVector<SpillDebugPair, 4>;
using TransferMap = SmallVector<TransferDebugPair, 4>;
/// 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
@@ -236,18 +238,23 @@ private:
bool isSpillInstruction(const MachineInstr &MI, MachineFunction *MF,
unsigned &Reg);
int extractSpillBaseRegAndOffset(const MachineInstr &MI, unsigned &Reg);
void insertTransferDebugPair(MachineInstr &MI, OpenRangesSet &OpenRanges,
TransferMap &Transfers, VarLocMap &VarLocIDs,
unsigned OldVarID, unsigned NewReg = 0);
void transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs);
void transferSpillInst(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs, SpillMap &Spills);
VarLocMap &VarLocIDs, TransferMap &Transfers);
void transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs, TransferMap &Transfers);
void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges,
const VarLocMap &VarLocIDs);
bool transferTerminatorInst(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs);
bool transfer(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocInMBB &OutLocs, VarLocMap &VarLocIDs, SpillMap &Spills,
bool transferSpills);
bool process(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocInMBB &OutLocs, VarLocMap &VarLocIDs,
TransferMap &Transfers, bool transferChanges);
bool join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
const VarLocMap &VarLocIDs,
@@ -370,6 +377,54 @@ void LiveDebugValues::transferDebugValue(const MachineInstr &MI,
}
}
/// Create new TransferDebugPair and insert it in \p Transfers. The VarLoc
/// with \p OldVarID should be deleted form \p OpenRanges and replaced with
/// new VarLoc. If \p NewReg is different than default zero value then the
/// new location will be register location created by the copy like instruction,
/// otherwise it is variable's location on the stack.
void LiveDebugValues::insertTransferDebugPair(
MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
VarLocMap &VarLocIDs, unsigned OldVarID, unsigned NewReg) {
const MachineInstr *DMI = &VarLocIDs[OldVarID].MI;
MachineFunction *MF = MI.getParent()->getParent();
MachineInstr *NewDMI;
if (NewReg) {
// Create a DBG_VALUE instruction to describe the Var in its new
// register location.
NewDMI = BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(),
DMI->isIndirectDebugValue(), NewReg,
DMI->getDebugVariable(), DMI->getDebugExpression());
if (DMI->isIndirectDebugValue())
NewDMI->getOperand(1).setImm(DMI->getOperand(1).getImm());
LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for register copy: ";
NewDMI->print(dbgs(), false, false, false, TII));
} else {
// Create a DBG_VALUE instruction to describe the Var in its spilled
// location.
unsigned SpillBase;
int SpillOffset = extractSpillBaseRegAndOffset(MI, SpillBase);
auto *SpillExpr = DIExpression::prepend(DMI->getDebugExpression(),
DIExpression::NoDeref, SpillOffset);
NewDMI = BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), true, SpillBase,
DMI->getDebugVariable(), SpillExpr);
LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for spill: ";
NewDMI->print(dbgs(), false, false, false, TII));
}
// The newly created DBG_VALUE instruction NewDMI must be inserted after
// MI. Keep track of the pairing.
TransferDebugPair MIP = {&MI, NewDMI};
Transfers.push_back(MIP);
// End all previous ranges of Var.
OpenRanges.erase(VarLocIDs[OldVarID].Var);
// Add the VarLoc to OpenRanges.
VarLoc VL(*NewDMI, LS);
unsigned LocID = VarLocIDs.insert(VL);
OpenRanges.insert(LocID, VL.Var);
}
/// A definition of a register may mark the end of a range.
void LiveDebugValues::transferRegisterDef(MachineInstr &MI,
OpenRangesSet &OpenRanges,
@@ -464,14 +519,14 @@ bool LiveDebugValues::isSpillInstruction(const MachineInstr &MI,
/// A spilled register may indicate that we have to end the current range of
/// a variable and create a new one for the spill location.
/// We don't want to insert any instructions in transfer(), so we just create
/// the DBG_VALUE witout inserting it and keep track of it in @Spills.
/// We don't want to insert any instructions in process(), so we just create
/// the DBG_VALUE without inserting it and keep track of it in \p Transfers.
/// It will be inserted into the BB when we're done iterating over the
/// instructions.
void LiveDebugValues::transferSpillInst(MachineInstr &MI,
OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs,
SpillMap &Spills) {
TransferMap &Transfers) {
unsigned Reg;
MachineFunction *MF = MI.getMF();
if (!isSpillInstruction(MI, MF, Reg))
@@ -482,33 +537,47 @@ void LiveDebugValues::transferSpillInst(MachineInstr &MI,
if (VarLocIDs[ID].isDescribedByReg() == Reg) {
LLVM_DEBUG(dbgs() << "Spilling Register " << printReg(Reg, TRI) << '('
<< VarLocIDs[ID].Var.getVar()->getName() << ")\n");
insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, ID);
return;
}
}
}
// Create a DBG_VALUE instruction to describe the Var in its spilled
// location, but don't insert it yet to avoid invalidating the
// iterator in our caller.
unsigned SpillBase;
int SpillOffset = extractSpillBaseRegAndOffset(MI, SpillBase);
const MachineInstr *DMI = &VarLocIDs[ID].MI;
auto *SpillExpr = DIExpression::prepend(
DMI->getDebugExpression(), DIExpression::NoDeref, SpillOffset);
MachineInstr *SpDMI =
BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), true, SpillBase,
DMI->getDebugVariable(), SpillExpr);
LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for spill: ";
SpDMI->print(dbgs(), false, TII));
/// If \p MI is a register copy instruction, that copies a previously tracked
/// value from one register to another register that is callee saved, we
/// create new DBG_VALUE instruction described with copy destination register.
void LiveDebugValues::transferRegisterCopy(MachineInstr &MI,
OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs,
TransferMap &Transfers) {
const MachineOperand *SrcRegOp, *DestRegOp;
// The newly created DBG_VALUE instruction SpDMI must be inserted after
// MI. Keep track of the pairing.
SpillDebugPair MIP = {&MI, SpDMI};
Spills.push_back(MIP);
if (!TII->isCopyInstr(MI, SrcRegOp, DestRegOp) || !SrcRegOp->isKill() ||
!DestRegOp->isDef())
return;
// End all previous ranges of Var.
OpenRanges.erase(VarLocIDs[ID].Var);
auto isCalleSavedReg = [&](unsigned Reg) {
for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI)
if (CalleeSavedRegs.test(*RAI))
return true;
return false;
};
// Add the VarLoc to OpenRanges.
VarLoc VL(*SpDMI, LS);
unsigned SpillLocID = VarLocIDs.insert(VL);
OpenRanges.insert(SpillLocID, VL.Var);
unsigned SrcReg = SrcRegOp->getReg();
unsigned DestReg = DestRegOp->getReg();
// We want to recognize instructions where destination register is callee
// saved register. If register that could be clobbered by the call is
// included, there would be a great chance that it is going to be clobbered
// soon. It is more likely that previous register location, which is callee
// saved, is going to stay unclobbered longer, even if it is killed.
if (!isCalleSavedReg(DestReg))
return;
for (unsigned ID : OpenRanges.getVarLocs()) {
if (VarLocIDs[ID].isDescribedByReg() == SrcReg) {
insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, ID,
DestReg);
return;
}
}
@@ -540,14 +609,16 @@ bool LiveDebugValues::transferTerminatorInst(MachineInstr &MI,
}
/// This routine creates OpenRanges and OutLocs.
bool LiveDebugValues::transfer(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocInMBB &OutLocs, VarLocMap &VarLocIDs,
SpillMap &Spills, bool transferSpills) {
bool LiveDebugValues::process(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocInMBB &OutLocs, VarLocMap &VarLocIDs,
TransferMap &Transfers, bool transferChanges) {
bool Changed = false;
transferDebugValue(MI, OpenRanges, VarLocIDs);
transferRegisterDef(MI, OpenRanges, VarLocIDs);
if (transferSpills)
transferSpillInst(MI, OpenRanges, VarLocIDs, Spills);
if (transferChanges) {
transferRegisterCopy(MI, OpenRanges, VarLocIDs, Transfers);
transferSpillInst(MI, OpenRanges, VarLocIDs, Transfers);
}
Changed = transferTerminatorInst(MI, OpenRanges, OutLocs, VarLocIDs);
return Changed;
}
@@ -609,7 +680,7 @@ bool LiveDebugValues::join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs,
for (auto ID : Diff) {
// This VarLoc is not found in InLocs i.e. it is not yet inserted. So, a
// new range is started for the var from the mbb's beginning by inserting
// a new DBG_VALUE. transfer() will end this range however appropriate.
// a new DBG_VALUE. process() will end this range however appropriate.
const VarLoc &DiffIt = VarLocIDs[ID];
const MachineInstr *DMI = &DiffIt.MI;
MachineInstr *MI =
@@ -639,7 +710,7 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
OpenRangesSet OpenRanges; // Ranges that are open until end of bb.
VarLocInMBB OutLocs; // Ranges that exist beyond bb.
VarLocInMBB InLocs; // Ranges that are incoming after joining.
SpillMap Spills; // DBG_VALUEs associated with spills.
TransferMap Transfers; // DBG_VALUEs associated with spills.
DenseMap<unsigned int, MachineBasicBlock *> OrderToBB;
DenseMap<MachineBasicBlock *, unsigned int> BBToOrder;
@@ -650,6 +721,8 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
std::greater<unsigned int>>
Pending;
enum : bool { dontTransferChanges = false, transferChanges = true };
// Initialize every mbb with OutLocs.
// We are not looking at any spill instructions during the initial pass
// over the BBs. The LiveDebugVariables pass has already created DBG_VALUE
@@ -657,8 +730,8 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
// within the BB in which the spill occurs.
for (auto &MBB : MF)
for (auto &MI : MBB)
transfer(MI, OpenRanges, OutLocs, VarLocIDs, Spills,
/*transferSpills=*/false);
process(MI, OpenRanges, OutLocs, VarLocIDs, Transfers,
dontTransferChanges);
LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"OutLocs after initialization", dbgs()));
@@ -672,7 +745,7 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
++RPONumber;
}
// This is a standard "union of predecessor outs" dataflow problem.
// To solve it, we perform join() and transfer() using the two worklist method
// To solve it, we perform join() and process() using the two worklist method
// until the ranges converge.
// Ranges have converged when both worklists are empty.
SmallPtrSet<const MachineBasicBlock *, 16> Visited;
@@ -694,14 +767,14 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
// examine spill instructions to see whether they spill registers that
// correspond to user variables.
for (auto &MI : *MBB)
OLChanged |= transfer(MI, OpenRanges, OutLocs, VarLocIDs, Spills,
/*transferSpills=*/true);
OLChanged |= process(MI, OpenRanges, OutLocs, VarLocIDs, Transfers,
transferChanges);
// Add any DBG_VALUE instructions necessitated by spills.
for (auto &SP : Spills)
MBB->insertAfter(MachineBasicBlock::iterator(*SP.SpillInst),
SP.DebugInst);
Spills.clear();
for (auto &TR : Transfers)
MBB->insertAfter(MachineBasicBlock::iterator(*TR.TransferInst),
TR.DebugInst);
Transfers.clear();
LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"OutLocs after propagating", dbgs()));
@@ -741,6 +814,8 @@ bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) {
TRI = MF.getSubtarget().getRegisterInfo();
TII = MF.getSubtarget().getInstrInfo();
TFI = MF.getSubtarget().getFrameLowering();
TFI->determineCalleeSaves(MF, CalleeSavedRegs,
make_unique<RegScavenger>().get());
LS.initialize(MF);
bool Changed = ExtendRanges(MF);