diff options
author | Wolfgang Pieb <Wolfgang.Pieb@sony.com> | 2019-02-04 20:42:45 +0000 |
---|---|---|
committer | Wolfgang Pieb <Wolfgang.Pieb@sony.com> | 2019-02-04 20:42:45 +0000 |
commit | 90d856cd5f4c4bfe415105f6bfc66f05457a334d (patch) | |
tree | 22d5f7196beed92b2db40456b05d30d86d00ed99 /llvm/lib/CodeGen/LiveDebugValues.cpp | |
parent | 690a20467b6684edb49f6f23a594e4649e8626a6 (diff) | |
download | bcm5719-llvm-90d856cd5f4c4bfe415105f6bfc66f05457a334d.tar.gz bcm5719-llvm-90d856cd5f4c4bfe415105f6bfc66f05457a334d.zip |
[DEBUGINFO] Reposting r352642: Handle restore instructions in LiveDebugValues
The LiveDebugValues pass recognizes spills but not restores, which can
cause large gaps in location information for some variables, depending
on control flow. This patch make LiveDebugValues recognize restores and
generate appropriate DBG_VALUE instructions.
This patch was posted previously with r352642 and reverted in r352666 due
to buildbot errors. A missing return statement was the cause for the
failures.
Reviewers: aprantl, NicolaPrica
Differential Revision: https://reviews.llvm.org/D57271
llvm-svn: 353089
Diffstat (limited to 'llvm/lib/CodeGen/LiveDebugValues.cpp')
-rw-r--r-- | llvm/lib/CodeGen/LiveDebugValues.cpp | 211 |
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; |