diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h --- 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 @@ return *(debug_operands().begin() + Index); } + SmallSet getUsedDebugRegs() const { + assert(isDebugValue() && "not a DBG_VALUE*"); + SmallSet 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 --- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -489,11 +489,16 @@ /// 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 &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 --- a/llvm/lib/CodeGen/InlineSpiller.cpp +++ b/llvm/lib/CodeGen/InlineSpiller.cpp @@ -1048,7 +1048,7 @@ // 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 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -2196,9 +2196,9 @@ /// 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 &SpilledOperands) { assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) && "Expected inlined-at fields to agree"); @@ -2211,19 +2211,26 @@ // We will replace the spilled register with a frame index, so // immediately deref all references to the spilled register. std::array 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 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 @@ } return NewMI; } +MachineInstr *llvm::buildDbgValueForSpill( + MachineBasicBlock &BB, MachineBasicBlock::iterator I, + const MachineInstr &Orig, int FrameIndex, + SmallVectorImpl &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 --- 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 @@ 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 @@ /// 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 @@ 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>; /// Sink an instruction and its associated debug instructions. static void performSink(MachineInstr &MI, MachineBasicBlock &SuccToSinkTo, MachineBasicBlock::iterator InsertPos, - SmallVectorImpl &DbgValuesToSink) { + SmallVectorImpl &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 @@ // 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 @@ ++InsertPos; // Collect debug users of any vreg that this inst defines. - SmallVector DbgUsersToSink; + SmallVector DbgUsersToSink; for (auto &MO : MI.operands()) { if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual()) continue; @@ -1398,10 +1415,11 @@ 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(1, MO.getReg())}); } } } @@ -1436,10 +1454,12 @@ // 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 DbgDefUsers; + SmallVector 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 @@ 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 @@ // 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 @@ 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> 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> SeenDbgInstrs; /// Sink Copy instructions unused in the same block close to their uses in /// successors. @@ -1704,18 +1730,27 @@ // 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 Units = getRegUnits(MO.getReg(), TRI); - for (MCRegister Reg : Units) - SeenDbgInstrs[Reg].push_back(MI); + SmallDenseMap, 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 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 @@ // 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 DbgValsToSinkSet; + MapVector DbgValsToSinkMap; for (auto &MO : MI->operands()) { if (!MO.isReg() || !MO.isDef()) continue; SmallSet 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 DbgValsToSink(DbgValsToSinkSet.begin(), - DbgValsToSinkSet.end()); + SmallVector 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 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -185,7 +185,8 @@ 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 @@ // 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 @@ // 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 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 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -108,7 +108,7 @@ /// Stores assigned virtual registers present in the bundle MI. DenseMap BundleVirtRegsMap; - DenseMap> LiveDbgValueMap; + DenseMap> 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> DanglingDbgValues; @@ -406,9 +406,15 @@ // 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 &LRIDbgValues = LiveDbgValueMap[VirtReg]; - for (MachineInstr *DBG : LRIDbgValues) { - MachineInstr *NewDV = buildDbgValueForSpill(*MBB, Before, *DBG, FI); + SmallVectorImpl &LRIDbgOperands = LiveDbgValueMap[VirtReg]; + SmallDenseMap> + 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 @@ // 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::handleDebugValue(MachineInstr &MI) { - SmallSet 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 @@ // 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 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 --- a/llvm/lib/CodeGen/RegisterCoalescer.cpp +++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp @@ -3585,8 +3585,12 @@ // 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 @@ 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 @@ 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 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -793,11 +793,15 @@ 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.h b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h @@ -23,6 +23,7 @@ class WebAssemblyDebugValueManager { SmallVector DbgValues; + unsigned CurrentReg; public: WebAssemblyDebugValueManager(MachineInstr *Instr); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp @@ -24,6 +24,7 @@ // 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::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 @@ 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); } }