xref: /src/contrib/llvm-project/llvm/lib/CodeGen/LiveIntervalUnion.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
171d5a254SDimitry Andric //===- LiveIntervalUnion.cpp - Live interval union data structure ---------===//
2cf099d11SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cf099d11SDimitry Andric //
7cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
8cf099d11SDimitry Andric //
9cf099d11SDimitry Andric // LiveIntervalUnion represents a coalesced set of live intervals. This may be
10cf099d11SDimitry Andric // used during coalescing to represent a congruence class, or during register
11cf099d11SDimitry Andric // allocation to model liveness of a physical register.
12cf099d11SDimitry Andric //
13cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
14cf099d11SDimitry Andric 
1571d5a254SDimitry Andric #include "llvm/CodeGen/LiveIntervalUnion.h"
167ab83427SDimitry Andric #include "llvm/ADT/STLExtras.h"
177ab83427SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
18044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
19cf099d11SDimitry Andric #include "llvm/Support/raw_ostream.h"
2071d5a254SDimitry Andric #include <cassert>
2171d5a254SDimitry Andric #include <cstdlib>
2263faed5bSDimitry Andric 
23cf099d11SDimitry Andric using namespace llvm;
24cf099d11SDimitry Andric 
255ca98fd9SDimitry Andric #define DEBUG_TYPE "regalloc"
265ca98fd9SDimitry Andric 
27cf099d11SDimitry Andric // Merge a LiveInterval's segments. Guarantee no overlaps.
unify(const LiveInterval & VirtReg,const LiveRange & Range)28145449b1SDimitry Andric void LiveIntervalUnion::unify(const LiveInterval &VirtReg,
29145449b1SDimitry Andric                               const LiveRange &Range) {
3067c32a98SDimitry Andric   if (Range.empty())
31cf099d11SDimitry Andric     return;
32cf099d11SDimitry Andric   ++Tag;
33cf099d11SDimitry Andric 
34cf099d11SDimitry Andric   // Insert each of the virtual register's live segments into the map.
3567c32a98SDimitry Andric   LiveRange::const_iterator RegPos = Range.begin();
3667c32a98SDimitry Andric   LiveRange::const_iterator RegEnd = Range.end();
37cf099d11SDimitry Andric   SegmentIter SegPos = Segments.find(RegPos->start);
38cf099d11SDimitry Andric 
396b943ff3SDimitry Andric   while (SegPos.valid()) {
40cf099d11SDimitry Andric     SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
41cf099d11SDimitry Andric     if (++RegPos == RegEnd)
42cf099d11SDimitry Andric       return;
43cf099d11SDimitry Andric     SegPos.advanceTo(RegPos->start);
44cf099d11SDimitry Andric   }
456b943ff3SDimitry Andric 
466b943ff3SDimitry Andric   // We have reached the end of Segments, so it is no longer necessary to search
476b943ff3SDimitry Andric   // for the insertion position.
486b943ff3SDimitry Andric   // It is faster to insert the end first.
496b943ff3SDimitry Andric   --RegEnd;
506b943ff3SDimitry Andric   SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg);
516b943ff3SDimitry Andric   for (; RegPos != RegEnd; ++RegPos, ++SegPos)
526b943ff3SDimitry Andric     SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
53cf099d11SDimitry Andric }
54cf099d11SDimitry Andric 
55cf099d11SDimitry Andric // Remove a live virtual register's segments from this union.
extract(const LiveInterval & VirtReg,const LiveRange & Range)56145449b1SDimitry Andric void LiveIntervalUnion::extract(const LiveInterval &VirtReg,
57145449b1SDimitry Andric                                 const LiveRange &Range) {
5867c32a98SDimitry Andric   if (Range.empty())
59cf099d11SDimitry Andric     return;
60cf099d11SDimitry Andric   ++Tag;
61cf099d11SDimitry Andric 
62cf099d11SDimitry Andric   // Remove each of the virtual register's live segments from the map.
6367c32a98SDimitry Andric   LiveRange::const_iterator RegPos = Range.begin();
6467c32a98SDimitry Andric   LiveRange::const_iterator RegEnd = Range.end();
65cf099d11SDimitry Andric   SegmentIter SegPos = Segments.find(RegPos->start);
66cf099d11SDimitry Andric 
6771d5a254SDimitry Andric   while (true) {
68cf099d11SDimitry Andric     assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval");
69cf099d11SDimitry Andric     SegPos.erase();
70cf099d11SDimitry Andric     if (!SegPos.valid())
71cf099d11SDimitry Andric       return;
72cf099d11SDimitry Andric 
73cf099d11SDimitry Andric     // Skip all segments that may have been coalesced.
7467c32a98SDimitry Andric     RegPos = Range.advanceTo(RegPos, SegPos.start());
75cf099d11SDimitry Andric     if (RegPos == RegEnd)
76cf099d11SDimitry Andric       return;
77cf099d11SDimitry Andric 
78cf099d11SDimitry Andric     SegPos.advanceTo(RegPos->start);
79cf099d11SDimitry Andric   }
80cf099d11SDimitry Andric }
81cf099d11SDimitry Andric 
82cf099d11SDimitry Andric void
print(raw_ostream & OS,const TargetRegisterInfo * TRI) const83cf099d11SDimitry Andric LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const {
84cf099d11SDimitry Andric   if (empty()) {
85cf099d11SDimitry Andric     OS << " empty\n";
86cf099d11SDimitry Andric     return;
87cf099d11SDimitry Andric   }
88cf099d11SDimitry Andric   for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
89b60736ecSDimitry Andric     OS << " [" << SI.start() << ' ' << SI.stop()
90b60736ecSDimitry Andric        << "):" << printReg(SI.value()->reg(), TRI);
91cf099d11SDimitry Andric   }
92cf099d11SDimitry Andric   OS << '\n';
93cf099d11SDimitry Andric }
94cf099d11SDimitry Andric 
95cf099d11SDimitry Andric #ifndef NDEBUG
96cf099d11SDimitry Andric // Verify the live intervals in this union and add them to the visited set.
verify(LiveVirtRegBitSet & VisitedVRegs)97cf099d11SDimitry Andric void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) {
98cf099d11SDimitry Andric   for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI)
99b60736ecSDimitry Andric     VisitedVRegs.set(SI.value()->reg());
100cf099d11SDimitry Andric }
101cf099d11SDimitry Andric #endif //!NDEBUG
102cf099d11SDimitry Andric 
getOneVReg() const103145449b1SDimitry Andric const LiveInterval *LiveIntervalUnion::getOneVReg() const {
104b60736ecSDimitry Andric   if (empty())
105b60736ecSDimitry Andric     return nullptr;
106b60736ecSDimitry Andric   for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
107b60736ecSDimitry Andric     // return the first valid live interval
108b60736ecSDimitry Andric     return SI.value();
109b60736ecSDimitry Andric   }
110b60736ecSDimitry Andric   return nullptr;
111b60736ecSDimitry Andric }
112b60736ecSDimitry Andric 
113cf099d11SDimitry Andric // Scan the vector of interfering virtual registers in this union. Assume it's
114cf099d11SDimitry Andric // quite small.
isSeenInterference(const LiveInterval * VirtReg) const115145449b1SDimitry Andric bool LiveIntervalUnion::Query::isSeenInterference(
116145449b1SDimitry Andric     const LiveInterval *VirtReg) const {
117c0981da4SDimitry Andric   return is_contained(InterferingVRegs, VirtReg);
118cf099d11SDimitry Andric }
119cf099d11SDimitry Andric 
12030815c53SDimitry Andric // Collect virtual registers in this union that interfere with this
121cf099d11SDimitry Andric // query's live virtual register.
122cf099d11SDimitry Andric //
12330815c53SDimitry Andric // The query state is one of:
124cf099d11SDimitry Andric //
12530815c53SDimitry Andric // 1. CheckedFirstInterference == false: Iterators are uninitialized.
12630815c53SDimitry Andric // 2. SeenAllInterferences == true: InterferingVRegs complete, iterators unused.
12730815c53SDimitry Andric // 3. Iterators left at the last seen intersection.
12830815c53SDimitry Andric //
129c0981da4SDimitry Andric unsigned
collectInterferingVRegs(unsigned MaxInterferingRegs)130c0981da4SDimitry Andric LiveIntervalUnion::Query::collectInterferingVRegs(unsigned MaxInterferingRegs) {
13130815c53SDimitry Andric   // Fast path return if we already have the desired information.
132c0981da4SDimitry Andric   if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs)
133c0981da4SDimitry Andric     return InterferingVRegs.size();
134cf099d11SDimitry Andric 
13530815c53SDimitry Andric   // Set up iterators on the first call.
13630815c53SDimitry Andric   if (!CheckedFirstInterference) {
13730815c53SDimitry Andric     CheckedFirstInterference = true;
138cf099d11SDimitry Andric 
13930815c53SDimitry Andric     // Quickly skip interference check for empty sets.
14071d5a254SDimitry Andric     if (LR->empty() || LiveUnion->empty()) {
14130815c53SDimitry Andric       SeenAllInterferences = true;
14230815c53SDimitry Andric       return 0;
143cf099d11SDimitry Andric     }
14430815c53SDimitry Andric 
14571d5a254SDimitry Andric     // In most cases, the union will start before LR.
14671d5a254SDimitry Andric     LRI = LR->begin();
14730815c53SDimitry Andric     LiveUnionI.setMap(LiveUnion->getMap());
14871d5a254SDimitry Andric     LiveUnionI.find(LRI->start);
14930815c53SDimitry Andric   }
15030815c53SDimitry Andric 
15171d5a254SDimitry Andric   LiveRange::const_iterator LREnd = LR->end();
152145449b1SDimitry Andric   const LiveInterval *RecentReg = nullptr;
15330815c53SDimitry Andric   while (LiveUnionI.valid()) {
15471d5a254SDimitry Andric     assert(LRI != LREnd && "Reached end of LR");
15530815c53SDimitry Andric 
15630815c53SDimitry Andric     // Check for overlapping interference.
15771d5a254SDimitry Andric     while (LRI->start < LiveUnionI.stop() && LRI->end > LiveUnionI.start()) {
15830815c53SDimitry Andric       // This is an overlap, record the interfering register.
159145449b1SDimitry Andric       const LiveInterval *VReg = LiveUnionI.value();
16030815c53SDimitry Andric       if (VReg != RecentReg && !isSeenInterference(VReg)) {
16130815c53SDimitry Andric         RecentReg = VReg;
162c0981da4SDimitry Andric         InterferingVRegs.push_back(VReg);
163c0981da4SDimitry Andric         if (InterferingVRegs.size() >= MaxInterferingRegs)
164c0981da4SDimitry Andric           return InterferingVRegs.size();
16530815c53SDimitry Andric       }
16630815c53SDimitry Andric       // This LiveUnion segment is no longer interesting.
16730815c53SDimitry Andric       if (!(++LiveUnionI).valid()) {
16830815c53SDimitry Andric         SeenAllInterferences = true;
169c0981da4SDimitry Andric         return InterferingVRegs.size();
17030815c53SDimitry Andric       }
17130815c53SDimitry Andric     }
17230815c53SDimitry Andric 
17330815c53SDimitry Andric     // The iterators are now not overlapping, LiveUnionI has been advanced
17471d5a254SDimitry Andric     // beyond LRI.
17571d5a254SDimitry Andric     assert(LRI->end <= LiveUnionI.start() && "Expected non-overlap");
17630815c53SDimitry Andric 
17730815c53SDimitry Andric     // Advance the iterator that ends first.
17871d5a254SDimitry Andric     LRI = LR->advanceTo(LRI, LiveUnionI.start());
17971d5a254SDimitry Andric     if (LRI == LREnd)
18030815c53SDimitry Andric       break;
18130815c53SDimitry Andric 
18230815c53SDimitry Andric     // Detect overlap, handle above.
18371d5a254SDimitry Andric     if (LRI->start < LiveUnionI.stop())
18430815c53SDimitry Andric       continue;
18530815c53SDimitry Andric 
18630815c53SDimitry Andric     // Still not overlapping. Catch up LiveUnionI.
18771d5a254SDimitry Andric     LiveUnionI.advanceTo(LRI->start);
188cf099d11SDimitry Andric   }
189cf099d11SDimitry Andric   SeenAllInterferences = true;
190c0981da4SDimitry Andric   return InterferingVRegs.size();
191cf099d11SDimitry Andric }
192cf099d11SDimitry Andric 
init(LiveIntervalUnion::Allocator & Alloc,unsigned NSize)19358b69754SDimitry Andric void LiveIntervalUnion::Array::init(LiveIntervalUnion::Allocator &Alloc,
19458b69754SDimitry Andric                                     unsigned NSize) {
19558b69754SDimitry Andric   // Reuse existing allocation.
19658b69754SDimitry Andric   if (NSize == Size)
19758b69754SDimitry Andric     return;
19858b69754SDimitry Andric   clear();
19958b69754SDimitry Andric   Size = NSize;
20058b69754SDimitry Andric   LIUs = static_cast<LiveIntervalUnion*>(
201eb11fae6SDimitry Andric       safe_malloc(sizeof(LiveIntervalUnion)*NSize));
20258b69754SDimitry Andric   for (unsigned i = 0; i != Size; ++i)
20358b69754SDimitry Andric     new(LIUs + i) LiveIntervalUnion(Alloc);
20458b69754SDimitry Andric }
20558b69754SDimitry Andric 
clear()20658b69754SDimitry Andric void LiveIntervalUnion::Array::clear() {
20758b69754SDimitry Andric   if (!LIUs)
20858b69754SDimitry Andric     return;
20958b69754SDimitry Andric   for (unsigned i = 0; i != Size; ++i)
21058b69754SDimitry Andric     LIUs[i].~LiveIntervalUnion();
21158b69754SDimitry Andric   free(LIUs);
21258b69754SDimitry Andric   Size =  0;
2135ca98fd9SDimitry Andric   LIUs = nullptr;
21458b69754SDimitry Andric }
215