summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/LiveDebugValues.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/LiveDebugValues.cpp')
-rw-r--r--llvm/lib/CodeGen/LiveDebugValues.cpp211
1 files changed, 152 insertions, 59 deletions
diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp
index 21791a92e74..449f10c7ef7 100644
--- a/llvm/lib/CodeGen/LiveDebugValues.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues.cpp
@@ -34,13 +34,14 @@
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#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/DIBuilder.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
@@ -85,6 +86,8 @@ private:
BitVector CalleeSavedRegs;
LexicalScopes LS;
+ enum struct TransferKind { TransferCopy, TransferSpill, TransferRestore };
+
/// Keeps track of lexical scopes associated with a user value's source
/// location.
class UserValueScopes {
@@ -124,15 +127,30 @@ private:
/// A pair of debug variable and value location.
struct VarLoc {
+ // The location at which a spilled variable resides. It consists of a
+ // register and an offset.
+ struct SpillLoc {
+ unsigned SpillBase;
+ int SpillOffset;
+ bool operator==(const SpillLoc &Other) const {
+ return SpillBase == Other.SpillBase && SpillOffset == Other.SpillOffset;
+ }
+ };
+
const DebugVariable Var;
const MachineInstr &MI; ///< Only used for cloning a new DBG_VALUE.
mutable UserValueScopes UVS;
- enum { InvalidKind = 0, RegisterKind } Kind = InvalidKind;
+ enum VarLocKind {
+ InvalidKind = 0,
+ RegisterKind,
+ SpillLocKind
+ } Kind = InvalidKind;
/// The value location. Stored separately to avoid repeatedly
/// extracting it from MI.
union {
uint64_t RegNo;
+ SpillLoc SpillLocation;
uint64_t Hash;
} Loc;
@@ -149,6 +167,17 @@ private:
}
}
+ /// The constructor for spill locations.
+ VarLoc(const MachineInstr &MI, unsigned SpillBase, int SpillOffset,
+ LexicalScopes &LS)
+ : Var(MI.getDebugVariable(), MI.getDebugLoc()->getInlinedAt()), MI(MI),
+ UVS(MI.getDebugLoc(), LS) {
+ assert(MI.isDebugValue() && "not a DBG_VALUE");
+ assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE");
+ Kind = SpillLocKind;
+ Loc.SpillLocation = {SpillBase, SpillOffset};
+ }
+
/// If this variable is described by a register, return it,
/// otherwise return 0.
unsigned isDescribedByReg() const {
@@ -236,15 +265,23 @@ private:
bool isSpillInstruction(const MachineInstr &MI, MachineFunction *MF,
unsigned &Reg);
- int extractSpillBaseRegAndOffset(const MachineInstr &MI, unsigned &Reg);
+ /// If a given instruction is identified as a spill, return the spill location
+ /// and set \p Reg to the spilled register.
+ Optional<VarLoc::SpillLoc> isRestoreInstruction(const MachineInstr &MI,
+ MachineFunction *MF,
+ unsigned &Reg);
+ /// Given a spill instruction, extract the register and offset used to
+ /// address the spill location in a target independent way.
+ VarLoc::SpillLoc extractSpillBaseRegAndOffset(const MachineInstr &MI);
void insertTransferDebugPair(MachineInstr &MI, OpenRangesSet &OpenRanges,
TransferMap &Transfers, VarLocMap &VarLocIDs,
- unsigned OldVarID, unsigned NewReg = 0);
+ unsigned OldVarID, TransferKind Kind,
+ unsigned NewReg = 0);
void transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs);
- void transferSpillInst(MachineInstr &MI, OpenRangesSet &OpenRanges,
- VarLocMap &VarLocIDs, TransferMap &Transfers);
+ void transferSpillOrRestoreInst(MachineInstr &MI, OpenRangesSet &OpenRanges,
+ VarLocMap &VarLocIDs, TransferMap &Transfers);
void transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs, TransferMap &Transfers);
void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges,
@@ -338,10 +375,8 @@ void LiveDebugValues::printVarLocInMBB(const MachineFunction &MF,
}
#endif
-/// Given a spill instruction, extract the register and offset used to
-/// address the spill location in a target independent way.
-int LiveDebugValues::extractSpillBaseRegAndOffset(const MachineInstr &MI,
- unsigned &Reg) {
+LiveDebugValues::VarLoc::SpillLoc
+LiveDebugValues::extractSpillBaseRegAndOffset(const MachineInstr &MI) {
assert(MI.hasOneMemOperand() &&
"Spill instruction does not have exactly one memory operand?");
auto MMOI = MI.memoperands_begin();
@@ -350,7 +385,9 @@ int LiveDebugValues::extractSpillBaseRegAndOffset(const MachineInstr &MI,
"Inconsistent memory operand in spill instruction");
int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
const MachineBasicBlock *MBB = MI.getParent();
- return TFI->getFrameIndexReference(*MBB->getParent(), FI, Reg);
+ unsigned Reg;
+ int Offset = TFI->getFrameIndexReference(*MBB->getParent(), FI, Reg);
+ return {Reg, Offset};
}
/// End all previous ranges related to @MI and start a new range from @MI
@@ -386,11 +423,28 @@ void LiveDebugValues::transferDebugValue(const MachineInstr &MI,
/// otherwise it is variable's location on the stack.
void LiveDebugValues::insertTransferDebugPair(
MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
- VarLocMap &VarLocIDs, unsigned OldVarID, unsigned NewReg) {
+ VarLocMap &VarLocIDs, unsigned OldVarID, TransferKind Kind,
+ unsigned NewReg) {
const MachineInstr *DMI = &VarLocIDs[OldVarID].MI;
MachineFunction *MF = MI.getParent()->getParent();
MachineInstr *NewDMI;
- if (NewReg) {
+
+ auto ProcessVarLoc = [&MI, &OpenRanges, &Transfers,
+ &VarLocIDs](VarLoc &VL, MachineInstr *NewDMI) {
+ unsigned LocId = VarLocIDs.insert(VL);
+ OpenRanges.insert(LocId, VL.Var);
+ // 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);
+ switch (Kind) {
+ case TransferKind::TransferCopy: {
+ assert(NewReg &&
+ "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.
NewDMI = BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(),
@@ -398,33 +452,43 @@ void LiveDebugValues::insertTransferDebugPair(
DMI->getDebugVariable(), DMI->getDebugExpression());
if (DMI->isIndirectDebugValue())
NewDMI->getOperand(1).setImm(DMI->getOperand(1).getImm());
+ VarLoc VL(*NewDMI, LS);
+ ProcessVarLoc(VL, NewDMI);
LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for register copy: ";
NewDMI->print(dbgs(), false, false, false, TII));
- } else {
+ return;
+ }
+ case TransferKind::TransferSpill: {
// 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);
+ VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI);
+ auto *SpillExpr =
+ DIExpression::prepend(DMI->getDebugExpression(), DIExpression::NoDeref,
+ SpillLocation.SpillOffset);
+ NewDMI =
+ BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), true,
+ SpillLocation.SpillBase, DMI->getDebugVariable(), SpillExpr);
+ VarLoc VL(*NewDMI, SpillLocation.SpillBase, SpillLocation.SpillOffset, LS);
+ ProcessVarLoc(VL, NewDMI);
LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for spill: ";
NewDMI->print(dbgs(), false, false, false, TII));
+ return;
}
-
- // 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);
+ case TransferKind::TransferRestore: {
+ assert(NewReg &&
+ "No register supplied when handling a restore of a debug value");
+ MachineFunction *MF = MI.getMF();
+ DIBuilder DIB(*const_cast<Function &>(MF->getFunction()).getParent());
+ NewDMI = BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), false, NewReg,
+ DMI->getDebugVariable(), DIB.createExpression());
+ VarLoc VL(*NewDMI, LS);
+ ProcessVarLoc(VL, NewDMI);
+ LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for register restore: ";
+ NewDMI->print(dbgs(), false, false, false, TII));
+ return;
+ }
+ }
+ llvm_unreachable("Invalid transfer kind");
}
/// A definition of a register may mark the end of a range.
@@ -470,24 +534,15 @@ void LiveDebugValues::transferRegisterDef(MachineInstr &MI,
/// other spills). We do not handle this yet (more than one memory operand).
bool LiveDebugValues::isSpillInstruction(const MachineInstr &MI,
MachineFunction *MF, unsigned &Reg) {
- const MachineFrameInfo &FrameInfo = MF->getFrameInfo();
- int FI;
SmallVector<const MachineMemOperand*, 1> Accesses;
// TODO: Handle multiple stores folded into one.
if (!MI.hasOneMemOperand())
return false;
- // To identify a spill instruction, use the same criteria as in AsmPrinter.
- if (!((TII->isStoreToStackSlotPostFE(MI, FI) &&
- FrameInfo.isSpillSlotObjectIndex(FI)) ||
- (TII->hasStoreToStackSlot(MI, Accesses) &&
- llvm::any_of(Accesses, [&FrameInfo](const MachineMemOperand *MMO) {
- return FrameInfo.isSpillSlotObjectIndex(
- cast<FixedStackPseudoSourceValue>(MMO->getPseudoValue())
- ->getFrameIndex());
- }))))
- return false;
+ if (!MI.getSpillSize(TII) && !MI.getFoldedSpillSize(TII))
+ return false; // This is not a spill instruction, since no valid size was
+ // returned from either function.
auto isKilledReg = [&](const MachineOperand MO, unsigned &Reg) {
if (!MO.isReg() || !MO.isUse()) {
@@ -524,29 +579,67 @@ bool LiveDebugValues::isSpillInstruction(const MachineInstr &MI,
return false;
}
+Optional<LiveDebugValues::VarLoc::SpillLoc>
+LiveDebugValues::isRestoreInstruction(const MachineInstr &MI,
+ MachineFunction *MF, unsigned &Reg) {
+ if (!MI.hasOneMemOperand())
+ return None;
+
+ // FIXME: Handle folded restore instructions with more than one memory
+ // operand.
+ if (MI.getRestoreSize(TII)) {
+ Reg = MI.getOperand(0).getReg();
+ return extractSpillBaseRegAndOffset(MI);
+ }
+ return None;
+}
+
/// 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.
+/// A restored register may indicate the reverse situation.
/// 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,
- TransferMap &Transfers) {
- unsigned Reg;
+void LiveDebugValues::transferSpillOrRestoreInst(MachineInstr &MI,
+ OpenRangesSet &OpenRanges,
+ VarLocMap &VarLocIDs,
+ TransferMap &Transfers) {
MachineFunction *MF = MI.getMF();
- if (!isSpillInstruction(MI, MF, Reg))
- return;
+ TransferKind TKind;
+ unsigned Reg;
+ Optional<VarLoc::SpillLoc> Loc;
- // Check if the register is the location of a debug value.
+ LLVM_DEBUG(dbgs() << "Examining instruction: "; MI.dump(););
+
+ if (isSpillInstruction(MI, MF, Reg)) {
+ TKind = TransferKind::TransferSpill;
+ LLVM_DEBUG(dbgs() << "Recognized as spill: "; MI.dump(););
+ LLVM_DEBUG(dbgs() << "Register: " << Reg << " " << printReg(Reg, TRI)
+ << "\n");
+ } else {
+ if (!(Loc = isRestoreInstruction(MI, MF, Reg)))
+ return;
+ TKind = TransferKind::TransferRestore;
+ LLVM_DEBUG(dbgs() << "Recognized as restore: "; MI.dump(););
+ LLVM_DEBUG(dbgs() << "Register: " << Reg << " " << printReg(Reg, TRI)
+ << "\n");
+ }
+ // Check if the register or spill location is the location of a debug value.
for (unsigned ID : OpenRanges.getVarLocs()) {
- if (VarLocIDs[ID].isDescribedByReg() == Reg) {
+ if (TKind == TransferKind::TransferSpill &&
+ 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;
- }
+ } else if (TKind == TransferKind::TransferRestore &&
+ VarLocIDs[ID].Loc.SpillLocation == *Loc) {
+ LLVM_DEBUG(dbgs() << "Restoring Register " << printReg(Reg, TRI) << '('
+ << VarLocIDs[ID].Var.getVar()->getName() << ")\n");
+ } else
+ continue;
+ insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, ID, TKind,
+ Reg);
+ return;
}
}
@@ -584,7 +677,7 @@ void LiveDebugValues::transferRegisterCopy(MachineInstr &MI,
for (unsigned ID : OpenRanges.getVarLocs()) {
if (VarLocIDs[ID].isDescribedByReg() == SrcReg) {
insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, ID,
- DestReg);
+ TransferKind::TransferCopy, DestReg);
return;
}
}
@@ -624,7 +717,7 @@ bool LiveDebugValues::process(MachineInstr &MI, OpenRangesSet &OpenRanges,
transferRegisterDef(MI, OpenRanges, VarLocIDs);
if (transferChanges) {
transferRegisterCopy(MI, OpenRanges, VarLocIDs, Transfers);
- transferSpillInst(MI, OpenRanges, VarLocIDs, Transfers);
+ transferSpillOrRestoreInst(MI, OpenRanges, VarLocIDs, Transfers);
}
Changed = transferTerminatorInst(MI, OpenRanges, OutLocs, VarLocIDs);
return Changed;
OpenPOWER on IntegriCloud