Index: lib/CodeGen/LiveDebugValues.cpp =================================================================== --- lib/CodeGen/LiveDebugValues.cpp +++ lib/CodeGen/LiveDebugValues.cpp @@ -143,16 +143,25 @@ typedef SparseBitVector<> VarLocSet; typedef SmallDenseMap VarLocInMBB; - /// This holds the working set of open ranges. For fast access, this - /// is done both as a set of VarLocIDs, and a map of DebugVariable - /// to recent VarLocID. Note that a DBG_VALUE ends all previous open - /// ranges for the same variable. + /// This holds the working set of open ranges. The canonical list is + /// implemented as a set of VarLocIDs. Redundant data structures + /// exist for optimization purposes: + /// + /// - For fast access in transferDebugValue() a map from + /// DebugVariable to recent VarLocID is stored. Note that a + /// DBG_VALUE ends all previous open ranges for the same variable. + /// + /// - For fast access in transferRegisterDef, a bitvector of + /// registers holding DebugVariables is stored. struct VarLocList { VarLocSet VarLocs; SmallDenseMap Vars; + BitVector Regs; + VarLocList(unsigned NumRegs) : Regs(NumRegs) {} void clear() { VarLocs.clear(); Vars.clear(); + Regs.reset(); } }; @@ -262,11 +271,13 @@ } // Add the VarLoc to OpenRanges from this DBG_VALUE. // TODO: Currently handles DBG_VALUE which has only reg as location. - if (isDbgValueDescribedByReg(MI)) { + if (unsigned RegNo = isDbgValueDescribedByReg(MI)) { VarLoc VL(MI); unsigned ID = VarLocIDs.insert(VL); OpenRanges.VarLocs.set(ID); OpenRanges.Vars.insert({VL.Var, ID}); + for (MCRegAliasIterator RAI(RegNo, TRI, true); RAI.isValid(); ++RAI) + OpenRanges.Regs.set(*RAI); } } @@ -277,30 +288,37 @@ MachineFunction *MF = MI.getParent()->getParent(); const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); - SparseBitVector<> KillSet; + BitVector ClobberedRegs(TRI->getNumRegs()); for (const MachineOperand &MO : MI.operands()) { if (MO.isReg() && MO.isDef() && MO.getReg() && TRI->isPhysicalRegister(MO.getReg())) { // Remove ranges of all aliased registers. - for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI) - for (unsigned ID : OpenRanges.VarLocs) - if (VarLocIDs[ID].isDescribedByReg() == *RAI) - KillSet.set(ID); + ClobberedRegs.set(MO.getReg()); } else if (MO.isRegMask()) { // Remove ranges of all clobbered registers. Register masks don't usually // list SP as preserved. While the debug info may be off for an // instruction or two around callee-cleanup calls, transferring the // DEBUG_VALUE across the call is still a better user experience. - for (unsigned ID : OpenRanges.VarLocs) { - unsigned Reg = VarLocIDs[ID].isDescribedByReg(); - if (Reg && Reg != SP && MO.clobbersPhysReg(Reg)) - KillSet.set(ID); - } + BitVector Mask(TRI->getNumRegs()); + Mask.setBitsNotInMask(MO.getRegMask()); + Mask.reset(SP); + ClobberedRegs |= Mask; } } + + // Remove ranges of all clobbered registers. + VarLocSet KillSet; + ClobberedRegs &= OpenRanges.Regs; + if (ClobberedRegs.any()) + for (unsigned ID : OpenRanges.VarLocs) + if (unsigned RegNo = VarLocIDs[ID].isDescribedByReg()) + for (MCRegAliasIterator RAI(RegNo, TRI, true); RAI.isValid(); ++RAI) + if (ClobberedRegs[*RAI]) { + OpenRanges.Regs.reset(*RAI); + OpenRanges.Vars.erase(VarLocIDs[ID].Var); + KillSet.set(ID); + } OpenRanges.VarLocs.intersectWithComplement(KillSet); - for (unsigned ID : KillSet) - OpenRanges.Vars.erase(VarLocIDs[ID].Var); } /// Terminate all open ranges at the end of the current basic block. @@ -402,7 +420,7 @@ bool MBBJoined = false; VarLocMap VarLocIDs; // Map VarLoc<>unique ID for use in bitvectors. - VarLocList OpenRanges; // Ranges that are open until end of bb. + VarLocList OpenRanges(TRI->getNumRegs()); // Ranges that are open until end of bb. VarLocInMBB OutLocs; // Ranges that exist beyond bb. VarLocInMBB InLocs; // Ranges that are incoming after joining.