Skip to content

Commit

Permalink
[NFC][regalloc] Pass RAGreedy to eviction adviser
Browse files Browse the repository at this point in the history
This patch simplifies the interface between RAGreedy and the eviction
adviser by passing the allocator to the adviser, which allows the latter
to extract needed information as needed, rather than requiring it be passed
piecemeal at construction time (which would also complicate later
evolution).

Part of this, the patch also moves ExtraRegInfo back to RAGreedy. We
keep the encapsulation of ExtraRegInfo because it has benefits (e.g.
improved readability by abstracting access to the cascade info) and also
simpler re-initialization at regalloc pass re-entry time (we just flush
the Optional).

Differential Revision: https://reviews.llvm.org/D116669
  • Loading branch information
mtrofin committed Jan 10, 2022
1 parent c0add16 commit e121269
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 114 deletions.
22 changes: 9 additions & 13 deletions llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -62,12 +63,8 @@ class DefaultEvictionAdvisorAnalysis final

private:
std::unique_ptr<RegAllocEvictionAdvisor>
getAdvisor(const MachineFunction &MF, LiveRegMatrix *Matrix,
LiveIntervals *LIS, VirtRegMap *VRM,
const RegisterClassInfo &RegClassInfo,
ExtraRegInfo *ExtraInfo) override {
return std::make_unique<DefaultEvictionAdvisor>(MF, Matrix, LIS, VRM,
RegClassInfo, ExtraInfo);
getAdvisor(const MachineFunction &MF, const RAGreedy &RA) override {
return std::make_unique<DefaultEvictionAdvisor>(MF, RA);
}
bool doInitialization(Module &M) override {
if (NotAsRequested)
Expand Down Expand Up @@ -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())) {}
100 changes: 6 additions & 94 deletions llvm/lib/CodeGen/RegAllocEvictionAdvisor.h
Expand Up @@ -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<RegInfo, VirtReg2IndexFunctor> 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 <typename Iterator>
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;
Expand All @@ -193,22 +115,19 @@ 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;
MachineRegisterInfo *const MRI;
const TargetRegisterInfo *const TRI;
const RegisterClassInfo &RegClassInfo;
const ArrayRef<uint8_t> RegCosts;
ExtraRegInfo *const ExtraInfo;

/// Run or not the local reassignment heuristic. This information is
/// obtained from the TargetSubtargetInfo.
Expand Down Expand Up @@ -243,10 +162,7 @@ class RegAllocEvictionAdvisorAnalysis : public ImmutablePass {

/// Get an advisor for the given context (i.e. machine function, etc)
virtual std::unique_ptr<RegAllocEvictionAdvisor>
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:
Expand Down Expand Up @@ -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 &,
Expand Down
14 changes: 7 additions & 7 deletions llvm/lib/CodeGen/RegAllocGreedy.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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<RegAllocEvictionAdvisorAnalysis>().getAdvisor(
*MF, Matrix, LIS, VRM, RegClassInfo, &*ExtraInfo);
EvictAdvisor =
getAnalysis<RegAllocEvictionAdvisorAnalysis>().getAdvisor(*MF, *this);
IntfCache.init(MF, Matrix->getLiveUnions(), Indexes, LIS, TRI);
GlobalCand.resize(32); // This will grow as needed.
SetOfBrokenHints.clear();
Expand Down
87 changes: 87 additions & 0 deletions llvm/lib/CodeGen/RegAllocGreedy.h
Expand Up @@ -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<RegInfo, VirtReg2IndexFunctor> 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 <typename Iterator>
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<std::pair<unsigned, unsigned>>;
using SmallLISet = SmallPtrSet<LiveInterval *, 4>;
Expand Down

0 comments on commit e121269

Please sign in to comment.