blob: 3953c5930ad80f4119a0bb32c964246c1fa40270 [file] [log] [blame]
Andrew Trick14e8d712010-10-22 23:09:15 +00001//===-- LiveIntervalUnion.h - Live interval union data struct --*- C++ -*--===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// LiveIntervalUnion is a union of live segments across multiple live virtual
11// registers. This may be used during coalescing to represent a congruence
12// class, or during register allocation to model liveness of a physical
13// register.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_CODEGEN_LIVEINTERVALUNION
18#define LLVM_CODEGEN_LIVEINTERVALUNION
19
20#include "llvm/CodeGen/LiveInterval.h"
21#include <vector>
22#include <set>
23
24namespace llvm {
25
26// A LiveSegment is a copy of a LiveRange object used within
27// LiveIntervalUnion. LiveSegment additionally contains a pointer to its
28// original live virtual register (LiveInterval). This allows quick lookup of
29// the live virtual register as we iterate over live segments in a union. Note
30// that LiveRange is misnamed and actually represents only a single contiguous
31// interval within a virtual register's liveness. To limit confusion, in this
32// file we refer it as a live segment.
33struct LiveSegment {
34 SlotIndex start;
35 SlotIndex end;
36 LiveInterval *liveVirtReg;
37
38 LiveSegment(SlotIndex s, SlotIndex e, LiveInterval &lvr)
39 : start(s), end(e), liveVirtReg(&lvr) {}
40
41 bool operator==(const LiveSegment &ls) const {
42 return start == ls.start && end == ls.end && liveVirtReg == ls.liveVirtReg;
43 }
44
45 bool operator!=(const LiveSegment &ls) const {
46 return !operator==(ls);
47 }
48
49 bool operator<(const LiveSegment &ls) const {
50 return start < ls.start || (start == ls.start && end < ls.end);
51 }
52};
53
54/// Compare a live virtual register segment to a LiveIntervalUnion segment.
55inline bool overlap(const LiveRange &lvrSeg, const LiveSegment &liuSeg) {
56 return lvrSeg.start < liuSeg.end && liuSeg.start < lvrSeg.end;
57}
58
59inline bool operator<(SlotIndex V, const LiveSegment &ls) {
60 return V < ls.start;
61}
62
63inline bool operator<(const LiveSegment &ls, SlotIndex V) {
64 return ls.start < V;
65}
66
67/// Union of live intervals that are strong candidates for coalescing into a
68/// single register (either physical or virtual depending on the context). We
69/// expect the constituent live intervals to be disjoint, although we may
70/// eventually make exceptions to handle value-based interference.
71class LiveIntervalUnion {
72 // A set of live virtual register segments that supports fast insertion,
73 // intersection, and removal.
74 //
75 // FIXME: std::set is a placeholder until we decide how to
76 // efficiently represent it. Probably need to roll our own B-tree.
77 typedef std::set<LiveSegment> LiveSegments;
78
79 // A set of live virtual registers. Elements have type LiveInterval, where
80 // each element represents the liveness of a single live virtual register.
81 // This is traditionally known as a live range, but we refer is as a live
82 // virtual register to avoid confusing it with the misnamed LiveRange
83 // class.
84 typedef std::vector<LiveInterval*> LiveVirtRegs;
85
86public:
87 // SegmentIter can advance to the next segment ordered by starting position
88 // which may belong to a different live virtual register. We also must be able
89 // to reach the current segment's containing virtual register.
90 typedef LiveSegments::iterator SegmentIter;
91
92 class InterferenceResult;
93 class Query;
94
95private:
96 unsigned repReg_; // representative register number
97 LiveSegments segments_; // union of virtual reg segements
98 LiveVirtRegs lvrs_; // set of live virtual regs in the union
99
100public:
101 // default ctor avoids placement new
102 LiveIntervalUnion() : repReg_(0) {}
103
104 void init(unsigned repReg) { repReg_ = repReg; }
105
106 SegmentIter begin() { return segments_.begin(); }
107 SegmentIter end() { return segments_.end(); }
108
109 /// FIXME: !!!!!!!!!!! Keeps a non-const ref
110 void unify(LiveInterval &lvr);
111
112 // FIXME: needed by RegAllocGreedy
113 //void extract(const LiveInterval &li);
114
115 /// Cache a single interference test result in the form of two intersecting
116 /// segments. This allows efficiently iterating over the interferences. The
117 /// iteration logic is handled by LiveIntervalUnion::Query which may
118 /// filter interferences depending on the type of query.
119 class InterferenceResult {
120 friend class Query;
121
122 LiveInterval::iterator lvrSegI_; // current position in _lvr
123 SegmentIter liuSegI_; // current position in _liu
124
125 // Internal ctor.
126 InterferenceResult(LiveInterval::iterator lvrSegI, SegmentIter liuSegI)
127 : lvrSegI_(lvrSegI), liuSegI_(liuSegI) {}
128
129 public:
130 // Public default ctor.
131 InterferenceResult(): lvrSegI_(), liuSegI_() {}
132
133 // Note: this interface provides raw access to the iterators because the
134 // result has no way to tell if it's valid to dereference them.
135
136 // Access the lvr segment.
137 const LiveInterval::iterator &lvrSegPos() const { return lvrSegI_; }
138
139 // Access the liu segment.
140 const SegmentIter &liuSeg() const { return liuSegI_; }
141
142 bool operator==(const InterferenceResult &ir) const {
143 return lvrSegI_ == ir.lvrSegI_ && liuSegI_ == ir.liuSegI_;
144 }
145 bool operator!=(const InterferenceResult &ir) const {
146 return !operator==(ir);
147 }
148 };
149
150 /// Query interferences between a single live virtual register and a live
151 /// interval union.
152 class Query {
153 LiveIntervalUnion &liu_;
154 LiveInterval &lvr_;
155 InterferenceResult firstInterference_;
156 // TBD: interfering vregs
157
158 public:
159 Query(LiveInterval &lvr, LiveIntervalUnion &liu): liu_(liu), lvr_(lvr) {}
160
161 LiveInterval &lvr() const { return lvr_; }
162
163 bool isInterference(const InterferenceResult &ir) const {
164 if (ir.lvrSegI_ != lvr_.end()) {
165 assert(overlap(*ir.lvrSegI_, *ir.liuSegI_) &&
166 "invalid segment iterators");
167 return true;
168 }
169 return false;
170 }
171
172 // Does this live virtual register interfere with the union.
173 bool checkInterference() { return isInterference(firstInterference()); }
174
175 // First pair of interfering segments, or a noninterfering result.
176 InterferenceResult firstInterference();
177
178 // Treat the result as an iterator and advance to the next interfering pair
179 // of segments. Visiting each unique interfering pairs means that the same
180 // lvr or liu segment may be visited multiple times.
181 bool nextInterference(InterferenceResult &ir) const;
182
183 // TBD: bool collectInterferingVirtRegs(unsigned maxInterference)
184
185 private:
186 // Private interface for queries
187 void findIntersection(InterferenceResult &ir) const;
188 };
189};
190
191} // end namespace llvm
192
193#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION)