summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorDjordje Todorovic <djordje.todorovic@rt-rk.com>2019-11-21 11:07:39 +0100
committerDjordje Todorovic <djordje.todorovic@rt-rk.com>2019-12-03 11:01:45 +0100
commit4cfceb910692f9e894622da1b394324503667e46 (patch)
tree695ffafb2543d29dcba719f53f08faa89187ec05 /llvm/lib/CodeGen
parent6d18e5366c9a0bffe45b179a830483b3f2ec9fa9 (diff)
downloadbcm5719-llvm-4cfceb910692f9e894622da1b394324503667e46.tar.gz
bcm5719-llvm-4cfceb910692f9e894622da1b394324503667e46.zip
[LiveDebugValues] Introduce entry values of unmodified params
The idea is to remove front-end analysis for the parameter's value modification and leave it to the value tracking system. Front-end in some cases marks a parameter as modified even the line of code that modifies the parameter gets optimized, that implies that this will cover more entry values even. In addition, extending the support for modified parameters will be easier with this approach. Since the goal is to recognize if a parameter’s value has changed, the idea at very high level is: If we encounter a DBG_VALUE other than the entry value one describing the same variable (parameter), we can assume that the variable’s value has changed and we should not track its entry value any more. That would be ideal scenario, but due to various LLVM optimizations, a variable’s value could be just moved around from one register to another (and there will be additional DBG_VALUEs describing the same variable), so we have to recognize such situation (otherwise, we will lose a lot of entry values) and salvage the debug entry value. Differential Revision: https://reviews.llvm.org/D68209
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/LiveDebugValues.cpp379
1 files changed, 301 insertions, 78 deletions
diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp
index 7734f5e5ef7..1da3ee7adcd 100644
--- a/llvm/lib/CodeGen/LiveDebugValues.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues.cpp
@@ -226,7 +226,9 @@ private:
RegisterKind,
SpillLocKind,
ImmediateKind,
- EntryValueKind
+ EntryValueKind,
+ EntryValueBackupKind,
+ EntryValueCopyBackupKind
} Kind = InvalidKind;
/// The value location. Stored separately to avoid repeatedly
@@ -248,7 +250,7 @@ private:
assert(MI.isDebugValue() && "not a DBG_VALUE");
assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE");
if (int RegNo = isDbgValueDescribedByReg(MI)) {
- Kind = MI.isDebugEntryValue() ? EntryValueKind : RegisterKind;
+ Kind = RegisterKind;
Loc.RegNo = RegNo;
} else if (MI.getOperand(0).isImm()) {
Kind = ImmediateKind;
@@ -260,17 +262,50 @@ private:
Kind = ImmediateKind;
Loc.CImm = MI.getOperand(0).getCImm();
}
- assert((Kind != ImmediateKind || !MI.isDebugEntryValue()) &&
- "entry values must be register locations");
+
+ // We create the debug entry values from the factory functions rather than
+ // from this ctor.
+ assert(Kind != EntryValueKind && !isEntryBackupLoc());
}
/// 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) {
+ const DIExpression *EntryExpr, unsigned Reg) {
VarLoc VL(MI, LS);
+ assert(VL.Kind == RegisterKind);
VL.Kind = EntryValueKind;
VL.Expr = EntryExpr;
+ VL.Loc.RegNo = Reg;
+ return VL;
+ }
+
+ /// Take the variable and machine-location from the DBG_VALUE (from the
+ /// function entry), and build an entry value backup location. The backup
+ /// location will turn into the normal location if the backup is valid at
+ /// the time of the primary location clobbering.
+ static VarLoc CreateEntryBackupLoc(const MachineInstr &MI,
+ LexicalScopes &LS,
+ const DIExpression *EntryExpr) {
+ VarLoc VL(MI, LS);
+ assert(VL.Kind == RegisterKind);
+ VL.Kind = EntryValueBackupKind;
+ VL.Expr = EntryExpr;
+ return VL;
+ }
+
+ /// Take the variable and machine-location from the DBG_VALUE (from the
+ /// function entry), and build a copy of an entry value backup location by
+ /// setting the register location to NewReg.
+ static VarLoc CreateEntryCopyBackupLoc(const MachineInstr &MI,
+ LexicalScopes &LS,
+ const DIExpression *EntryExpr,
+ unsigned NewReg) {
+ VarLoc VL(MI, LS);
+ assert(VL.Kind == RegisterKind);
+ VL.Kind = EntryValueCopyBackupKind;
+ VL.Expr = EntryExpr;
+ VL.Loc.RegNo = NewReg;
return VL;
}
@@ -309,8 +344,11 @@ private:
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);
+ // expression. The register location of such DBG_VALUE is always the one
+ // from the entry DBG_VALUE, it does not matter if the entry value was
+ // copied in to another register due to some optimizations.
+ return BuildMI(MF, DbgLoc, IID, Indirect, MI.getOperand(0).getReg(),
+ Var, Expr);
case RegisterKind:
// Register locations are like the source DBG_VALUE, but with the
// register number from this VarLoc.
@@ -329,8 +367,11 @@ private:
MachineOperand MO = MI.getOperand(0);
return BuildMI(MF, DbgLoc, IID, Indirect, MO, Var, DIExpr);
}
+ case EntryValueBackupKind:
+ case EntryValueCopyBackupKind:
case InvalidKind:
- llvm_unreachable("Tried to produce DBG_VALUE for invalid VarLoc");
+ llvm_unreachable(
+ "Tried to produce DBG_VALUE for invalid or backup VarLoc");
}
llvm_unreachable("Unrecognized LiveDebugValues.VarLoc.Kind enum");
}
@@ -338,6 +379,27 @@ private:
/// Is the Loc field a constant or constant object?
bool isConstant() const { return Kind == ImmediateKind; }
+ /// Check if the Loc field is an entry backup location.
+ bool isEntryBackupLoc() const {
+ return Kind == EntryValueBackupKind || Kind == EntryValueCopyBackupKind;
+ }
+
+ /// If this variable is described by a register holding the entry value,
+ /// return it, otherwise return 0.
+ unsigned getEntryValueBackupReg() const {
+ if (Kind == EntryValueBackupKind)
+ return Loc.RegNo;
+ return 0;
+ }
+
+ /// If this variable is described by a register holding the copy of the
+ /// entry value, return it, otherwise return 0.
+ unsigned getEntryValueCopyBackupReg() const {
+ if (Kind == EntryValueCopyBackupKind)
+ return Loc.RegNo;
+ return 0;
+ }
+
/// If this variable is described by a register, return it,
/// otherwise return 0.
unsigned isDescribedByReg() const {
@@ -357,6 +419,8 @@ private:
switch (Kind) {
case RegisterKind:
case EntryValueKind:
+ case EntryValueBackupKind:
+ case EntryValueCopyBackupKind:
dbgs() << printReg(Loc.RegNo, TRI);
break;
case SpillLocKind:
@@ -374,7 +438,12 @@ private:
if (Var.getInlinedAt())
dbgs() << "!" << Var.getInlinedAt()->getMetadataID() << ")\n";
else
- dbgs() << "(null))\n";
+ dbgs() << "(null))";
+
+ if (isEntryBackupLoc())
+ dbgs() << " (backup loc)\n";
+ else
+ dbgs() << "\n";
}
#endif
@@ -390,7 +459,6 @@ private:
}
};
- using DebugParamMap = SmallDenseMap<const DILocalVariable *, MachineInstr *>;
using VarLocMap = UniqueVector<VarLoc>;
using VarLocSet = SparseBitVector<>;
using VarLocInMBB = SmallDenseMap<const MachineBasicBlock *, VarLocSet>;
@@ -416,10 +484,18 @@ private:
/// 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
/// DebugVariable to recent VarLocID. Note that a DBG_VALUE ends all
- /// previous open ranges for the same variable.
+ /// previous open ranges for the same variable. In addition, we keep
+ /// two different maps (Vars/EntryValuesBackupVars), so erase/insert
+ /// methods act differently depending on whether a VarLoc is primary
+ /// location or backup one. In the case the VarLoc is backup location
+ /// we will erase/insert from the EntryValuesBackupVars map, otherwise
+ /// we perform the operation on the Vars.
class OpenRangesSet {
VarLocSet VarLocs;
+ // Map the DebugVariable to recent primary location ID.
SmallDenseMap<DebugVariable, unsigned, 8> Vars;
+ // Map the DebugVariable to recent backup location ID.
+ SmallDenseMap<DebugVariable, unsigned, 8> EntryValuesBackupVars;
OverlapMap &OverlappingFragments;
public:
@@ -427,40 +503,38 @@ private:
const VarLocSet &getVarLocs() const { return VarLocs; }
- /// Terminate all open ranges for Var by removing it from the set.
- void erase(DebugVariable Var);
+ /// Terminate all open ranges for VL.Var by removing it from the set.
+ void erase(const VarLoc &VL);
/// Terminate all open ranges listed in \c KillSet by removing
/// them from the set.
- void erase(const VarLocSet &KillSet, const VarLocMap &VarLocIDs) {
- VarLocs.intersectWithComplement(KillSet);
- for (unsigned ID : KillSet)
- Vars.erase(VarLocIDs[ID].Var);
- }
+ void erase(const VarLocSet &KillSet, const VarLocMap &VarLocIDs);
/// Insert a new range into the set.
- void insert(unsigned VarLocID, DebugVariable Var) {
- VarLocs.set(VarLocID);
- Vars.insert({Var, VarLocID});
- }
+ void insert(unsigned VarLocID, const VarLoc &VL);
/// Insert a set of ranges.
void insertFromLocSet(const VarLocSet &ToLoad, const VarLocMap &Map) {
for (unsigned Id : ToLoad) {
- const VarLoc &Var = Map[Id];
- insert(Id, Var.Var);
+ const VarLoc &VarL = Map[Id];
+ insert(Id, VarL);
}
}
+ llvm::Optional<unsigned> getEntryValueBackup(DebugVariable Var);
+
/// Empty the set.
void clear() {
VarLocs.clear();
Vars.clear();
+ EntryValuesBackupVars.clear();
}
/// Return whether the set is empty or not.
bool empty() const {
- assert(Vars.empty() == VarLocs.empty() && "open ranges are inconsistent");
+ assert(Vars.empty() == EntryValuesBackupVars.empty() &&
+ Vars.empty() == VarLocs.empty() &&
+ "open ranges are inconsistent");
return VarLocs.empty();
}
};
@@ -502,21 +576,23 @@ private:
VarLocMap &VarLocIDs);
void transferSpillOrRestoreInst(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs, TransferMap &Transfers);
+ bool removeEntryValue(const MachineInstr &MI, OpenRangesSet &OpenRanges,
+ VarLocMap &VarLocIDs, const VarLoc &EntryVL);
void emitEntryValues(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs, TransferMap &Transfers,
- DebugParamMap &DebugEntryVals,
SparseBitVector<> &KillSet);
+ void recordEntryValue(const MachineInstr &MI,
+ const DefinedRegsSet &DefinedRegs,
+ OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs);
void transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs, TransferMap &Transfers);
void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges,
- VarLocMap &VarLocIDs, TransferMap &Transfers,
- DebugParamMap &DebugEntryVals);
+ VarLocMap &VarLocIDs, TransferMap &Transfers);
bool transferTerminator(MachineBasicBlock *MBB, OpenRangesSet &OpenRanges,
VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs);
void process(MachineInstr &MI, OpenRangesSet &OpenRanges,
- VarLocMap &VarLocIDs, TransferMap &Transfers,
- DebugParamMap &DebugEntryVals);
+ VarLocMap &VarLocIDs, TransferMap &Transfers);
void accumulateFragmentMap(MachineInstr &MI, VarToFragments &SeenFragments,
OverlapMap &OLapMap);
@@ -619,18 +695,24 @@ void LiveDebugValues::getAnalysisUsage(AnalysisUsage &AU) const {
}
/// Erase a variable from the set of open ranges, and additionally erase any
-/// fragments that may overlap it.
-void LiveDebugValues::OpenRangesSet::erase(DebugVariable Var) {
+/// fragments that may overlap it. If the VarLoc is a buckup location, erase
+/// the variable from the EntryValuesBackupVars set, indicating we should stop
+/// tracking its backup entry location. Otherwise, if the VarLoc is primary
+/// location, erase the variable from the Vars set.
+void LiveDebugValues::OpenRangesSet::erase(const VarLoc &VL) {
// Erasure helper.
- auto DoErase = [this](DebugVariable VarToErase) {
- auto It = Vars.find(VarToErase);
- if (It != Vars.end()) {
+ auto DoErase = [VL, this](DebugVariable VarToErase) {
+ auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
+ auto It = EraseFrom->find(VarToErase);
+ if (It != EraseFrom->end()) {
unsigned ID = It->second;
VarLocs.reset(ID);
- Vars.erase(It);
+ EraseFrom->erase(It);
}
};
+ DebugVariable Var = VL.Var;
+
// Erase the variable/fragment that ends here.
DoErase(Var);
@@ -651,6 +733,34 @@ void LiveDebugValues::OpenRangesSet::erase(DebugVariable Var) {
}
}
+void LiveDebugValues::OpenRangesSet::erase(const VarLocSet &KillSet,
+ const VarLocMap &VarLocIDs) {
+ VarLocs.intersectWithComplement(KillSet);
+ for (unsigned ID : KillSet) {
+ const VarLoc *VL = &VarLocIDs[ID];
+ auto *EraseFrom = VL->isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
+ EraseFrom->erase(VL->Var);
+ }
+}
+
+void LiveDebugValues::OpenRangesSet::insert(unsigned VarLocID,
+ const VarLoc &VL) {
+ auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
+ VarLocs.set(VarLocID);
+ InsertInto->insert({VL.Var, VarLocID});
+}
+
+/// Return the Loc ID of an entry value backup location, if it exists for the
+/// variable.
+llvm::Optional<unsigned>
+LiveDebugValues::OpenRangesSet::getEntryValueBackup(DebugVariable Var) {
+ auto It = EntryValuesBackupVars.find(Var);
+ if (It != EntryValuesBackupVars.end())
+ return It->second;
+
+ return llvm::None;
+}
+
//===----------------------------------------------------------------------===//
// Debug Range Extension Implementation
//===----------------------------------------------------------------------===//
@@ -693,6 +803,62 @@ LiveDebugValues::extractSpillBaseRegAndOffset(const MachineInstr &MI) {
return {Reg, Offset};
}
+/// Try to salvage the debug entry value if we encounter a new debug value
+/// describing the same parameter, otherwise stop tracking the value. Return
+/// true if we should stop tracking the entry value, otherwise return false.
+bool LiveDebugValues::removeEntryValue(const MachineInstr &MI,
+ OpenRangesSet &OpenRanges,
+ VarLocMap &VarLocIDs,
+ const VarLoc &EntryVL) {
+ // Skip the DBG_VALUE which is the debug entry value itself.
+ if (MI.isIdenticalTo(EntryVL.MI))
+ return false;
+
+ // If the parameter's location is not register location, we can not track
+ // the entry value any more. In addition, if the debug expression from the
+ // DBG_VALUE is not empty, we can assume the parameter's value has changed
+ // indicating that we should stop tracking its entry value as well.
+ if (!MI.getOperand(0).isReg() ||
+ MI.getDebugExpression()->getNumElements() != 0)
+ return true;
+
+ // If the DBG_VALUE comes from a copy instruction that copies the entry value,
+ // it means the parameter's value has not changed and we should be able to use
+ // its entry value.
+ bool TrySalvageEntryValue = false;
+ Register Reg = MI.getOperand(0).getReg();
+ auto I = std::next(MI.getReverseIterator());
+ const MachineOperand *SrcRegOp, *DestRegOp;
+ if (I != MI.getParent()->rend()) {
+ // TODO: Try to keep tracking of an entry value if we encounter a propagated
+ // DBG_VALUE describing the copy of the entry value. (Propagated entry value
+ // does not indicate the parameter modification.)
+ auto DestSrc = TII->isCopyInstr(*I);
+ if (!DestSrc)
+ return true;
+
+ SrcRegOp = DestSrc->Source;
+ DestRegOp = DestSrc->Destination;
+ if (Reg != DestRegOp->getReg())
+ return true;
+ TrySalvageEntryValue = true;
+ }
+
+ if (TrySalvageEntryValue) {
+ for (unsigned ID : OpenRanges.getVarLocs()) {
+ const VarLoc &VL = VarLocIDs[ID];
+ if (!VL.isEntryBackupLoc())
+ continue;
+
+ if (VL.getEntryValueCopyBackupReg() == Reg &&
+ VL.MI.getOperand(0).getReg() == SrcRegOp->getReg())
+ return false;
+ }
+ }
+
+ return true;
+}
+
/// End all previous ranges related to @MI and start a new range from @MI
/// if it is a DBG_VALUE instr.
void LiveDebugValues::transferDebugValue(const MachineInstr &MI,
@@ -707,18 +873,33 @@ void LiveDebugValues::transferDebugValue(const MachineInstr &MI,
assert(Var->isValidLocationForIntrinsic(DebugLoc) &&
"Expected inlined-at fields to agree");
- // End all previous ranges of Var.
DebugVariable V(Var, Expr, InlinedAt);
- OpenRanges.erase(V);
- // Add the VarLoc to OpenRanges from this DBG_VALUE.
+ // Check if this DBG_VALUE indicates a parameter's value changing.
+ // If that is the case, we should stop tracking its entry value.
+ auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);
+ if (Var->isParameter() && EntryValBackupID) {
+ const VarLoc &EntryVL = VarLocIDs[*EntryValBackupID];
+ if (removeEntryValue(MI, OpenRanges, VarLocIDs, EntryVL)) {
+ LLVM_DEBUG(dbgs() << "Deleting a DBG entry value because of: ";
+ MI.print(dbgs(), /*IsStandalone*/ false,
+ /*SkipOpers*/ false, /*SkipDebugLoc*/ false,
+ /*AddNewLine*/ true, TII));
+ OpenRanges.erase(EntryVL);
+ }
+ }
+
unsigned ID;
if (isDbgValueDescribedByReg(MI) || MI.getOperand(0).isImm() ||
MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm()) {
// Use normal VarLoc constructor for registers and immediates.
VarLoc VL(MI, LS);
+ // End all previous ranges of VL.Var.
+ OpenRanges.erase(VL);
+
ID = VarLocIDs.insert(VL);
- OpenRanges.insert(ID, VL.Var);
+ // Add the VarLoc to OpenRanges from this DBG_VALUE.
+ OpenRanges.insert(ID, VL);
} else if (MI.hasOneMemOperand()) {
llvm_unreachable("DBG_VALUE with mem operand encountered after regalloc?");
} else {
@@ -728,32 +909,30 @@ void LiveDebugValues::transferDebugValue(const MachineInstr &MI,
}
}
+/// Turn the entry value backup locations into primary locations.
void LiveDebugValues::emitEntryValues(MachineInstr &MI,
OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs,
TransferMap &Transfers,
- DebugParamMap &DebugEntryVals,
SparseBitVector<> &KillSet) {
for (unsigned ID : KillSet) {
if (!VarLocIDs[ID].Var.getVar()->isParameter())
continue;
- const MachineInstr *CurrDebugInstr = &VarLocIDs[ID].MI;
+ auto DebugVar = VarLocIDs[ID].Var;
+ auto EntryValBackupID = OpenRanges.getEntryValueBackup(DebugVar);
- // If parameter's DBG_VALUE is not in the map that means we can't
- // generate parameter's entry value.
- if (!DebugEntryVals.count(CurrDebugInstr->getDebugVariable()))
+ // If the parameter has the entry value backup, it means we should
+ // be able to use its entry value.
+ if (!EntryValBackupID)
continue;
- auto ParamDebugInstr = DebugEntryVals[CurrDebugInstr->getDebugVariable()];
- DIExpression *NewExpr = DIExpression::prepend(
- ParamDebugInstr->getDebugExpression(), DIExpression::EntryValue);
-
- VarLoc EntryLoc = VarLoc::CreateEntryLoc(*ParamDebugInstr, LS, NewExpr);
-
- unsigned EntryValLocID = VarLocIDs.insert(EntryLoc);
- Transfers.push_back({&MI, EntryValLocID});
- OpenRanges.insert(EntryValLocID, EntryLoc.Var);
+ const VarLoc &EntryVL = VarLocIDs[*EntryValBackupID];
+ VarLoc EntryLoc =
+ VarLoc::CreateEntryLoc(EntryVL.MI, LS, EntryVL.Expr, EntryVL.Loc.RegNo);
+ unsigned EntryValueID = VarLocIDs.insert(EntryLoc);
+ Transfers.push_back({&MI, EntryValueID});
+ OpenRanges.insert(EntryValueID, EntryLoc);
}
}
@@ -774,17 +953,17 @@ void LiveDebugValues::insertTransferDebugPair(
// Close this variable's previous location range.
DebugVariable V(*DebugInstr);
- OpenRanges.erase(V);
+ OpenRanges.erase(VL);
// Record the new location as an open range, and a postponed transfer
// inserting a DBG_VALUE for this location.
- OpenRanges.insert(LocId, VL.Var);
+ OpenRanges.insert(LocId, VL);
TransferDebugPair MIP = {&MI, LocId};
Transfers.push_back(MIP);
};
- // End all previous ranges of Var.
- OpenRanges.erase(VarLocIDs[OldVarID].Var);
+ // End all previous ranges of VL.Var.
+ OpenRanges.erase(VarLocIDs[OldVarID]);
switch (Kind) {
case TransferKind::TransferCopy: {
assert(NewReg &&
@@ -832,7 +1011,7 @@ void LiveDebugValues::insertTransferDebugPair(
/// A definition of a register may mark the end of a range.
void LiveDebugValues::transferRegisterDef(
MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,
- TransferMap &Transfers, DebugParamMap &DebugEntryVals) {
+ TransferMap &Transfers) {
MachineFunction *MF = MI.getMF();
const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
@@ -866,8 +1045,7 @@ void LiveDebugValues::transferRegisterDef(
if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>()) {
auto &TM = TPC->getTM<TargetMachine>();
if (TM.Options.EnableDebugEntryValues)
- emitEntryValues(MI, OpenRanges, VarLocIDs, Transfers, DebugEntryVals,
- KillSet);
+ emitEntryValues(MI, OpenRanges, VarLocIDs, Transfers, KillSet);
}
}
@@ -1026,14 +1204,14 @@ void LiveDebugValues::transferRegisterCopy(MachineInstr &MI,
OpenRangesSet &OpenRanges,
VarLocMap &VarLocIDs,
TransferMap &Transfers) {
-
auto DestSrc = TII->isCopyInstr(MI);
if (!DestSrc)
return;
const MachineOperand *DestRegOp = DestSrc->Destination;
const MachineOperand *SrcRegOp = DestSrc->Source;
- if (!SrcRegOp->isKill() || !DestRegOp->isDef())
+
+ if (!DestRegOp->isDef())
return;
auto isCalleeSavedReg = [&](unsigned Reg) {
@@ -1054,6 +1232,30 @@ void LiveDebugValues::transferRegisterCopy(MachineInstr &MI,
if (!isCalleeSavedReg(DestReg))
return;
+ // Remember an entry value movement. If we encounter a new debug value of
+ // a parameter describing only a moving of the value around, rather then
+ // modifying it, we are still able to use the entry value if needed.
+ if (isRegOtherThanSPAndFP(*DestRegOp, MI, TRI)) {
+ for (unsigned ID : OpenRanges.getVarLocs()) {
+ if (VarLocIDs[ID].getEntryValueBackupReg() == SrcReg) {
+ LLVM_DEBUG(dbgs() << "Copy of the entry value: "; MI.dump(););
+ VarLoc EntryValLocCopyBackup = VarLoc::CreateEntryCopyBackupLoc(
+ VarLocIDs[ID].MI, LS, VarLocIDs[ID].Expr, DestReg);
+
+ // Stop tracking the original entry value.
+ OpenRanges.erase(VarLocIDs[ID]);
+
+ // Start tracking the entry value copy.
+ unsigned EntryValCopyLocID = VarLocIDs.insert(EntryValLocCopyBackup);
+ OpenRanges.insert(EntryValCopyLocID, EntryValLocCopyBackup);
+ break;
+ }
+ }
+ }
+
+ if (!SrcRegOp->isKill())
+ return;
+
for (unsigned ID : OpenRanges.getVarLocs()) {
if (VarLocIDs[ID].isDescribedByReg() == SrcReg) {
insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, ID,
@@ -1148,11 +1350,9 @@ void LiveDebugValues::accumulateFragmentMap(MachineInstr &MI,
/// This routine creates OpenRanges.
void LiveDebugValues::process(MachineInstr &MI, OpenRangesSet &OpenRanges,
- VarLocMap &VarLocIDs, TransferMap &Transfers,
- DebugParamMap &DebugEntryVals) {
+ VarLocMap &VarLocIDs, TransferMap &Transfers) {
transferDebugValue(MI, OpenRanges, VarLocIDs);
- transferRegisterDef(MI, OpenRanges, VarLocIDs, Transfers,
- DebugEntryVals);
+ transferRegisterDef(MI, OpenRanges, VarLocIDs, Transfers);
transferRegisterCopy(MI, OpenRanges, VarLocIDs, Transfers);
transferSpillOrRestoreInst(MI, OpenRanges, VarLocIDs, Transfers);
}
@@ -1273,6 +1473,8 @@ 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];
+ if (DiffIt.isEntryBackupLoc())
+ continue;
MachineInstr *MI = DiffIt.BuildDbgValue(*MBB.getParent());
MBB.insert(MBB.instr_begin(), MI);
@@ -1284,8 +1486,7 @@ void LiveDebugValues::flushPendingLocs(VarLocInMBB &PendingInLocs,
bool LiveDebugValues::isEntryValueCandidate(
const MachineInstr &MI, const DefinedRegsSet &DefinedRegs) const {
- if (!MI.isDebugValue())
- return false;
+ assert(MI.isDebugValue() && "This must be DBG_VALUE.");
// TODO: Add support for local variables that are expressed in terms of
// parameters entry values.
@@ -1332,6 +1533,34 @@ static void collectRegDefs(const MachineInstr &MI, DefinedRegsSet &Regs,
Regs.insert(*AI);
}
+/// This routine records the entry values of function parameters. The values
+/// could be used as backup values. If we loose the track of some unmodified
+/// parameters, the backup values will be used as a primary locations.
+void LiveDebugValues::recordEntryValue(const MachineInstr &MI,
+ const DefinedRegsSet &DefinedRegs,
+ OpenRangesSet &OpenRanges,
+ VarLocMap &VarLocIDs) {
+ if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>()) {
+ auto &TM = TPC->getTM<TargetMachine>();
+ if (!TM.Options.EnableDebugEntryValues)
+ return;
+ }
+
+ if (!isEntryValueCandidate(MI, DefinedRegs) ||
+ OpenRanges.getEntryValueBackup(DebugVariable(MI)))
+ return;
+
+ LLVM_DEBUG(dbgs() << "Creating the backup entry location: "; MI.dump(););
+
+ // Create the entry value and use it as a backup location until it is
+ // valid. It is valid until a parameter is not changed.
+ DIExpression *NewExpr =
+ DIExpression::prepend(MI.getDebugExpression(), DIExpression::EntryValue);
+ VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(MI, LS, NewExpr);
+ unsigned EntryValLocID = VarLocIDs.insert(EntryValLocAsBackup);
+ OpenRanges.insert(EntryValLocID, EntryValLocAsBackup);
+}
+
/// Calculate the liveness information for the given machine function and
/// extend ranges across basic blocks.
bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
@@ -1368,23 +1597,17 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
std::greater<unsigned int>>
Pending;
- // Working set of currently collected debug variables mapped to DBG_VALUEs
- // representing candidates for production of debug entry values.
- DebugParamMap DebugEntryVals;
-
// Set of register defines that are seen when traversing the entry block
// looking for debug entry value candidates.
DefinedRegsSet DefinedRegs;
// Only in the case of entry MBB collect DBG_VALUEs representing
// function parameters in order to generate debug entry values for them.
-
MachineBasicBlock &First_MBB = *(MF.begin());
for (auto &MI : First_MBB) {
collectRegDefs(MI, DefinedRegs, TRI);
- if (isEntryValueCandidate(MI, DefinedRegs) &&
- !DebugEntryVals.count(MI.getDebugVariable()))
- DebugEntryVals[MI.getDebugVariable()] = &MI;
+ if (MI.isDebugValue())
+ recordEntryValue(MI, DefinedRegs, OpenRanges, VarLocIDs);
}
// Initialize per-block structures and scan for fragment overlaps.
@@ -1443,7 +1666,7 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
// First load any pending inlocs.
OpenRanges.insertFromLocSet(PendingInLocs[MBB], VarLocIDs);
for (auto &MI : *MBB)
- process(MI, OpenRanges, VarLocIDs, Transfers, DebugEntryVals);
+ process(MI, OpenRanges, VarLocIDs, Transfers);
OLChanged |= transferTerminator(MBB, OpenRanges, OutLocs, VarLocIDs);
LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
OpenPOWER on IntegriCloud