diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h index e4e92581b893..af6a5fa171a6 100644 --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -977,6 +977,36 @@ public: virtual bool shouldRegionSplitForVirtReg(const MachineFunction &MF, const LiveInterval &VirtReg) const; + /// Last chance recoloring has a high compile time cost especially for + /// targets with a lot of registers. + /// This method is used to decide whether or not \p VirtReg should + /// go through this expensive heuristic. + /// When this target hook is hit, by returning false, there is a high + /// chance that the register allocation will fail altogether (usually with + /// ran out of registers). + /// That said, this error usually points to another problem in the + /// optimization pipeline. + virtual bool + shouldUseLastChanceRecoloringForVirtReg(const MachineFunction &MF, + const LiveInterval &VirtReg) const { + return true; + } + + /// Deferred spilling delais the spill insertion of a virtual register + /// after every other allocations. 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; + } + //===--------------------------------------------------------------------===// /// Debug information queries. diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp index dbb8f27cffcd..415eb6a8fe7f 100644 --- a/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -2590,6 +2590,9 @@ unsigned RAGreedy::tryLastChanceRecoloring(LiveInterval &VirtReg, SmallVectorImpl &NewVRegs, SmallVirtRegSet &FixedRegisters, unsigned Depth) { + if (!TRI->shouldUseLastChanceRecoloringForVirtReg(*MF, VirtReg)) + return ~0u; + LLVM_DEBUG(dbgs() << "Try last chance recoloring for " << VirtReg << '\n'); // Ranges must be Done. assert((getStage(VirtReg) >= RS_Done || !VirtReg.isSpillable()) && @@ -3096,7 +3099,9 @@ Register RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg, Depth); // Finally spill VirtReg itself. - if (EnableDeferredSpilling && getStage(VirtReg) < RS_Memory) { + if ((EnableDeferredSpilling || + TRI->shouldUseDeferredSpillingForVirtReg(*MF, VirtReg)) && + 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