// Merge a LiveInterval's segments. Guarantee no overlaps. void LiveIntervalUnion::unify(LiveInterval &VirtReg, const LiveRange &Range) { if (Range.empty()) return; ++Tag; // Insert each of the virtual register's live segments into the map. LiveRange::const_iterator RegPos = Range.begin(); LiveRange::const_iterator RegEnd = Range.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); }
/// MergeValueInAsValue - Merge all of the live segments of a specific val# /// in RHS into this live range as the specified value number. /// The segments in RHS are allowed to overlap with segments in the /// current range, it will replace the value numbers of the overlaped /// segments with the specified value number. void LiveRange::MergeValueInAsValue(const LiveRange &RHS, const VNInfo *RHSValNo, VNInfo *LHSValNo) { LiveRangeUpdater Updater(this); for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) if (I->valno == RHSValNo) Updater.add(I->start, I->end, LHSValNo); }
// overlaps - Return true if the intersection of the two live ranges is // not empty. // // An example for overlaps(): // // 0: A = ... // 4: B = ... // 8: C = A + B ;; last use of A // // The live ranges should look like: // // A = [3, 11) // B = [7, x) // C = [11, y) // // A->overlaps(C) should return false since we want to be able to join // A and C. // bool LiveRange::overlapsFrom(const LiveRange& other, const_iterator StartPos) const { assert(!empty() && "empty range"); const_iterator i = begin(); const_iterator ie = end(); const_iterator j = StartPos; const_iterator je = other.end(); assert((StartPos->start <= i->start || StartPos == other.begin()) && StartPos != other.end() && "Bogus start position hint!"); if (i->start < j->start) { i = std::upper_bound(i, ie, j->start); if (i != begin()) --i; } else if (j->start < i->start) { ++StartPos; if (StartPos != other.end() && StartPos->start <= i->start) { assert(StartPos < other.end() && i < end()); j = std::upper_bound(j, je, i->start); if (j != other.begin()) --j; } } else { return true; } if (j == je) return false; while (i != ie) { if (i->start > j->start) { std::swap(i, j); std::swap(ie, je); } if (i->end > j->start) return true; ++i; } return false; }
// 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); } }
/// Merge all of the segments in RHS into this live range as the specified /// value number. The segments in RHS are allowed to overlap with segments in /// the current range, but only if the overlapping segments have the /// specified value number. void LiveRange::MergeSegmentsInAsValue(const LiveRange &RHS, VNInfo *LHSValNo) { LiveRangeUpdater Updater(this); for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) Updater.add(I->start, I->end, LHSValNo); }
void LiveRange::join(LiveRange &Other, const int *LHSValNoAssignments, const int *RHSValNoAssignments, SmallVectorImpl<VNInfo *> &NewVNInfo) { verify(); // Determine if any of our values are mapped. This is uncommon, so we want // to avoid the range scan if not. bool MustMapCurValNos = false; unsigned NumVals = getNumValNums(); unsigned NumNewVals = NewVNInfo.size(); for (unsigned i = 0; i != NumVals; ++i) { unsigned LHSValID = LHSValNoAssignments[i]; if (i != LHSValID || (NewVNInfo[LHSValID] && NewVNInfo[LHSValID] != getValNumInfo(i))) { MustMapCurValNos = true; break; } } // If we have to apply a mapping to our base range assignment, rewrite it now. if (MustMapCurValNos && !empty()) { // Map the first live range. iterator OutIt = begin(); OutIt->valno = NewVNInfo[LHSValNoAssignments[OutIt->valno->id]]; for (iterator I = std::next(OutIt), E = end(); I != E; ++I) { VNInfo* nextValNo = NewVNInfo[LHSValNoAssignments[I->valno->id]]; assert(nextValNo != 0 && "Huh?"); // If this live range has the same value # as its immediate predecessor, // and if they are neighbors, remove one Segment. This happens when we // have [0,4:0)[4,7:1) and map 0/1 onto the same value #. if (OutIt->valno == nextValNo && OutIt->end == I->start) { OutIt->end = I->end; } else { // Didn't merge. Move OutIt to the next segment, ++OutIt; OutIt->valno = nextValNo; if (OutIt != I) { OutIt->start = I->start; OutIt->end = I->end; } } } // If we merge some segments, chop off the end. ++OutIt; segments.erase(OutIt, end()); } // Rewrite Other values before changing the VNInfo ids. // This can leave Other in an invalid state because we're not coalescing // touching segments that now have identical values. That's OK since Other is // not supposed to be valid after calling join(); for (iterator I = Other.begin(), E = Other.end(); I != E; ++I) I->valno = NewVNInfo[RHSValNoAssignments[I->valno->id]]; // Update val# info. Renumber them and make sure they all belong to this // LiveRange now. Also remove dead val#'s. unsigned NumValNos = 0; for (unsigned i = 0; i < NumNewVals; ++i) { VNInfo *VNI = NewVNInfo[i]; if (VNI) { if (NumValNos >= NumVals) valnos.push_back(VNI); else valnos[NumValNos] = VNI; VNI->id = NumValNos++; // Renumber val#. } } if (NumNewVals < NumVals) valnos.resize(NumNewVals); // shrinkify // Okay, now insert the RHS live segments into the LHS. LiveRangeUpdater Updater(this); for (iterator I = Other.begin(), E = Other.end(); I != E; ++I) Updater.add(*I); }
bool LiveRangeCalc::isDefOnEntry(LiveRange &LR, ArrayRef<SlotIndex> Undefs, MachineBasicBlock &MBB, BitVector &DefOnEntry, BitVector &UndefOnEntry) { unsigned BN = MBB.getNumber(); if (DefOnEntry[BN]) return true; if (UndefOnEntry[BN]) return false; auto MarkDefined = [BN, &DefOnEntry](MachineBasicBlock &B) -> bool { for (MachineBasicBlock *S : B.successors()) DefOnEntry[S->getNumber()] = true; DefOnEntry[BN] = true; return true; }; SetVector<unsigned> WorkList; // Checking if the entry of MBB is reached by some def: add all predecessors // that are potentially defined-on-exit to the work list. for (MachineBasicBlock *P : MBB.predecessors()) WorkList.insert(P->getNumber()); for (unsigned i = 0; i != WorkList.size(); ++i) { // Determine if the exit from the block is reached by some def. unsigned N = WorkList[i]; MachineBasicBlock &B = *MF->getBlockNumbered(N); if (Seen[N]) { const LiveOutPair &LOB = Map[&B]; if (LOB.first != nullptr && LOB.first != &UndefVNI) return MarkDefined(B); } SlotIndex Begin, End; std::tie(Begin, End) = Indexes->getMBBRange(&B); // Treat End as not belonging to B. // If LR has a segment S that starts at the next block, i.e. [End, ...), // std::upper_bound will return the segment following S. Instead, // S should be treated as the first segment that does not overlap B. LiveRange::iterator UB = std::upper_bound(LR.begin(), LR.end(), End.getPrevSlot()); if (UB != LR.begin()) { LiveRange::Segment &Seg = *std::prev(UB); if (Seg.end > Begin) { // There is a segment that overlaps B. If the range is not explicitly // undefined between the end of the segment and the end of the block, // treat the block as defined on exit. If it is, go to the next block // on the work list. if (LR.isUndefIn(Undefs, Seg.end, End)) continue; return MarkDefined(B); } } // No segment overlaps with this block. If this block is not defined on // entry, or it undefines the range, do not process its predecessors. if (UndefOnEntry[N] || LR.isUndefIn(Undefs, Begin, End)) { UndefOnEntry[N] = true; continue; } if (DefOnEntry[N]) return MarkDefined(B); // Still don't know: add all predecessors to the work list. for (MachineBasicBlock *P : B.predecessors()) WorkList.insert(P->getNumber()); } UndefOnEntry[BN] = true; return false; }