#include "RegAllocGreedy.h"
#include "AllocationOrder.h"
#include "InterferenceCache.h"
#include "RegAllocBase.h"
#include "RegAllocEvictionAdvisor.h"
#include "RegAllocPriorityAdvisor.h"
#include "SpillPlacement.h"
#include "SplitKit.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/EdgeBundles.h"
#include "llvm/CodeGen/LiveDebugVariables.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervalUnion.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/LiveRangeEdit.h"
#include "llvm/CodeGen/LiveRegMatrix.h"
#include "llvm/CodeGen/LiveStacks.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/Spiller.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Pass.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <utility>
usingnamespacellvm;
#define DEBUG_TYPE …
STATISTIC(NumGlobalSplits, "Number of split global live ranges");
STATISTIC(NumLocalSplits, "Number of split local live ranges");
STATISTIC(NumEvicted, "Number of interferences evicted");
static cl::opt<SplitEditor::ComplementSpillMode> SplitSpillMode(
"split-spill-mode", cl::Hidden,
cl::desc("Spill mode for splitting live ranges"),
cl::values(clEnumValN(SplitEditor::SM_Partition, "default", "Default"),
clEnumValN(SplitEditor::SM_Size, "size", "Optimize for size"),
clEnumValN(SplitEditor::SM_Speed, "speed", "Optimize for speed")),
cl::init(SplitEditor::SM_Speed));
static cl::opt<unsigned>
LastChanceRecoloringMaxDepth("lcr-max-depth", cl::Hidden,
cl::desc("Last chance recoloring max depth"),
cl::init(5));
static cl::opt<unsigned> LastChanceRecoloringMaxInterference(
"lcr-max-interf", cl::Hidden,
cl::desc("Last chance recoloring maximum number of considered"
" interference at a time"),
cl::init(8));
static cl::opt<bool> ExhaustiveSearch(
"exhaustive-register-search", cl::NotHidden,
cl::desc("Exhaustive Search for registers bypassing the depth "
"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));
static cl::opt<unsigned>
CSRFirstTimeCost("regalloc-csr-first-time-cost",
cl::desc("Cost for first time use of callee-saved register."),
cl::init(0), cl::Hidden);
static cl::opt<unsigned long> GrowRegionComplexityBudget(
"grow-region-complexity-budget",
cl::desc("growRegion() does not scale with the number of BB edges, so "
"limit its budget and bail out once we reach the limit."),
cl::init(10000), cl::Hidden);
static cl::opt<bool> GreedyRegClassPriorityTrumpsGlobalness(
"greedy-regclass-priority-trumps-globalness",
cl::desc("Change the greedy register allocator's live range priority "
"calculation to make the AllocationPriority of the register class "
"more important then whether the range is global"),
cl::Hidden);
static cl::opt<bool> GreedyReverseLocalAssignment(
"greedy-reverse-local-assignment",
cl::desc("Reverse allocation order of local live ranges, such that "
"shorter local live ranges will tend to be allocated first"),
cl::Hidden);
static cl::opt<unsigned> SplitThresholdForRegWithHint(
"split-threshold-for-reg-with-hint",
cl::desc("The threshold for splitting a virtual register with a hint, in "
"percentate"),
cl::init(75), cl::Hidden);
static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator",
createGreedyRegisterAllocator);
char RAGreedy::ID = …;
char &llvm::RAGreedyID = …;
INITIALIZE_PASS_BEGIN(RAGreedy, "greedy",
"Greedy Register Allocator", false, false)
INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables)
INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(RegisterCoalescer)
INITIALIZE_PASS_DEPENDENCY(MachineScheduler)
INITIALIZE_PASS_DEPENDENCY(LiveStacks)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(VirtRegMap)
INITIALIZE_PASS_DEPENDENCY(LiveRegMatrix)
INITIALIZE_PASS_DEPENDENCY(EdgeBundles)
INITIALIZE_PASS_DEPENDENCY(SpillPlacement)
INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass)
INITIALIZE_PASS_DEPENDENCY(RegAllocEvictionAdvisorAnalysis)
INITIALIZE_PASS_DEPENDENCY(RegAllocPriorityAdvisorAnalysis)
INITIALIZE_PASS_END(RAGreedy, "greedy",
"Greedy Register Allocator", false, false)
#ifndef NDEBUG
const char *const RAGreedy::StageName[] = {
"RS_New",
"RS_Assign",
"RS_Split",
"RS_Split2",
"RS_Spill",
"RS_Memory",
"RS_Done"
};
#endif
const float Hysteresis = …;
FunctionPass* llvm::createGreedyRegisterAllocator() { … }
FunctionPass *llvm::createGreedyRegisterAllocator(RegAllocFilterFunc Ftor) { … }
RAGreedy::RAGreedy(RegAllocFilterFunc F)
: … { … }
void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const { … }
bool RAGreedy::LRE_CanEraseVirtReg(Register VirtReg) { … }
void RAGreedy::LRE_WillShrinkVirtReg(Register VirtReg) { … }
void RAGreedy::LRE_DidCloneVirtReg(Register New, Register Old) { … }
void RAGreedy::ExtraRegInfo::LRE_DidCloneVirtReg(Register New, Register Old) { … }
void RAGreedy::releaseMemory() { … }
void RAGreedy::enqueueImpl(const LiveInterval *LI) { … }
void RAGreedy::enqueue(PQueue &CurQueue, const LiveInterval *LI) { … }
unsigned DefaultPriorityAdvisor::getPriority(const LiveInterval &LI) const { … }
const LiveInterval *RAGreedy::dequeue() { … }
const LiveInterval *RAGreedy::dequeue(PQueue &CurQueue) { … }
MCRegister RAGreedy::tryAssign(const LiveInterval &VirtReg,
AllocationOrder &Order,
SmallVectorImpl<Register> &NewVRegs,
const SmallVirtRegSet &FixedRegisters) { … }
bool RegAllocEvictionAdvisor::canReassign(const LiveInterval &VirtReg,
MCRegister FromReg) const { … }
void RAGreedy::evictInterference(const LiveInterval &VirtReg,
MCRegister PhysReg,
SmallVectorImpl<Register> &NewVRegs) { … }
bool RegAllocEvictionAdvisor::isUnusedCalleeSavedReg(MCRegister PhysReg) const { … }
std::optional<unsigned>
RegAllocEvictionAdvisor::getOrderLimit(const LiveInterval &VirtReg,
const AllocationOrder &Order,
unsigned CostPerUseLimit) const { … }
bool RegAllocEvictionAdvisor::canAllocatePhysReg(unsigned CostPerUseLimit,
MCRegister PhysReg) const { … }
MCRegister RAGreedy::tryEvict(const LiveInterval &VirtReg,
AllocationOrder &Order,
SmallVectorImpl<Register> &NewVRegs,
uint8_t CostPerUseLimit,
const SmallVirtRegSet &FixedRegisters) { … }
bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf,
BlockFrequency &Cost) { … }
bool RAGreedy::addThroughConstraints(InterferenceCache::Cursor Intf,
ArrayRef<unsigned> Blocks) { … }
bool RAGreedy::growRegion(GlobalSplitCandidate &Cand) { … }
bool RAGreedy::calcCompactRegion(GlobalSplitCandidate &Cand) { … }
BlockFrequency RAGreedy::calcSpillCost() { … }
BlockFrequency RAGreedy::calcGlobalSplitCost(GlobalSplitCandidate &Cand,
const AllocationOrder &Order) { … }
void RAGreedy::splitAroundRegion(LiveRangeEdit &LREdit,
ArrayRef<unsigned> UsedCands) { … }
MCRegister RAGreedy::tryRegionSplit(const LiveInterval &VirtReg,
AllocationOrder &Order,
SmallVectorImpl<Register> &NewVRegs) { … }
unsigned
RAGreedy::calculateRegionSplitCostAroundReg(MCPhysReg PhysReg,
AllocationOrder &Order,
BlockFrequency &BestCost,
unsigned &NumCands,
unsigned &BestCand) { … }
unsigned RAGreedy::calculateRegionSplitCost(const LiveInterval &VirtReg,
AllocationOrder &Order,
BlockFrequency &BestCost,
unsigned &NumCands,
bool IgnoreCSR) { … }
unsigned RAGreedy::doRegionSplit(const LiveInterval &VirtReg, unsigned BestCand,
bool HasCompact,
SmallVectorImpl<Register> &NewVRegs) { … }
bool RAGreedy::trySplitAroundHintReg(MCPhysReg Hint,
const LiveInterval &VirtReg,
SmallVectorImpl<Register> &NewVRegs,
AllocationOrder &Order) { … }
unsigned RAGreedy::tryBlockSplit(const LiveInterval &VirtReg,
AllocationOrder &Order,
SmallVectorImpl<Register> &NewVRegs) { … }
static unsigned getNumAllocatableRegsForConstraints(
const MachineInstr *MI, Register Reg, const TargetRegisterClass *SuperRC,
const TargetInstrInfo *TII, const TargetRegisterInfo *TRI,
const RegisterClassInfo &RCI) { … }
static LaneBitmask getInstReadLaneMask(const MachineRegisterInfo &MRI,
const TargetRegisterInfo &TRI,
const MachineInstr &FirstMI,
Register Reg) { … }
static bool readsLaneSubset(const MachineRegisterInfo &MRI,
const MachineInstr *MI, const LiveInterval &VirtReg,
const TargetRegisterInfo *TRI, SlotIndex Use,
const TargetInstrInfo *TII) { … }
unsigned RAGreedy::tryInstructionSplit(const LiveInterval &VirtReg,
AllocationOrder &Order,
SmallVectorImpl<Register> &NewVRegs) { … }
void RAGreedy::calcGapWeights(MCRegister PhysReg,
SmallVectorImpl<float> &GapWeight) { … }
unsigned RAGreedy::tryLocalSplit(const LiveInterval &VirtReg,
AllocationOrder &Order,
SmallVectorImpl<Register> &NewVRegs) { … }
unsigned RAGreedy::trySplit(const LiveInterval &VirtReg, AllocationOrder &Order,
SmallVectorImpl<Register> &NewVRegs,
const SmallVirtRegSet &FixedRegisters) { … }
static bool hasTiedDef(MachineRegisterInfo *MRI, unsigned reg) { … }
static bool assignedRegPartiallyOverlaps(const TargetRegisterInfo &TRI,
const VirtRegMap &VRM,
MCRegister PhysReg,
const LiveInterval &Intf) { … }
bool RAGreedy::mayRecolorAllInterferences(
MCRegister PhysReg, const LiveInterval &VirtReg,
SmallLISet &RecoloringCandidates, const SmallVirtRegSet &FixedRegisters) { … }
unsigned RAGreedy::tryLastChanceRecoloring(const LiveInterval &VirtReg,
AllocationOrder &Order,
SmallVectorImpl<Register> &NewVRegs,
SmallVirtRegSet &FixedRegisters,
RecoloringStack &RecolorStack,
unsigned Depth) { … }
bool RAGreedy::tryRecoloringCandidates(PQueue &RecoloringQueue,
SmallVectorImpl<Register> &NewVRegs,
SmallVirtRegSet &FixedRegisters,
RecoloringStack &RecolorStack,
unsigned Depth) { … }
MCRegister RAGreedy::selectOrSplit(const LiveInterval &VirtReg,
SmallVectorImpl<Register> &NewVRegs) { … }
MCRegister RAGreedy::tryAssignCSRFirstTime(
const LiveInterval &VirtReg, AllocationOrder &Order, MCRegister PhysReg,
uint8_t &CostPerUseLimit, SmallVectorImpl<Register> &NewVRegs) { … }
void RAGreedy::aboutToRemoveInterval(const LiveInterval &LI) { … }
void RAGreedy::initializeCSRCost() { … }
void RAGreedy::collectHintInfo(Register Reg, HintsInfo &Out) { … }
BlockFrequency RAGreedy::getBrokenHintFreq(const HintsInfo &List,
MCRegister PhysReg) { … }
void RAGreedy::tryHintRecoloring(const LiveInterval &VirtReg) { … }
void RAGreedy::tryHintsRecoloring() { … }
MCRegister RAGreedy::selectOrSplitImpl(const LiveInterval &VirtReg,
SmallVectorImpl<Register> &NewVRegs,
SmallVirtRegSet &FixedRegisters,
RecoloringStack &RecolorStack,
unsigned Depth) { … }
void RAGreedy::RAGreedyStats::report(MachineOptimizationRemarkMissed &R) { … }
RAGreedy::RAGreedyStats RAGreedy::computeStats(MachineBasicBlock &MBB) { … }
RAGreedy::RAGreedyStats RAGreedy::reportStats(MachineLoop *L) { … }
void RAGreedy::reportStats() { … }
bool RAGreedy::hasVirtRegAlloc() { … }
bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { … }