aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/CodeGen/LiveDebugValues.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/LiveDebugValues.cpp')
-rw-r--r--contrib/llvm/lib/CodeGen/LiveDebugValues.cpp261
1 files changed, 181 insertions, 80 deletions
diff --git a/contrib/llvm/lib/CodeGen/LiveDebugValues.cpp b/contrib/llvm/lib/CodeGen/LiveDebugValues.cpp
index 19ec281079cb..fea83e92de8f 100644
--- a/contrib/llvm/lib/CodeGen/LiveDebugValues.cpp
+++ b/contrib/llvm/lib/CodeGen/LiveDebugValues.cpp
@@ -40,6 +40,8 @@
#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"
#include "llvm/IR/Function.h"
@@ -64,7 +66,7 @@ using namespace llvm;
STATISTIC(NumInserted, "Number of DBG_VALUE instructions inserted");
-// \brief If @MI is a DBG_VALUE with debug value described by a defined
+// 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 unsigned isDbgValueDescribedByReg(const MachineInstr &MI) {
assert(MI.isDebugValue() && "expected a DBG_VALUE");
@@ -81,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
@@ -178,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
@@ -235,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,
@@ -369,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,
@@ -426,28 +482,51 @@ bool LiveDebugValues::isSpillInstruction(const MachineInstr &MI,
FrameInfo.isSpillSlotObjectIndex(FI)))
return false;
- // In a spill instruction generated by the InlineSpiller the spilled register
- // has its kill flag set. Return false if we don't find such a register.
- 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()) {
- if (MO.isReg() && MO.isUse() && MO.isKill()) {
- Reg = MO.getReg();
- break;
+ // 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 Reg != 0;
+ // Return false if we didn't find spilled register.
+ return false;
}
/// 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))
@@ -456,35 +535,49 @@ void LiveDebugValues::transferSpillInst(MachineInstr &MI,
// Check if the register is the location of a debug value.
for (unsigned ID : OpenRanges.getVarLocs()) {
if (VarLocIDs[ID].isDescribedByReg() == Reg) {
- DEBUG(dbgs() << "Spilling Register " << printReg(Reg, TRI) << '('
- << VarLocIDs[ID].Var.getVar()->getName() << ")\n");
-
- // 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);
- DEBUG(dbgs() << "Creating DBG_VALUE inst for spill: ";
- SpDMI->print(dbgs(), false, TII));
-
- // 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);
-
- // End all previous ranges of Var.
- OpenRanges.erase(VarLocIDs[ID].Var);
-
- // Add the VarLoc to OpenRanges.
- VarLoc VL(*SpDMI, LS);
- unsigned SpillLocID = VarLocIDs.insert(VL);
- OpenRanges.insert(SpillLocID, VL.Var);
+ LLVM_DEBUG(dbgs() << "Spilling Register " << printReg(Reg, TRI) << '('
+ << VarLocIDs[ID].Var.getVar()->getName() << ")\n");
+ insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, ID);
+ return;
+ }
+ }
+}
+
+/// 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;
+
+ if (!TII->isCopyInstr(MI, SrcRegOp, DestRegOp) || !SrcRegOp->isKill() ||
+ !DestRegOp->isDef())
+ return;
+
+ auto isCalleSavedReg = [&](unsigned Reg) {
+ for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI)
+ if (CalleeSavedRegs.test(*RAI))
+ return true;
+ return false;
+ };
+
+ 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;
}
}
@@ -497,16 +590,18 @@ bool LiveDebugValues::transferTerminatorInst(MachineInstr &MI,
const VarLocMap &VarLocIDs) {
bool Changed = false;
const MachineBasicBlock *CurMBB = MI.getParent();
- if (!(MI.isTerminator() || (&MI == &CurMBB->instr_back())))
+ if (!(MI.isTerminator() || (&MI == &CurMBB->back())))
return false;
if (OpenRanges.empty())
return false;
- DEBUG(for (unsigned ID : OpenRanges.getVarLocs()) {
- // Copy OpenRanges to OutLocs, if not already present.
- dbgs() << "Add to OutLocs: "; VarLocIDs[ID].dump();
- });
+ LLVM_DEBUG(for (unsigned ID
+ : OpenRanges.getVarLocs()) {
+ // Copy OpenRanges to OutLocs, if not already present.
+ dbgs() << "Add to OutLocs: ";
+ VarLocIDs[ID].dump();
+ });
VarLocSet &VLS = OutLocs[CurMBB];
Changed = VLS |= OpenRanges.getVarLocs();
OpenRanges.clear();
@@ -514,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;
}
@@ -532,7 +629,7 @@ bool LiveDebugValues::transfer(MachineInstr &MI, OpenRangesSet &OpenRanges,
bool LiveDebugValues::join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs,
VarLocInMBB &InLocs, const VarLocMap &VarLocIDs,
SmallPtrSet<const MachineBasicBlock *, 16> &Visited) {
- DEBUG(dbgs() << "join MBB: " << MBB.getName() << "\n");
+ LLVM_DEBUG(dbgs() << "join MBB: " << MBB.getName() << "\n");
bool Changed = false;
VarLocSet InLocsT; // Temporary incoming locations.
@@ -583,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 =
@@ -592,7 +689,7 @@ bool LiveDebugValues::join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs,
DMI->getDebugVariable(), DMI->getDebugExpression());
if (DMI->isIndirectDebugValue())
MI->getOperand(1).setImm(DMI->getOperand(1).getImm());
- DEBUG(dbgs() << "Inserted: "; MI->dump(););
+ LLVM_DEBUG(dbgs() << "Inserted: "; MI->dump(););
ILS.set(ID);
++NumInserted;
Changed = true;
@@ -603,7 +700,7 @@ bool LiveDebugValues::join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs,
/// Calculate the liveness information for the given machine function and
/// extend ranges across basic blocks.
bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
- DEBUG(dbgs() << "\nDebug Range Extension\n");
+ LLVM_DEBUG(dbgs() << "\nDebug Range Extension\n");
bool Changed = false;
bool OLChanged = false;
@@ -613,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;
@@ -624,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
@@ -631,11 +730,11 @@ 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);
- DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "OutLocs after initialization",
- dbgs()));
+ LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
+ "OutLocs after initialization", dbgs()));
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
unsigned int RPONumber = 0;
@@ -646,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;
@@ -655,7 +754,7 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
// thing twice. We could avoid this with a custom priority queue, but this
// is probably not worth it.
SmallPtrSet<MachineBasicBlock *, 16> OnPending;
- DEBUG(dbgs() << "Processing Worklist\n");
+ LLVM_DEBUG(dbgs() << "Processing Worklist\n");
while (!Worklist.empty()) {
MachineBasicBlock *MBB = OrderToBB[Worklist.top()];
Worklist.pop();
@@ -668,19 +767,19 @@ 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();
- DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
- "OutLocs after propagating", dbgs()));
- DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
- "InLocs after propagating", dbgs()));
+ LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
+ "OutLocs after propagating", dbgs()));
+ LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
+ "InLocs after propagating", dbgs()));
if (OLChanged) {
OLChanged = false;
@@ -697,8 +796,8 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
assert(Pending.empty() && "Pending should be empty");
}
- DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "Final OutLocs", dbgs()));
- DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs, "Final InLocs", dbgs()));
+ LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "Final OutLocs", dbgs()));
+ LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs, "Final InLocs", dbgs()));
return Changed;
}
@@ -715,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);