diff --git a/llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp b/llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp index 9f1012c9596496..a41da98977c7d2 100644 --- a/llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp +++ b/llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "RegAllocEvictionAdvisor.h" +#include "RegAllocGreedy.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/RegisterClassInfo.h" #include "llvm/CodeGen/VirtRegMap.h" @@ -62,12 +63,8 @@ class DefaultEvictionAdvisorAnalysis final private: std::unique_ptr - getAdvisor(const MachineFunction &MF, LiveRegMatrix *Matrix, - LiveIntervals *LIS, VirtRegMap *VRM, - const RegisterClassInfo &RegClassInfo, - ExtraRegInfo *ExtraInfo) override { - return std::make_unique(MF, Matrix, LIS, VRM, - RegClassInfo, ExtraInfo); + getAdvisor(const MachineFunction &MF, const RAGreedy &RA) override { + return std::make_unique(MF, RA); } bool doInitialization(Module &M) override { if (NotAsRequested) @@ -109,13 +106,12 @@ StringRef RegAllocEvictionAdvisorAnalysis::getPassName() const { llvm_unreachable("Unknown advisor kind"); } -RegAllocEvictionAdvisor::RegAllocEvictionAdvisor( - const MachineFunction &MF, LiveRegMatrix *Matrix, LiveIntervals *LIS, - VirtRegMap *VRM, const RegisterClassInfo &RegClassInfo, - ExtraRegInfo *ExtraInfo) - : MF(MF), Matrix(Matrix), LIS(LIS), VRM(VRM), MRI(&VRM->getRegInfo()), - TRI(MF.getSubtarget().getRegisterInfo()), RegClassInfo(RegClassInfo), - RegCosts(TRI->getRegisterCosts(MF)), ExtraInfo(ExtraInfo), +RegAllocEvictionAdvisor::RegAllocEvictionAdvisor(const MachineFunction &MF, + const RAGreedy &RA) + : MF(MF), RA(RA), Matrix(RA.getInterferenceMatrix()), + LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()), + MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()), + RegClassInfo(RA.getRegClassInfo()), RegCosts(TRI->getRegisterCosts(MF)), EnableLocalReassign(EnableLocalReassignment || MF.getSubtarget().enableRALocalReassignment( MF.getTarget().getOptLevel())) {} diff --git a/llvm/lib/CodeGen/RegAllocEvictionAdvisor.h b/llvm/lib/CodeGen/RegAllocEvictionAdvisor.h index debb75ed502041..d99ebfc7c534b4 100644 --- a/llvm/lib/CodeGen/RegAllocEvictionAdvisor.h +++ b/llvm/lib/CodeGen/RegAllocEvictionAdvisor.h @@ -87,87 +87,9 @@ struct EvictionCost { } }; -/// Track allocation stage and eviction loop prevention during allocation. -// TODO(mtrofin): Consider exposing RAGreedy in a header instead, and folding -// this back into it. -class ExtraRegInfo final { - // RegInfo - Keep additional information about each live range. - struct RegInfo { - LiveRangeStage Stage = RS_New; - - // Cascade - Eviction loop prevention. See - // canEvictInterferenceBasedOnCost(). - unsigned Cascade = 0; - - RegInfo() = default; - }; - - IndexedMap Info; - unsigned NextCascade = 1; - -public: - ExtraRegInfo() = default; - ExtraRegInfo(const ExtraRegInfo &) = delete; - - LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; } - - LiveRangeStage getStage(const LiveInterval &VirtReg) const { - return getStage(VirtReg.reg()); - } - - void setStage(Register Reg, LiveRangeStage Stage) { - Info.grow(Reg.id()); - Info[Reg].Stage = Stage; - } - - void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) { - setStage(VirtReg.reg(), Stage); - } - - /// Return the current stage of the register, if present, otherwise initialize - /// it and return that. - LiveRangeStage getOrInitStage(Register Reg) { - Info.grow(Reg.id()); - return getStage(Reg); - } - - unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; } - - void setCascade(Register Reg, unsigned Cascade) { - Info.grow(Reg.id()); - Info[Reg].Cascade = Cascade; - } - - unsigned getOrAssignNewCascade(Register Reg) { - unsigned Cascade = getCascade(Reg); - if (!Cascade) { - Cascade = NextCascade++; - setCascade(Reg, Cascade); - } - return Cascade; - } - - unsigned getCascadeOrCurrentNext(Register Reg) const { - unsigned Cascade = getCascade(Reg); - if (!Cascade) - Cascade = NextCascade; - return Cascade; - } - - template - void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) { - for (; Begin != End; ++Begin) { - Register Reg = *Begin; - Info.grow(Reg.id()); - if (Info[Reg].Stage == RS_New) - Info[Reg].Stage = NewStage; - } - } - void LRE_DidCloneVirtReg(Register New, Register Old); -}; - /// Interface to the eviction advisor, which is responsible for making a /// decision as to which live ranges should be evicted (if any). +class RAGreedy; class RegAllocEvictionAdvisor { public: RegAllocEvictionAdvisor(const RegAllocEvictionAdvisor &) = delete; @@ -193,14 +115,12 @@ class RegAllocEvictionAdvisor { bool isUnusedCalleeSavedReg(MCRegister PhysReg) const; protected: - RegAllocEvictionAdvisor(const MachineFunction &MF, LiveRegMatrix *Matrix, - LiveIntervals *LIS, VirtRegMap *VRM, - const RegisterClassInfo &RegClassInfo, - ExtraRegInfo *ExtraInfo); + RegAllocEvictionAdvisor(const MachineFunction &MF, const RAGreedy &RA); Register canReassign(LiveInterval &VirtReg, Register PrevReg) const; const MachineFunction &MF; + const RAGreedy &RA; LiveRegMatrix *const Matrix; LiveIntervals *const LIS; VirtRegMap *const VRM; @@ -208,7 +128,6 @@ class RegAllocEvictionAdvisor { const TargetRegisterInfo *const TRI; const RegisterClassInfo &RegClassInfo; const ArrayRef RegCosts; - ExtraRegInfo *const ExtraInfo; /// Run or not the local reassignment heuristic. This information is /// obtained from the TargetSubtargetInfo. @@ -243,10 +162,7 @@ class RegAllocEvictionAdvisorAnalysis : public ImmutablePass { /// Get an advisor for the given context (i.e. machine function, etc) virtual std::unique_ptr - getAdvisor(const MachineFunction &MF, LiveRegMatrix *Matrix, - LiveIntervals *LIS, VirtRegMap *VRM, - const RegisterClassInfo &RegClassInfo, - ExtraRegInfo *ExtraInfo) = 0; + getAdvisor(const MachineFunction &MF, const RAGreedy &RA) = 0; AdvisorMode getAdvisorMode() const { return Mode; } private: @@ -277,12 +193,8 @@ RegAllocEvictionAdvisorAnalysis *createDevelopmentModeAdvisor(); // out of RegAllocGreedy.cpp class DefaultEvictionAdvisor : public RegAllocEvictionAdvisor { public: - DefaultEvictionAdvisor(const MachineFunction &MF, LiveRegMatrix *Matrix, - LiveIntervals *LIS, VirtRegMap *VRM, - const RegisterClassInfo &RegClassInfo, - ExtraRegInfo *ExtraInfo) - : RegAllocEvictionAdvisor(MF, Matrix, LIS, VRM, RegClassInfo, ExtraInfo) { - } + DefaultEvictionAdvisor(const MachineFunction &MF, const RAGreedy &RA) + : RegAllocEvictionAdvisor(MF, RA) {} private: MCRegister tryFindEvictionCandidate(LiveInterval &, const AllocationOrder &, diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp index 7088c944f5b1ba..7b1f6d156625d7 100644 --- a/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -258,7 +258,7 @@ void RAGreedy::LRE_DidCloneVirtReg(Register New, Register Old) { ExtraInfo->LRE_DidCloneVirtReg(New, Old); } -void ExtraRegInfo::LRE_DidCloneVirtReg(Register New, Register Old) { +void RAGreedy::ExtraRegInfo::LRE_DidCloneVirtReg(Register New, Register Old) { // Cloning a register we haven't even heard about yet? Just ignore it. if (!Info.inBounds(Old)) return; @@ -456,7 +456,7 @@ Register RegAllocEvictionAdvisor::canReassign(LiveInterval &VirtReg, bool DefaultEvictionAdvisor::shouldEvict(LiveInterval &A, bool IsHint, LiveInterval &B, bool BreaksHint) const { - bool CanSplit = ExtraInfo->getStage(B) < RS_Spill; + bool CanSplit = RA.getExtraInfo().getStage(B) < RS_Spill; // Be fairly aggressive about following hints as long as the evictee can be // split. @@ -506,7 +506,7 @@ bool DefaultEvictionAdvisor::canEvictInterferenceBasedOnCost( // // This works out so a register without a cascade number is allowed to evict // anything, and it can be evicted by anything. - unsigned Cascade = ExtraInfo->getCascadeOrCurrentNext(VirtReg.reg()); + unsigned Cascade = RA.getExtraInfo().getCascadeOrCurrentNext(VirtReg.reg()); EvictionCost Cost; for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { @@ -528,7 +528,7 @@ bool DefaultEvictionAdvisor::canEvictInterferenceBasedOnCost( return false; // Never evict spill products. They cannot split or spill. - if (ExtraInfo->getStage(*Intf) == RS_Done) + if (RA.getExtraInfo().getStage(*Intf) == RS_Done) return false; // Once a live range becomes small enough, it is urgent that we find a // register for it. This is indicated by an infinite spill weight. These @@ -543,7 +543,7 @@ bool DefaultEvictionAdvisor::canEvictInterferenceBasedOnCost( RegClassInfo.getNumAllocatableRegs( MRI->getRegClass(Intf->reg()))); // Only evict older cascades or live ranges without a cascade. - unsigned IntfCascade = ExtraInfo->getCascade(Intf->reg()); + unsigned IntfCascade = RA.getExtraInfo().getCascade(Intf->reg()); if (Cascade <= IntfCascade) { if (!Urgent) return false; @@ -2914,8 +2914,8 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { SA.reset(new SplitAnalysis(*VRM, *LIS, *Loops)); SE.reset(new SplitEditor(*SA, *AA, *LIS, *VRM, *DomTree, *MBFI, *VRAI)); ExtraInfo.emplace(); - EvictAdvisor = getAnalysis().getAdvisor( - *MF, Matrix, LIS, VRM, RegClassInfo, &*ExtraInfo); + EvictAdvisor = + getAnalysis().getAdvisor(*MF, *this); IntfCache.init(MF, Matrix->getLiveUnions(), Indexes, LIS, TRI); GlobalCand.resize(32); // This will grow as needed. SetOfBrokenHints.clear(); diff --git a/llvm/lib/CodeGen/RegAllocGreedy.h b/llvm/lib/CodeGen/RegAllocGreedy.h index 3d8f541bc5e7ae..bb8c3e7a5b4619 100644 --- a/llvm/lib/CodeGen/RegAllocGreedy.h +++ b/llvm/lib/CodeGen/RegAllocGreedy.h @@ -72,6 +72,93 @@ namespace llvm { class LLVM_LIBRARY_VISIBILITY RAGreedy : public MachineFunctionPass, public RegAllocBase, private LiveRangeEdit::Delegate { + // Interface to eviction advisers +public: + /// Track allocation stage and eviction loop prevention during allocation. + class ExtraRegInfo final { + // RegInfo - Keep additional information about each live range. + struct RegInfo { + LiveRangeStage Stage = RS_New; + + // Cascade - Eviction loop prevention. See + // canEvictInterferenceBasedOnCost(). + unsigned Cascade = 0; + + RegInfo() = default; + }; + + IndexedMap Info; + unsigned NextCascade = 1; + + public: + ExtraRegInfo() = default; + ExtraRegInfo(const ExtraRegInfo &) = delete; + + LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; } + + LiveRangeStage getStage(const LiveInterval &VirtReg) const { + return getStage(VirtReg.reg()); + } + + void setStage(Register Reg, LiveRangeStage Stage) { + Info.grow(Reg.id()); + Info[Reg].Stage = Stage; + } + + void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) { + setStage(VirtReg.reg(), Stage); + } + + /// Return the current stage of the register, if present, otherwise + /// initialize it and return that. + LiveRangeStage getOrInitStage(Register Reg) { + Info.grow(Reg.id()); + return getStage(Reg); + } + + unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; } + + void setCascade(Register Reg, unsigned Cascade) { + Info.grow(Reg.id()); + Info[Reg].Cascade = Cascade; + } + + unsigned getOrAssignNewCascade(Register Reg) { + unsigned Cascade = getCascade(Reg); + if (!Cascade) { + Cascade = NextCascade++; + setCascade(Reg, Cascade); + } + return Cascade; + } + + unsigned getCascadeOrCurrentNext(Register Reg) const { + unsigned Cascade = getCascade(Reg); + if (!Cascade) + Cascade = NextCascade; + return Cascade; + } + + template + void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) { + for (; Begin != End; ++Begin) { + Register Reg = *Begin; + Info.grow(Reg.id()); + if (Info[Reg].Stage == RS_New) + Info[Reg].Stage = NewStage; + } + } + void LRE_DidCloneVirtReg(Register New, Register Old); + }; + + LiveRegMatrix *getInterferenceMatrix() const { return Matrix; } + LiveIntervals *getLiveIntervals() const { return LIS; } + VirtRegMap *getVirtRegMap() const { return VRM; } + const RegisterClassInfo &getRegClassInfo() const { return RegClassInfo; } + const ExtraRegInfo &getExtraInfo() const { return *ExtraInfo; } + // end (interface to eviction advisers) + +private: // Convenient shortcuts. using PQueue = std::priority_queue>; using SmallLISet = SmallPtrSet;