Skip to content

[CodeGen] Remove experimental deferred spilling from GreedyRegAlloc #137850

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions llvm/include/llvm/CodeGen/RegAllocEvictionAdvisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ enum LiveRangeStage {
/// Live range will be spilled. No more splitting will be attempted.
RS_Spill,

/// Live range is in memory. Because of other evictions, it might get moved
/// in a register in the end.
RS_Memory,

/// There is nothing more we can do to this live range. Abort compilation
/// if it can't be assigned.
RS_Done
Expand Down
15 changes: 0 additions & 15 deletions llvm/include/llvm/CodeGen/TargetRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1192,21 +1192,6 @@ class TargetRegisterInfo : public MCRegisterInfo {
return true;
}

/// Deferred spilling delays the spill insertion of a virtual register
/// after every other allocation. By deferring the spilling, it is
/// sometimes possible to eliminate that spilling altogether because
/// something else could have been eliminated, thus leaving some space
/// for the virtual register.
/// However, this comes with a compile time impact because it adds one
/// more stage to the greedy register allocator.
/// This method is used to decide whether \p VirtReg should use the deferred
/// spilling stage instead of being spilled right away.
virtual bool
shouldUseDeferredSpillingForVirtReg(const MachineFunction &MF,
const LiveInterval &VirtReg) const {
return false;
}

/// When prioritizing live ranges in register allocation, if this hook returns
/// true then the AllocationPriority of the register class will be treated as
/// more important than whether the range is local to a basic block or global.
Expand Down
58 changes: 15 additions & 43 deletions llvm/lib/CodeGen/RegAllocGreedy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,6 @@ static cl::opt<bool> ExhaustiveSearch(
"and interference cutoffs of last chance recoloring"),
cl::Hidden);

static cl::opt<bool> EnableDeferredSpilling(
"enable-deferred-spilling", cl::Hidden,
cl::desc("Instead of spilling a variable right away, defer the actual "
"code insertion to the end of the allocation. That way the "
"allocator might still find a suitable coloring for this "
"variable because of other evicted variables."),
cl::init(false));

// FIXME: Find a good default for this flag and remove the flag.
static cl::opt<unsigned>
CSRFirstTimeCost("regalloc-csr-first-time-cost",
Expand Down Expand Up @@ -328,7 +320,6 @@ const char *const RAGreedy::StageName[] = {
"RS_Split",
"RS_Split2",
"RS_Spill",
"RS_Memory",
"RS_Done"
};
#endif
Expand Down Expand Up @@ -456,13 +447,6 @@ unsigned DefaultPriorityAdvisor::getPriority(const LiveInterval &LI) const {
// Unsplit ranges that couldn't be allocated immediately are deferred until
// everything else has been allocated.
Prio = Size;
} else if (Stage == RS_Memory) {
// Memory operand should be considered last.
// Change the priority such that Memory operand are assigned in
// the reverse order that they came in.
// TODO: Make this a member variable and probably do something about hints.
static unsigned MemOp = 0;
Prio = MemOp++;
} else {
// Giant live ranges fall back to the global assignment heuristic, which
// prevents excessive spilling in pathological cases.
Expand Down Expand Up @@ -2650,34 +2634,22 @@ MCRegister RAGreedy::selectOrSplitImpl(const LiveInterval &VirtReg,
}

// Finally spill VirtReg itself.
if ((EnableDeferredSpilling ||
TRI->shouldUseDeferredSpillingForVirtReg(*MF, VirtReg)) &&
ExtraInfo->getStage(VirtReg) < RS_Memory) {
// TODO: This is experimental and in particular, we do not model
// the live range splitting done by spilling correctly.
// We would need a deep integration with the spiller to do the
// right thing here. Anyway, that is still good for early testing.
ExtraInfo->setStage(VirtReg, RS_Memory);
LLVM_DEBUG(dbgs() << "Do as if this register is in memory\n");
NewVRegs.push_back(VirtReg.reg());
} else {
NamedRegionTimer T("spill", "Spiller", TimerGroupName,
TimerGroupDescription, TimePassesIsEnabled);
LiveRangeEdit LRE(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
spiller().spill(LRE, &Order);
ExtraInfo->setStage(NewVRegs.begin(), NewVRegs.end(), RS_Done);

// Tell LiveDebugVariables about the new ranges. Ranges not being covered by
// the new regs are kept in LDV (still mapping to the old register), until
// we rewrite spilled locations in LDV at a later stage.
for (Register r : spiller().getSpilledRegs())
DebugVars->splitRegister(r, LRE.regs(), *LIS);
for (Register r : spiller().getReplacedRegs())
DebugVars->splitRegister(r, LRE.regs(), *LIS);
NamedRegionTimer T("spill", "Spiller", TimerGroupName,
TimerGroupDescription, TimePassesIsEnabled);
LiveRangeEdit LRE(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
spiller().spill(LRE, &Order);
ExtraInfo->setStage(NewVRegs.begin(), NewVRegs.end(), RS_Done);

// Tell LiveDebugVariables about the new ranges. Ranges not being covered by
// the new regs are kept in LDV (still mapping to the old register), until
// we rewrite spilled locations in LDV at a later stage.
for (Register r : spiller().getSpilledRegs())
DebugVars->splitRegister(r, LRE.regs(), *LIS);
for (Register r : spiller().getReplacedRegs())
DebugVars->splitRegister(r, LRE.regs(), *LIS);

if (VerifyEnabled)
MF->verify(LIS, Indexes, "After spilling", &errs());
}
if (VerifyEnabled)
MF->verify(LIS, Indexes, "After spilling", &errs());

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