"...lib/CodeGen/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "124ae13421b0ca3ffb0e136bce2277ae41509a80"
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 "VirtRegMap.h"
#include "VirtRegRewriter.h"
Alkis Evlogimenos
committed
#include "llvm/Function.h"
#include "llvm/CodeGen/CalcSpillWeights.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/ErrorHandling.h"
Daniel Dunbar
committed
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <set>
#include <queue>
Lang Hames
committed
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");
STATISTIC(NumDowngrade, "Number of registers downgraded");
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);
Jakob Stoklund Olesen
committed
static cl::opt<bool>
TrivCoalesceEnds("trivial-coalesce-ends",
cl::desc("Attempt trivial coalescing of interval ends"),
cl::init(false), cl::Hidden);
linearscanRegAlloc("linearscan", "linear scan register allocator",
createLinearScanRegisterAllocator);
// When we allocate a register, add it to a fixed-size queue of
// registers to skip in subsequent allocations. This trades a small
// amount of register pressure and increased spills for flexibility in
// the post-pass scheduler.
//
// Note that in a the number of registers used for reloading spills
// will be one greater than the value of this option.
//
// One big limitation of this is that it doesn't differentiate between
// different register classes. So on x86-64, if there is xmm register
// pressure, it can caused fewer GPRs to be held in the queue.
static cl::opt<unsigned>
NumRecentlyUsedRegs("linearscan-skip-count",
cl::desc("Number of registers for linearscan to remember"
"to skip."),
Nick Lewycky
committed
struct RALinScan : public MachineFunctionPass {
RALinScan() : MachineFunctionPass(ID) {
// Initialize the queue to record recently-used registers.
if (NumRecentlyUsedRegs > 0)
RecentRegs.resize(NumRecentlyUsedRegs, 0);
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;
// NextReloadMap - For each register in the map, it maps to the another
// register which is defined by a reload from the same stack slot and
// both reloads are in the same basic block.
DenseMap<unsigned, unsigned> NextReloadMap;
// DowngradedRegs - A set of registers which are being "downgraded", i.e.
// un-favored for allocation.
SmallSet<unsigned, 8> DowngradedRegs;
// DowngradeMap - A map from virtual registers to physical registers being
// downgraded for the virtual registers.
DenseMap<unsigned, unsigned> DowngradeMap;
MachineRegisterInfo* mri_;
const TargetRegisterInfo* tri_;
const TargetInstrInfo* tii_;
BitVector allocatableRegs_;
BitVector reservedRegs_;
Jakob Stoklund Olesen
committed
MachineLoopInfo *loopInfo;
/// 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_;
/// regUse_ - Tracks register usage.
SmallVector<unsigned, 32> regUse_;
SmallVector<unsigned, 32> regUseBackUp_;
/// vrm_ - Tracks register assignments.
std::auto_ptr<VirtRegRewriter> rewriter_;
std::auto_ptr<Spiller> spiller_;
SmallVector<unsigned, 4> RecentRegs;
SmallVector<unsigned, 4>::iterator RecentNext;
// Record that we just picked this register.
void recordRecentlyUsed(unsigned reg) {
assert(reg != 0 && "Recently used register is NOREG!");
if (!RecentRegs.empty()) {
*RecentNext++ = reg;
if (RecentNext == RecentRegs.end())
RecentNext = RecentRegs.begin();
public:
virtual const char* getPassName() const {
return "Linear Scan Register Allocator";
}
Alkis Evlogimenos
committed
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
if (StrongPHIElim)
AU.addRequiredID(StrongPHIEliminationID);
// Make sure PassManager knows which analyses to make available
// to coalescing and which analyses coalescing invalidates.
AU.addRequiredTransitive<RegisterCoalescer>();
AU.addRequired<CalculateSpillWeights>();
Evan Cheng
committed
if (PreSplitIntervals)
AU.addRequiredID(PreAllocSplittingID);
AU.addRequired<LiveStacks>();
AU.addPreserved<LiveStacks>();
AU.addPreserved<MachineLoopInfo>();
AU.addRequired<VirtRegMap>();
Loading
Loading full blame...