[llvm] 1db137b - [DebugInfo] Handle DBG_VALUES with multiple variable location operands in MIR
Stephen Tozer via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 10 09:16:09 PST 2021
Author: Stephen Tozer
Date: 2021-03-10T17:15:24Z
New Revision: 1db137b1859692ae33228c530d4df9f2431b2151
URL: https://github.com/llvm/llvm-project/commit/1db137b1859692ae33228c530d4df9f2431b2151
DIFF: https://github.com/llvm/llvm-project/commit/1db137b1859692ae33228c530d4df9f2431b2151.diff
LOG: [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
Added:
Modified:
llvm/include/llvm/CodeGen/MachineInstr.h
llvm/include/llvm/CodeGen/MachineInstrBuilder.h
llvm/lib/CodeGen/InlineSpiller.cpp
llvm/lib/CodeGen/MachineInstr.cpp
llvm/lib/CodeGen/MachineSink.cpp
llvm/lib/CodeGen/PrologEpilogInserter.cpp
llvm/lib/CodeGen/RegAllocFast.cpp
llvm/lib/CodeGen/RegisterCoalescer.cpp
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 6071f73d6b83..4760459d5a15 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/PointerSumType.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
@@ -502,6 +503,15 @@ class MachineInstr
return *(debug_operands().begin() + Index);
}
+ SmallSet<Register, 4> getUsedDebugRegs() const {
+ assert(isDebugValue() && "not a DBG_VALUE*");
+ SmallSet<Register, 4> UsedRegs;
+ for (auto MO : debug_operands())
+ if (MO.isReg() && MO.getReg())
+ UsedRegs.insert(MO.getReg());
+ return UsedRegs;
+ }
+
/// Returns whether this debug value has at least one debug operand with the
/// register \p Reg.
bool hasDebugOperandForReg(Register Reg) const {
diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
index 10f487e0430b..5a6f688a1e57 100644
--- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -489,11 +489,16 @@ MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
/// Clone a DBG_VALUE whose value has been spilled to FrameIndex.
MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
- const MachineInstr &Orig, int FrameIndex);
+ const MachineInstr &Orig, int FrameIndex,
+ Register SpillReg);
+MachineInstr *
+buildDbgValueForSpill(MachineBasicBlock &BB, MachineBasicBlock::iterator I,
+ const MachineInstr &Orig, int FrameIndex,
+ SmallVectorImpl<const MachineOperand *> &SpilledOperands);
/// Update a DBG_VALUE whose value has been spilled to FrameIndex. Useful when
/// modifying an instruction in place while iterating over a basic block.
-void updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex);
+void updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex, Register Reg);
inline unsigned getDefRegState(bool B) {
return B ? RegState::Define : 0;
diff --git a/llvm/lib/CodeGen/InlineSpiller.cpp b/llvm/lib/CodeGen/InlineSpiller.cpp
index 7c280233cfaf..4635daf71e54 100644
--- a/llvm/lib/CodeGen/InlineSpiller.cpp
+++ b/llvm/lib/CodeGen/InlineSpiller.cpp
@@ -1048,7 +1048,7 @@ void InlineSpiller::spillAroundUses(Register Reg) {
// Modify DBG_VALUE now that the value is in a spill slot.
MachineBasicBlock *MBB = MI->getParent();
LLVM_DEBUG(dbgs() << "Modifying debug info due to spill:\t" << *MI);
- buildDbgValueForSpill(*MBB, MI, *MI, StackSlot);
+ buildDbgValueForSpill(*MBB, MI, *MI, StackSlot, Reg);
MBB->erase(MI);
continue;
}
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index f0b2eaa79a8d..b220ba2af0b6 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -2196,9 +2196,9 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
/// Compute the new DIExpression to use with a DBG_VALUE for a spill slot.
/// This prepends DW_OP_deref when spilling an indirect DBG_VALUE.
-static const DIExpression *computeExprForSpill(const MachineInstr &MI,
- Register SpillReg) {
- assert(MI.hasDebugOperandForReg(SpillReg) && "Spill Reg is not used in MI.");
+static const DIExpression *
+computeExprForSpill(const MachineInstr &MI,
+ SmallVectorImpl<const MachineOperand *> &SpilledOperands) {
assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
"Expected inlined-at fields to agree");
@@ -2211,19 +2211,26 @@ static const DIExpression *computeExprForSpill(const MachineInstr &MI,
// We will replace the spilled register with a frame index, so
// immediately deref all references to the spilled register.
std::array<uint64_t, 1> Ops{{dwarf::DW_OP_deref}};
- for (const MachineOperand &Op : MI.getDebugOperandsForReg(SpillReg)) {
- unsigned OpIdx = MI.getDebugOperandIndex(&Op);
+ for (const MachineOperand *Op : SpilledOperands) {
+ unsigned OpIdx = MI.getDebugOperandIndex(Op);
Expr = DIExpression::appendOpsToArg(Expr, Ops, OpIdx);
}
}
return Expr;
}
+static const DIExpression *computeExprForSpill(const MachineInstr &MI,
+ Register SpillReg) {
+ assert(MI.hasDebugOperandForReg(SpillReg) && "Spill Reg is not used in MI.");
+ SmallVector<const MachineOperand *> SpillOperands;
+ for (const MachineOperand &Op : MI.getDebugOperandsForReg(SpillReg))
+ SpillOperands.push_back(&Op);
+ return computeExprForSpill(MI, SpillOperands);
+}
MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
const MachineInstr &Orig,
- int FrameIndex) {
- Register SpillReg = Orig.getDebugOperand(0).getReg();
+ int FrameIndex, Register SpillReg) {
const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
MachineInstrBuilder NewMI =
BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
@@ -2241,13 +2248,34 @@ MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
}
return NewMI;
}
+MachineInstr *llvm::buildDbgValueForSpill(
+ MachineBasicBlock &BB, MachineBasicBlock::iterator I,
+ const MachineInstr &Orig, int FrameIndex,
+ SmallVectorImpl<const MachineOperand *> &SpilledOperands) {
+ const DIExpression *Expr = computeExprForSpill(Orig, SpilledOperands);
+ MachineInstrBuilder NewMI =
+ BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
+ // Non-Variadic Operands: Location, Offset, Variable, Expression
+ // Variadic Operands: Variable, Expression, Locations...
+ if (Orig.isNonListDebugValue())
+ NewMI.addFrameIndex(FrameIndex).addImm(0U);
+ NewMI.addMetadata(Orig.getDebugVariable()).addMetadata(Expr);
+ if (Orig.isDebugValueList()) {
+ for (const MachineOperand &Op : Orig.debug_operands())
+ if (is_contained(SpilledOperands, &Op))
+ NewMI.addFrameIndex(FrameIndex);
+ else
+ NewMI.add(MachineOperand(Op));
+ }
+ return NewMI;
+}
-void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex) {
- Register SpillReg = Orig.getDebugOperand(0).getReg();
- const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
+void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex,
+ Register Reg) {
+ const DIExpression *Expr = computeExprForSpill(Orig, Reg);
if (Orig.isNonListDebugValue())
Orig.getDebugOffset().ChangeToImmediate(0U);
- for (MachineOperand &Op : Orig.getDebugOperandsForReg(SpillReg))
+ for (MachineOperand &Op : Orig.getDebugOperandsForReg(Reg))
Op.ChangeToFrameIndex(FrameIndex);
Orig.getDebugExpressionOp().setMetadata(Expr);
}
diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp
index 0a2c5f2e74b6..6be9f4e31b49 100644
--- a/llvm/lib/CodeGen/MachineSink.cpp
+++ b/llvm/lib/CodeGen/MachineSink.cpp
@@ -16,6 +16,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h"
@@ -566,9 +567,10 @@ void MachineSinking::ProcessDbgInst(MachineInstr &MI) {
MI.getDebugLoc()->getInlinedAt());
bool SeenBefore = SeenDbgVars.contains(Var);
- MachineOperand &MO = MI.getDebugOperand(0);
- if (MO.isReg() && MO.getReg().isVirtual())
- SeenDbgUsers[MO.getReg()].push_back(SeenDbgUser(&MI, SeenBefore));
+ for (MachineOperand &MO : MI.debug_operands()) {
+ if (MO.isReg() && MO.getReg().isVirtual())
+ SeenDbgUsers[MO.getReg()].push_back(SeenDbgUser(&MI, SeenBefore));
+ }
// Record the variable for any DBG_VALUE, to avoid re-ordering any of them.
SeenDbgVars.insert(Var);
@@ -1028,14 +1030,14 @@ static bool SinkingPreventsImplicitNullCheck(MachineInstr &MI,
/// leaving an 'undef' DBG_VALUE in the original location. Don't do this if
/// there's any subregister weirdness involved. Returns true if copy
/// propagation occurred.
-static bool attemptDebugCopyProp(MachineInstr &SinkInst, MachineInstr &DbgMI) {
+static bool attemptDebugCopyProp(MachineInstr &SinkInst, MachineInstr &DbgMI,
+ Register Reg) {
const MachineRegisterInfo &MRI = SinkInst.getMF()->getRegInfo();
const TargetInstrInfo &TII = *SinkInst.getMF()->getSubtarget().getInstrInfo();
// Copy DBG_VALUE operand and set the original to undef. We then check to
// see whether this is something that can be copy-forwarded. If it isn't,
// continue around the loop.
- MachineOperand &DbgMO = DbgMI.getDebugOperand(0);
const MachineOperand *SrcMO = nullptr, *DstMO = nullptr;
auto CopyOperands = TII.isCopyInstr(SinkInst);
@@ -1048,36 +1050,41 @@ static bool attemptDebugCopyProp(MachineInstr &SinkInst, MachineInstr &DbgMI) {
bool PostRA = MRI.getNumVirtRegs() == 0;
// Trying to forward between physical and virtual registers is too hard.
- if (DbgMO.getReg().isVirtual() != SrcMO->getReg().isVirtual())
+ if (Reg.isVirtual() != SrcMO->getReg().isVirtual())
return false;
// Only try virtual register copy-forwarding before regalloc, and physical
// register copy-forwarding after regalloc.
- bool arePhysRegs = !DbgMO.getReg().isVirtual();
+ bool arePhysRegs = !Reg.isVirtual();
if (arePhysRegs != PostRA)
return false;
// Pre-regalloc, only forward if all subregisters agree (or there are no
// subregs at all). More analysis might recover some forwardable copies.
- if (!PostRA && (DbgMO.getSubReg() != SrcMO->getSubReg() ||
- DbgMO.getSubReg() != DstMO->getSubReg()))
- return false;
+ if (!PostRA)
+ for (auto &DbgMO : DbgMI.getDebugOperandsForReg(Reg))
+ if (DbgMO.getSubReg() != SrcMO->getSubReg() ||
+ DbgMO.getSubReg() != DstMO->getSubReg())
+ return false;
// Post-regalloc, we may be sinking a DBG_VALUE of a sub or super-register
// of this copy. Only forward the copy if the DBG_VALUE operand exactly
// matches the copy destination.
- if (PostRA && DbgMO.getReg() != DstMO->getReg())
+ if (PostRA && Reg != DstMO->getReg())
return false;
- DbgMO.setReg(SrcMO->getReg());
- DbgMO.setSubReg(SrcMO->getSubReg());
+ for (auto &DbgMO : DbgMI.getDebugOperandsForReg(Reg)) {
+ DbgMO.setReg(SrcMO->getReg());
+ DbgMO.setSubReg(SrcMO->getSubReg());
+ }
return true;
}
+using MIRegs = std::pair<MachineInstr *, SmallVector<unsigned, 2>>;
/// Sink an instruction and its associated debug instructions.
static void performSink(MachineInstr &MI, MachineBasicBlock &SuccToSinkTo,
MachineBasicBlock::iterator InsertPos,
- SmallVectorImpl<MachineInstr *> &DbgValuesToSink) {
+ SmallVectorImpl<MIRegs> &DbgValuesToSink) {
// If we cannot find a location to use (merge with), then we erase the debug
// location to prevent debug-info driven tools from potentially reporting
@@ -1097,11 +1104,21 @@ static void performSink(MachineInstr &MI, MachineBasicBlock &SuccToSinkTo,
// DBG_VALUE location as 'undef', indicating that any earlier variable
// location should be terminated as we've optimised away the value at this
// point.
- for (MachineInstr *DbgMI : DbgValuesToSink) {
+ for (auto DbgValueToSink : DbgValuesToSink) {
+ MachineInstr *DbgMI = DbgValueToSink.first;
MachineInstr *NewDbgMI = DbgMI->getMF()->CloneMachineInstr(DbgMI);
SuccToSinkTo.insert(InsertPos, NewDbgMI);
- if (!attemptDebugCopyProp(MI, *DbgMI))
+ bool PropagatedAllSunkOps = true;
+ for (unsigned Reg : DbgValueToSink.second) {
+ if (DbgMI->hasDebugOperandForReg(Reg)) {
+ if (!attemptDebugCopyProp(MI, *DbgMI, Reg)) {
+ PropagatedAllSunkOps = false;
+ break;
+ }
+ }
+ }
+ if (!PropagatedAllSunkOps)
DbgMI->setDebugValueUndef();
}
}
@@ -1384,7 +1401,7 @@ bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore,
++InsertPos;
// Collect debug users of any vreg that this inst defines.
- SmallVector<MachineInstr *, 4> DbgUsersToSink;
+ SmallVector<MIRegs, 4> DbgUsersToSink;
for (auto &MO : MI.operands()) {
if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual())
continue;
@@ -1398,10 +1415,11 @@ bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore,
if (User.getInt()) {
// This DBG_VALUE would re-order assignments. If we can't copy-propagate
// it, it can't be recovered. Set it undef.
- if (!attemptDebugCopyProp(MI, *DbgMI))
+ if (!attemptDebugCopyProp(MI, *DbgMI, MO.getReg()))
DbgMI->setDebugValueUndef();
} else {
- DbgUsersToSink.push_back(DbgMI);
+ DbgUsersToSink.push_back(
+ {DbgMI, SmallVector<unsigned, 2>(1, MO.getReg())});
}
}
}
@@ -1436,10 +1454,12 @@ void MachineSinking::SalvageUnsunkDebugUsersOfCopy(
// be sunk. For the rest, if they are not dominated by the block we will sink
// MI into, propagate the copy source to them.
SmallVector<MachineInstr *, 4> DbgDefUsers;
+ SmallVector<Register, 4> DbgUseRegs;
const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
for (auto &MO : MI.operands()) {
if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual())
continue;
+ DbgUseRegs.push_back(MO.getReg());
for (auto &User : MRI.use_instructions(MO.getReg())) {
if (!User.isDebugValue() || DT->dominates(TargetBlock, User.getParent()))
continue;
@@ -1448,8 +1468,8 @@ void MachineSinking::SalvageUnsunkDebugUsersOfCopy(
if (User.getParent() == MI.getParent())
continue;
- assert(User.getDebugOperand(0).isReg() &&
- "DBG_VALUE user of vreg, but non reg operand?");
+ assert(User.hasDebugOperandForReg(MO.getReg()) &&
+ "DBG_VALUE user of vreg, but has no operand for it?");
DbgDefUsers.push_back(&User);
}
}
@@ -1457,8 +1477,12 @@ void MachineSinking::SalvageUnsunkDebugUsersOfCopy(
// Point the users of this copy that are no longer dominated, at the source
// of the copy.
for (auto *User : DbgDefUsers) {
- User->getDebugOperand(0).setReg(MI.getOperand(1).getReg());
- User->getDebugOperand(0).setSubReg(MI.getOperand(1).getSubReg());
+ for (auto &Reg : DbgUseRegs) {
+ for (auto &DbgOp : User->getDebugOperandsForReg(Reg)) {
+ DbgOp.setReg(MI.getOperand(1).getReg());
+ DbgOp.setSubReg(MI.getOperand(1).getSubReg());
+ }
+ }
}
}
@@ -1521,8 +1545,10 @@ class PostRAMachineSinking : public MachineFunctionPass {
LiveRegUnits ModifiedRegUnits, UsedRegUnits;
/// Track DBG_VALUEs of (unmodified) register units. Each DBG_VALUE has an
- /// entry in this map for each unit it touches.
- DenseMap<unsigned, TinyPtrVector<MachineInstr *>> SeenDbgInstrs;
+ /// entry in this map for each unit it touches. The DBG_VALUE's entry
+ /// consists of a pointer to the instruction itself, and a vector of registers
+ /// referred to by the instruction that overlap the key register unit.
+ DenseMap<unsigned, SmallVector<MIRegs, 2>> SeenDbgInstrs;
/// Sink Copy instructions unused in the same block close to their uses in
/// successors.
@@ -1704,18 +1730,27 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
// We must sink this DBG_VALUE if its operand is sunk. To avoid searching
// for DBG_VALUEs later, record them when they're encountered.
if (MI->isDebugValue()) {
- auto &MO = MI->getDebugOperand(0);
- if (MO.isReg() && Register::isPhysicalRegister(MO.getReg())) {
- // Bail if we can already tell the sink would be rejected, rather
- // than needlessly accumulating lots of DBG_VALUEs.
- if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy,
- ModifiedRegUnits, UsedRegUnits))
- continue;
-
- // Record debug use of each reg unit.
- SmallSet<MCRegister, 4> Units = getRegUnits(MO.getReg(), TRI);
- for (MCRegister Reg : Units)
- SeenDbgInstrs[Reg].push_back(MI);
+ SmallDenseMap<MCRegister, SmallVector<unsigned, 2>, 4> MIUnits;
+ bool IsValid = true;
+ for (MachineOperand &MO : MI->debug_operands()) {
+ if (MO.isReg() && Register::isPhysicalRegister(MO.getReg())) {
+ // Bail if we can already tell the sink would be rejected, rather
+ // than needlessly accumulating lots of DBG_VALUEs.
+ if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy,
+ ModifiedRegUnits, UsedRegUnits)) {
+ IsValid = false;
+ break;
+ }
+
+ // Record debug use of each reg unit.
+ SmallSet<MCRegister, 4> RegUnits = getRegUnits(MO.getReg(), TRI);
+ for (MCRegister Reg : RegUnits)
+ MIUnits[Reg].push_back(MO.getReg());
+ }
+ }
+ if (IsValid) {
+ for (auto RegOps : MIUnits)
+ SeenDbgInstrs[RegOps.first].push_back({MI, RegOps.second});
}
continue;
}
@@ -1757,18 +1792,22 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
// Collect DBG_VALUEs that must sink with this copy. We've previously
// recorded which reg units that DBG_VALUEs read, if this instruction
// writes any of those units then the corresponding DBG_VALUEs must sink.
- SetVector<MachineInstr *> DbgValsToSinkSet;
+ MapVector<MachineInstr *, MIRegs::second_type> DbgValsToSinkMap;
for (auto &MO : MI->operands()) {
if (!MO.isReg() || !MO.isDef())
continue;
SmallSet<MCRegister, 4> Units = getRegUnits(MO.getReg(), TRI);
- for (MCRegister Reg : Units)
- for (auto *MI : SeenDbgInstrs.lookup(Reg))
- DbgValsToSinkSet.insert(MI);
+ for (MCRegister Reg : Units) {
+ for (auto MIRegs : SeenDbgInstrs.lookup(Reg)) {
+ auto &Regs = DbgValsToSinkMap[MIRegs.first];
+ for (unsigned Reg : MIRegs.second)
+ Regs.push_back(Reg);
+ }
+ }
}
- SmallVector<MachineInstr *, 4> DbgValsToSink(DbgValsToSinkSet.begin(),
- DbgValsToSinkSet.end());
+ SmallVector<MIRegs, 4> DbgValsToSink(DbgValsToSinkMap.begin(),
+ DbgValsToSinkMap.end());
// Clear the kill flag if SrcReg is killed between MI and the end of the
// block.
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 91c69119e541..a40eaf18ada4 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -185,7 +185,8 @@ static void stashEntryDbgValues(MachineBasicBlock &MBB,
break;
if (!MI.isDebugValue() || !MI.getDebugVariable()->isParameter())
continue;
- if (MI.getDebugOperand(0).isFI()) {
+ if (any_of(MI.debug_operands(),
+ [](const MachineOperand &MO) { return MO.isFI(); })) {
// We can only emit valid locations for frame indices after the frame
// setup, so do not stash away them.
FrameIndexValues.push_back(&MI);
@@ -1215,16 +1216,19 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF,
// way with simply the frame index and offset rather than any
// target-specific addressing mode.
if (MI.isDebugValue()) {
- assert(i == 0 && "Frame indices can only appear as the first "
- "operand of a DBG_VALUE machine instruction");
+ MachineOperand &Op = MI.getOperand(i);
+ assert(
+ MI.isDebugOperand(&Op) &&
+ "Frame indices can only appear as a debug operand in a DBG_VALUE*"
+ " machine instruction");
Register Reg;
- unsigned FrameIdx = MI.getOperand(0).getIndex();
+ unsigned FrameIdx = Op.getIndex();
unsigned Size = MF.getFrameInfo().getObjectSize(FrameIdx);
StackOffset Offset =
TFI->getFrameIndexReference(MF, FrameIdx, Reg);
- MI.getOperand(0).ChangeToRegister(Reg, false /*isDef*/);
- MI.getOperand(0).setIsDebug();
+ Op.ChangeToRegister(Reg, false /*isDef*/);
+ Op.setIsDebug();
const DIExpression *DIExpr = MI.getDebugExpression();
@@ -1255,7 +1259,7 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF,
// The debug operand at DebugOpIndex was a frame index at offset
// `Offset`; now the operand has been replaced with the frame
// register, we must add Offset with `register x, plus Offset`.
- unsigned DebugOpIndex = MI.getDebugOperandIndex(&MI.getOperand(i));
+ unsigned DebugOpIndex = MI.getDebugOperandIndex(&Op);
SmallVector<uint64_t, 3> Ops;
TRI.getOffsetOpcodes(Offset, Ops);
DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, DebugOpIndex);
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 5690023be036..6d4194006afd 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -108,7 +108,7 @@ namespace {
/// Stores assigned virtual registers present in the bundle MI.
DenseMap<Register, MCPhysReg> BundleVirtRegsMap;
- DenseMap<unsigned, SmallVector<MachineInstr *, 2>> LiveDbgValueMap;
+ DenseMap<unsigned, SmallVector<MachineOperand *, 2>> LiveDbgValueMap;
/// List of DBG_VALUE that we encountered without the vreg being assigned
/// because they were placed after the last use of the vreg.
DenseMap<unsigned, SmallVector<MachineInstr *, 1>> DanglingDbgValues;
@@ -406,9 +406,15 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg,
// When we spill a virtual register, we will have spill instructions behind
// every definition of it, meaning we can switch all the DBG_VALUEs over
// to just reference the stack slot.
- SmallVectorImpl<MachineInstr *> &LRIDbgValues = LiveDbgValueMap[VirtReg];
- for (MachineInstr *DBG : LRIDbgValues) {
- MachineInstr *NewDV = buildDbgValueForSpill(*MBB, Before, *DBG, FI);
+ SmallVectorImpl<MachineOperand *> &LRIDbgOperands = LiveDbgValueMap[VirtReg];
+ SmallDenseMap<MachineInstr *, SmallVector<const MachineOperand *>>
+ SpilledOperandsMap;
+ for (MachineOperand *MO : LRIDbgOperands)
+ SpilledOperandsMap[MO->getParent()].push_back(MO);
+ for (auto MISpilledOperands : SpilledOperandsMap) {
+ MachineInstr &DBG = *MISpilledOperands.first;
+ MachineInstr *NewDV = buildDbgValueForSpill(
+ *MBB, Before, *MISpilledOperands.first, FI, MISpilledOperands.second);
assert(NewDV->getParent() == MBB && "dangling parent pointer");
(void)NewDV;
LLVM_DEBUG(dbgs() << "Inserting debug info due to spill:\n" << *NewDV);
@@ -426,17 +432,17 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg,
// Rewrite unassigned dbg_values to use the stack slot.
// TODO We can potentially do this for list debug values as well if we know
// how the dbg_values are getting unassigned.
- if (DBG->isNonListDebugValue()) {
- MachineOperand &MO = DBG->getDebugOperand(0);
+ if (DBG.isNonListDebugValue()) {
+ MachineOperand &MO = DBG.getDebugOperand(0);
if (MO.isReg() && MO.getReg() == 0) {
- updateDbgValueForSpill(*DBG, FI);
+ updateDbgValueForSpill(DBG, FI, 0);
}
}
}
// Now this register is spilled there is should not be any DBG_VALUE
// pointing to this register because they are all pointing to spilled value
// now.
- LRIDbgValues.clear();
+ LRIDbgOperands.clear();
}
/// Insert reload instruction for \p PhysReg before \p Before.
@@ -1366,25 +1372,17 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
}
void RegAllocFast::handleDebugValue(MachineInstr &MI) {
- SmallSet<Register, 4> SeenRegisters;
- for (MachineOperand &MO : MI.debug_operands()) {
- // Ignore DBG_VALUEs that aren't based on virtual registers. These are
- // mostly constants and frame indices.
- if (!MO.isReg())
- continue;
- Register Reg = MO.getReg();
+ // Ignore DBG_VALUEs that aren't based on virtual registers. These are
+ // mostly constants and frame indices.
+ for (Register Reg : MI.getUsedDebugRegs()) {
if (!Register::isVirtualRegister(Reg))
continue;
- // Only process each register once per MI, each use of that register will
- // be updated if necessary.
- if (!SeenRegisters.insert(Reg).second)
- continue;
// Already spilled to a stackslot?
int SS = StackSlotForVirtReg[Reg];
if (SS != -1) {
// Modify DBG_VALUE now that the value is in a spill slot.
- updateDbgValueForSpill(MI, SS);
+ updateDbgValueForSpill(MI, SS, Reg);
LLVM_DEBUG(dbgs() << "Rewrite DBG_VALUE for spilled memory: " << MI);
continue;
}
@@ -1392,17 +1390,21 @@ void RegAllocFast::handleDebugValue(MachineInstr &MI) {
// See if this virtual register has already been allocated to a physical
// register or spilled to a stack slot.
LiveRegMap::iterator LRI = findLiveVirtReg(Reg);
+ SmallVector<MachineOperand *> DbgOps;
+ for (MachineOperand &Op : MI.getDebugOperandsForReg(Reg))
+ DbgOps.push_back(&Op);
+
if (LRI != LiveVirtRegs.end() && LRI->PhysReg) {
// Update every use of Reg within MI.
- for (auto &RegMO : MI.getDebugOperandsForReg(Reg))
- setPhysReg(MI, RegMO, LRI->PhysReg);
+ for (auto &RegMO : DbgOps)
+ setPhysReg(MI, *RegMO, LRI->PhysReg);
} else {
DanglingDbgValues[Reg].push_back(&MI);
}
// If Reg hasn't been spilled, put this DBG_VALUE in LiveDbgValueMap so
// that future spills of Reg will have DBG_VALUEs.
- LiveDbgValueMap[Reg].push_back(&MI);
+ LiveDbgValueMap[Reg].append(DbgOps.begin(), DbgOps.end());
}
}
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index 3e4b2ba0c1ae..4a20648ec4ce 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -3585,8 +3585,12 @@ void RegisterCoalescer::buildVRegToDbgValueMap(MachineFunction &MF)
// After collecting a block of DBG_VALUEs into ToInsert, enter them into the
// vreg => DbgValueLoc map.
auto CloseNewDVRange = [this, &ToInsert](SlotIndex Slot) {
- for (auto *X : ToInsert)
- DbgVRegToValues[X->getDebugOperand(0).getReg()].push_back({Slot, X});
+ for (auto *X : ToInsert) {
+ for (auto Op : X->debug_operands()) {
+ if (Op.isReg() && Op.getReg().isVirtual())
+ DbgVRegToValues[Op.getReg()].push_back({Slot, X});
+ }
+ }
ToInsert.clear();
};
@@ -3598,9 +3602,11 @@ void RegisterCoalescer::buildVRegToDbgValueMap(MachineFunction &MF)
SlotIndex CurrentSlot = Slots.getMBBStartIdx(&MBB);
for (auto &MI : MBB) {
- if (MI.isDebugValue() && MI.getDebugOperand(0).isReg() &&
- MI.getDebugOperand(0).getReg().isVirtual()) {
- ToInsert.push_back(&MI);
+ if (MI.isDebugValue()) {
+ if (any_of(MI.debug_operands(), [](const MachineOperand &MO) {
+ return MO.isReg() && MO.getReg().isVirtual();
+ }))
+ ToInsert.push_back(&MI);
} else if (!MI.isDebugInstr()) {
CurrentSlot = Slots.getInstructionIndex(MI);
CloseNewDVRange(CurrentSlot);
@@ -3697,12 +3703,14 @@ void RegisterCoalescer::checkMergingChangesDbgValuesImpl(Register Reg,
if (DbgValueSetIt->first < SegmentIt->end) {
// "Other" is live and there is a DBG_VALUE of Reg: test if we should
// set it undef.
- if (DbgValueSetIt->first >= SegmentIt->start &&
- DbgValueSetIt->second->getDebugOperand(0).getReg() != 0 &&
- ShouldUndef(DbgValueSetIt->first)) {
- // Mark undef, erase record of this DBG_VALUE to avoid revisiting.
- DbgValueSetIt->second->setDebugValueUndef();
- continue;
+ if (DbgValueSetIt->first >= SegmentIt->start) {
+ bool HasReg = DbgValueSetIt->second->hasDebugOperandForReg(Reg);
+ bool ShouldUndefReg = ShouldUndef(DbgValueSetIt->first);
+ if (HasReg && ShouldUndefReg) {
+ // Mark undef, erase record of this DBG_VALUE to avoid revisiting.
+ DbgValueSetIt->second->setDebugValueUndef();
+ continue;
+ }
}
++DbgValueSetIt;
} else {
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 289df8e3d1e5..9b757f7aba5e 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -793,11 +793,15 @@ void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
OS << MI->getDebugVariable()->getName();
OS << " <- ";
// Frame address. Currently handles register +- offset only.
- assert(MI->getDebugOperand(0).isReg() && MI->isDebugOffsetImm());
+ assert(MI->isIndirectDebugValue());
OS << '[';
- printOperand(MI, 0, OS);
- OS << '+';
- printOperand(MI, 1, OS);
+ for (unsigned I = 0, E = std::distance(MI->debug_operands().begin(),
+ MI->debug_operands().end());
+ I < E; ++I) {
+ if (I != 0)
+ OS << ", ";
+ printOperand(MI, I, OS);
+ }
OS << ']';
OS << "+";
printOperand(MI, NOps - 2, OS);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
index d511fde5c330..55be64ad7da0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
@@ -24,6 +24,7 @@ WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(
// the whole BB, not just contiguous DBG_VALUEs.
if (!Instr->getOperand(0).isReg())
return;
+ CurrentReg = Instr->getOperand(0).getReg();
MachineBasicBlock::iterator DI = *Instr;
++DI;
@@ -43,7 +44,9 @@ void WebAssemblyDebugValueManager::move(MachineInstr *Insert) {
void WebAssemblyDebugValueManager::updateReg(unsigned Reg) {
for (auto *DBI : DbgValues)
- DBI->getDebugOperand(0).setReg(Reg);
+ for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
+ MO.setReg(Reg);
+ CurrentReg = Reg;
}
void WebAssemblyDebugValueManager::clone(MachineInstr *Insert,
@@ -52,18 +55,18 @@ void WebAssemblyDebugValueManager::clone(MachineInstr *Insert,
MachineFunction *MF = MBB->getParent();
for (MachineInstr *DBI : reverse(DbgValues)) {
MachineInstr *Clone = MF->CloneMachineInstr(DBI);
- Clone->getDebugOperand(0).setReg(NewReg);
+ for (auto &MO : Clone->getDebugOperandsForReg(CurrentReg))
+ MO.setReg(NewReg);
MBB->insert(Insert, Clone);
}
}
void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) {
for (auto *DBI : DbgValues) {
- MachineOperand &Op0 = DBI->getDebugOperand(0);
- MachineOperand &Op1 = DBI->getOperand(1);
- bool Indirect = Op1.isImm() && Op1.getImm() == 0;
- Op0.ChangeToTargetIndex(Indirect ? llvm::WebAssembly::TI_LOCAL_INDIRECT
- : llvm::WebAssembly::TI_LOCAL,
- LocalId);
+ auto IndexType = DBI->isIndirectDebugValue()
+ ? llvm::WebAssembly::TI_LOCAL_INDIRECT
+ : llvm::WebAssembly::TI_LOCAL;
+ for (auto &MO : DBI->getDebugOperandsForReg(CurrentReg))
+ MO.ChangeToTargetIndex(IndexType, LocalId);
}
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h
index 7eae3cb5febd..c2dd56909304 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h
@@ -23,6 +23,7 @@ class MachineInstr;
class WebAssemblyDebugValueManager {
SmallVector<MachineInstr *, 2> DbgValues;
+ unsigned CurrentReg;
public:
WebAssemblyDebugValueManager(MachineInstr *Instr);
More information about the llvm-commits
mailing list