Index: include/llvm/CodeGen/LiveIntervalAnalysis.h =================================================================== --- include/llvm/CodeGen/LiveIntervalAnalysis.h +++ include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -436,6 +436,10 @@ /// have any segments or value numbers. void constructMainRangeFromSubranges(LiveInterval &LI); + /// Simple check to verify that segments/SlotIndices are valid in + /// LiveIntervals including SubRanges + bool verifySegments(void) const; + private: /// Compute live intervals for all virtual registers. void computeVirtRegs(); Index: lib/CodeGen/LiveIntervalAnalysis.cpp =================================================================== --- lib/CodeGen/LiveIntervalAnalysis.cpp +++ lib/CodeGen/LiveIntervalAnalysis.cpp @@ -1596,3 +1596,59 @@ LRCalc->reset(MF, getSlotIndexes(), DomTree, &getVNInfoAllocator()); LRCalc->constructMainRangeFromSubranges(LI); } + +bool LiveIntervals::verifySegments(void) const { + // Simple verification that ensures that all the Intervals and SubRanges refer + // to valid slots. + // This is intended to be used for testing purposes - usually after + // encountering code that provokes a SubRange join assertion + + bool Result = true; + + for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + if (hasInterval(Reg)) { + const LiveInterval &Interval = getInterval(Reg); + for (const LiveInterval::Segment &S : Interval.segments) { + MachineInstr *MI = nullptr; + if (!S.start.isBlock()) { + MI = getInstructionFromIndex(S.start); + if (!MI) { + DEBUG(dbgs() << "verifySegments " << Interval << " : bad segment start = " << S << "\n"); + Result = false; + } + } + if (!S.end.isBlock()) { + MI = getInstructionFromIndex(S.end); + if (!MI) { + DEBUG(dbgs() << "verifySegments " << Interval << " : bad segment end = " << S << "\n"); + Result = false; + } + } + } + + // Check SubRanges + for (const LiveInterval::SubRange &SR : Interval.subranges()) { + for (const LiveInterval::Segment &S : SR.segments) { + MachineInstr *MI = nullptr; + if (!S.start.isBlock()) { + MI = getInstructionFromIndex(S.start); + if (!MI) { + DEBUG(dbgs() << "verifySegments " << Interval << " : SubRange : " << SR << " : bad segment start = " << S << "\n"); + Result = false; + } + } + if (!S.end.isBlock()) { + MI = getInstructionFromIndex(S.end); + if (!MI) { + DEBUG(dbgs() << "verifySegments " << Interval << " : SubRange : " << SR << " : bad segment end = " << S << "\n"); + Result = false; + } + } + } + } + } + } + return Result; +} + Index: lib/CodeGen/RegisterCoalescer.cpp =================================================================== --- lib/CodeGen/RegisterCoalescer.cpp +++ lib/CodeGen/RegisterCoalescer.cpp @@ -95,6 +95,11 @@ cl::desc("Verify machine instrs before and after register coalescing"), cl::Hidden); +static cl::opt +VerifyLiveIntervals("verify-live-intervals", + cl::desc("Verify LiveIntervals by inspecting all Segments for invalid slot indices"), + cl::Hidden); + namespace { class RegisterCoalescer : public MachineFunctionPass, @@ -3323,6 +3328,8 @@ // until we make no progress. while (copyCoalesceWorkList(WorkList)) /* empty */ ; + //LIS->verifySlots(); + //LIS->dump(); } void RegisterCoalescer::releaseMemory() { @@ -3399,6 +3406,15 @@ } } + // Verify that the Segments in the LiveIntervals are still valid + // This check looks for Segments within Intervals that start or end with + // invalid slot indices + // It is often more helpful for debug to insert this check after each joinCopy + // to pinpoint the precise cause of the error + if (VerifyLiveIntervals) + // Check that LiveIntervals are still valid after joinCopy + assert(LIS->verifySegments() && "joinCopy has resulted in invalid Segments in liveIntervals"); + DEBUG(dump()); if (VerifyCoalescing) MF->verify(this, "After register coalescing");