10b57cec5SDimitry Andric //===- LiveIntervalUnion.cpp - Live interval union data structure ---------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // LiveIntervalUnion represents a coalesced set of live intervals. This may be
100b57cec5SDimitry Andric // used during coalescing to represent a congruence class, or during register
110b57cec5SDimitry Andric // allocation to model liveness of a physical register.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervalUnion.h"
160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SparseBitVector.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
200b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
210b57cec5SDimitry Andric #include <cassert>
220b57cec5SDimitry Andric #include <cstdlib>
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric #define DEBUG_TYPE "regalloc"
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric // Merge a LiveInterval's segments. Guarantee no overlaps.
unify(LiveInterval & VirtReg,const LiveRange & Range)290b57cec5SDimitry Andric void LiveIntervalUnion::unify(LiveInterval &VirtReg, const LiveRange &Range) {
300b57cec5SDimitry Andric if (Range.empty())
310b57cec5SDimitry Andric return;
320b57cec5SDimitry Andric ++Tag;
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric // Insert each of the virtual register's live segments into the map.
350b57cec5SDimitry Andric LiveRange::const_iterator RegPos = Range.begin();
360b57cec5SDimitry Andric LiveRange::const_iterator RegEnd = Range.end();
370b57cec5SDimitry Andric SegmentIter SegPos = Segments.find(RegPos->start);
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric while (SegPos.valid()) {
400b57cec5SDimitry Andric SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
410b57cec5SDimitry Andric if (++RegPos == RegEnd)
420b57cec5SDimitry Andric return;
430b57cec5SDimitry Andric SegPos.advanceTo(RegPos->start);
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric // We have reached the end of Segments, so it is no longer necessary to search
470b57cec5SDimitry Andric // for the insertion position.
480b57cec5SDimitry Andric // It is faster to insert the end first.
490b57cec5SDimitry Andric --RegEnd;
500b57cec5SDimitry Andric SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg);
510b57cec5SDimitry Andric for (; RegPos != RegEnd; ++RegPos, ++SegPos)
520b57cec5SDimitry Andric SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric // Remove a live virtual register's segments from this union.
extract(LiveInterval & VirtReg,const LiveRange & Range)560b57cec5SDimitry Andric void LiveIntervalUnion::extract(LiveInterval &VirtReg, const LiveRange &Range) {
570b57cec5SDimitry Andric if (Range.empty())
580b57cec5SDimitry Andric return;
590b57cec5SDimitry Andric ++Tag;
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric // Remove each of the virtual register's live segments from the map.
620b57cec5SDimitry Andric LiveRange::const_iterator RegPos = Range.begin();
630b57cec5SDimitry Andric LiveRange::const_iterator RegEnd = Range.end();
640b57cec5SDimitry Andric SegmentIter SegPos = Segments.find(RegPos->start);
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric while (true) {
670b57cec5SDimitry Andric assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval");
680b57cec5SDimitry Andric SegPos.erase();
690b57cec5SDimitry Andric if (!SegPos.valid())
700b57cec5SDimitry Andric return;
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric // Skip all segments that may have been coalesced.
730b57cec5SDimitry Andric RegPos = Range.advanceTo(RegPos, SegPos.start());
740b57cec5SDimitry Andric if (RegPos == RegEnd)
750b57cec5SDimitry Andric return;
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric SegPos.advanceTo(RegPos->start);
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric void
print(raw_ostream & OS,const TargetRegisterInfo * TRI) const820b57cec5SDimitry Andric LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const {
830b57cec5SDimitry Andric if (empty()) {
840b57cec5SDimitry Andric OS << " empty\n";
850b57cec5SDimitry Andric return;
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
88af732203SDimitry Andric OS << " [" << SI.start() << ' ' << SI.stop()
89af732203SDimitry Andric << "):" << printReg(SI.value()->reg(), TRI);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric OS << '\n';
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric #ifndef NDEBUG
950b57cec5SDimitry Andric // Verify the live intervals in this union and add them to the visited set.
verify(LiveVirtRegBitSet & VisitedVRegs)960b57cec5SDimitry Andric void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) {
970b57cec5SDimitry Andric for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI)
98af732203SDimitry Andric VisitedVRegs.set(SI.value()->reg());
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric #endif //!NDEBUG
1010b57cec5SDimitry Andric
getOneVReg() const102af732203SDimitry Andric LiveInterval *LiveIntervalUnion::getOneVReg() const {
103af732203SDimitry Andric if (empty())
104af732203SDimitry Andric return nullptr;
105af732203SDimitry Andric for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
106af732203SDimitry Andric // return the first valid live interval
107af732203SDimitry Andric return SI.value();
108af732203SDimitry Andric }
109af732203SDimitry Andric return nullptr;
110af732203SDimitry Andric }
111af732203SDimitry Andric
1120b57cec5SDimitry Andric // Scan the vector of interfering virtual registers in this union. Assume it's
1130b57cec5SDimitry Andric // quite small.
isSeenInterference(LiveInterval * VirtReg) const1140b57cec5SDimitry Andric bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const {
115*5f7ddb14SDimitry Andric return is_contained(*InterferingVRegs, VirtReg);
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric // Collect virtual registers in this union that interfere with this
1190b57cec5SDimitry Andric // query's live virtual register.
1200b57cec5SDimitry Andric //
1210b57cec5SDimitry Andric // The query state is one of:
1220b57cec5SDimitry Andric //
1230b57cec5SDimitry Andric // 1. CheckedFirstInterference == false: Iterators are uninitialized.
1240b57cec5SDimitry Andric // 2. SeenAllInterferences == true: InterferingVRegs complete, iterators unused.
1250b57cec5SDimitry Andric // 3. Iterators left at the last seen intersection.
1260b57cec5SDimitry Andric //
1270b57cec5SDimitry Andric unsigned LiveIntervalUnion::Query::
collectInterferingVRegs(unsigned MaxInterferingRegs)1280b57cec5SDimitry Andric collectInterferingVRegs(unsigned MaxInterferingRegs) {
129*5f7ddb14SDimitry Andric if (!InterferingVRegs)
130*5f7ddb14SDimitry Andric InterferingVRegs.emplace();
131*5f7ddb14SDimitry Andric
1320b57cec5SDimitry Andric // Fast path return if we already have the desired information.
133*5f7ddb14SDimitry Andric if (SeenAllInterferences || InterferingVRegs->size() >= MaxInterferingRegs)
134*5f7ddb14SDimitry Andric return InterferingVRegs->size();
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric // Set up iterators on the first call.
1370b57cec5SDimitry Andric if (!CheckedFirstInterference) {
1380b57cec5SDimitry Andric CheckedFirstInterference = true;
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric // Quickly skip interference check for empty sets.
1410b57cec5SDimitry Andric if (LR->empty() || LiveUnion->empty()) {
1420b57cec5SDimitry Andric SeenAllInterferences = true;
1430b57cec5SDimitry Andric return 0;
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric // In most cases, the union will start before LR.
1470b57cec5SDimitry Andric LRI = LR->begin();
1480b57cec5SDimitry Andric LiveUnionI.setMap(LiveUnion->getMap());
1490b57cec5SDimitry Andric LiveUnionI.find(LRI->start);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric LiveRange::const_iterator LREnd = LR->end();
1530b57cec5SDimitry Andric LiveInterval *RecentReg = nullptr;
1540b57cec5SDimitry Andric while (LiveUnionI.valid()) {
1550b57cec5SDimitry Andric assert(LRI != LREnd && "Reached end of LR");
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andric // Check for overlapping interference.
1580b57cec5SDimitry Andric while (LRI->start < LiveUnionI.stop() && LRI->end > LiveUnionI.start()) {
1590b57cec5SDimitry Andric // This is an overlap, record the interfering register.
1600b57cec5SDimitry Andric LiveInterval *VReg = LiveUnionI.value();
1610b57cec5SDimitry Andric if (VReg != RecentReg && !isSeenInterference(VReg)) {
1620b57cec5SDimitry Andric RecentReg = VReg;
163*5f7ddb14SDimitry Andric InterferingVRegs->push_back(VReg);
164*5f7ddb14SDimitry Andric if (InterferingVRegs->size() >= MaxInterferingRegs)
165*5f7ddb14SDimitry Andric return InterferingVRegs->size();
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric // This LiveUnion segment is no longer interesting.
1680b57cec5SDimitry Andric if (!(++LiveUnionI).valid()) {
1690b57cec5SDimitry Andric SeenAllInterferences = true;
170*5f7ddb14SDimitry Andric return InterferingVRegs->size();
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andric // The iterators are now not overlapping, LiveUnionI has been advanced
1750b57cec5SDimitry Andric // beyond LRI.
1760b57cec5SDimitry Andric assert(LRI->end <= LiveUnionI.start() && "Expected non-overlap");
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric // Advance the iterator that ends first.
1790b57cec5SDimitry Andric LRI = LR->advanceTo(LRI, LiveUnionI.start());
1800b57cec5SDimitry Andric if (LRI == LREnd)
1810b57cec5SDimitry Andric break;
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric // Detect overlap, handle above.
1840b57cec5SDimitry Andric if (LRI->start < LiveUnionI.stop())
1850b57cec5SDimitry Andric continue;
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric // Still not overlapping. Catch up LiveUnionI.
1880b57cec5SDimitry Andric LiveUnionI.advanceTo(LRI->start);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric SeenAllInterferences = true;
191*5f7ddb14SDimitry Andric return InterferingVRegs->size();
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
init(LiveIntervalUnion::Allocator & Alloc,unsigned NSize)1940b57cec5SDimitry Andric void LiveIntervalUnion::Array::init(LiveIntervalUnion::Allocator &Alloc,
1950b57cec5SDimitry Andric unsigned NSize) {
1960b57cec5SDimitry Andric // Reuse existing allocation.
1970b57cec5SDimitry Andric if (NSize == Size)
1980b57cec5SDimitry Andric return;
1990b57cec5SDimitry Andric clear();
2000b57cec5SDimitry Andric Size = NSize;
2010b57cec5SDimitry Andric LIUs = static_cast<LiveIntervalUnion*>(
2020b57cec5SDimitry Andric safe_malloc(sizeof(LiveIntervalUnion)*NSize));
2030b57cec5SDimitry Andric for (unsigned i = 0; i != Size; ++i)
2040b57cec5SDimitry Andric new(LIUs + i) LiveIntervalUnion(Alloc);
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric
clear()2070b57cec5SDimitry Andric void LiveIntervalUnion::Array::clear() {
2080b57cec5SDimitry Andric if (!LIUs)
2090b57cec5SDimitry Andric return;
2100b57cec5SDimitry Andric for (unsigned i = 0; i != Size; ++i)
2110b57cec5SDimitry Andric LIUs[i].~LiveIntervalUnion();
2120b57cec5SDimitry Andric free(LIUs);
2130b57cec5SDimitry Andric Size = 0;
2140b57cec5SDimitry Andric LIUs = nullptr;
2150b57cec5SDimitry Andric }
216