Index: lib/CodeGen/LiveDebugValues.cpp =================================================================== --- lib/CodeGen/LiveDebugValues.cpp +++ lib/CodeGen/LiveDebugValues.cpp @@ -464,30 +464,29 @@ /// address the spill location in a target independent way. VarLoc::SpillLoc extractSpillBaseRegAndOffset(const MachineInstr &MI); void insertTransferDebugPair(MachineInstr &MI, OpenRangesSet &OpenRanges, - TransferMap &Transfers, VarLocMap &VarLocIDs, + TransferMap *Transfers, VarLocMap &VarLocIDs, unsigned OldVarID, TransferKind Kind, unsigned NewReg = 0); void transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs); void transferSpillOrRestoreInst(MachineInstr &MI, OpenRangesSet &OpenRanges, - VarLocMap &VarLocIDs, TransferMap &Transfers); + VarLocMap &VarLocIDs, TransferMap *Transfers); void emitEntryValues(MachineInstr &MI, OpenRangesSet &OpenRanges, - VarLocMap &VarLocIDs, TransferMap &Transfers, + VarLocMap &VarLocIDs, TransferMap *Transfers, DebugParamMap &DebugEntryVals, SparseBitVector<> &KillSet); void transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges, - VarLocMap &VarLocIDs, TransferMap &Transfers); + VarLocMap &VarLocIDs, TransferMap *Transfers); void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges, - VarLocMap &VarLocIDs, TransferMap &Transfers, + VarLocMap &VarLocIDs, TransferMap *Transfers, DebugParamMap &DebugEntryVals); bool transferTerminator(MachineBasicBlock *MBB, OpenRangesSet &OpenRanges, VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs); void process(MachineInstr &MI, OpenRangesSet &OpenRanges, - VarLocInMBB &OutLocs, VarLocMap &VarLocIDs, - TransferMap &Transfers, DebugParamMap &DebugEntryVals, - OverlapMap &OverlapFragments, + VarLocMap &VarLocIDs, TransferMap *Transfers, + DebugParamMap &DebugEntryVals, OverlapMap &OverlapFragments, VarToFragments &SeenFragments); void accumulateFragmentMap(MachineInstr &MI, VarToFragments &SeenFragments, @@ -703,7 +702,7 @@ void LiveDebugValues::emitEntryValues(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, - TransferMap &Transfers, + TransferMap *Transfers, DebugParamMap &DebugEntryVals, SparseBitVector<> &KillSet) { for (unsigned ID : KillSet) { @@ -724,18 +723,20 @@ VarLoc EntryLoc = VarLoc::CreateEntryLoc(*ParamDebugInstr, LS, NewExpr); unsigned EntryValLocID = VarLocIDs.insert(EntryLoc); - Transfers.push_back({&MI, EntryValLocID}); OpenRanges.insert(EntryValLocID, EntryLoc.Var); + + if (Transfers) + Transfers->push_back({&MI, EntryValLocID}); } } -/// Create new TransferDebugPair and insert it in \p Transfers. The VarLoc -/// with \p OldVarID should be deleted form \p OpenRanges and replaced with -/// new VarLoc. If \p NewReg is different than default zero value then the -/// new location will be register location created by the copy like instruction, -/// otherwise it is variable's location on the stack. +/// Implement a transfer -- the VarLoc with \p OldVarID should be deleted from +/// \p OpenRanges and replaced with a new VarLoc. If \p NewReg is different +/// than default zero value then the new location will be register location +/// created by the copy like instruction, otherwise it is variable's location +/// on the stack. If \p Transfers is non-null, record the transfers location. void LiveDebugValues::insertTransferDebugPair( - MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers, + MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap *Transfers, VarLocMap &VarLocIDs, unsigned OldVarID, TransferKind Kind, unsigned NewReg) { const MachineInstr *DebugInstr = &VarLocIDs[OldVarID].MI; @@ -748,11 +749,14 @@ DebugVariable V(*DebugInstr); OpenRanges.erase(V); - // Record the new location as an open range, and a postponed transfer - // inserting a DBG_VALUE for this location. + // Record the new location as an open range OpenRanges.insert(LocId, VL.Var); - TransferDebugPair MIP = {&MI, LocId}; - Transfers.push_back(MIP); + + // If requested, record the transfer between locations. + if (Transfers) { + TransferDebugPair MIP = {&MI, LocId}; + Transfers->push_back(MIP); + } }; // End all previous ranges of Var. @@ -806,7 +810,7 @@ /// A definition of a register may mark the end of a range. void LiveDebugValues::transferRegisterDef( MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, - TransferMap &Transfers, DebugParamMap &DebugEntryVals) { + TransferMap *Transfers, DebugParamMap &DebugEntryVals) { MachineFunction *MF = MI.getMF(); const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); @@ -916,14 +920,12 @@ /// A spilled register may indicate that we have to end the current range of /// a variable and create a new one for the spill location. /// A restored register may indicate the reverse situation. -/// We don't want to insert any instructions in process(), so we just create -/// the DBG_VALUE without inserting it and keep track of it in \p Transfers. -/// It will be inserted into the BB when we're done iterating over the -/// instructions. +/// Any change in location will be recorded in \p OpenRanges, and \p Transfers +/// if it is non-null. void LiveDebugValues::transferSpillOrRestoreInst(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, - TransferMap &Transfers) { + TransferMap *Transfers) { MachineFunction *MF = MI.getMF(); TransferKind TKind; unsigned Reg; @@ -953,7 +955,9 @@ KillSet.set(ID); VarLoc UndefVL = VarLoc::CreateCopyLoc(VL.MI, LS, 0); unsigned UndefLocID = VarLocIDs.insert(UndefVL); - Transfers.push_back({&MI, UndefLocID}); + + if (Transfers) + Transfers->push_back({&MI, UndefLocID}); } } OpenRanges.erase(KillSet, VarLocIDs); @@ -999,7 +1003,7 @@ void LiveDebugValues::transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, - TransferMap &Transfers) { + TransferMap *Transfers) { const MachineOperand *SrcRegOp, *DestRegOp; if (!TII->isCopyInstr(MI, SrcRegOp, DestRegOp) || !SrcRegOp->isKill() || @@ -1118,8 +1122,7 @@ /// This routine creates OpenRanges and OutLocs. void LiveDebugValues::process(MachineInstr &MI, OpenRangesSet &OpenRanges, - VarLocInMBB &OutLocs, VarLocMap &VarLocIDs, - TransferMap &Transfers, + VarLocMap &VarLocIDs, TransferMap *Transfers, DebugParamMap &DebugEntryVals, OverlapMap &OverlapFragments, VarToFragments &SeenFragments) { @@ -1382,9 +1385,12 @@ // correspond to user variables. // First load any pending inlocs. OpenRanges.insertFromLocSet(PendingInLocs[MBB], VarLocIDs); + + // Don't record transfers while propagating locations: they may be + // be invalidated by future iterations. for (auto &MI : *MBB) - process(MI, OpenRanges, OutLocs, VarLocIDs, Transfers, - DebugEntryVals, OverlapFragments, SeenFragments); + process(MI, OpenRanges, VarLocIDs, nullptr, DebugEntryVals, + OverlapFragments, SeenFragments); OLChanged |= transferTerminator(MBB, OpenRanges, OutLocs, VarLocIDs); LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, @@ -1407,6 +1413,16 @@ assert(Pending.empty() && "Pending should be empty"); } + // Reprocess all instructions a final time and record transfers. The live-in + // locations should not change as we've reached a fixedpoint. + for (MachineBasicBlock &MBB : MF) { + OpenRanges.insertFromLocSet(PendingInLocs[&MBB], VarLocIDs); + for (auto &MI : MBB) + process(MI, OpenRanges, VarLocIDs, &Transfers, DebugEntryVals, + OverlapFragments, SeenFragments); + OpenRanges.clear(); + } + // Add any DBG_VALUE instructions created by location transfers. for (auto &TR : Transfers) { MachineBasicBlock *MBB = TR.TransferInst->getParent(); Index: test/DebugInfo/MIR/X86/live-debug-values-bad-transfer.mir =================================================================== --- test/DebugInfo/MIR/X86/live-debug-values-bad-transfer.mir +++ test/DebugInfo/MIR/X86/live-debug-values-bad-transfer.mir @@ -6,17 +6,10 @@ # loop. There should be no transfer from ecx to ebx -- this is ensured by the # FileCheck implicit-check-not option. # -# FIXME: we successfully prevent the false location (ebx) from being -# propagated into block 2, but the original transfer isn't yet eliminated. -# Thus we get no DBG_VALUe in block 2, but an invalid one in block 1. -# # CHECK-LABEL: name: foo # CHECK-LABEL: bb.0.entry: # CHECK: $ecx = MOV32ri 0 # CHECK-NEXT: DBG_VALUE -# CHECK-LABEL: bb.1.loop: -# CHECK: $ebx = COPY killed $ecx -# CHECK-NEXT: DBG_VALUE --- | source_filename = "live-debug-values-remove-range.ll"