[DebugInfo] Avoid creating entry values for clobbered registers
Summary:
Entry values are considered for parameters that have register-described
DBG_VALUEs in the entry block (along with other conditions).
If a parameter's value has been propagated from the caller to the
callee, then the parameter's DBG_VALUE in the entry block may be
described using a register defined by some instruction, and entry values
should not be emitted for the parameter, which can currently occur.
One such case was seen in the attached test case, in which the second
parameter, which is described by a redefinition of the first parameter's
register, would incorrectly get an entry value using the first
parameter's register. This commit intends to solve such cases by keeping
track of register defines, and ignoring DBG_VALUEs in the entry block
that are described by such registers.
In a RelWithDebInfo build of clang-8, the average size of the set was
27, and in a RelWithDebInfo+ASan build it was 30.
Reviewers: djtodoro, NikolaPrica, aprantl, vsk
Reviewed By: djtodoro, vsk
Subscribers: hiraditya, llvm-commits
Tags: #debug-info, #llvm
Differential Revision: https://reviews.llvm.org/D69889
diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp
index 1b2dfe5..065a9e2 100644
--- a/llvm/lib/CodeGen/LiveDebugValues.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues.cpp
@@ -109,6 +109,8 @@
namespace {
+using DefinedRegsSet = SmallSet<Register, 32>;
+
class LiveDebugValues : public MachineFunctionPass {
private:
const TargetRegisterInfo *TRI;
@@ -479,7 +481,8 @@
///
/// 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;
+ bool isEntryValueCandidate(const MachineInstr &MI,
+ const DefinedRegsSet &Regs) const;
/// If a given instruction is identified as a spill, return the spill location
/// and set \p Reg to the spilled register.
@@ -1278,7 +1281,8 @@
}
}
-bool LiveDebugValues::isEntryValueCandidate(const MachineInstr &MI) const {
+bool LiveDebugValues::isEntryValueCandidate(
+ const MachineInstr &MI, const DefinedRegsSet &DefinedRegs) const {
if (!MI.isDebugValue())
return false;
@@ -1304,6 +1308,13 @@
if (!isRegOtherThanSPAndFP(MI.getOperand(0), MI, TRI))
return false;
+ // If a parameter's value has been propagated from the caller, then the
+ // parameter's DBG_VALUE may be described using a register defined by some
+ // instruction in the entry block, in which case we shouldn't create an
+ // entry value.
+ if (DefinedRegs.count(MI.getOperand(0).getReg()))
+ return false;
+
// TODO: Add support for parameters that are described as fragments.
if (MI.getDebugExpression()->isFragment())
return false;
@@ -1311,6 +1322,15 @@
return true;
}
+/// Collect all register defines (including aliases) for the given instruction.
+static void collectRegDefs(const MachineInstr &MI, DefinedRegsSet &Regs,
+ const TargetRegisterInfo *TRI) {
+ for (const MachineOperand &MO : MI.operands())
+ if (MO.isReg() && MO.isDef() && MO.getReg())
+ for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI)
+ Regs.insert(*AI);
+}
+
/// Calculate the liveness information for the given machine function and
/// extend ranges across basic blocks.
bool LiveDebugValues::ExtendRanges(MachineFunction &MF) {
@@ -1351,13 +1371,20 @@
// 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)
- if (isEntryValueCandidate(MI) &&
+ for (auto &MI : First_MBB) {
+ collectRegDefs(MI, DefinedRegs, TRI);
+ if (isEntryValueCandidate(MI, DefinedRegs) &&
!DebugEntryVals.count(MI.getDebugVariable()))
DebugEntryVals[MI.getDebugVariable()] = &MI;
+ }
// Initialize per-block structures and scan for fragment overlaps.
for (auto &MBB : MF) {