Skip to content

Commit 34f4fe3

Browse files
committed
[NFC][Regalloc] Ensure Query::interferingVRegs is accurate.
To correctly use Query, one had to first call collectInterferingVRegs to pre-cache the query result, then call interferingVRegs. Failing the former, interferingVRegs could be stale. This did cause a bug which was addressed in D98232, but the underlying usability issue of the Query API wasn't. This patch addresses the latter by making collectInterferingVRegs an implementation detail, and having interferingVRegs play both roles. One side-effect of this is that interferingVRegs is not const anymore. Differential Revision: https://reviews.llvm.org/D112882
1 parent 1b108ab commit 34f4fe3

File tree

4 files changed

+31
-37
lines changed

4 files changed

+31
-37
lines changed

llvm/include/llvm/CodeGen/LiveIntervalUnion.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,19 @@ class LiveIntervalUnion {
114114
const LiveRange *LR = nullptr;
115115
LiveRange::const_iterator LRI; ///< current position in LR
116116
ConstSegmentIter LiveUnionI; ///< current position in LiveUnion
117-
Optional<SmallVector<LiveInterval *, 4>> InterferingVRegs;
117+
SmallVector<LiveInterval *, 4> InterferingVRegs;
118118
bool CheckedFirstInterference = false;
119119
bool SeenAllInterferences = false;
120120
unsigned Tag = 0;
121121
unsigned UserTag = 0;
122122

123+
// Count the virtual registers in this union that interfere with this
124+
// query's live virtual register, up to maxInterferingRegs.
125+
unsigned collectInterferingVRegs(unsigned MaxInterferingRegs);
126+
127+
// Was this virtual register visited during collectInterferingVRegs?
128+
bool isSeenInterference(LiveInterval *VirtReg) const;
129+
123130
public:
124131
Query() = default;
125132
Query(const LiveRange &LR, const LiveIntervalUnion &LIU)
@@ -131,7 +138,7 @@ class LiveIntervalUnion {
131138
const LiveIntervalUnion &NewLiveUnion) {
132139
LiveUnion = &NewLiveUnion;
133140
LR = &NewLR;
134-
InterferingVRegs = None;
141+
InterferingVRegs.clear();
135142
CheckedFirstInterference = false;
136143
SeenAllInterferences = false;
137144
Tag = NewLiveUnion.getTag();
@@ -151,20 +158,12 @@ class LiveIntervalUnion {
151158
// Does this live virtual register interfere with the union?
152159
bool checkInterference() { return collectInterferingVRegs(1); }
153160

154-
// Count the virtual registers in this union that interfere with this
155-
// query's live virtual register, up to maxInterferingRegs.
156-
unsigned collectInterferingVRegs(
157-
unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max());
158-
159-
// Was this virtual register visited during collectInterferingVRegs?
160-
bool isSeenInterference(LiveInterval *VirtReg) const;
161-
162-
// Did collectInterferingVRegs collect all interferences?
163-
bool seenAllInterferences() const { return SeenAllInterferences; }
164-
165161
// Vector generated by collectInterferingVRegs.
166-
const SmallVectorImpl<LiveInterval*> &interferingVRegs() const {
167-
return *InterferingVRegs;
162+
const SmallVectorImpl<LiveInterval *> &interferingVRegs(
163+
unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max()) {
164+
if (!SeenAllInterferences || MaxInterferingRegs < InterferingVRegs.size())
165+
collectInterferingVRegs(MaxInterferingRegs);
166+
return InterferingVRegs;
168167
}
169168
};
170169

llvm/lib/CodeGen/LiveIntervalUnion.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ LiveInterval *LiveIntervalUnion::getOneVReg() const {
112112
// Scan the vector of interfering virtual registers in this union. Assume it's
113113
// quite small.
114114
bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const {
115-
return is_contained(*InterferingVRegs, VirtReg);
115+
return is_contained(InterferingVRegs, VirtReg);
116116
}
117117

118118
// Collect virtual registers in this union that interfere with this
@@ -124,14 +124,11 @@ bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const {
124124
// 2. SeenAllInterferences == true: InterferingVRegs complete, iterators unused.
125125
// 3. Iterators left at the last seen intersection.
126126
//
127-
unsigned LiveIntervalUnion::Query::
128-
collectInterferingVRegs(unsigned MaxInterferingRegs) {
129-
if (!InterferingVRegs)
130-
InterferingVRegs.emplace();
131-
127+
unsigned
128+
LiveIntervalUnion::Query::collectInterferingVRegs(unsigned MaxInterferingRegs) {
132129
// Fast path return if we already have the desired information.
133-
if (SeenAllInterferences || InterferingVRegs->size() >= MaxInterferingRegs)
134-
return InterferingVRegs->size();
130+
if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs)
131+
return InterferingVRegs.size();
135132

136133
// Set up iterators on the first call.
137134
if (!CheckedFirstInterference) {
@@ -160,14 +157,14 @@ collectInterferingVRegs(unsigned MaxInterferingRegs) {
160157
LiveInterval *VReg = LiveUnionI.value();
161158
if (VReg != RecentReg && !isSeenInterference(VReg)) {
162159
RecentReg = VReg;
163-
InterferingVRegs->push_back(VReg);
164-
if (InterferingVRegs->size() >= MaxInterferingRegs)
165-
return InterferingVRegs->size();
160+
InterferingVRegs.push_back(VReg);
161+
if (InterferingVRegs.size() >= MaxInterferingRegs)
162+
return InterferingVRegs.size();
166163
}
167164
// This LiveUnion segment is no longer interesting.
168165
if (!(++LiveUnionI).valid()) {
169166
SeenAllInterferences = true;
170-
return InterferingVRegs->size();
167+
return InterferingVRegs.size();
171168
}
172169
}
173170

@@ -188,7 +185,7 @@ collectInterferingVRegs(unsigned MaxInterferingRegs) {
188185
LiveUnionI.advanceTo(LRI->start);
189186
}
190187
SeenAllInterferences = true;
191-
return InterferingVRegs->size();
188+
return InterferingVRegs.size();
192189
}
193190

194191
void LiveIntervalUnion::Array::init(LiveIntervalUnion::Allocator &Alloc,

llvm/lib/CodeGen/RegAllocBasic.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,7 @@ bool RABasic::spillInterferences(LiveInterval &VirtReg, MCRegister PhysReg,
217217
// Collect interferences assigned to any alias of the physical register.
218218
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
219219
LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, *Units);
220-
Q.collectInterferingVRegs();
221-
for (unsigned i = Q.interferingVRegs().size(); i; --i) {
222-
LiveInterval *Intf = Q.interferingVRegs()[i - 1];
220+
for (auto *Intf : reverse(Q.interferingVRegs())) {
223221
if (!Intf->isSpillable() || Intf->weight() > VirtReg.weight())
224222
return false;
225223
Intfs.push_back(Intf);

llvm/lib/CodeGen/RegAllocGreedy.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -955,11 +955,12 @@ bool RAGreedy::canEvictInterference(
955955
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
956956
LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, *Units);
957957
// If there is 10 or more interferences, chances are one is heavier.
958-
if (Q.collectInterferingVRegs(10) >= 10)
958+
const auto &Interferences = Q.interferingVRegs(10);
959+
if (Interferences.size() >= 10)
959960
return false;
960961

961962
// Check if any interfering live range is heavier than MaxWeight.
962-
for (LiveInterval *Intf : reverse(Q.interferingVRegs())) {
963+
for (LiveInterval *Intf : reverse(Interferences)) {
963964
assert(Register::isVirtualRegister(Intf->reg()) &&
964965
"Only expecting virtual register interference from query");
965966

@@ -1037,7 +1038,6 @@ bool RAGreedy::canEvictInterferenceInRange(const LiveInterval &VirtReg,
10371038

10381039
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
10391040
LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, *Units);
1040-
Q.collectInterferingVRegs();
10411041

10421042
// Check if any interfering live range is heavier than MaxWeight.
10431043
for (const LiveInterval *Intf : reverse(Q.interferingVRegs())) {
@@ -1127,7 +1127,6 @@ void RAGreedy::evictInterference(LiveInterval &VirtReg, MCRegister PhysReg,
11271127
// should be fast, we may need to recalculate if when different physregs
11281128
// overlap the same register unit so we had different SubRanges queried
11291129
// against it.
1130-
Q.collectInterferingVRegs();
11311130
ArrayRef<LiveInterval*> IVR = Q.interferingVRegs();
11321131
Intfs.append(IVR.begin(), IVR.end());
11331132
}
@@ -2547,8 +2546,9 @@ bool RAGreedy::mayRecolorAllInterferences(
25472546
LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, *Units);
25482547
// If there is LastChanceRecoloringMaxInterference or more interferences,
25492548
// chances are one would not be recolorable.
2550-
if (Q.collectInterferingVRegs(LastChanceRecoloringMaxInterference) >=
2551-
LastChanceRecoloringMaxInterference && !ExhaustiveSearch) {
2549+
if (Q.interferingVRegs(LastChanceRecoloringMaxInterference).size() >=
2550+
LastChanceRecoloringMaxInterference &&
2551+
!ExhaustiveSearch) {
25522552
LLVM_DEBUG(dbgs() << "Early abort: too many interferences.\n");
25532553
CutOffInfo |= CO_Interf;
25542554
return false;

0 commit comments

Comments
 (0)