Skip to content

Commit 1192294

Browse files
author
Quentin Colombet
committed
[RAGreedy] Add an experimental deferred spilling feature.
The idea of deferred spilling is to delay the insertion of spill code until the very end of the allocation. A "candidate" to spill variable might not required to be spilled because of other evictions that happened after this decision was taken. The spirit is similar to the optimistic coloring strategy implemented in Preston and Briggs graph coloring algorithm. For now, this feature is highly experimental. Although correct, it would require much more modification to properly model the effect of spilling. Anyway, this early patch helps prototyping this feature. Note: The test case cannot unfortunately be reduced and is probably fragile. llvm-svn: 242585
1 parent 484903e commit 1192294

File tree

2 files changed

+549
-6
lines changed

2 files changed

+549
-6
lines changed

llvm/lib/CodeGen/RegAllocGreedy.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ static cl::opt<bool> EnableLocalReassignment(
8686
"may be compile time intensive"),
8787
cl::init(false));
8888

89+
static cl::opt<bool> EnableDeferredSpilling(
90+
"enable-deferred-spilling", cl::Hidden,
91+
cl::desc("Instead of spilling a variable right away, defer the actual "
92+
"code insertion to the end of the allocation. That way the "
93+
"allocator might still find a suitable coloring for this "
94+
"variable because of other evicted variables."),
95+
cl::init(false));
96+
8997
// FIXME: Find a good default for this flag and remove the flag.
9098
static cl::opt<unsigned>
9199
CSRFirstTimeCost("regalloc-csr-first-time-cost",
@@ -157,6 +165,11 @@ class RAGreedy : public MachineFunctionPass,
157165
/// Live range will be spilled. No more splitting will be attempted.
158166
RS_Spill,
159167

168+
169+
/// Live range is in memory. Because of other evictions, it might get moved
170+
/// in a register in the end.
171+
RS_Memory,
172+
160173
/// There is nothing more we can do to this live range. Abort compilation
161174
/// if it can't be assigned.
162175
RS_Done
@@ -414,6 +427,7 @@ const char *const RAGreedy::StageName[] = {
414427
"RS_Split",
415428
"RS_Split2",
416429
"RS_Spill",
430+
"RS_Memory",
417431
"RS_Done"
418432
};
419433
#endif
@@ -536,6 +550,13 @@ void RAGreedy::enqueue(PQueue &CurQueue, LiveInterval *LI) {
536550
// Unsplit ranges that couldn't be allocated immediately are deferred until
537551
// everything else has been allocated.
538552
Prio = Size;
553+
} else if (ExtraRegInfo[Reg].Stage == RS_Memory) {
554+
// Memory operand should be considered last.
555+
// Change the priority such that Memory operand are assigned in
556+
// the reverse order that they came in.
557+
// TODO: Make this a member variable and probably do something about hints.
558+
static unsigned MemOp = 0;
559+
Prio = MemOp++;
539560
} else {
540561
// Giant live ranges fall back to the global assignment heuristic, which
541562
// prevents excessive spilling in pathological cases.
@@ -2512,13 +2533,23 @@ unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
25122533
return PhysReg;
25132534

25142535
// Finally spill VirtReg itself.
2515-
NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled);
2516-
LiveRangeEdit LRE(&VirtReg, NewVRegs, *MF, *LIS, VRM, this);
2517-
spiller().spill(LRE);
2518-
setStage(NewVRegs.begin(), NewVRegs.end(), RS_Done);
2536+
if (EnableDeferredSpilling && getStage(VirtReg) < RS_Memory) {
2537+
// TODO: This is experimental and in particular, we do not model
2538+
// the live range splitting done by spilling correctly.
2539+
// We would need a deep integration with the spiller to do the
2540+
// right thing here. Anyway, that is still good for early testing.
2541+
setStage(VirtReg, RS_Memory);
2542+
DEBUG(dbgs() << "Do as if this register is in memory\n");
2543+
NewVRegs.push_back(VirtReg.reg);
2544+
} else {
2545+
NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled);
2546+
LiveRangeEdit LRE(&VirtReg, NewVRegs, *MF, *LIS, VRM, this);
2547+
spiller().spill(LRE);
2548+
setStage(NewVRegs.begin(), NewVRegs.end(), RS_Done);
25192549

2520-
if (VerifyEnabled)
2521-
MF->verify(this, "After spilling");
2550+
if (VerifyEnabled)
2551+
MF->verify(this, "After spilling");
2552+
}
25222553

25232554
// The live virtual register requesting allocation was spilled, so tell
25242555
// the caller not to allocate anything during this round.

0 commit comments

Comments
 (0)