Newer
Older
//===-- RegAllocGreedy.cpp - greedy register allocator --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the RAGreedy function pass for register allocation in
// optimized builds.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "regalloc"
Jakob Stoklund Olesen
committed
#include "AllocationOrder.h"
Jakob Stoklund Olesen
committed
#include "InterferenceCache.h"
#include "LiveDebugVariables.h"
#include "LiveRangeEdit.h"
#include "RegAllocBase.h"
#include "Spiller.h"
#include "SpillPlacement.h"
Jakob Stoklund Olesen
committed
#include "SplitKit.h"
#include "RegisterCoalescer.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Function.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/EdgeBundles.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
Jakob Stoklund Olesen
committed
#include "llvm/Support/Timer.h"
Jakob Stoklund Olesen
committed
#include <queue>
STATISTIC(NumGlobalSplits, "Number of split global live ranges");
STATISTIC(NumLocalSplits, "Number of split local live ranges");
STATISTIC(NumEvicted, "Number of interferences evicted");
static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator",
createGreedyRegisterAllocator);
namespace {
class RAGreedy : public MachineFunctionPass,
public RegAllocBase,
private LiveRangeEdit::Delegate {
// context
MachineFunction *MF;
// analyses
SlotIndexes *Indexes;
MachineDominatorTree *DomTree;
Jakob Stoklund Olesen
committed
MachineLoopInfo *Loops;
EdgeBundles *Bundles;
SpillPlacement *SpillPlacer;
LiveDebugVariables *DebugVars;
// state
std::auto_ptr<Spiller> SpillerInstance;
Jakob Stoklund Olesen
committed
std::priority_queue<std::pair<unsigned, unsigned> > Queue;
unsigned NextCascade;
Jakob Stoklund Olesen
committed
// Live ranges pass through a number of stages as we try to allocate them.
// Some of the stages may also create new live ranges:
//
// - Region splitting.
// - Per-block splitting.
// - Local splitting.
// - Spilling.
//
// Ranges produced by one of the stages skip the previous stages when they are
// dequeued. This improves performance because we can skip interference checks
// that are unlikely to give any results. It also guarantees that the live
// range splitting algorithm terminates, something that is otherwise hard to
// ensure.
enum LiveRangeStage {
/// Newly created live range that has never been queued.
RS_New,
/// Only attempt assignment and eviction. Then requeue as RS_Split.
RS_Assign,
/// Attempt live range splitting if assignment is impossible.
RS_Split,
/// Attempt more aggressive live range splitting that is guaranteed to make
/// progress. This is used for split products that may not be making
/// progress.
RS_Split2,
/// Live range will be spilled. No more splitting will be attempted.
RS_Spill,
/// There is nothing more we can do to this live range. Abort compilation
/// if it can't be assigned.
RS_Done
Jakob Stoklund Olesen
committed
};
static const char *const StageName[];
// RegInfo - Keep additional information about each live range.
struct RegInfo {
LiveRangeStage Stage;
// Cascade - Eviction loop prevention. See canEvictInterference().
unsigned Cascade;
RegInfo() : Stage(RS_New), Cascade(0) {}
};
IndexedMap<RegInfo, VirtReg2IndexFunctor> ExtraRegInfo;
Jakob Stoklund Olesen
committed
LiveRangeStage getStage(const LiveInterval &VirtReg) const {
return ExtraRegInfo[VirtReg.reg].Stage;
}
void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) {
ExtraRegInfo.resize(MRI->getNumVirtRegs());
ExtraRegInfo[VirtReg.reg].Stage = Stage;
Jakob Stoklund Olesen
committed
}
template<typename Iterator>
void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) {
ExtraRegInfo.resize(MRI->getNumVirtRegs());
for (;Begin != End; ++Begin) {
unsigned Reg = (*Begin)->reg;
if (ExtraRegInfo[Reg].Stage == RS_New)
ExtraRegInfo[Reg].Stage = NewStage;
Jakob Stoklund Olesen
committed
}
/// Cost of evicting interference.
struct EvictionCost {
unsigned BrokenHints; ///< Total number of broken hints.
float MaxWeight; ///< Maximum spill weight evicted.
EvictionCost(unsigned B = 0) : BrokenHints(B), MaxWeight(0) {}
bool operator<(const EvictionCost &O) const {
if (BrokenHints != O.BrokenHints)
return BrokenHints < O.BrokenHints;
return MaxWeight < O.MaxWeight;
}
};
// splitting state.
Jakob Stoklund Olesen
committed
std::auto_ptr<SplitAnalysis> SA;
Jakob Stoklund Olesen
committed
std::auto_ptr<SplitEditor> SE;
/// Cached per-block interference maps
InterferenceCache IntfCache;
Jakob Stoklund Olesen
committed
/// All basic blocks where the current register has uses.
Jakob Stoklund Olesen
committed
SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints;
Jakob Stoklund Olesen
committed
/// Global live range splitting candidate info.
struct GlobalSplitCandidate {
unsigned PhysReg;
InterferenceCache::Cursor Intf;
Jakob Stoklund Olesen
committed
BitVector LiveBundles;
SmallVector<unsigned, 8> ActiveBlocks;
void reset(InterferenceCache &Cache, unsigned Reg) {
Intf.setPhysReg(Cache, Reg);
LiveBundles.clear();
ActiveBlocks.clear();
}
Jakob Stoklund Olesen
committed
};
/// Candidate info for for each PhysReg in AllocationOrder.
/// This vector never shrinks, but grows to the size of the largest register
/// class.
SmallVector<GlobalSplitCandidate, 32> GlobalCand;
public:
RAGreedy();
/// Return the pass name.
virtual const char* getPassName() const {
Jakob Stoklund Olesen
committed
return "Greedy Register Allocator";
Loading
Loading full blame...