// Merge a LiveInterval's segments. Guarantee no overlaps. void LiveIntervalUnion::unify(LiveInterval &VirtReg) { if (VirtReg.empty()) return; // Insert each of the virtual register's live segments into the map. LiveInterval::iterator RegPos = VirtReg.begin(); LiveInterval::iterator RegEnd = VirtReg.end(); SegmentIter SegPos = Segments.find(RegPos->start); for (;;) { SegPos.insert(RegPos->start, RegPos->end, &VirtReg); if (++RegPos == RegEnd) return; SegPos.advanceTo(RegPos->start); } }
// Merge a LiveInterval's segments. Guarantee no overlaps. void LiveIntervalUnion::unify(LiveInterval &VirtReg) { if (VirtReg.empty()) return; ++Tag; // Insert each of the virtual register's live segments into the map. LiveInterval::iterator RegPos = VirtReg.begin(); LiveInterval::iterator RegEnd = VirtReg.end(); SegmentIter SegPos = Segments.find(RegPos->start); while (SegPos.valid()) { SegPos.insert(RegPos->start, RegPos->end, &VirtReg); if (++RegPos == RegEnd) return; SegPos.advanceTo(RegPos->start); } // We have reached the end of Segments, so it is no longer necessary to search // for the insertion position. // It is faster to insert the end first. --RegEnd; SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg); for (; RegPos != RegEnd; ++RegPos, ++SegPos) SegPos.insert(RegPos->start, RegPos->end, &VirtReg); }
// Remove a live virtual register's segments from this union. void LiveIntervalUnion::extract(LiveInterval &VirtReg) { if (VirtReg.empty()) return; // Remove each of the virtual register's live segments from the map. LiveInterval::iterator RegPos = VirtReg.begin(); LiveInterval::iterator RegEnd = VirtReg.end(); SegmentIter SegPos = Segments.find(RegPos->start); for (;;) { assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval"); SegPos.erase(); if (!SegPos.valid()) return; // Skip all segments that may have been coalesced. RegPos = VirtReg.advanceTo(RegPos, SegPos.start()); if (RegPos == RegEnd) return; SegPos.advanceTo(RegPos->start); } }
// Remove a live virtual register's segments from this union. void LiveIntervalUnion::extract(LiveInterval &VirtReg, const LiveRange &Range) { if (Range.empty()) return; ++Tag; // Remove each of the virtual register's live segments from the map. LiveRange::const_iterator RegPos = Range.begin(); LiveRange::const_iterator RegEnd = Range.end(); SegmentIter SegPos = Segments.find(RegPos->start); while (true) { assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval"); SegPos.erase(); if (!SegPos.valid()) return; // Skip all segments that may have been coalesced. RegPos = Range.advanceTo(RegPos, SegPos.start()); if (RegPos == RegEnd) return; SegPos.advanceTo(RegPos->start); } }
// Verify the live intervals in this union and add them to the visited set. void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) { for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI) VisitedVRegs.set(SI.value()->reg); }
Segment QueueItem::getNextSegment(int64_t blockSize, int64_t wantedSize) const { if(getSize() == -1 || blockSize == 0) { return Segment(0, -1); } if(!BOOLSETTING(SEGMENTED_DL) && !downloads.empty()) { return Segment(0, 0); } int64_t remaining = getSize() - getDownloadedBytes(); int64_t targetSize; if(BOOLSETTING(SEGMENTED_DL)) { double done = static_cast<double>(getDownloadedBytes()) / getSize(); // We want smaller blocks at the end of the transfer, squaring gives a nice curve... targetSize = wantedSize * std::max(0.25, (1. - (done * done))); if(targetSize > blockSize) { // Round off to nearest block size targetSize = ((targetSize + (blockSize / 2)) / blockSize) * blockSize; } else { targetSize = blockSize; } } else { targetSize = remaining; } int64_t start = 0; int64_t curSize = targetSize; while(start < getSize()) { int64_t end = std::min(getSize(), start + curSize); Segment block(start, end - start); bool overlaps = false; for(SegmentIter i = done.begin(); !overlaps && i != done.end(); ++i) { if(curSize <= blockSize) { int64_t dstart = i->getStart(); int64_t dend = i->getEnd(); // We accept partial overlaps, only consider the block done if it is fully consumed by the done block if(dstart <= start && dend >= end) { overlaps = true; } } else { overlaps = block.overlaps(*i); } } for(DownloadList::const_iterator i = downloads.begin(); !overlaps && i !=downloads.end(); ++i) { overlaps = block.overlaps((*i)->getSegment()); } if(!overlaps) { return block; } if(curSize > blockSize) { curSize -= blockSize; } else { start = end; curSize = targetSize; } } return Segment(0, 0); }