Eliminate the last use of InterferenceResult.

The Query class now holds two iterators instead of an InterferenceResult
instance. The iterators are used as bookmarks for repeated
collectInterferingVRegs calls.

llvm-svn: 137380
This commit is contained in:
Jakob Stoklund Olesen 2011-08-11 22:46:04 +00:00
parent 79d60d0e94
commit cd14efaec2
2 changed files with 57 additions and 63 deletions

View File

@ -117,68 +117,35 @@ void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) {
// //
// Assumes that segments are sorted by start position in both // Assumes that segments are sorted by start position in both
// LiveInterval and LiveSegments. // LiveInterval and LiveSegments.
void LiveIntervalUnion::Query::findIntersection(InterferenceResult &IR) const { void LiveIntervalUnion::Query::findIntersection() {
// Search until reaching the end of the LiveUnion segments. // Search until reaching the end of the LiveUnion segments.
LiveInterval::iterator VirtRegEnd = VirtReg->end(); LiveInterval::iterator VirtRegEnd = VirtReg->end();
if (IR.VirtRegI == VirtRegEnd) if (VirtRegI == VirtRegEnd)
return; return;
while (IR.LiveUnionI.valid()) { while (LiveUnionI.valid()) {
// Slowly advance the live virtual reg iterator until we surpass the next // Slowly advance the live virtual reg iterator until we surpass the next
// segment in LiveUnion. // segment in LiveUnion.
// //
// Note: If this is ever used for coalescing of fixed registers and we have // Note: If this is ever used for coalescing of fixed registers and we have
// a live vreg with thousands of segments, then change this code to use // a live vreg with thousands of segments, then change this code to use
// upperBound instead. // upperBound instead.
IR.VirtRegI = VirtReg->advanceTo(IR.VirtRegI, IR.LiveUnionI.start()); VirtRegI = VirtReg->advanceTo(VirtRegI, LiveUnionI.start());
if (IR.VirtRegI == VirtRegEnd) if (VirtRegI == VirtRegEnd)
break; // Retain current (nonoverlapping) LiveUnionI break; // Retain current (nonoverlapping) LiveUnionI
// VirtRegI may have advanced far beyond LiveUnionI, catch up. // VirtRegI may have advanced far beyond LiveUnionI, catch up.
IR.LiveUnionI.advanceTo(IR.VirtRegI->start); LiveUnionI.advanceTo(VirtRegI->start);
// Check if no LiveUnionI exists with VirtRegI->Start < LiveUnionI.end // Check if no LiveUnionI exists with VirtRegI->Start < LiveUnionI.end
if (!IR.LiveUnionI.valid()) if (!LiveUnionI.valid())
break; break;
if (IR.LiveUnionI.start() < IR.VirtRegI->end) { if (LiveUnionI.start() < VirtRegI->end) {
assert(overlap(*IR.VirtRegI, IR.LiveUnionI) && assert(overlap(*VirtRegI, LiveUnionI) && "upperBound postcondition");
"upperBound postcondition");
break; break;
} }
} }
if (!IR.LiveUnionI.valid()) if (!LiveUnionI.valid())
IR.VirtRegI = VirtRegEnd; VirtRegI = VirtRegEnd;
}
// Find the first intersection, and cache interference info
// (retain segment iterators into both VirtReg and LiveUnion).
const LiveIntervalUnion::InterferenceResult &
LiveIntervalUnion::Query::firstInterference() {
if (CheckedFirstInterference)
return FirstInterference;
CheckedFirstInterference = true;
InterferenceResult &IR = FirstInterference;
IR.LiveUnionI.setMap(LiveUnion->getMap());
// Quickly skip interference check for empty sets.
if (VirtReg->empty() || LiveUnion->empty()) {
IR.VirtRegI = VirtReg->end();
} else if (VirtReg->beginIndex() < LiveUnion->startIndex()) {
// VirtReg starts first, perform double binary search.
IR.VirtRegI = VirtReg->find(LiveUnion->startIndex());
if (IR.VirtRegI != VirtReg->end())
IR.LiveUnionI.find(IR.VirtRegI->start);
} else {
// LiveUnion starts first, perform double binary search.
IR.LiveUnionI.find(VirtReg->beginIndex());
if (IR.LiveUnionI.valid())
IR.VirtRegI = VirtReg->find(IR.LiveUnionI.start());
else
IR.VirtRegI = VirtReg->end();
}
findIntersection(FirstInterference);
assert((IR.VirtRegI == VirtReg->end() || IR.LiveUnionI.valid())
&& "Uninitialized iterator");
return FirstInterference;
} }
// Scan the vector of interfering virtual registers in this union. Assume it's // Scan the vector of interfering virtual registers in this union. Assume it's
@ -200,37 +167,64 @@ bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const {
// For comments on how to speed it up, see Query::findIntersection(). // For comments on how to speed it up, see Query::findIntersection().
unsigned LiveIntervalUnion::Query:: unsigned LiveIntervalUnion::Query::
collectInterferingVRegs(unsigned MaxInterferingRegs) { collectInterferingVRegs(unsigned MaxInterferingRegs) {
if (InterferingVRegs.size() >= MaxInterferingRegs) // Fast path return if we already have the desired information.
if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs)
return InterferingVRegs.size(); return InterferingVRegs.size();
InterferenceResult IR = firstInterference();
// Set up iterators on the first call.
if (!CheckedFirstInterference) {
CheckedFirstInterference = true;
LiveUnionI.setMap(LiveUnion->getMap());
// Quickly skip interference check for empty sets.
if (VirtReg->empty() || LiveUnion->empty()) {
VirtRegI = VirtReg->end();
} else if (VirtReg->beginIndex() < LiveUnion->startIndex()) {
// VirtReg starts first, perform double binary search.
VirtRegI = VirtReg->find(LiveUnion->startIndex());
if (VirtRegI != VirtReg->end())
LiveUnionI.find(VirtRegI->start);
} else {
// LiveUnion starts first, perform double binary search.
LiveUnionI.find(VirtReg->beginIndex());
if (LiveUnionI.valid())
VirtRegI = VirtReg->find(LiveUnionI.start());
else
VirtRegI = VirtReg->end();
}
findIntersection();
assert((VirtRegI == VirtReg->end() || LiveUnionI.valid())
&& "Uninitialized iterator");
}
LiveInterval::iterator VirtRegEnd = VirtReg->end(); LiveInterval::iterator VirtRegEnd = VirtReg->end();
LiveInterval *RecentInterferingVReg = NULL; LiveInterval *RecentInterferingVReg = NULL;
if (IR.VirtRegI != VirtRegEnd) while (IR.LiveUnionI.valid()) { if (VirtRegI != VirtRegEnd) while (LiveUnionI.valid()) {
// Advance the union's iterator to reach an unseen interfering vreg. // Advance the union's iterator to reach an unseen interfering vreg.
do { do {
if (IR.LiveUnionI.value() == RecentInterferingVReg) if (LiveUnionI.value() == RecentInterferingVReg)
continue; continue;
if (!isSeenInterference(IR.LiveUnionI.value())) if (!isSeenInterference(LiveUnionI.value()))
break; break;
// Cache the most recent interfering vreg to bypass isSeenInterference. // Cache the most recent interfering vreg to bypass isSeenInterference.
RecentInterferingVReg = IR.LiveUnionI.value(); RecentInterferingVReg = LiveUnionI.value();
} while ((++IR.LiveUnionI).valid()); } while ((++LiveUnionI).valid());
if (!IR.LiveUnionI.valid()) if (!LiveUnionI.valid())
break; break;
// Advance the VirtReg iterator until surpassing the next segment in // Advance the VirtReg iterator until surpassing the next segment in
// LiveUnion. // LiveUnion.
IR.VirtRegI = VirtReg->advanceTo(IR.VirtRegI, IR.LiveUnionI.start()); VirtRegI = VirtReg->advanceTo(VirtRegI, LiveUnionI.start());
if (IR.VirtRegI == VirtRegEnd) if (VirtRegI == VirtRegEnd)
break; break;
// Check for intersection with the union's segment. // Check for intersection with the union's segment.
if (overlap(*IR.VirtRegI, IR.LiveUnionI)) { if (overlap(*VirtRegI, LiveUnionI)) {
if (!IR.LiveUnionI.value()->isSpillable()) if (!LiveUnionI.value()->isSpillable())
SeenUnspillableVReg = true; SeenUnspillableVReg = true;
if (InterferingVRegs.size() == MaxInterferingRegs) if (InterferingVRegs.size() == MaxInterferingRegs)
@ -238,17 +232,17 @@ collectInterferingVRegs(unsigned MaxInterferingRegs) {
// interference exists beyond those we collected. // interference exists beyond those we collected.
return MaxInterferingRegs; return MaxInterferingRegs;
InterferingVRegs.push_back(IR.LiveUnionI.value()); InterferingVRegs.push_back(LiveUnionI.value());
// Cache the most recent interfering vreg to bypass isSeenInterference. // Cache the most recent interfering vreg to bypass isSeenInterference.
RecentInterferingVReg = IR.LiveUnionI.value(); RecentInterferingVReg = LiveUnionI.value();
++IR.LiveUnionI; ++LiveUnionI;
continue; continue;
} }
// VirtRegI may have advanced far beyond LiveUnionI, // VirtRegI may have advanced far beyond LiveUnionI,
// do a fast intersection test to "catch up" // do a fast intersection test to "catch up"
IR.LiveUnionI.advanceTo(IR.VirtRegI->start); LiveUnionI.advanceTo(VirtRegI->start);
} }
SeenAllInterferences = true; SeenAllInterferences = true;
return InterferingVRegs.size(); return InterferingVRegs.size();

View File

@ -142,7 +142,8 @@ public:
class Query { class Query {
LiveIntervalUnion *LiveUnion; LiveIntervalUnion *LiveUnion;
LiveInterval *VirtReg; LiveInterval *VirtReg;
InterferenceResult FirstInterference; LiveInterval::iterator VirtRegI; // current position in VirtReg
SegmentIter LiveUnionI; // current position in LiveUnion
SmallVector<LiveInterval*,4> InterferingVRegs; SmallVector<LiveInterval*,4> InterferingVRegs;
bool CheckedFirstInterference; bool CheckedFirstInterference;
bool SeenAllInterferences; bool SeenAllInterferences;
@ -217,8 +218,7 @@ public:
void operator=(const Query&); // DO NOT IMPLEMENT void operator=(const Query&); // DO NOT IMPLEMENT
// Private interface for queries // Private interface for queries
const InterferenceResult &firstInterference(); void findIntersection();
void findIntersection(InterferenceResult &IR) const;
}; };
}; };