[DebugInfo] Add helper for finding entry value candidates [NFC]

Summary:
The conditions that are used to determine if entry values should be
emitted for a parameter are quite many, and will grow slightly
in a follow-up commit, so move those to a helper function, as was
suggested in the code review for D69889.

Reviewers: djtodoro, NikolaPrica

Reviewed By: djtodoro

Subscribers: probinson, hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69955
This commit is contained in:
David Stenberg 2019-11-13 10:36:13 +01:00
parent 3367686b4d
commit 4fec44cd61
1 changed files with 61 additions and 28 deletions

View File

@ -89,6 +89,24 @@ static Register isDbgValueDescribedByReg(const MachineInstr &MI) {
return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : Register();
}
/// If \p Op is a stack or frame register return true, otherwise return false.
/// This is used to avoid basing the debug entry values on the registers, since
/// we do not support it at the moment.
static bool isRegOtherThanSPAndFP(const MachineOperand &Op,
const MachineInstr &MI,
const TargetRegisterInfo *TRI) {
if (!Op.isReg())
return false;
const MachineFunction *MF = MI.getParent()->getParent();
const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
Register FP = TRI->getFrameRegister(*MF);
Register Reg = Op.getReg();
return Reg && Reg != SP && Reg != FP;
}
namespace {
class LiveDebugValues : public MachineFunctionPass {
@ -456,6 +474,13 @@ private:
bool isLocationSpill(const MachineInstr &MI, MachineFunction *MF,
unsigned &Reg);
/// Returns true if the given machine instruction is a debug value which we
/// can emit entry values for.
///
/// Currently, we generate debug entry values only for parameters that are
/// unmodified throughout the function and located in a register.
bool isEntryValueCandidate(const MachineInstr &MI) const;
/// 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,
@ -1253,6 +1278,39 @@ void LiveDebugValues::flushPendingLocs(VarLocInMBB &PendingInLocs,
}
}
bool LiveDebugValues::isEntryValueCandidate(const MachineInstr &MI) const {
if (!MI.isDebugValue())
return false;
// TODO: Add support for local variables that are expressed in terms of
// parameters entry values.
// TODO: Add support for modified arguments that can be expressed
// by using its entry value.
auto *DIVar = MI.getDebugVariable();
if (!DIVar->isParameter() || !DIVar->isNotModified())
return false;
// Do not consider parameters that belong to an inlined function.
if (MI.getDebugLoc()->getInlinedAt())
return false;
// Do not consider indirect debug values (TODO: explain why).
if (MI.isIndirectDebugValue())
return false;
// Only consider parameters that are described using registers. Parameters
// that are passed on the stack are not yet supported, so ignore debug
// values that are described by the frame or stack pointer.
if (!isRegOtherThanSPAndFP(MI.getOperand(0), MI, TRI))
return false;
// TODO: Add support for parameters that are described as fragments.
if (MI.getDebugExpression()->isFragment())
return false;
return true;
}
/// Calculate the liveness information for the given machine function and
/// extend ranges across basic blocks.
bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
@ -1289,41 +1347,16 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
std::greater<unsigned int>>
Pending;
// Besides parameter's modification, check whether a DBG_VALUE is inlined
// in order to deduce whether the variable that it tracks comes from
// a different function. If that is the case we can't track its entry value.
auto IsUnmodifiedFuncParam = [&](const MachineInstr &MI) {
auto *DIVar = MI.getDebugVariable();
return DIVar->isParameter() && DIVar->isNotModified() &&
!MI.getDebugLoc()->getInlinedAt();
};
const TargetLowering *TLI = MF.getSubtarget().getTargetLowering();
unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
Register FP = TRI->getFrameRegister(MF);
auto IsRegOtherThanSPAndFP = [&](const MachineOperand &Op) -> bool {
return Op.isReg() && Op.getReg() != SP && Op.getReg() != FP;
};
// Working set of currently collected debug variables mapped to DBG_VALUEs
// representing candidates for production of debug entry values.
DebugParamMap DebugEntryVals;
MachineBasicBlock &First_MBB = *(MF.begin());
// Only in the case of entry MBB collect DBG_VALUEs representing
// function parameters in order to generate debug entry values for them.
// Currently, we generate debug entry values only for parameters that are
// unmodified throughout the function and located in a register.
// TODO: Add support for parameters that are described as fragments.
// TODO: Add support for modified arguments that can be expressed
// by using its entry value.
// TODO: Add support for local variables that are expressed in terms of
// parameters entry values.
MachineBasicBlock &First_MBB = *(MF.begin());
for (auto &MI : First_MBB)
if (MI.isDebugValue() && IsUnmodifiedFuncParam(MI) &&
!MI.isIndirectDebugValue() && IsRegOtherThanSPAndFP(MI.getOperand(0)) &&
!DebugEntryVals.count(MI.getDebugVariable()) &&
!MI.getDebugExpression()->isFragment())
if (isEntryValueCandidate(MI) &&
!DebugEntryVals.count(MI.getDebugVariable()))
DebugEntryVals[MI.getDebugVariable()] = &MI;
// Initialize per-block structures and scan for fragment overlaps.