-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/RegisterCoalescer.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/RegisterCoalescer.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/EquivalenceClasses.h"
/// handled_ - Intervals are added to the handled_ set in the order of their
/// start value. This is uses for backtracking.
/// handled_ - Intervals are added to the handled_ set in the order of their
/// start value. This is uses for backtracking.
// Make sure PassManager knows which analyses to make available
// to coalescing and which analyses coalescing invalidates.
AU.addRequiredTransitive<RegisterCoalescer>();
// Make sure PassManager knows which analyses to make available
// to coalescing and which analyses coalescing invalidates.
AU.addRequiredTransitive<RegisterCoalescer>();
// First pass, add all reg classes to the union, and determine at least one
// reg class that each register is in.
bool HasAliases = false;
// 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 (MRegisterInfo::regclass_iterator RCI = MRI.regclass_begin(),
- E = MRI.regclass_end(); RCI != E; ++RCI) {
+ 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) {
RelatedRegClasses.insert(*RCI);
for (TargetRegisterClass::iterator I = (*RCI)->begin(), E = (*RCI)->end();
I != E; ++I) {
for (std::map<unsigned, const TargetRegisterClass*>::iterator
I = OneClassForEachPhysReg.begin(), E = OneClassForEachPhysReg.end();
I != E; ++I)
for (std::map<unsigned, const TargetRegisterClass*>::iterator
I = OneClassForEachPhysReg.begin(), E = OneClassForEachPhysReg.end();
I != E; ++I)
/// different register classes or because the coalescer was overly
/// conservative.
unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
/// different register classes or because the coalescer was overly
/// conservative.
unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
if (!RC->contains(SrcReg))
return Reg;
// Try to coalesce.
if (!li_->conflictsWithPhysRegDef(cur, *vrm_, SrcReg)) {
if (!RC->contains(SrcReg))
return Reg;
// Try to coalesce.
if (!li_->conflictsWithPhysRegDef(cur, *vrm_, SrcReg)) {
vrm_->clearVirt(cur.reg);
vrm_->assignVirt2Phys(cur.reg, SrcReg);
++NumCoalesce;
vrm_->clearVirt(cur.reg);
vrm_->assignVirt2Phys(cur.reg, SrcReg);
++NumCoalesce;
// We don't run the coalescer here because we have no reason to
// interact with it. If the coalescer requires interaction, it
// We don't run the coalescer here because we have no reason to
// interact with it. If the coalescer requires interaction, it
"interval sets should be empty on initialization");
for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) {
"interval sets should be empty on initialization");
for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) {
fixed_.push_back(std::make_pair(&i->second, i->second.begin()));
} else
unhandled_.push(&i->second);
fixed_.push_back(std::make_pair(&i->second, i->second.begin()));
} else
unhandled_.push(&i->second);
IntervalPtr &IP = active_.back();
unsigned reg = IP.first->reg;
DOUT << "\tinterval " << *IP.first << " expired\n";
IntervalPtr &IP = active_.back();
unsigned reg = IP.first->reg;
DOUT << "\tinterval " << *IP.first << " expired\n";
MachineFunction::iterator EntryMBB = mf_->begin();
SmallVector<MachineBasicBlock*, 8> LiveInMBBs;
for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) {
LiveInterval &cur = i->second;
unsigned Reg = 0;
MachineFunction::iterator EntryMBB = mf_->begin();
SmallVector<MachineBasicBlock*, 8> LiveInMBBs;
for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) {
LiveInterval &cur = i->second;
unsigned Reg = 0;
Reg = i->second.reg;
else if (vrm_->isAssignedReg(cur.reg))
Reg = attemptTrivialCoalescing(cur, vrm_->getPhys(cur.reg));
if (!Reg)
continue;
Reg = i->second.reg;
else if (vrm_->isAssignedReg(cur.reg))
Reg = attemptTrivialCoalescing(cur, vrm_->getPhys(cur.reg));
if (!Reg)
continue;
for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end();
I != E; ++I) {
const LiveRange &LR = *I;
for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end();
I != E; ++I) {
const LiveRange &LR = *I;
if (IntervalPos == Interval->end()) { // Remove expired intervals.
DOUT << "\t\tinterval " << *Interval << " expired\n";
if (IntervalPos == Interval->end()) { // Remove expired intervals.
DOUT << "\t\tinterval " << *Interval << " expired\n";
} else if (IntervalPos->start > CurPoint) {
// Move inactive intervals to inactive list.
DOUT << "\t\tinterval " << *Interval << " inactive\n";
} else if (IntervalPos->start > CurPoint) {
// Move inactive intervals to inactive list.
DOUT << "\t\tinterval " << *Interval << " inactive\n";
} else if (IntervalPos->start <= CurPoint) {
// move re-activated intervals in active list
DOUT << "\t\tinterval " << *Interval << " active\n";
} else if (IntervalPos->start <= CurPoint) {
// move re-activated intervals in active list
DOUT << "\t\tinterval " << *Interval << " active\n";
/// register and its weight.
static void updateSpillWeights(std::vector<float> &Weights,
unsigned reg, float weight,
/// register and its weight.
static void updateSpillWeights(std::vector<float> &Weights,
unsigned reg, float weight,
std::vector<std::pair<unsigned, float> > SpillWeightsToAdd;
unsigned StartPosition = cur->beginNumber();
std::vector<std::pair<unsigned, float> > SpillWeightsToAdd;
unsigned StartPosition = cur->beginNumber();
const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC);
// If this live interval is defined by a move instruction and its source is
const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC);
// If this live interval is defined by a move instruction and its source is
for (IntervalPtrs::const_iterator i = inactive_.begin(),
e = inactive_.end(); i != e; ++i) {
unsigned Reg = i->first->reg;
for (IntervalPtrs::const_iterator i = inactive_.begin(),
e = inactive_.end(); i != e; ++i) {
unsigned Reg = i->first->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 &&
// If this is not in a related reg class to the register we're allocating,
// don't check it.
if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader &&
// conflict with it. Check to see if we conflict with it or any of its
// aliases.
SmallSet<unsigned, 8> RegAliases;
// conflict with it. Check to see if we conflict with it or any of its
// aliases.
SmallSet<unsigned, 8> RegAliases;
vrm_->assignVirt2Phys(cur->reg, physReg);
prt_->addRegUse(physReg);
active_.push_back(std::make_pair(cur, cur->begin()));
vrm_->assignVirt2Phys(cur->reg, physReg);
prt_->addRegUse(physReg);
active_.push_back(std::make_pair(cur, cur->begin()));
DOUT << "no free registers\n";
// Compile the spill weights into an array that is better for scanning.
DOUT << "no free registers\n";
// Compile the spill weights into an array that is better for scanning.
for (std::vector<std::pair<unsigned, float> >::iterator
I = SpillWeightsToAdd.begin(), E = SpillWeightsToAdd.end(); I != E; ++I)
for (std::vector<std::pair<unsigned, float> >::iterator
I = SpillWeightsToAdd.begin(), E = SpillWeightsToAdd.end(); I != E; ++I)
- updateSpillWeights(SpillWeights, I->first, I->second, mri_);
+ updateSpillWeights(SpillWeights, I->first, I->second, tri_);
// for each interval in active, update spill weights.
for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end();
i != e; ++i) {
unsigned reg = i->first->reg;
// for each interval in active, update spill weights.
for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end();
i != e; ++i) {
unsigned reg = i->first->reg;
- updateSpillWeights(SpillWeights, reg, i->first->weight, mri_);
+ updateSpillWeights(SpillWeights, reg, i->first->weight, tri_);
unsigned reg = *i;
// No need to worry about if the alias register size < regsize of RC.
// We are going to spill all registers that alias it anyway.
unsigned reg = *i;
// No need to worry about if the alias register size < regsize of RC.
// We are going to spill all registers that alias it anyway.
// if the current has the minimum weight, we need to spill it and
// add any added intervals back to unhandled, and restart
// if the current has the minimum weight, we need to spill it and
// add any added intervals back to unhandled, and restart
if (cur->weight != HUGE_VALF && cur->weight <= minWeight) {
DOUT << "\t\t\tspilling(c): " << *cur << '\n';
std::vector<LiveInterval*> added =
if (cur->weight != HUGE_VALF && cur->weight <= minWeight) {
DOUT << "\t\t\tspilling(c): " << *cur << '\n';
std::vector<LiveInterval*> added =
// minimum weight, rollback to the interval with the earliest
// start point and let the linear scan algorithm run again
std::vector<LiveInterval*> added;
// minimum weight, rollback to the interval with the earliest
// start point and let the linear scan algorithm run again
std::vector<LiveInterval*> added;
// mark our rollback point.
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
unsigned reg = i->first->reg;
// mark our rollback point.
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
unsigned reg = i->first->reg;
toSpill[vrm_->getPhys(reg)] &&
cur->overlapsFrom(*i->first, i->second)) {
DOUT << "\t\t\tspilling(a): " << *i->first << '\n';
earliestStart = std::min(earliestStart, i->first->beginNumber());
std::vector<LiveInterval*> newIs =
toSpill[vrm_->getPhys(reg)] &&
cur->overlapsFrom(*i->first, i->second)) {
DOUT << "\t\t\tspilling(a): " << *i->first << '\n';
earliestStart = std::min(earliestStart, i->first->beginNumber());
std::vector<LiveInterval*> newIs =
std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
spilled.insert(reg);
}
}
for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ++i){
unsigned reg = i->first->reg;
std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
spilled.insert(reg);
}
}
for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ++i){
unsigned reg = i->first->reg;
toSpill[vrm_->getPhys(reg)] &&
cur->overlapsFrom(*i->first, i->second-1)) {
DOUT << "\t\t\tspilling(i): " << *i->first << '\n';
earliestStart = std::min(earliestStart, i->first->beginNumber());
std::vector<LiveInterval*> newIs =
toSpill[vrm_->getPhys(reg)] &&
cur->overlapsFrom(*i->first, i->second-1)) {
DOUT << "\t\t\tspilling(i): " << *i->first << '\n';
earliestStart = std::min(earliestStart, i->first->beginNumber());
std::vector<LiveInterval*> newIs =
IntervalPtrs::iterator it;
if ((it = FindIntervalInVector(active_, i)) != active_.end()) {
active_.erase(it);
IntervalPtrs::iterator it;
if ((it = FindIntervalInVector(active_, i)) != active_.end()) {
active_.erase(it);
if (!spilled.count(i->reg))
unhandled_.push(i);
prt_->delRegUse(vrm_->getPhys(i->reg));
vrm_->clearVirt(i->reg);
} else if ((it = FindIntervalInVector(inactive_, i)) != inactive_.end()) {
inactive_.erase(it);
if (!spilled.count(i->reg))
unhandled_.push(i);
prt_->delRegUse(vrm_->getPhys(i->reg));
vrm_->clearVirt(i->reg);
} else if ((it = FindIntervalInVector(inactive_, i)) != inactive_.end()) {
inactive_.erase(it);
HI->expiredAt(cur->beginNumber())) {
DOUT << "\t\t\tundo changes for: " << *HI << '\n';
active_.push_back(std::make_pair(HI, HI->begin()));
HI->expiredAt(cur->beginNumber())) {
DOUT << "\t\t\tundo changes for: " << *HI << '\n';
active_.push_back(std::make_pair(HI, HI->begin()));
/// getFreePhysReg - return a free physical register for this virtual register
/// interval if we have one, otherwise return 0.
unsigned RALinScan::getFreePhysReg(LiveInterval *cur) {
/// getFreePhysReg - return a free physical register for this virtual register
/// interval if we have one, otherwise return 0.
unsigned RALinScan::getFreePhysReg(LiveInterval *cur) {
const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC);
for (IntervalPtrs::iterator i = inactive_.begin(), e = inactive_.end();
i != e; ++i) {
unsigned reg = i->first->reg;
const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC);
for (IntervalPtrs::iterator i = inactive_.begin(), e = inactive_.end();
i != e; ++i) {
unsigned reg = i->first->reg;
"Can only allocate virtual registers!");
// If this is not in a related reg class to the register we're allocating,
// don't check it.
"Can only allocate virtual registers!");
// If this is not in a related reg class to the register we're allocating,
// don't check it.
// Scan for the first available register.
TargetRegisterClass::iterator I = RC->allocation_order_begin(*mf_);
// Scan for the first available register.
TargetRegisterClass::iterator I = RC->allocation_order_begin(*mf_);