Newer
Older
Alkis Evlogimenos
committed
//===-- RegAllocLinearScan.cpp - Linear Scan register allocator -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
Alkis Evlogimenos
committed
//
//===----------------------------------------------------------------------===//
//
// This file implements a linear scan register allocator.
//
//===----------------------------------------------------------------------===//
Alkis Evlogimenos
committed
#define DEBUG_TYPE "regalloc"
#include "PhysRegTracker.h"
#include "VirtRegMap.h"
Owen Anderson
committed
#include "Spiller.h"
Alkis Evlogimenos
committed
#include "llvm/Function.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
Alkis Evlogimenos
committed
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
Alkis Evlogimenos
committed
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/Target/TargetRegisterInfo.h"
Alkis Evlogimenos
committed
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <set>
#include <queue>
Alkis Evlogimenos
committed
using namespace llvm;
STATISTIC(NumIters , "Number of iterations performed");
STATISTIC(NumBacktracks, "Number of times we had to backtrack");
STATISTIC(NumCoalesce, "Number of copies coalesced");
static cl::opt<bool>
NewHeuristic("new-spilling-heuristic",
cl::desc("Use new spilling heuristic"),
cl::init(false), cl::Hidden);
Evan Cheng
committed
static cl::opt<bool>
PreSplitIntervals("pre-alloc-split",
cl::desc("Pre-register allocation live interval splitting"),
cl::init(false), cl::Hidden);
linearscanRegAlloc("linearscan", "linear scan register allocator",
createLinearScanRegisterAllocator);
Bill Wendling
committed
struct VISIBILITY_HIDDEN RALinScan : public MachineFunctionPass {
RALinScan() : MachineFunctionPass(&ID) {}
typedef std::pair<LiveInterval*, LiveInterval::iterator> IntervalPtr;
typedef SmallVector<IntervalPtr, 32> IntervalPtrs;
/// RelatedRegClasses - This structure is built the first time a function is
/// compiled, and keeps track of which register classes have registers that
/// belong to multiple classes or have aliases that are in other classes.
EquivalenceClasses<const TargetRegisterClass*> RelatedRegClasses;
DenseMap<unsigned, const TargetRegisterClass*> OneClassForEachPhysReg;
MachineRegisterInfo* mri_;
const TargetInstrInfo* tii_;
BitVector allocatableRegs_;
/// handled_ - Intervals are added to the handled_ set in the order of their
/// start value. This is uses for backtracking.
std::vector<LiveInterval*> handled_;
/// fixed_ - Intervals that correspond to machine registers.
///
IntervalPtrs fixed_;
/// active_ - Intervals that are currently being processed, and which have a
/// live range active for the current point.
IntervalPtrs active_;
/// inactive_ - Intervals that are currently being processed, but which have
/// a hold at the current point.
IntervalPtrs inactive_;
typedef std::priority_queue<LiveInterval*,
SmallVector<LiveInterval*, 64>,
greater_ptr<LiveInterval> > IntervalHeap;
IntervalHeap unhandled_;
std::auto_ptr<PhysRegTracker> prt_;
std::auto_ptr<Spiller> spiller_;
public:
virtual const char* getPassName() const {
return "Linear Scan Register Allocator";
}
Alkis Evlogimenos
committed
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LiveIntervals>();
if (StrongPHIElim)
AU.addRequiredID(StrongPHIEliminationID);
// Make sure PassManager knows which analyses to make available
// to coalescing and which analyses coalescing invalidates.
AU.addRequiredTransitive<RegisterCoalescer>();
Evan Cheng
committed
if (PreSplitIntervals)
AU.addRequiredID(PreAllocSplittingID);
AU.addRequired<LiveStacks>();
AU.addPreserved<LiveStacks>();
AU.addPreserved<MachineLoopInfo>();
AU.addRequired<VirtRegMap>();
AU.addPreserved<VirtRegMap>();
AU.addPreservedID(MachineDominatorsID);
MachineFunctionPass::getAnalysisUsage(AU);
}
/// runOnMachineFunction - register allocate the whole function
bool runOnMachineFunction(MachineFunction&);
private:
/// linearScan - the linear scan algorithm
void linearScan();
/// initIntervalSets - initialize the interval sets.
///
/// processActiveIntervals - expire old intervals and move non-overlapping
/// ones to the inactive list.
void processActiveIntervals(unsigned CurPoint);
Alkis Evlogimenos
committed
/// processInactiveIntervals - expire old intervals and move overlapping
/// ones to the active list.
void processInactiveIntervals(unsigned CurPoint);
/// assignRegOrStackSlotAtInterval - assign a register if one
/// is available, or spill.
void assignRegOrStackSlotAtInterval(LiveInterval* cur);
Evan Cheng
committed
void updateSpillWeights(std::vector<float> &Weights,
unsigned reg, float weight,
const TargetRegisterClass *RC);
/// findIntervalsToSpill - Determine the intervals to spill for the
/// specified interval. It's passed the physical registers whose spill
/// weight is the lowest among all the registers whose live intervals
/// conflict with the interval.
void findIntervalsToSpill(LiveInterval *cur,
std::vector<std::pair<unsigned,float> > &Candidates,
unsigned NumCands,
SmallVector<LiveInterval*, 8> &SpillIntervals);
/// attemptTrivialCoalescing - If a simple interval is defined by a copy,
/// try allocate the definition the same register as the source register
/// if the register is not defined during live time of the interval. This
/// eliminate a copy. This is used to coalesce copies which were not
/// coalesced away before allocation either due to dest and src being in
/// different register classes or because the coalescer was overly
/// conservative.
unsigned attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg);
///
/// register handling helpers
///
/// getFreePhysReg - return a free physical register for this virtual
/// register interval if we have one, otherwise return 0.
unsigned getFreePhysReg(LiveInterval* cur);
/// assignVirt2StackSlot - assigns this virtual register to a
/// stack slot. returns the stack slot
int assignVirt2StackSlot(unsigned virtReg);
void ComputeRelatedRegClasses();
template <typename ItTy>
void printIntervals(const char* const str, ItTy i, ItTy e) const {
if (str) DOUT << str << " intervals:\n";
DOUT << "\t" << *i->first << " -> ";
unsigned reg = i->first->reg;
if (TargetRegisterInfo::isVirtualRegister(reg)) {
Loading
Loading full blame...