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"
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");
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);
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;
// 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 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_;
/// regUse_ - Tracks register usage.
SmallVector<unsigned, 32> regUse_;
SmallVector<unsigned, 32> regUseBackUp_;
/// vrm_ - Tracks register assignments.
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);
/// 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 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 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) {
cerr << tri_->getName(i) << " is still in use!\n";
Error = true;
}
}
if (Error)
abort();
#endif
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
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(const TargetRegisterClass *RC,
unsigned MaxInactiveCount,
SmallVector<unsigned, 256> &inactiveCounts,
bool SkipDGRegs);
/// 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)) {
Alkis Evlogimenos
committed
}
Bill Wendling
committed
char RALinScan::ID = 0;
Alkis Evlogimenos
committed
}
static RegisterPass<RALinScan>
X("linearscan-regalloc", "Linear Scan Register Allocator");
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]);
}
/// 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 RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
Evan Cheng
committed
if ((cur.preference && cur.preference == Reg) || !cur.containsOneValue())
return Reg;
VNInfo *vni = cur.begin()->valno;
if (!vni->def || vni->def == ~1U || vni->def == ~0U)
return Reg;
MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
Evan Cheng
committed
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (!CopyMI ||
!tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg))
return Reg;
if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
if (!vrm_->isAssignedReg(SrcReg))
return Reg;
else
SrcReg = vrm_->getPhys(SrcReg);
if (Reg == SrcReg)
return Reg;
const TargetRegisterClass *RC = mri_->getRegClass(cur.reg);
if (!RC->contains(SrcReg))
return Reg;
// Try to coalesce.
if (!li_->conflictsWithPhysRegDef(cur, *vrm_, SrcReg)) {
DOUT << "Coalescing: " << cur << " -> " << tri_->getName(SrcReg)
Bill Wendling
committed
<< '\n';
vrm_->clearVirt(cur.reg);
vrm_->assignVirt2Phys(cur.reg, SrcReg);
++NumCoalesce;
return SrcReg;
}
return Reg;
}
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 (!spiller_.get()) spiller_.reset(createSpiller());
Alkis Evlogimenos
committed
Chris Lattner
committed
// Rewrite spill code and update the PhysRegsUsed set.
spiller_->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();
/// 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)) {
mri_->setPhysRegUsed(i->second->reg);
Owen Anderson
committed
fixed_.push_back(std::make_pair(i->second, i->second->begin()));
Chris Lattner
committed
} else
Owen Anderson
committed
unhandled_.push(i->second);
Bill Wendling
committed
void RALinScan::linearScan()
DOUT << "********** LINEAR SCAN **********\n";
DOUT << "********** Function: " << mf_->getFunction()->getName() << '\n';
DEBUG(printIntervals("fixed", fixed_.begin(), fixed_.end()));
while (!unhandled_.empty()) {
// pick the interval with the earliest start point
LiveInterval* cur = unhandled_.top();
unhandled_.pop();
DOUT << "\n*** CURRENT ***: " << *cur << '\n';
if (!cur->empty()) {
processActiveIntervals(cur->beginNumber());
processInactiveIntervals(cur->beginNumber());
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()));
DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end()));
}
// Expire any remaining active intervals
while (!active_.empty()) {
IntervalPtr &IP = active_.back();
unsigned reg = IP.first->reg;
DOUT << "\tinterval " << *IP.first << " expired\n";
assert(TargetRegisterInfo::isVirtualRegister(reg) &&
"Can only allocate virtual registers!");
reg = vrm_->getPhys(reg);
// Expire any remaining inactive intervals
i = inactive_.rbegin(); i != inactive_.rend(); ++i)
DOUT << "\tinterval " << *i->first << " expired\n");
inactive_.clear();
// 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)
if (LiveInMBBs[i] != EntryMBB)
LiveInMBBs[i]->addLiveIn(Reg);
DOUT << *vrm_;
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(tri_, li_))
return;
Alkis Evlogimenos
committed
}
/// processActiveIntervals - expire old intervals and move non-overlapping ones
/// to the inactive list.
Bill Wendling
committed
void RALinScan::processActiveIntervals(unsigned CurPoint)
Alkis Evlogimenos
committed
{
DOUT << "\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.
DOUT << "\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.
DOUT << "\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.
Bill Wendling
committed
void RALinScan::processInactiveIntervals(unsigned CurPoint)
Alkis Evlogimenos
committed
{
DOUT << "\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.
DOUT << "\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
DOUT << "\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();
}
Bill Wendling
committed
static void RevertVectorIteratorsTo(RALinScan::IntervalPtrs &V, unsigned 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
VNI = SI.getNextValue(~0U, 0, 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_,
const MachineLoopInfo *loopInfo) {
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
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 += powf(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];
DOUT << "\tConsidering " << NumCands << " candidates: ";
DEBUG(for (unsigned i = 0; i != NumCands; ++i)
DOUT << tri_->getName(Candidates[i].first) << " ";
DOUT << "\n";);
// 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 {
typedef std::pair<unsigned, float> RegWeightPair;
bool operator()(const RegWeightPair &LHS, const RegWeightPair &RHS) const {
return LHS.second < RHS.second;
}
};
}
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%.
}
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
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->beginNumber() < B->beginNumber();
}
};
}
/// assignRegOrStackSlotAtInterval - assign a register if one is available, or
/// spill.
Bill Wendling
committed
void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
Alkis Evlogimenos
committed
{
DOUT << "\tallocating current interval: ";
// This is an implicitly defined live interval, just assign any register.
const TargetRegisterClass *RC = mri_->getRegClass(cur->reg);
if (cur->empty()) {
unsigned physReg = cur->preference;
if (!physReg)
physReg = *RC->allocation_order_begin(*mf_);
DOUT << 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;
unsigned StartPosition = cur->beginNumber();
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 (!cur->preference && cur->hasAtLeastOneValue()) {
VNInfo *vni = cur->begin()->valno;
if (vni->def && vni->def != ~1U && vni->def != ~0U) {
MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
Evan Cheng
committed
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (CopyMI &&
tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg)) {
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))
cur->preference = 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) {
unsigned Reg = i->first->reg;
assert(TargetRegisterInfo::isVirtualRegister(Reg) &&
"Can only allocate virtual registers!");
const TargetRegisterClass *RegRC = mri_->getRegClass(Reg);
// If this is not in a related reg class to the register we're allocating,
// don't check it.
if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader &&
cur->overlapsFrom(*i->first, i->second-1)) {
Reg = vrm_->getPhys(Reg);
SpillWeightsToAdd.push_back(std::make_pair(Reg, i->first->weight));
Alkis Evlogimenos
committed
}
// Speculatively check to see if we can get a register right now. If not,
// we know we won't be able to by adding more constraints. If so, we can
// check to see if it is valid. Doing an exhaustive search of the fixed_ list
// is very bad (it contains all callee clobbered registers for any functions
// with a call), so we want to avoid doing that if possible.
unsigned physReg = getFreePhysReg(cur);
Evan Cheng
committed
unsigned BestPhysReg = physReg;
if (physReg) {
// We got a register. However, if it's in the fixed_ list, we might
Chris Lattner
committed
// conflict with it. Check to see if we conflict with it or any of its
// aliases.
SmallSet<unsigned, 8> RegAliases;
for (const unsigned *AS = tri_->getAliasSet(physReg); *AS; ++AS)
Chris Lattner
committed
RegAliases.insert(*AS);
bool ConflictsWithFixed = false;
for (unsigned i = 0, e = fixed_.size(); i != e; ++i) {
IntervalPtr &IP = fixed_[i];
if (physReg == IP.first->reg || RegAliases.count(IP.first->reg)) {
// Okay, this reg is on the fixed list. Check to see if we actually
// conflict.
LiveInterval *I = IP.first;
if (I->endNumber() > StartPosition) {
LiveInterval::iterator II = I->advanceTo(IP.second, StartPosition);
IP.second = II;
if (II != I->begin() && II->start > StartPosition)
--II;
Chris Lattner
committed
if (cur->overlapsFrom(*I, II)) {
ConflictsWithFixed = true;
Chris Lattner
committed
break;
}
}
Chris Lattner
committed
}
// Okay, the register picked by our speculative getFreePhysReg call turned
// out to be in use. Actually add all of the conflicting fixed registers to
// regUse_ so we can do an accurate query.
if (ConflictsWithFixed) {
// For every interval in fixed we overlap with, mark the register as not
// free and update spill weights.
for (unsigned i = 0, e = fixed_.size(); i != e; ++i) {
IntervalPtr &IP = fixed_[i];
LiveInterval *I = IP.first;
const TargetRegisterClass *RegRC = OneClassForEachPhysReg[I->reg];
if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader &&
I->endNumber() > StartPosition) {
LiveInterval::iterator II = I->advanceTo(IP.second, StartPosition);
IP.second = II;
if (II != I->begin() && II->start > StartPosition)
--II;
if (cur->overlapsFrom(*I, II)) {
unsigned reg = I->reg;
SpillWeightsToAdd.push_back(std::make_pair(reg, I->weight));
}
}
}
// Using the newly updated regUse_ object, which includes conflicts in the
// future, see if there are any registers available.
physReg = getFreePhysReg(cur);
}
}
// Restore the physical register tracker, removing information about the
// future.
// If we find a free register, we are done: assign this virtual to
// the free physical register and add this interval to the active
// list.
if (physReg) {
vrm_->assignVirt2Phys(cur->reg, physReg);
active_.push_back(std::make_pair(cur, cur->begin()));
// "Upgrade" the physical register since it has been allocated.
UpgradeRegister(physReg);
if (LiveInterval *NextReloadLI = hasNextReloadInterval(cur)) {
// "Downgrade" physReg to try to keep physReg from being allocated until
// the next reload from the same SS is allocated.
NextReloadLI->preference = physReg;
DowngradeRegister(cur, physReg);
}
DOUT << "no free registers\n";