Skip to content

Commit c270cb6

Browse files
committed
Count references to interference cache entries.
Each InterferenceCache::Cursor instance references a cache entry. A non-zero reference count guarantees that the entry won't be reused for a new register. This makes it possible to have multiple live cursors examining interference for different physregs. The total number of live cursors into a cache must be kept below InterferenceCache::getMaxCursors(). Code generation should be unaffected by this change, and it doesn't seem to affect the cache replacement strategy either. llvm-svn: 135121
1 parent bc2ae1c commit c270cb6

File tree

3 files changed

+70
-11
lines changed

3 files changed

+70
-11
lines changed

llvm/lib/CodeGen/InterferenceCache.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define DEBUG_TYPE "regalloc"
1515
#include "InterferenceCache.h"
1616
#include "llvm/Target/TargetRegisterInfo.h"
17+
#include "llvm/Support/ErrorHandling.h"
1718

1819
using namespace llvm;
1920

@@ -40,9 +41,18 @@ InterferenceCache::Entry *InterferenceCache::get(unsigned PhysReg) {
4041
E = RoundRobin;
4142
if (++RoundRobin == CacheEntries)
4243
RoundRobin = 0;
43-
Entries[E].reset(PhysReg, LIUArray, TRI, MF);
44-
PhysRegEntries[PhysReg] = E;
45-
return &Entries[E];
44+
for (unsigned i = 0; i != CacheEntries; ++i) {
45+
// Skip entries that are in use.
46+
if (Entries[E].hasRefs()) {
47+
if (++E == CacheEntries)
48+
E = 0;
49+
continue;
50+
}
51+
Entries[E].reset(PhysReg, LIUArray, TRI, MF);
52+
PhysRegEntries[PhysReg] = E;
53+
return &Entries[E];
54+
}
55+
llvm_unreachable("Ran out of interference cache entries.");
4656
}
4757

4858
/// revalidate - LIU contents have changed, update tags.
@@ -59,6 +69,7 @@ void InterferenceCache::Entry::reset(unsigned physReg,
5969
LiveIntervalUnion *LIUArray,
6070
const TargetRegisterInfo *TRI,
6171
const MachineFunction *MF) {
72+
assert(!hasRefs() && "Cannot reset cache entry with references");
6273
// LIU's changed, invalidate cache.
6374
++Tag;
6475
PhysReg = physReg;

llvm/lib/CodeGen/InterferenceCache.h

+40-3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class InterferenceCache {
4343
/// change.
4444
unsigned Tag;
4545

46+
/// RefCount - The total number of Cursor instances referring to this Entry.
47+
unsigned RefCount;
48+
4649
/// MF - The current function.
4750
MachineFunction *MF;
4851

@@ -68,16 +71,21 @@ class InterferenceCache {
6871
void update(unsigned MBBNum);
6972

7073
public:
71-
Entry() : PhysReg(0), Tag(0), Indexes(0) {}
74+
Entry() : PhysReg(0), Tag(0), RefCount(0), Indexes(0) {}
7275

7376
void clear(MachineFunction *mf, SlotIndexes *indexes) {
77+
assert(!hasRefs() && "Cannot clear cache entry with references");
7478
PhysReg = 0;
7579
MF = mf;
7680
Indexes = indexes;
7781
}
7882

7983
unsigned getPhysReg() const { return PhysReg; }
8084

85+
void addRef(int Delta) { RefCount += Delta; }
86+
87+
bool hasRefs() const { return RefCount > 0; }
88+
8189
void revalidate();
8290

8391
/// valid - Return true if this is a valid entry for physReg.
@@ -122,18 +130,47 @@ class InterferenceCache {
122130
void init(MachineFunction*, LiveIntervalUnion*, SlotIndexes*,
123131
const TargetRegisterInfo *);
124132

133+
/// getMaxCursors - Return the maximum number of concurrent cursors that can
134+
/// be supported.
135+
unsigned getMaxCursors() const { return CacheEntries; }
136+
125137
/// Cursor - The primary query interface for the block interference cache.
126138
class Cursor {
127139
Entry *CacheEntry;
128140
BlockInterference *Current;
141+
142+
void setEntry(Entry *E) {
143+
// Update reference counts. Nothing happens when RefCount reaches 0, so
144+
// we don't have to check for E == CacheEntry etc.
145+
if (CacheEntry)
146+
CacheEntry->addRef(-1);
147+
CacheEntry = E;
148+
if (CacheEntry)
149+
CacheEntry->addRef(+1);
150+
Current = 0;
151+
}
152+
129153
public:
130154
/// Cursor - Create a dangling cursor.
131155
Cursor() : CacheEntry(0), Current(0) {}
156+
~Cursor() { setEntry(0); }
157+
158+
Cursor(const Cursor &O) {
159+
setEntry(O.CacheEntry);
160+
}
161+
162+
Cursor &operator=(const Cursor &O) {
163+
setEntry(O.CacheEntry);
164+
return *this;
165+
}
132166

133167
/// setPhysReg - Point this cursor to PhysReg's interference.
134168
void setPhysReg(InterferenceCache &Cache, unsigned PhysReg) {
135-
CacheEntry = Cache.get(PhysReg);
136-
Current = 0;
169+
// Release reference before getting a new one. That guarantees we can
170+
// actually have CacheEntries live cursors.
171+
setEntry(0);
172+
if (PhysReg)
173+
setEntry(Cache.get(PhysReg));
137174
}
138175

139176
/// moveTo - Move cursor to basic block MBBNum.

llvm/lib/CodeGen/RegAllocGreedy.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -854,11 +854,6 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
854854
});
855855

856856
InterferenceCache::Cursor &Intf = Cand.Intf;
857-
858-
// FIXME: We need cache reference counts to guarantee that Intf hasn't been
859-
// clobbered.
860-
Intf.setPhysReg(IntfCache, Cand.PhysReg);
861-
862857
LiveRangeEdit LREdit(VirtReg, NewVRegs, this);
863858
SE->reset(LREdit);
864859

@@ -1252,6 +1247,22 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
12521247

12531248
Order.rewind();
12541249
while (unsigned PhysReg = Order.next()) {
1250+
// Discard bad candidates before we run out of interference cache cursors.
1251+
// This will only affect register classes with a lot of registers (>32).
1252+
if (NumCands == IntfCache.getMaxCursors()) {
1253+
unsigned WorstCount = ~0u;
1254+
unsigned Worst = 0;
1255+
for (unsigned i = 0; i != NumCands; ++i) {
1256+
if (i == BestCand)
1257+
continue;
1258+
unsigned Count = GlobalCand[i].LiveBundles.count();
1259+
if (Count < WorstCount)
1260+
Worst = i, WorstCount = Count;
1261+
}
1262+
--NumCands;
1263+
GlobalCand[Worst] = GlobalCand[NumCands];
1264+
}
1265+
12551266
if (GlobalCand.size() <= NumCands)
12561267
GlobalCand.resize(NumCands+1);
12571268
GlobalSplitCandidate &Cand = GlobalCand[NumCands];

0 commit comments

Comments
 (0)