17a7e6055SDimitry Andric //===- LiveIntervalUnion.cpp - Live interval union data structure ---------===//
22754fe60SDimitry Andric //
32754fe60SDimitry Andric // The LLVM Compiler Infrastructure
42754fe60SDimitry Andric //
52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source
62754fe60SDimitry Andric // License. See LICENSE.TXT for details.
72754fe60SDimitry Andric //
82754fe60SDimitry Andric //===----------------------------------------------------------------------===//
92754fe60SDimitry Andric //
102754fe60SDimitry Andric // LiveIntervalUnion represents a coalesced set of live intervals. This may be
112754fe60SDimitry Andric // used during coalescing to represent a congruence class, or during register
122754fe60SDimitry Andric // allocation to model liveness of a physical register.
132754fe60SDimitry Andric //
142754fe60SDimitry Andric //===----------------------------------------------------------------------===//
152754fe60SDimitry Andric
167a7e6055SDimitry Andric #include "llvm/CodeGen/LiveIntervalUnion.h"
17db17bf38SDimitry Andric #include "llvm/ADT/STLExtras.h"
18db17bf38SDimitry Andric #include "llvm/ADT/SparseBitVector.h"
19db17bf38SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
202cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
212754fe60SDimitry Andric #include "llvm/Support/raw_ostream.h"
227a7e6055SDimitry Andric #include <cassert>
237a7e6055SDimitry Andric #include <cstdlib>
24dff0c46cSDimitry Andric
252754fe60SDimitry Andric using namespace llvm;
262754fe60SDimitry Andric
2791bc56edSDimitry Andric #define DEBUG_TYPE "regalloc"
2891bc56edSDimitry Andric
292754fe60SDimitry Andric // Merge a LiveInterval's segments. Guarantee no overlaps.
unify(LiveInterval & VirtReg,const LiveRange & Range)3039d628a0SDimitry Andric void LiveIntervalUnion::unify(LiveInterval &VirtReg, const LiveRange &Range) {
3139d628a0SDimitry Andric if (Range.empty())
322754fe60SDimitry Andric return;
332754fe60SDimitry Andric ++Tag;
342754fe60SDimitry Andric
352754fe60SDimitry Andric // Insert each of the virtual register's live segments into the map.
3639d628a0SDimitry Andric LiveRange::const_iterator RegPos = Range.begin();
3739d628a0SDimitry Andric LiveRange::const_iterator RegEnd = Range.end();
382754fe60SDimitry Andric SegmentIter SegPos = Segments.find(RegPos->start);
392754fe60SDimitry Andric
403b0f4066SDimitry Andric while (SegPos.valid()) {
412754fe60SDimitry Andric SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
422754fe60SDimitry Andric if (++RegPos == RegEnd)
432754fe60SDimitry Andric return;
442754fe60SDimitry Andric SegPos.advanceTo(RegPos->start);
452754fe60SDimitry Andric }
463b0f4066SDimitry Andric
473b0f4066SDimitry Andric // We have reached the end of Segments, so it is no longer necessary to search
483b0f4066SDimitry Andric // for the insertion position.
493b0f4066SDimitry Andric // It is faster to insert the end first.
503b0f4066SDimitry Andric --RegEnd;
513b0f4066SDimitry Andric SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg);
523b0f4066SDimitry Andric for (; RegPos != RegEnd; ++RegPos, ++SegPos)
533b0f4066SDimitry Andric SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
542754fe60SDimitry Andric }
552754fe60SDimitry Andric
562754fe60SDimitry Andric // Remove a live virtual register's segments from this union.
extract(LiveInterval & VirtReg,const LiveRange & Range)5739d628a0SDimitry Andric void LiveIntervalUnion::extract(LiveInterval &VirtReg, const LiveRange &Range) {
5839d628a0SDimitry Andric if (Range.empty())
592754fe60SDimitry Andric return;
602754fe60SDimitry Andric ++Tag;
612754fe60SDimitry Andric
622754fe60SDimitry Andric // Remove each of the virtual register's live segments from the map.
6339d628a0SDimitry Andric LiveRange::const_iterator RegPos = Range.begin();
6439d628a0SDimitry Andric LiveRange::const_iterator RegEnd = Range.end();
652754fe60SDimitry Andric SegmentIter SegPos = Segments.find(RegPos->start);
662754fe60SDimitry Andric
677a7e6055SDimitry Andric while (true) {
682754fe60SDimitry Andric assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval");
692754fe60SDimitry Andric SegPos.erase();
702754fe60SDimitry Andric if (!SegPos.valid())
712754fe60SDimitry Andric return;
722754fe60SDimitry Andric
732754fe60SDimitry Andric // Skip all segments that may have been coalesced.
7439d628a0SDimitry Andric RegPos = Range.advanceTo(RegPos, SegPos.start());
752754fe60SDimitry Andric if (RegPos == RegEnd)
762754fe60SDimitry Andric return;
772754fe60SDimitry Andric
782754fe60SDimitry Andric SegPos.advanceTo(RegPos->start);
792754fe60SDimitry Andric }
802754fe60SDimitry Andric }
812754fe60SDimitry Andric
822754fe60SDimitry Andric void
print(raw_ostream & OS,const TargetRegisterInfo * TRI) const832754fe60SDimitry Andric LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const {
842754fe60SDimitry Andric if (empty()) {
852754fe60SDimitry Andric OS << " empty\n";
862754fe60SDimitry Andric return;
872754fe60SDimitry Andric }
882754fe60SDimitry Andric for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
892754fe60SDimitry Andric OS << " [" << SI.start() << ' ' << SI.stop() << "):"
902cab237bSDimitry Andric << printReg(SI.value()->reg, TRI);
912754fe60SDimitry Andric }
922754fe60SDimitry Andric OS << '\n';
932754fe60SDimitry Andric }
942754fe60SDimitry Andric
952754fe60SDimitry Andric #ifndef NDEBUG
962754fe60SDimitry Andric // Verify the live intervals in this union and add them to the visited set.
verify(LiveVirtRegBitSet & VisitedVRegs)972754fe60SDimitry Andric void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) {
982754fe60SDimitry Andric for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI)
992754fe60SDimitry Andric VisitedVRegs.set(SI.value()->reg);
1002754fe60SDimitry Andric }
1012754fe60SDimitry Andric #endif //!NDEBUG
1022754fe60SDimitry Andric
1032754fe60SDimitry Andric // Scan the vector of interfering virtual registers in this union. Assume it's
1042754fe60SDimitry Andric // quite small.
isSeenInterference(LiveInterval * VirtReg) const1052754fe60SDimitry Andric bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const {
106d88c1a5aSDimitry Andric return is_contained(InterferingVRegs, VirtReg);
1072754fe60SDimitry Andric }
1082754fe60SDimitry Andric
1096122f3e6SDimitry Andric // Collect virtual registers in this union that interfere with this
1102754fe60SDimitry Andric // query's live virtual register.
1112754fe60SDimitry Andric //
1126122f3e6SDimitry Andric // The query state is one of:
1132754fe60SDimitry Andric //
1146122f3e6SDimitry Andric // 1. CheckedFirstInterference == false: Iterators are uninitialized.
1156122f3e6SDimitry Andric // 2. SeenAllInterferences == true: InterferingVRegs complete, iterators unused.
1166122f3e6SDimitry Andric // 3. Iterators left at the last seen intersection.
1176122f3e6SDimitry Andric //
1182754fe60SDimitry Andric unsigned LiveIntervalUnion::Query::
collectInterferingVRegs(unsigned MaxInterferingRegs)11917a519f9SDimitry Andric collectInterferingVRegs(unsigned MaxInterferingRegs) {
1206122f3e6SDimitry Andric // Fast path return if we already have the desired information.
1216122f3e6SDimitry Andric if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs)
1226122f3e6SDimitry Andric return InterferingVRegs.size();
1232754fe60SDimitry Andric
1246122f3e6SDimitry Andric // Set up iterators on the first call.
1256122f3e6SDimitry Andric if (!CheckedFirstInterference) {
1266122f3e6SDimitry Andric CheckedFirstInterference = true;
1272754fe60SDimitry Andric
1286122f3e6SDimitry Andric // Quickly skip interference check for empty sets.
1297a7e6055SDimitry Andric if (LR->empty() || LiveUnion->empty()) {
1306122f3e6SDimitry Andric SeenAllInterferences = true;
1316122f3e6SDimitry Andric return 0;
1322754fe60SDimitry Andric }
1336122f3e6SDimitry Andric
1347a7e6055SDimitry Andric // In most cases, the union will start before LR.
1357a7e6055SDimitry Andric LRI = LR->begin();
1366122f3e6SDimitry Andric LiveUnionI.setMap(LiveUnion->getMap());
1377a7e6055SDimitry Andric LiveUnionI.find(LRI->start);
1386122f3e6SDimitry Andric }
1396122f3e6SDimitry Andric
1407a7e6055SDimitry Andric LiveRange::const_iterator LREnd = LR->end();
14191bc56edSDimitry Andric LiveInterval *RecentReg = nullptr;
1426122f3e6SDimitry Andric while (LiveUnionI.valid()) {
1437a7e6055SDimitry Andric assert(LRI != LREnd && "Reached end of LR");
1446122f3e6SDimitry Andric
1456122f3e6SDimitry Andric // Check for overlapping interference.
1467a7e6055SDimitry Andric while (LRI->start < LiveUnionI.stop() && LRI->end > LiveUnionI.start()) {
1476122f3e6SDimitry Andric // This is an overlap, record the interfering register.
1486122f3e6SDimitry Andric LiveInterval *VReg = LiveUnionI.value();
1496122f3e6SDimitry Andric if (VReg != RecentReg && !isSeenInterference(VReg)) {
1506122f3e6SDimitry Andric RecentReg = VReg;
1516122f3e6SDimitry Andric InterferingVRegs.push_back(VReg);
1526122f3e6SDimitry Andric if (InterferingVRegs.size() >= MaxInterferingRegs)
1536122f3e6SDimitry Andric return InterferingVRegs.size();
1546122f3e6SDimitry Andric }
1556122f3e6SDimitry Andric // This LiveUnion segment is no longer interesting.
1566122f3e6SDimitry Andric if (!(++LiveUnionI).valid()) {
1576122f3e6SDimitry Andric SeenAllInterferences = true;
1586122f3e6SDimitry Andric return InterferingVRegs.size();
1596122f3e6SDimitry Andric }
1606122f3e6SDimitry Andric }
1616122f3e6SDimitry Andric
1626122f3e6SDimitry Andric // The iterators are now not overlapping, LiveUnionI has been advanced
1637a7e6055SDimitry Andric // beyond LRI.
1647a7e6055SDimitry Andric assert(LRI->end <= LiveUnionI.start() && "Expected non-overlap");
1656122f3e6SDimitry Andric
1666122f3e6SDimitry Andric // Advance the iterator that ends first.
1677a7e6055SDimitry Andric LRI = LR->advanceTo(LRI, LiveUnionI.start());
1687a7e6055SDimitry Andric if (LRI == LREnd)
1696122f3e6SDimitry Andric break;
1706122f3e6SDimitry Andric
1716122f3e6SDimitry Andric // Detect overlap, handle above.
1727a7e6055SDimitry Andric if (LRI->start < LiveUnionI.stop())
1736122f3e6SDimitry Andric continue;
1746122f3e6SDimitry Andric
1756122f3e6SDimitry Andric // Still not overlapping. Catch up LiveUnionI.
1767a7e6055SDimitry Andric LiveUnionI.advanceTo(LRI->start);
1772754fe60SDimitry Andric }
1782754fe60SDimitry Andric SeenAllInterferences = true;
1792754fe60SDimitry Andric return InterferingVRegs.size();
1802754fe60SDimitry Andric }
1812754fe60SDimitry Andric
init(LiveIntervalUnion::Allocator & Alloc,unsigned NSize)1827ae0e2c9SDimitry Andric void LiveIntervalUnion::Array::init(LiveIntervalUnion::Allocator &Alloc,
1837ae0e2c9SDimitry Andric unsigned NSize) {
1847ae0e2c9SDimitry Andric // Reuse existing allocation.
1857ae0e2c9SDimitry Andric if (NSize == Size)
1867ae0e2c9SDimitry Andric return;
1877ae0e2c9SDimitry Andric clear();
1887ae0e2c9SDimitry Andric Size = NSize;
1897ae0e2c9SDimitry Andric LIUs = static_cast<LiveIntervalUnion*>(
190*4ba319b5SDimitry Andric safe_malloc(sizeof(LiveIntervalUnion)*NSize));
1917ae0e2c9SDimitry Andric for (unsigned i = 0; i != Size; ++i)
1927ae0e2c9SDimitry Andric new(LIUs + i) LiveIntervalUnion(Alloc);
1937ae0e2c9SDimitry Andric }
1947ae0e2c9SDimitry Andric
clear()1957ae0e2c9SDimitry Andric void LiveIntervalUnion::Array::clear() {
1967ae0e2c9SDimitry Andric if (!LIUs)
1977ae0e2c9SDimitry Andric return;
1987ae0e2c9SDimitry Andric for (unsigned i = 0; i != Size; ++i)
1997ae0e2c9SDimitry Andric LIUs[i].~LiveIntervalUnion();
2007ae0e2c9SDimitry Andric free(LIUs);
2017ae0e2c9SDimitry Andric Size = 0;
20291bc56edSDimitry Andric LIUs = nullptr;
2037ae0e2c9SDimitry Andric }
204