Skip to content

Commit 1db137b

Browse files
committed
[DebugInfo] Handle DBG_VALUES with multiple variable location operands in MIR
This patch adds handling for DBG_VALUE_LIST in the MIR-passes (after finalize-isel), excluding the debug liveness passes and DWARF emission. This most significantly affects MachineSink, which now needs to consider all used registers of a debug value when sinking, but for most passes this change is simply replacing getDebugOperand(0) with an iteration over all debug operands. Differential Revision: https://reviews.llvm.org/D92578
1 parent 6a9a686 commit 1db137b

11 files changed

+214
-110
lines changed

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "llvm/ADT/DenseMapInfo.h"
1919
#include "llvm/ADT/PointerSumType.h"
20+
#include "llvm/ADT/SmallSet.h"
2021
#include "llvm/ADT/ilist.h"
2122
#include "llvm/ADT/ilist_node.h"
2223
#include "llvm/ADT/iterator_range.h"
@@ -502,6 +503,15 @@ class MachineInstr
502503
return *(debug_operands().begin() + Index);
503504
}
504505

506+
SmallSet<Register, 4> getUsedDebugRegs() const {
507+
assert(isDebugValue() && "not a DBG_VALUE*");
508+
SmallSet<Register, 4> UsedRegs;
509+
for (auto MO : debug_operands())
510+
if (MO.isReg() && MO.getReg())
511+
UsedRegs.insert(MO.getReg());
512+
return UsedRegs;
513+
}
514+
505515
/// Returns whether this debug value has at least one debug operand with the
506516
/// register \p Reg.
507517
bool hasDebugOperandForReg(Register Reg) const {

llvm/include/llvm/CodeGen/MachineInstrBuilder.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,11 +489,16 @@ MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
489489
/// Clone a DBG_VALUE whose value has been spilled to FrameIndex.
490490
MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB,
491491
MachineBasicBlock::iterator I,
492-
const MachineInstr &Orig, int FrameIndex);
492+
const MachineInstr &Orig, int FrameIndex,
493+
Register SpillReg);
494+
MachineInstr *
495+
buildDbgValueForSpill(MachineBasicBlock &BB, MachineBasicBlock::iterator I,
496+
const MachineInstr &Orig, int FrameIndex,
497+
SmallVectorImpl<const MachineOperand *> &SpilledOperands);
493498

494499
/// Update a DBG_VALUE whose value has been spilled to FrameIndex. Useful when
495500
/// modifying an instruction in place while iterating over a basic block.
496-
void updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex);
501+
void updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex, Register Reg);
497502

498503
inline unsigned getDefRegState(bool B) {
499504
return B ? RegState::Define : 0;

llvm/lib/CodeGen/InlineSpiller.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,7 @@ void InlineSpiller::spillAroundUses(Register Reg) {
10481048
// Modify DBG_VALUE now that the value is in a spill slot.
10491049
MachineBasicBlock *MBB = MI->getParent();
10501050
LLVM_DEBUG(dbgs() << "Modifying debug info due to spill:\t" << *MI);
1051-
buildDbgValueForSpill(*MBB, MI, *MI, StackSlot);
1051+
buildDbgValueForSpill(*MBB, MI, *MI, StackSlot, Reg);
10521052
MBB->erase(MI);
10531053
continue;
10541054
}

llvm/lib/CodeGen/MachineInstr.cpp

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,9 +2196,9 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
21962196

21972197
/// Compute the new DIExpression to use with a DBG_VALUE for a spill slot.
21982198
/// This prepends DW_OP_deref when spilling an indirect DBG_VALUE.
2199-
static const DIExpression *computeExprForSpill(const MachineInstr &MI,
2200-
Register SpillReg) {
2201-
assert(MI.hasDebugOperandForReg(SpillReg) && "Spill Reg is not used in MI.");
2199+
static const DIExpression *
2200+
computeExprForSpill(const MachineInstr &MI,
2201+
SmallVectorImpl<const MachineOperand *> &SpilledOperands) {
22022202
assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
22032203
"Expected inlined-at fields to agree");
22042204

@@ -2211,19 +2211,26 @@ static const DIExpression *computeExprForSpill(const MachineInstr &MI,
22112211
// We will replace the spilled register with a frame index, so
22122212
// immediately deref all references to the spilled register.
22132213
std::array<uint64_t, 1> Ops{{dwarf::DW_OP_deref}};
2214-
for (const MachineOperand &Op : MI.getDebugOperandsForReg(SpillReg)) {
2215-
unsigned OpIdx = MI.getDebugOperandIndex(&Op);
2214+
for (const MachineOperand *Op : SpilledOperands) {
2215+
unsigned OpIdx = MI.getDebugOperandIndex(Op);
22162216
Expr = DIExpression::appendOpsToArg(Expr, Ops, OpIdx);
22172217
}
22182218
}
22192219
return Expr;
22202220
}
2221+
static const DIExpression *computeExprForSpill(const MachineInstr &MI,
2222+
Register SpillReg) {
2223+
assert(MI.hasDebugOperandForReg(SpillReg) && "Spill Reg is not used in MI.");
2224+
SmallVector<const MachineOperand *> SpillOperands;
2225+
for (const MachineOperand &Op : MI.getDebugOperandsForReg(SpillReg))
2226+
SpillOperands.push_back(&Op);
2227+
return computeExprForSpill(MI, SpillOperands);
2228+
}
22212229

22222230
MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
22232231
MachineBasicBlock::iterator I,
22242232
const MachineInstr &Orig,
2225-
int FrameIndex) {
2226-
Register SpillReg = Orig.getDebugOperand(0).getReg();
2233+
int FrameIndex, Register SpillReg) {
22272234
const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
22282235
MachineInstrBuilder NewMI =
22292236
BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
@@ -2241,13 +2248,34 @@ MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
22412248
}
22422249
return NewMI;
22432250
}
2251+
MachineInstr *llvm::buildDbgValueForSpill(
2252+
MachineBasicBlock &BB, MachineBasicBlock::iterator I,
2253+
const MachineInstr &Orig, int FrameIndex,
2254+
SmallVectorImpl<const MachineOperand *> &SpilledOperands) {
2255+
const DIExpression *Expr = computeExprForSpill(Orig, SpilledOperands);
2256+
MachineInstrBuilder NewMI =
2257+
BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
2258+
// Non-Variadic Operands: Location, Offset, Variable, Expression
2259+
// Variadic Operands: Variable, Expression, Locations...
2260+
if (Orig.isNonListDebugValue())
2261+
NewMI.addFrameIndex(FrameIndex).addImm(0U);
2262+
NewMI.addMetadata(Orig.getDebugVariable()).addMetadata(Expr);
2263+
if (Orig.isDebugValueList()) {
2264+
for (const MachineOperand &Op : Orig.debug_operands())
2265+
if (is_contained(SpilledOperands, &Op))
2266+
NewMI.addFrameIndex(FrameIndex);
2267+
else
2268+
NewMI.add(MachineOperand(Op));
2269+
}
2270+
return NewMI;
2271+
}
22442272

2245-
void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex) {
2246-
Register SpillReg = Orig.getDebugOperand(0).getReg();
2247-
const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
2273+
void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex,
2274+
Register Reg) {
2275+
const DIExpression *Expr = computeExprForSpill(Orig, Reg);
22482276
if (Orig.isNonListDebugValue())
22492277
Orig.getDebugOffset().ChangeToImmediate(0U);
2250-
for (MachineOperand &Op : Orig.getDebugOperandsForReg(SpillReg))
2278+
for (MachineOperand &Op : Orig.getDebugOperandsForReg(Reg))
22512279
Op.ChangeToFrameIndex(FrameIndex);
22522280
Orig.getDebugExpressionOp().setMetadata(Expr);
22532281
}

llvm/lib/CodeGen/MachineSink.cpp

Lines changed: 82 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "llvm/ADT/DenseSet.h"
19+
#include "llvm/ADT/MapVector.h"
1920
#include "llvm/ADT/PointerIntPair.h"
2021
#include "llvm/ADT/SetVector.h"
2122
#include "llvm/ADT/SmallSet.h"
@@ -566,9 +567,10 @@ void MachineSinking::ProcessDbgInst(MachineInstr &MI) {
566567
MI.getDebugLoc()->getInlinedAt());
567568
bool SeenBefore = SeenDbgVars.contains(Var);
568569

569-
MachineOperand &MO = MI.getDebugOperand(0);
570-
if (MO.isReg() && MO.getReg().isVirtual())
571-
SeenDbgUsers[MO.getReg()].push_back(SeenDbgUser(&MI, SeenBefore));
570+
for (MachineOperand &MO : MI.debug_operands()) {
571+
if (MO.isReg() && MO.getReg().isVirtual())
572+
SeenDbgUsers[MO.getReg()].push_back(SeenDbgUser(&MI, SeenBefore));
573+
}
572574

573575
// Record the variable for any DBG_VALUE, to avoid re-ordering any of them.
574576
SeenDbgVars.insert(Var);
@@ -1028,14 +1030,14 @@ static bool SinkingPreventsImplicitNullCheck(MachineInstr &MI,
10281030
/// leaving an 'undef' DBG_VALUE in the original location. Don't do this if
10291031
/// there's any subregister weirdness involved. Returns true if copy
10301032
/// propagation occurred.
1031-
static bool attemptDebugCopyProp(MachineInstr &SinkInst, MachineInstr &DbgMI) {
1033+
static bool attemptDebugCopyProp(MachineInstr &SinkInst, MachineInstr &DbgMI,
1034+
Register Reg) {
10321035
const MachineRegisterInfo &MRI = SinkInst.getMF()->getRegInfo();
10331036
const TargetInstrInfo &TII = *SinkInst.getMF()->getSubtarget().getInstrInfo();
10341037

10351038
// Copy DBG_VALUE operand and set the original to undef. We then check to
10361039
// see whether this is something that can be copy-forwarded. If it isn't,
10371040
// continue around the loop.
1038-
MachineOperand &DbgMO = DbgMI.getDebugOperand(0);
10391041

10401042
const MachineOperand *SrcMO = nullptr, *DstMO = nullptr;
10411043
auto CopyOperands = TII.isCopyInstr(SinkInst);
@@ -1048,36 +1050,41 @@ static bool attemptDebugCopyProp(MachineInstr &SinkInst, MachineInstr &DbgMI) {
10481050
bool PostRA = MRI.getNumVirtRegs() == 0;
10491051

10501052
// Trying to forward between physical and virtual registers is too hard.
1051-
if (DbgMO.getReg().isVirtual() != SrcMO->getReg().isVirtual())
1053+
if (Reg.isVirtual() != SrcMO->getReg().isVirtual())
10521054
return false;
10531055

10541056
// Only try virtual register copy-forwarding before regalloc, and physical
10551057
// register copy-forwarding after regalloc.
1056-
bool arePhysRegs = !DbgMO.getReg().isVirtual();
1058+
bool arePhysRegs = !Reg.isVirtual();
10571059
if (arePhysRegs != PostRA)
10581060
return false;
10591061

10601062
// Pre-regalloc, only forward if all subregisters agree (or there are no
10611063
// subregs at all). More analysis might recover some forwardable copies.
1062-
if (!PostRA && (DbgMO.getSubReg() != SrcMO->getSubReg() ||
1063-
DbgMO.getSubReg() != DstMO->getSubReg()))
1064-
return false;
1064+
if (!PostRA)
1065+
for (auto &DbgMO : DbgMI.getDebugOperandsForReg(Reg))
1066+
if (DbgMO.getSubReg() != SrcMO->getSubReg() ||
1067+
DbgMO.getSubReg() != DstMO->getSubReg())
1068+
return false;
10651069

10661070
// Post-regalloc, we may be sinking a DBG_VALUE of a sub or super-register
10671071
// of this copy. Only forward the copy if the DBG_VALUE operand exactly
10681072
// matches the copy destination.
1069-
if (PostRA && DbgMO.getReg() != DstMO->getReg())
1073+
if (PostRA && Reg != DstMO->getReg())
10701074
return false;
10711075

1072-
DbgMO.setReg(SrcMO->getReg());
1073-
DbgMO.setSubReg(SrcMO->getSubReg());
1076+
for (auto &DbgMO : DbgMI.getDebugOperandsForReg(Reg)) {
1077+
DbgMO.setReg(SrcMO->getReg());
1078+
DbgMO.setSubReg(SrcMO->getSubReg());
1079+
}
10741080
return true;
10751081
}
10761082

1083+
using MIRegs = std::pair<MachineInstr *, SmallVector<unsigned, 2>>;
10771084
/// Sink an instruction and its associated debug instructions.
10781085
static void performSink(MachineInstr &MI, MachineBasicBlock &SuccToSinkTo,
10791086
MachineBasicBlock::iterator InsertPos,
1080-
SmallVectorImpl<MachineInstr *> &DbgValuesToSink) {
1087+
SmallVectorImpl<MIRegs> &DbgValuesToSink) {
10811088

10821089
// If we cannot find a location to use (merge with), then we erase the debug
10831090
// location to prevent debug-info driven tools from potentially reporting
@@ -1097,11 +1104,21 @@ static void performSink(MachineInstr &MI, MachineBasicBlock &SuccToSinkTo,
10971104
// DBG_VALUE location as 'undef', indicating that any earlier variable
10981105
// location should be terminated as we've optimised away the value at this
10991106
// point.
1100-
for (MachineInstr *DbgMI : DbgValuesToSink) {
1107+
for (auto DbgValueToSink : DbgValuesToSink) {
1108+
MachineInstr *DbgMI = DbgValueToSink.first;
11011109
MachineInstr *NewDbgMI = DbgMI->getMF()->CloneMachineInstr(DbgMI);
11021110
SuccToSinkTo.insert(InsertPos, NewDbgMI);
11031111

1104-
if (!attemptDebugCopyProp(MI, *DbgMI))
1112+
bool PropagatedAllSunkOps = true;
1113+
for (unsigned Reg : DbgValueToSink.second) {
1114+
if (DbgMI->hasDebugOperandForReg(Reg)) {
1115+
if (!attemptDebugCopyProp(MI, *DbgMI, Reg)) {
1116+
PropagatedAllSunkOps = false;
1117+
break;
1118+
}
1119+
}
1120+
}
1121+
if (!PropagatedAllSunkOps)
11051122
DbgMI->setDebugValueUndef();
11061123
}
11071124
}
@@ -1384,7 +1401,7 @@ bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore,
13841401
++InsertPos;
13851402

13861403
// Collect debug users of any vreg that this inst defines.
1387-
SmallVector<MachineInstr *, 4> DbgUsersToSink;
1404+
SmallVector<MIRegs, 4> DbgUsersToSink;
13881405
for (auto &MO : MI.operands()) {
13891406
if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual())
13901407
continue;
@@ -1398,10 +1415,11 @@ bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore,
13981415
if (User.getInt()) {
13991416
// This DBG_VALUE would re-order assignments. If we can't copy-propagate
14001417
// it, it can't be recovered. Set it undef.
1401-
if (!attemptDebugCopyProp(MI, *DbgMI))
1418+
if (!attemptDebugCopyProp(MI, *DbgMI, MO.getReg()))
14021419
DbgMI->setDebugValueUndef();
14031420
} else {
1404-
DbgUsersToSink.push_back(DbgMI);
1421+
DbgUsersToSink.push_back(
1422+
{DbgMI, SmallVector<unsigned, 2>(1, MO.getReg())});
14051423
}
14061424
}
14071425
}
@@ -1436,10 +1454,12 @@ void MachineSinking::SalvageUnsunkDebugUsersOfCopy(
14361454
// be sunk. For the rest, if they are not dominated by the block we will sink
14371455
// MI into, propagate the copy source to them.
14381456
SmallVector<MachineInstr *, 4> DbgDefUsers;
1457+
SmallVector<Register, 4> DbgUseRegs;
14391458
const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
14401459
for (auto &MO : MI.operands()) {
14411460
if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual())
14421461
continue;
1462+
DbgUseRegs.push_back(MO.getReg());
14431463
for (auto &User : MRI.use_instructions(MO.getReg())) {
14441464
if (!User.isDebugValue() || DT->dominates(TargetBlock, User.getParent()))
14451465
continue;
@@ -1448,17 +1468,21 @@ void MachineSinking::SalvageUnsunkDebugUsersOfCopy(
14481468
if (User.getParent() == MI.getParent())
14491469
continue;
14501470

1451-
assert(User.getDebugOperand(0).isReg() &&
1452-
"DBG_VALUE user of vreg, but non reg operand?");
1471+
assert(User.hasDebugOperandForReg(MO.getReg()) &&
1472+
"DBG_VALUE user of vreg, but has no operand for it?");
14531473
DbgDefUsers.push_back(&User);
14541474
}
14551475
}
14561476

14571477
// Point the users of this copy that are no longer dominated, at the source
14581478
// of the copy.
14591479
for (auto *User : DbgDefUsers) {
1460-
User->getDebugOperand(0).setReg(MI.getOperand(1).getReg());
1461-
User->getDebugOperand(0).setSubReg(MI.getOperand(1).getSubReg());
1480+
for (auto &Reg : DbgUseRegs) {
1481+
for (auto &DbgOp : User->getDebugOperandsForReg(Reg)) {
1482+
DbgOp.setReg(MI.getOperand(1).getReg());
1483+
DbgOp.setSubReg(MI.getOperand(1).getSubReg());
1484+
}
1485+
}
14621486
}
14631487
}
14641488

@@ -1521,8 +1545,10 @@ class PostRAMachineSinking : public MachineFunctionPass {
15211545
LiveRegUnits ModifiedRegUnits, UsedRegUnits;
15221546

15231547
/// Track DBG_VALUEs of (unmodified) register units. Each DBG_VALUE has an
1524-
/// entry in this map for each unit it touches.
1525-
DenseMap<unsigned, TinyPtrVector<MachineInstr *>> SeenDbgInstrs;
1548+
/// entry in this map for each unit it touches. The DBG_VALUE's entry
1549+
/// consists of a pointer to the instruction itself, and a vector of registers
1550+
/// referred to by the instruction that overlap the key register unit.
1551+
DenseMap<unsigned, SmallVector<MIRegs, 2>> SeenDbgInstrs;
15261552

15271553
/// Sink Copy instructions unused in the same block close to their uses in
15281554
/// successors.
@@ -1704,18 +1730,27 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
17041730
// We must sink this DBG_VALUE if its operand is sunk. To avoid searching
17051731
// for DBG_VALUEs later, record them when they're encountered.
17061732
if (MI->isDebugValue()) {
1707-
auto &MO = MI->getDebugOperand(0);
1708-
if (MO.isReg() && Register::isPhysicalRegister(MO.getReg())) {
1709-
// Bail if we can already tell the sink would be rejected, rather
1710-
// than needlessly accumulating lots of DBG_VALUEs.
1711-
if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy,
1712-
ModifiedRegUnits, UsedRegUnits))
1713-
continue;
1714-
1715-
// Record debug use of each reg unit.
1716-
SmallSet<MCRegister, 4> Units = getRegUnits(MO.getReg(), TRI);
1717-
for (MCRegister Reg : Units)
1718-
SeenDbgInstrs[Reg].push_back(MI);
1733+
SmallDenseMap<MCRegister, SmallVector<unsigned, 2>, 4> MIUnits;
1734+
bool IsValid = true;
1735+
for (MachineOperand &MO : MI->debug_operands()) {
1736+
if (MO.isReg() && Register::isPhysicalRegister(MO.getReg())) {
1737+
// Bail if we can already tell the sink would be rejected, rather
1738+
// than needlessly accumulating lots of DBG_VALUEs.
1739+
if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy,
1740+
ModifiedRegUnits, UsedRegUnits)) {
1741+
IsValid = false;
1742+
break;
1743+
}
1744+
1745+
// Record debug use of each reg unit.
1746+
SmallSet<MCRegister, 4> RegUnits = getRegUnits(MO.getReg(), TRI);
1747+
for (MCRegister Reg : RegUnits)
1748+
MIUnits[Reg].push_back(MO.getReg());
1749+
}
1750+
}
1751+
if (IsValid) {
1752+
for (auto RegOps : MIUnits)
1753+
SeenDbgInstrs[RegOps.first].push_back({MI, RegOps.second});
17191754
}
17201755
continue;
17211756
}
@@ -1757,18 +1792,22 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
17571792
// Collect DBG_VALUEs that must sink with this copy. We've previously
17581793
// recorded which reg units that DBG_VALUEs read, if this instruction
17591794
// writes any of those units then the corresponding DBG_VALUEs must sink.
1760-
SetVector<MachineInstr *> DbgValsToSinkSet;
1795+
MapVector<MachineInstr *, MIRegs::second_type> DbgValsToSinkMap;
17611796
for (auto &MO : MI->operands()) {
17621797
if (!MO.isReg() || !MO.isDef())
17631798
continue;
17641799

17651800
SmallSet<MCRegister, 4> Units = getRegUnits(MO.getReg(), TRI);
1766-
for (MCRegister Reg : Units)
1767-
for (auto *MI : SeenDbgInstrs.lookup(Reg))
1768-
DbgValsToSinkSet.insert(MI);
1801+
for (MCRegister Reg : Units) {
1802+
for (auto MIRegs : SeenDbgInstrs.lookup(Reg)) {
1803+
auto &Regs = DbgValsToSinkMap[MIRegs.first];
1804+
for (unsigned Reg : MIRegs.second)
1805+
Regs.push_back(Reg);
1806+
}
1807+
}
17691808
}
1770-
SmallVector<MachineInstr *, 4> DbgValsToSink(DbgValsToSinkSet.begin(),
1771-
DbgValsToSinkSet.end());
1809+
SmallVector<MIRegs, 4> DbgValsToSink(DbgValsToSinkMap.begin(),
1810+
DbgValsToSinkMap.end());
17721811

17731812
// Clear the kill flag if SrcReg is killed between MI and the end of the
17741813
// block.

0 commit comments

Comments
 (0)