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_;
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>();
AU.addPreserved<VirtRegMap>();
AU.addPreservedID(MachineDominatorsID);
MachineFunctionPass::getAnalysisUsage(AU);
}
/// runOnMachineFunction - register allocate the whole function
bool runOnMachineFunction(MachineFunction&);
// Determine if we skip this register due to its being recently used.
bool isRecentlyUsed(unsigned reg) const {
return std::find(RecentRegs.begin(), RecentRegs.end(), reg) !=
RecentRegs.end();
}
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.
Alkis Evlogimenos
committed
/// processInactiveIntervals - expire old intervals and move overlapping
/// ones to the active list.
/// hasNextReloadInterval - Return the next liveinterval that's being
/// defined by a reload from the same SS as the specified one.
LiveInterval *hasNextReloadInterval(LiveInterval *cur);
/// DowngradeRegister - Downgrade a register for allocation.
void DowngradeRegister(LiveInterval *li, unsigned Reg);
/// UpgradeRegister - Upgrade a register for allocation.
void UpgradeRegister(unsigned Reg);
/// 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 to allocate the definition to the same register as the source,
/// if the register is not defined during the life time of the interval.
/// This eliminates a copy, and 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 usage / availability tracking helpers.
///
void initRegUses() {
regUse_.resize(tri_->getNumRegs(), 0);
regUseBackUp_.resize(tri_->getNumRegs(), 0);
}
void finalizeRegUses() {
Evan Cheng
committed
#ifndef NDEBUG
// Verify all the registers are "freed".
bool Error = false;
for (unsigned i = 0, e = tri_->getNumRegs(); i != e; ++i) {
if (regUse_[i] != 0) {
dbgs() << tri_->getName(i) << " is still in use!\n";
Evan Cheng
committed
Error = true;
}
}
if (Error)
llvm_unreachable(0);
Evan Cheng
committed
#endif
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
regUse_.clear();
regUseBackUp_.clear();
}
void addRegUse(unsigned physReg) {
assert(TargetRegisterInfo::isPhysicalRegister(physReg) &&
"should be physical register!");
++regUse_[physReg];
for (const unsigned* as = tri_->getAliasSet(physReg); *as; ++as)
++regUse_[*as];
}
void delRegUse(unsigned physReg) {
assert(TargetRegisterInfo::isPhysicalRegister(physReg) &&
"should be physical register!");
assert(regUse_[physReg] != 0);
--regUse_[physReg];
for (const unsigned* as = tri_->getAliasSet(physReg); *as; ++as) {
assert(regUse_[*as] != 0);
--regUse_[*as];
}
}
bool isRegAvail(unsigned physReg) const {
assert(TargetRegisterInfo::isPhysicalRegister(physReg) &&
"should be physical register!");
return regUse_[physReg] == 0;
}
void backUpRegUses() {
regUseBackUp_ = regUse_;
}
void restoreRegUses() {
regUse_ = regUseBackUp_;
}
///
/// 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);
unsigned getFreePhysReg(LiveInterval* cur,
const TargetRegisterClass *RC,
unsigned MaxInactiveCount,
SmallVector<unsigned, 256> &inactiveCounts,
bool SkipDGRegs);
void ComputeRelatedRegClasses();
template <typename ItTy>
void printIntervals(const char* const str, ItTy i, ItTy e) const {
unsigned reg = i->first->reg;
if (TargetRegisterInfo::isVirtualRegister(reg))
reg = vrm_->getPhys(reg);
Bill Wendling
committed
char RALinScan::ID = 0;
Alkis Evlogimenos
committed
}
INITIALIZE_PASS(RALinScan, "linearscan-regalloc",
"Linear Scan Register Allocator", false, false);
Bill Wendling
committed
void RALinScan::ComputeRelatedRegClasses() {
// First pass, add all reg classes to the union, and determine at least one
// reg class that each register is in.
bool HasAliases = false;
for (TargetRegisterInfo::regclass_iterator RCI = tri_->regclass_begin(),
E = tri_->regclass_end(); RCI != E; ++RCI) {
RelatedRegClasses.insert(*RCI);
for (TargetRegisterClass::iterator I = (*RCI)->begin(), E = (*RCI)->end();
I != E; ++I) {
HasAliases = HasAliases || *tri_->getAliasSet(*I) != 0;
const TargetRegisterClass *&PRC = OneClassForEachPhysReg[*I];
if (PRC) {
// Already processed this register. Just make sure we know that
// multiple register classes share a register.
RelatedRegClasses.unionSets(PRC, *RCI);
} else {
PRC = *RCI;
}
}
}
// Second pass, now that we know conservatively what register classes each reg
// belongs to, add info about aliases. We don't need to do this for targets
// without register aliases.
if (HasAliases)
for (DenseMap<unsigned, const TargetRegisterClass*>::iterator
I = OneClassForEachPhysReg.begin(), E = OneClassForEachPhysReg.end();
I != E; ++I)
for (const unsigned *AS = tri_->getAliasSet(I->first); *AS; ++AS)
RelatedRegClasses.unionSets(I->second, OneClassForEachPhysReg[*AS]);
}
Jakob Stoklund Olesen
committed
/// 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. If the interval is
/// killed by a copy, try to use the destination register. This eliminates 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 RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
unsigned Preference = vrm_->getRegAllocPref(cur.reg);
if ((Preference && Preference == Reg) || !cur.containsOneValue())
return Reg;
Jakob Stoklund Olesen
committed
// We cannot handle complicated live ranges. Simple linear stuff only.
if (cur.ranges.size() != 1)
return Reg;
Jakob Stoklund Olesen
committed
const LiveRange &range = cur.ranges.front();
VNInfo *vni = range.valno;
if (vni->isUnused())
Bill Wendling
committed
return Reg;
Jakob Stoklund Olesen
committed
unsigned CandReg;
{
MachineInstr *CopyMI;
if (vni->def != SlotIndex() && vni->isDefAccurate() &&
Jakob Stoklund Olesen
committed
(CopyMI = li_->getInstructionFromIndex(vni->def)) && CopyMI->isCopy())
Jakob Stoklund Olesen
committed
// Defined by a copy, try to extend SrcReg forward
Jakob Stoklund Olesen
committed
CandReg = CopyMI->getOperand(1).getReg();
Jakob Stoklund Olesen
committed
else if (TrivCoalesceEnds &&
Jakob Stoklund Olesen
committed
(CopyMI = li_->getInstructionFromIndex(range.end.getBaseIndex())) &&
CopyMI->isCopy() && cur.reg == CopyMI->getOperand(1).getReg())
Jakob Stoklund Olesen
committed
// Only used by a copy, try to extend DstReg backwards
Jakob Stoklund Olesen
committed
CandReg = CopyMI->getOperand(0).getReg();
Jakob Stoklund Olesen
committed
else
return Reg;
Jakob Stoklund Olesen
committed
if (TargetRegisterInfo::isVirtualRegister(CandReg)) {
if (!vrm_->isAssignedReg(CandReg))
return Reg;
CandReg = vrm_->getPhys(CandReg);
}
if (Reg == CandReg)
return Reg;
const TargetRegisterClass *RC = mri_->getRegClass(cur.reg);
Jakob Stoklund Olesen
committed
if (!RC->contains(CandReg))
return Reg;
Jakob Stoklund Olesen
committed
if (li_->conflictsWithPhysReg(cur, *vrm_, CandReg))
return Reg;
Bill Wendling
committed
Jakob Stoklund Olesen
committed
// Try to coalesce.
DEBUG(dbgs() << "Coalescing: " << cur << " -> " << tri_->getName(CandReg)
Jakob Stoklund Olesen
committed
<< '\n');
vrm_->clearVirt(cur.reg);
vrm_->assignVirt2Phys(cur.reg, CandReg);
Jakob Stoklund Olesen
committed
Jakob Stoklund Olesen
committed
++NumCoalesce;
return CandReg;
}
Bill Wendling
committed
bool RALinScan::runOnMachineFunction(MachineFunction &fn) {
mri_ = &fn.getRegInfo();
tii_ = tm_->getInstrInfo();
allocatableRegs_ = tri_->getAllocatableSet(fn);
li_ = &getAnalysis<LiveIntervals>();
ls_ = &getAnalysis<LiveStacks>();
loopInfo = &getAnalysis<MachineLoopInfo>();
Chris Lattner
committed
// We don't run the coalescer here because we have no reason to
// interact with it. If the coalescer requires interaction, it
// won't do anything. If it doesn't require interaction, we assume
// it was run as a separate pass.
// If this is the first function compiled, compute the related reg classes.
if (RelatedRegClasses.empty())
ComputeRelatedRegClasses();
// Also resize register usage trackers.
initRegUses();
vrm_ = &getAnalysis<VirtRegMap>();
if (!rewriter_.get()) rewriter_.reset(createVirtRegRewriter());
Jakob Stoklund Olesen
committed
spiller_.reset(createSpiller(*this, *mf_, *vrm_));
Lang Hames
committed
Alkis Evlogimenos
committed
Chris Lattner
committed
// Rewrite spill code and update the PhysRegsUsed set.
rewriter_->runOnMachineFunction(*mf_, *vrm_, li_);
assert(unhandled_.empty() && "Unhandled live intervals remain!");
fixed_.clear();
active_.clear();
inactive_.clear();
handled_.clear();
NextReloadMap.clear();
DowngradedRegs.clear();
DowngradeMap.clear();
Lang Hames
committed
spiller_.reset(0);
/// initIntervalSets - initialize the interval sets.
///
Bill Wendling
committed
void RALinScan::initIntervalSets()
{
assert(unhandled_.empty() && fixed_.empty() &&
active_.empty() && inactive_.empty() &&
"interval sets should be empty on initialization");
handled_.reserve(li_->getNumIntervals());
for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) {
Owen Anderson
committed
if (TargetRegisterInfo::isPhysicalRegister(i->second->reg)) {
if (!i->second->empty()) {
mri_->setPhysRegUsed(i->second->reg);
fixed_.push_back(std::make_pair(i->second, i->second->begin()));
}
} else {
if (i->second->empty()) {
assignRegOrStackSlotAtInterval(i->second);
}
else
unhandled_.push(i->second);
}
<< "********** Function: "
<< mf_->getFunction()->getName() << '\n';
printIntervals("fixed", fixed_.begin(), fixed_.end());
});
while (!unhandled_.empty()) {
// pick the interval with the earliest start point
LiveInterval* cur = unhandled_.top();
unhandled_.pop();
DEBUG(dbgs() << "\n*** CURRENT ***: " << *cur << '\n');
assert(!cur->empty() && "Empty interval in unhandled set.");
processActiveIntervals(cur->beginIndex());
processInactiveIntervals(cur->beginIndex());
assert(TargetRegisterInfo::isVirtualRegister(cur->reg) &&
"Can only allocate virtual registers!");
// Allocating a virtual register. try to find a free
// physical register or spill an interval (possibly this one) in order to
// assign it one.
assignRegOrStackSlotAtInterval(cur);
DEBUG({
printIntervals("active", active_.begin(), active_.end());
printIntervals("inactive", inactive_.begin(), inactive_.end());
});
// Expire any remaining active intervals
while (!active_.empty()) {
IntervalPtr &IP = active_.back();
unsigned reg = IP.first->reg;
DEBUG(dbgs() << "\tinterval " << *IP.first << " expired\n");
assert(TargetRegisterInfo::isVirtualRegister(reg) &&
"Can only allocate virtual registers!");
reg = vrm_->getPhys(reg);
// Expire any remaining inactive intervals
DEBUG({
for (IntervalPtrs::reverse_iterator
i = inactive_.rbegin(); i != inactive_.rend(); ++i)
dbgs() << "\tinterval " << *i->first << " expired\n";
// Add live-ins to every BB except for entry. Also perform trivial coalescing.
MachineFunction::iterator EntryMBB = mf_->begin();
for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) {
Owen Anderson
committed
LiveInterval &cur = *i->second;
bool isPhys = TargetRegisterInfo::isPhysicalRegister(cur.reg);
Owen Anderson
committed
Reg = cur.reg;
else if (vrm_->isAssignedReg(cur.reg))
Reg = attemptTrivialCoalescing(cur, vrm_->getPhys(cur.reg));
// Ignore splited live intervals.
if (!isPhys && vrm_->getPreSplitReg(cur.reg))
continue;
for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end();
I != E; ++I) {
const LiveRange &LR = *I;
if (li_->findLiveInMBBs(LR.start, LR.end, LiveInMBBs)) {
for (unsigned i = 0, e = LiveInMBBs.size(); i != e; ++i)
Evan Cheng
committed
if (LiveInMBBs[i] != EntryMBB) {
assert(TargetRegisterInfo::isPhysicalRegister(Reg) &&
"Adding a virtual register to livein set?");
Evan Cheng
committed
}
Evan Cheng
committed
// Look for physical registers that end up not being allocated even though
// register allocator had to spill other registers in its register class.
if (ls_->getNumIntervals() == 0)
return;
if (!vrm_->FindUnusedRegisters(li_))
Evan Cheng
committed
return;
Alkis Evlogimenos
committed
}
/// processActiveIntervals - expire old intervals and move non-overlapping ones
/// to the inactive list.
void RALinScan::processActiveIntervals(SlotIndex CurPoint)
Alkis Evlogimenos
committed
{
DEBUG(dbgs() << "\tprocessing active intervals:\n");
for (unsigned i = 0, e = active_.size(); i != e; ++i) {
LiveInterval *Interval = active_[i].first;
LiveInterval::iterator IntervalPos = active_[i].second;
unsigned reg = Interval->reg;
IntervalPos = Interval->advanceTo(IntervalPos, CurPoint);
if (IntervalPos == Interval->end()) { // Remove expired intervals.
DEBUG(dbgs() << "\t\tinterval " << *Interval << " expired\n");
assert(TargetRegisterInfo::isVirtualRegister(reg) &&
"Can only allocate virtual registers!");
reg = vrm_->getPhys(reg);
// Pop off the end of the list.
active_[i] = active_.back();
active_.pop_back();
--i; --e;
} else if (IntervalPos->start > CurPoint) {
// Move inactive intervals to inactive list.
DEBUG(dbgs() << "\t\tinterval " << *Interval << " inactive\n");
assert(TargetRegisterInfo::isVirtualRegister(reg) &&
"Can only allocate virtual registers!");
reg = vrm_->getPhys(reg);
// add to inactive.
inactive_.push_back(std::make_pair(Interval, IntervalPos));
// Pop off the end of the list.
active_[i] = active_.back();
active_.pop_back();
--i; --e;
} else {
// Otherwise, just update the iterator position.
active_[i].second = IntervalPos;
Alkis Evlogimenos
committed
}
/// processInactiveIntervals - expire old intervals and move overlapping
/// ones to the active list.
void RALinScan::processInactiveIntervals(SlotIndex CurPoint)
Alkis Evlogimenos
committed
{
DEBUG(dbgs() << "\tprocessing inactive intervals:\n");
for (unsigned i = 0, e = inactive_.size(); i != e; ++i) {
LiveInterval *Interval = inactive_[i].first;
LiveInterval::iterator IntervalPos = inactive_[i].second;
unsigned reg = Interval->reg;
IntervalPos = Interval->advanceTo(IntervalPos, CurPoint);
if (IntervalPos == Interval->end()) { // remove expired intervals.
DEBUG(dbgs() << "\t\tinterval " << *Interval << " expired\n");
// Pop off the end of the list.
inactive_[i] = inactive_.back();
inactive_.pop_back();
--i; --e;
} else if (IntervalPos->start <= CurPoint) {
// move re-activated intervals in active list
DEBUG(dbgs() << "\t\tinterval " << *Interval << " active\n");
assert(TargetRegisterInfo::isVirtualRegister(reg) &&
"Can only allocate virtual registers!");
reg = vrm_->getPhys(reg);
active_.push_back(std::make_pair(Interval, IntervalPos));
// Pop off the end of the list.
inactive_[i] = inactive_.back();
inactive_.pop_back();
--i; --e;
} else {
// Otherwise, just update the iterator position.
inactive_[i].second = IntervalPos;
}
}
/// updateSpillWeights - updates the spill weights of the specifed physical
/// register and its weight.
Evan Cheng
committed
void RALinScan::updateSpillWeights(std::vector<float> &Weights,
unsigned reg, float weight,
const TargetRegisterClass *RC) {
SmallSet<unsigned, 4> Processed;
SmallSet<unsigned, 4> SuperAdded;
SmallVector<unsigned, 4> Supers;
Weights[reg] += weight;
Evan Cheng
committed
Processed.insert(reg);
for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) {
Weights[*as] += weight;
Evan Cheng
committed
Processed.insert(*as);
if (tri_->isSubRegister(*as, reg) &&
SuperAdded.insert(*as) &&
RC->contains(*as)) {
Supers.push_back(*as);
}
}
// If the alias is a super-register, and the super-register is in the
// register class we are trying to allocate. Then add the weight to all
// sub-registers of the super-register even if they are not aliases.
// e.g. allocating for GR32, bh is not used, updating bl spill weight.
// bl should get the same spill weight otherwise it will be choosen
// as a spill candidate since spilling bh doesn't make ebx available.
for (unsigned i = 0, e = Supers.size(); i != e; ++i) {
Evan Cheng
committed
for (const unsigned *sr = tri_->getSubRegisters(Supers[i]); *sr; ++sr)
if (!Processed.count(*sr))
Weights[*sr] += weight;
Evan Cheng
committed
}
Alkis Evlogimenos
committed
}
Bill Wendling
committed
static
RALinScan::IntervalPtrs::iterator
FindIntervalInVector(RALinScan::IntervalPtrs &IP, LiveInterval *LI) {
for (RALinScan::IntervalPtrs::iterator I = IP.begin(), E = IP.end();
I != E; ++I)
if (I->first == LI) return I;
return IP.end();
}
static void RevertVectorIteratorsTo(RALinScan::IntervalPtrs &V, SlotIndex Point){
for (unsigned i = 0, e = V.size(); i != e; ++i) {
Bill Wendling
committed
RALinScan::IntervalPtr &IP = V[i];
LiveInterval::iterator I = std::upper_bound(IP.first->begin(),
IP.second, Point);
if (I != IP.first->begin()) --I;
IP.second = I;
}
}
/// addStackInterval - Create a LiveInterval for stack if the specified live
/// interval has been spilled.
static void addStackInterval(LiveInterval *cur, LiveStacks *ls_,
Evan Cheng
committed
LiveIntervals *li_,
MachineRegisterInfo* mri_, VirtRegMap &vrm_) {
int SS = vrm_.getStackSlot(cur->reg);
if (SS == VirtRegMap::NO_STACK_SLOT)
return;
Evan Cheng
committed
const TargetRegisterClass *RC = mri_->getRegClass(cur->reg);
LiveInterval &SI = ls_->getOrCreateInterval(SS, RC);
Evan Cheng
committed
if (SI.hasAtLeastOneValue())
VNI = SI.getValNumInfo(0);
else
ls_->getVNInfoAllocator());
LiveInterval &RI = li_->getInterval(cur->reg);
// FIXME: This may be overly conservative.
SI.MergeRangesInAsValue(RI, VNI);
}
/// getConflictWeight - Return the number of conflicts between cur
/// live interval and defs and uses of Reg weighted by loop depthes.
Evan Cheng
committed
static
float getConflictWeight(LiveInterval *cur, unsigned Reg, LiveIntervals *li_,
MachineRegisterInfo *mri_,
Jakob Stoklund Olesen
committed
MachineLoopInfo *loopInfo) {
float Conflicts = 0;
for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(Reg),
E = mri_->reg_end(); I != E; ++I) {
MachineInstr *MI = &*I;
if (cur->liveAt(li_->getInstructionIndex(MI))) {
unsigned loopDepth = loopInfo->getLoopDepth(MI->getParent());
Conflicts += std::pow(10.0f, (float)loopDepth);
}
}
return Conflicts;
}
/// 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 RALinScan::findIntervalsToSpill(LiveInterval *cur,
std::vector<std::pair<unsigned,float> > &Candidates,
unsigned NumCands,
SmallVector<LiveInterval*, 8> &SpillIntervals) {
// We have figured out the *best* register to spill. But there are other
// registers that are pretty good as well (spill weight within 3%). Spill
// the one that has fewest defs and uses that conflict with cur.
float Conflicts[3] = { 0.0f, 0.0f, 0.0f };
SmallVector<LiveInterval*, 8> SLIs[3];
dbgs() << "\tConsidering " << NumCands << " candidates: ";
for (unsigned i = 0; i != NumCands; ++i)
dbgs() << tri_->getName(Candidates[i].first) << " ";
dbgs() << "\n";
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
// Calculate the number of conflicts of each candidate.
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
unsigned Reg = i->first->reg;
unsigned PhysReg = vrm_->getPhys(Reg);
if (!cur->overlapsFrom(*i->first, i->second))
continue;
for (unsigned j = 0; j < NumCands; ++j) {
unsigned Candidate = Candidates[j].first;
if (tri_->regsOverlap(PhysReg, Candidate)) {
if (NumCands > 1)
Conflicts[j] += getConflictWeight(cur, Reg, li_, mri_, loopInfo);
SLIs[j].push_back(i->first);
}
}
}
for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ++i){
unsigned Reg = i->first->reg;
unsigned PhysReg = vrm_->getPhys(Reg);
if (!cur->overlapsFrom(*i->first, i->second-1))
continue;
for (unsigned j = 0; j < NumCands; ++j) {
unsigned Candidate = Candidates[j].first;
if (tri_->regsOverlap(PhysReg, Candidate)) {
if (NumCands > 1)
Conflicts[j] += getConflictWeight(cur, Reg, li_, mri_, loopInfo);
SLIs[j].push_back(i->first);
}
}
}
// Which is the best candidate?
unsigned BestCandidate = 0;
float MinConflicts = Conflicts[0];
for (unsigned i = 1; i != NumCands; ++i) {
if (Conflicts[i] < MinConflicts) {
BestCandidate = i;
MinConflicts = Conflicts[i];
}
}
std::copy(SLIs[BestCandidate].begin(), SLIs[BestCandidate].end(),
std::back_inserter(SpillIntervals));
}
namespace {
struct WeightCompare {
Douglas Gregor
committed
WeightCompare(const RALinScan &Alloc) : Allocator(Alloc) {}
typedef std::pair<unsigned, float> RegWeightPair;
bool operator()(const RegWeightPair &LHS, const RegWeightPair &RHS) const {
}
};
}
static bool weightsAreClose(float w1, float w2) {
if (!NewHeuristic)
return false;
float diff = w1 - w2;
if (diff <= 0.02f) // Within 0.02f
return true;
return (diff / w2) <= 0.05f; // Within 5%.
}
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
LiveInterval *RALinScan::hasNextReloadInterval(LiveInterval *cur) {
DenseMap<unsigned, unsigned>::iterator I = NextReloadMap.find(cur->reg);
if (I == NextReloadMap.end())
return 0;
return &li_->getInterval(I->second);
}
void RALinScan::DowngradeRegister(LiveInterval *li, unsigned Reg) {
bool isNew = DowngradedRegs.insert(Reg);
isNew = isNew; // Silence compiler warning.
assert(isNew && "Multiple reloads holding the same register?");
DowngradeMap.insert(std::make_pair(li->reg, Reg));
for (const unsigned *AS = tri_->getAliasSet(Reg); *AS; ++AS) {
isNew = DowngradedRegs.insert(*AS);
isNew = isNew; // Silence compiler warning.
assert(isNew && "Multiple reloads holding the same register?");
DowngradeMap.insert(std::make_pair(li->reg, *AS));
}
++NumDowngrade;
}
void RALinScan::UpgradeRegister(unsigned Reg) {
if (Reg) {
DowngradedRegs.erase(Reg);
for (const unsigned *AS = tri_->getAliasSet(Reg); *AS; ++AS)
DowngradedRegs.erase(*AS);
}
}
namespace {
struct LISorter {
bool operator()(LiveInterval* A, LiveInterval* B) {
return A->beginIndex() < B->beginIndex();
}
};
}
/// assignRegOrStackSlotAtInterval - assign a register if one is available, or
/// spill.
void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) {
DEBUG(dbgs() << "\tallocating current interval: ");
// This is an implicitly defined live interval, just assign any register.
const TargetRegisterClass *RC = mri_->getRegClass(cur->reg);
unsigned physReg = vrm_->getRegAllocPref(cur->reg);
if (!physReg)
physReg = *RC->allocation_order_begin(*mf_);
DEBUG(dbgs() << tri_->getName(physReg) << '\n');
// Note the register is not really in use.
vrm_->assignVirt2Phys(cur->reg, physReg);
return;
}
std::vector<std::pair<unsigned, float> > SpillWeightsToAdd;
const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC);
// If start of this live interval is defined by a move instruction and its
// source is assigned a physical register that is compatible with the target
// register class, then we should try to assign it the same register.
// This can happen when the move is from a larger register class to a smaller
// one, e.g. X86::mov32to32_. These move instructions are not coalescable.
if (!vrm_->getRegAllocPref(cur->reg) && cur->hasAtLeastOneValue()) {
VNInfo *vni = cur->begin()->valno;
vni->isDefAccurate()) {
MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
Jakob Stoklund Olesen
committed
if (CopyMI && CopyMI->isCopy()) {
unsigned DstSubReg = CopyMI->getOperand(0).getSubReg();
unsigned SrcReg = CopyMI->getOperand(1).getReg();
unsigned SrcSubReg = CopyMI->getOperand(1).getSubReg();
unsigned Reg = 0;
if (TargetRegisterInfo::isPhysicalRegister(SrcReg))
Reg = SrcReg;
else if (vrm_->isAssignedReg(SrcReg))
Reg = vrm_->getPhys(SrcReg);
if (Reg) {
if (SrcSubReg)
Reg = tri_->getSubReg(Reg, SrcSubReg);
if (DstSubReg)
Reg = tri_->getMatchingSuperReg(Reg, DstSubReg, RC);
if (Reg && allocatableRegs_[Reg] && RC->contains(Reg))
}
}
}
}
// For every interval in inactive we overlap with, mark the
// register as not free and update spill weights.
for (IntervalPtrs::const_iterator i = inactive_.begin(),
e = inactive_.end(); i != e; ++i) {