1*0b57cec5SDimitry Andric //===- LiveIntervalUnion.cpp - Live interval union data structure ---------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // LiveIntervalUnion represents a coalesced set of live intervals. This may be
10*0b57cec5SDimitry Andric // used during coalescing to represent a congruence class, or during register
11*0b57cec5SDimitry Andric // allocation to model liveness of a physical register.
12*0b57cec5SDimitry Andric //
13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14*0b57cec5SDimitry Andric 
15*0b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervalUnion.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
19*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
20*0b57cec5SDimitry Andric #include <cassert>
21*0b57cec5SDimitry Andric #include <cstdlib>
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric using namespace llvm;
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric #define DEBUG_TYPE "regalloc"
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric // Merge a LiveInterval's segments. Guarantee no overlaps.
unify(const LiveInterval & VirtReg,const LiveRange & Range)2881ad6265SDimitry Andric void LiveIntervalUnion::unify(const LiveInterval &VirtReg,
2981ad6265SDimitry Andric                               const LiveRange &Range) {
30*0b57cec5SDimitry Andric   if (Range.empty())
31*0b57cec5SDimitry Andric     return;
32*0b57cec5SDimitry Andric   ++Tag;
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric   // Insert each of the virtual register's live segments into the map.
35*0b57cec5SDimitry Andric   LiveRange::const_iterator RegPos = Range.begin();
36*0b57cec5SDimitry Andric   LiveRange::const_iterator RegEnd = Range.end();
37*0b57cec5SDimitry Andric   SegmentIter SegPos = Segments.find(RegPos->start);
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric   while (SegPos.valid()) {
40*0b57cec5SDimitry Andric     SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
41*0b57cec5SDimitry Andric     if (++RegPos == RegEnd)
42*0b57cec5SDimitry Andric       return;
43*0b57cec5SDimitry Andric     SegPos.advanceTo(RegPos->start);
44*0b57cec5SDimitry Andric   }
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric   // We have reached the end of Segments, so it is no longer necessary to search
47*0b57cec5SDimitry Andric   // for the insertion position.
48*0b57cec5SDimitry Andric   // It is faster to insert the end first.
49*0b57cec5SDimitry Andric   --RegEnd;
50*0b57cec5SDimitry Andric   SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg);
51*0b57cec5SDimitry Andric   for (; RegPos != RegEnd; ++RegPos, ++SegPos)
52*0b57cec5SDimitry Andric     SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
53*0b57cec5SDimitry Andric }
54*0b57cec5SDimitry Andric 
55*0b57cec5SDimitry Andric // Remove a live virtual register's segments from this union.
extract(const LiveInterval & VirtReg,const LiveRange & Range)5681ad6265SDimitry Andric void LiveIntervalUnion::extract(const LiveInterval &VirtReg,
5781ad6265SDimitry Andric                                 const LiveRange &Range) {
58*0b57cec5SDimitry Andric   if (Range.empty())
59*0b57cec5SDimitry Andric     return;
60*0b57cec5SDimitry Andric   ++Tag;
61*0b57cec5SDimitry Andric 
62*0b57cec5SDimitry Andric   // Remove each of the virtual register's live segments from the map.
63*0b57cec5SDimitry Andric   LiveRange::const_iterator RegPos = Range.begin();
64*0b57cec5SDimitry Andric   LiveRange::const_iterator RegEnd = Range.end();
65*0b57cec5SDimitry Andric   SegmentIter SegPos = Segments.find(RegPos->start);
66*0b57cec5SDimitry Andric 
67*0b57cec5SDimitry Andric   while (true) {
68*0b57cec5SDimitry Andric     assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval");
69*0b57cec5SDimitry Andric     SegPos.erase();
70*0b57cec5SDimitry Andric     if (!SegPos.valid())
71*0b57cec5SDimitry Andric       return;
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric     // Skip all segments that may have been coalesced.
74*0b57cec5SDimitry Andric     RegPos = Range.advanceTo(RegPos, SegPos.start());
75*0b57cec5SDimitry Andric     if (RegPos == RegEnd)
76*0b57cec5SDimitry Andric       return;
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric     SegPos.advanceTo(RegPos->start);
79*0b57cec5SDimitry Andric   }
80*0b57cec5SDimitry Andric }
81*0b57cec5SDimitry Andric 
82*0b57cec5SDimitry Andric void
print(raw_ostream & OS,const TargetRegisterInfo * TRI) const83*0b57cec5SDimitry Andric LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const {
84*0b57cec5SDimitry Andric   if (empty()) {
85*0b57cec5SDimitry Andric     OS << " empty\n";
86*0b57cec5SDimitry Andric     return;
87*0b57cec5SDimitry Andric   }
88*0b57cec5SDimitry Andric   for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
89e8d8bef9SDimitry Andric     OS << " [" << SI.start() << ' ' << SI.stop()
90e8d8bef9SDimitry Andric        << "):" << printReg(SI.value()->reg(), TRI);
91*0b57cec5SDimitry Andric   }
92*0b57cec5SDimitry Andric   OS << '\n';
93*0b57cec5SDimitry Andric }
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric #ifndef NDEBUG
96*0b57cec5SDimitry Andric // Verify the live intervals in this union and add them to the visited set.
verify(LiveVirtRegBitSet & VisitedVRegs)97*0b57cec5SDimitry Andric void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) {
98*0b57cec5SDimitry Andric   for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI)
99e8d8bef9SDimitry Andric     VisitedVRegs.set(SI.value()->reg());
100*0b57cec5SDimitry Andric }
101*0b57cec5SDimitry Andric #endif //!NDEBUG
102*0b57cec5SDimitry Andric 
getOneVReg() const10381ad6265SDimitry Andric const LiveInterval *LiveIntervalUnion::getOneVReg() const {
104e8d8bef9SDimitry Andric   if (empty())
105e8d8bef9SDimitry Andric     return nullptr;
106e8d8bef9SDimitry Andric   for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
107e8d8bef9SDimitry Andric     // return the first valid live interval
108e8d8bef9SDimitry Andric     return SI.value();
109e8d8bef9SDimitry Andric   }
110e8d8bef9SDimitry Andric   return nullptr;
111e8d8bef9SDimitry Andric }
112e8d8bef9SDimitry Andric 
113*0b57cec5SDimitry Andric // Scan the vector of interfering virtual registers in this union. Assume it's
114*0b57cec5SDimitry Andric // quite small.
isSeenInterference(const LiveInterval * VirtReg) const11581ad6265SDimitry Andric bool LiveIntervalUnion::Query::isSeenInterference(
11681ad6265SDimitry Andric     const LiveInterval *VirtReg) const {
117349cc55cSDimitry Andric   return is_contained(InterferingVRegs, VirtReg);
118*0b57cec5SDimitry Andric }
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric // Collect virtual registers in this union that interfere with this
121*0b57cec5SDimitry Andric // query's live virtual register.
122*0b57cec5SDimitry Andric //
123*0b57cec5SDimitry Andric // The query state is one of:
124*0b57cec5SDimitry Andric //
125*0b57cec5SDimitry Andric // 1. CheckedFirstInterference == false: Iterators are uninitialized.
126*0b57cec5SDimitry Andric // 2. SeenAllInterferences == true: InterferingVRegs complete, iterators unused.
127*0b57cec5SDimitry Andric // 3. Iterators left at the last seen intersection.
128*0b57cec5SDimitry Andric //
129349cc55cSDimitry Andric unsigned
collectInterferingVRegs(unsigned MaxInterferingRegs)130349cc55cSDimitry Andric LiveIntervalUnion::Query::collectInterferingVRegs(unsigned MaxInterferingRegs) {
131*0b57cec5SDimitry Andric   // Fast path return if we already have the desired information.
132349cc55cSDimitry Andric   if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs)
133349cc55cSDimitry Andric     return InterferingVRegs.size();
134*0b57cec5SDimitry Andric 
135*0b57cec5SDimitry Andric   // Set up iterators on the first call.
136*0b57cec5SDimitry Andric   if (!CheckedFirstInterference) {
137*0b57cec5SDimitry Andric     CheckedFirstInterference = true;
138*0b57cec5SDimitry Andric 
139*0b57cec5SDimitry Andric     // Quickly skip interference check for empty sets.
140*0b57cec5SDimitry Andric     if (LR->empty() || LiveUnion->empty()) {
141*0b57cec5SDimitry Andric       SeenAllInterferences = true;
142*0b57cec5SDimitry Andric       return 0;
143*0b57cec5SDimitry Andric     }
144*0b57cec5SDimitry Andric 
145*0b57cec5SDimitry Andric     // In most cases, the union will start before LR.
146*0b57cec5SDimitry Andric     LRI = LR->begin();
147*0b57cec5SDimitry Andric     LiveUnionI.setMap(LiveUnion->getMap());
148*0b57cec5SDimitry Andric     LiveUnionI.find(LRI->start);
149*0b57cec5SDimitry Andric   }
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric   LiveRange::const_iterator LREnd = LR->end();
15281ad6265SDimitry Andric   const LiveInterval *RecentReg = nullptr;
153*0b57cec5SDimitry Andric   while (LiveUnionI.valid()) {
154*0b57cec5SDimitry Andric     assert(LRI != LREnd && "Reached end of LR");
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric     // Check for overlapping interference.
157*0b57cec5SDimitry Andric     while (LRI->start < LiveUnionI.stop() && LRI->end > LiveUnionI.start()) {
158*0b57cec5SDimitry Andric       // This is an overlap, record the interfering register.
15981ad6265SDimitry Andric       const LiveInterval *VReg = LiveUnionI.value();
160*0b57cec5SDimitry Andric       if (VReg != RecentReg && !isSeenInterference(VReg)) {
161*0b57cec5SDimitry Andric         RecentReg = VReg;
162349cc55cSDimitry Andric         InterferingVRegs.push_back(VReg);
163349cc55cSDimitry Andric         if (InterferingVRegs.size() >= MaxInterferingRegs)
164349cc55cSDimitry Andric           return InterferingVRegs.size();
165*0b57cec5SDimitry Andric       }
166*0b57cec5SDimitry Andric       // This LiveUnion segment is no longer interesting.
167*0b57cec5SDimitry Andric       if (!(++LiveUnionI).valid()) {
168*0b57cec5SDimitry Andric         SeenAllInterferences = true;
169349cc55cSDimitry Andric         return InterferingVRegs.size();
170*0b57cec5SDimitry Andric       }
171*0b57cec5SDimitry Andric     }
172*0b57cec5SDimitry Andric 
173*0b57cec5SDimitry Andric     // The iterators are now not overlapping, LiveUnionI has been advanced
174*0b57cec5SDimitry Andric     // beyond LRI.
175*0b57cec5SDimitry Andric     assert(LRI->end <= LiveUnionI.start() && "Expected non-overlap");
176*0b57cec5SDimitry Andric 
177*0b57cec5SDimitry Andric     // Advance the iterator that ends first.
178*0b57cec5SDimitry Andric     LRI = LR->advanceTo(LRI, LiveUnionI.start());
179*0b57cec5SDimitry Andric     if (LRI == LREnd)
180*0b57cec5SDimitry Andric       break;
181*0b57cec5SDimitry Andric 
182*0b57cec5SDimitry Andric     // Detect overlap, handle above.
183*0b57cec5SDimitry Andric     if (LRI->start < LiveUnionI.stop())
184*0b57cec5SDimitry Andric       continue;
185*0b57cec5SDimitry Andric 
186*0b57cec5SDimitry Andric     // Still not overlapping. Catch up LiveUnionI.
187*0b57cec5SDimitry Andric     LiveUnionI.advanceTo(LRI->start);
188*0b57cec5SDimitry Andric   }
189*0b57cec5SDimitry Andric   SeenAllInterferences = true;
190349cc55cSDimitry Andric   return InterferingVRegs.size();
191*0b57cec5SDimitry Andric }
192*0b57cec5SDimitry Andric 
init(LiveIntervalUnion::Allocator & Alloc,unsigned NSize)193*0b57cec5SDimitry Andric void LiveIntervalUnion::Array::init(LiveIntervalUnion::Allocator &Alloc,
194*0b57cec5SDimitry Andric                                     unsigned NSize) {
195*0b57cec5SDimitry Andric   // Reuse existing allocation.
196*0b57cec5SDimitry Andric   if (NSize == Size)
197*0b57cec5SDimitry Andric     return;
198*0b57cec5SDimitry Andric   clear();
199*0b57cec5SDimitry Andric   Size = NSize;
200*0b57cec5SDimitry Andric   LIUs = static_cast<LiveIntervalUnion*>(
201*0b57cec5SDimitry Andric       safe_malloc(sizeof(LiveIntervalUnion)*NSize));
202*0b57cec5SDimitry Andric   for (unsigned i = 0; i != Size; ++i)
203*0b57cec5SDimitry Andric     new(LIUs + i) LiveIntervalUnion(Alloc);
204*0b57cec5SDimitry Andric }
205*0b57cec5SDimitry Andric 
clear()206*0b57cec5SDimitry Andric void LiveIntervalUnion::Array::clear() {
207*0b57cec5SDimitry Andric   if (!LIUs)
208*0b57cec5SDimitry Andric     return;
209*0b57cec5SDimitry Andric   for (unsigned i = 0; i != Size; ++i)
210*0b57cec5SDimitry Andric     LIUs[i].~LiveIntervalUnion();
211*0b57cec5SDimitry Andric   free(LIUs);
212*0b57cec5SDimitry Andric   Size =  0;
213*0b57cec5SDimitry Andric   LIUs = nullptr;
214*0b57cec5SDimitry Andric }
215