#define DEBUG_TYPE "regalloc"
#include "VirtRegMap.h"
#include "VirtRegRewriter.h"
+#include "Spiller.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
#include <queue>
#include <memory>
#include <cmath>
+
using namespace llvm;
STATISTIC(NumIters , "Number of iterations performed");
cl::desc("Pre-register allocation live interval splitting"),
cl::init(false), cl::Hidden);
+static cl::opt<bool>
+NewSpillFramework("new-spill-framework",
+ cl::desc("New spilling framework"),
+ cl::init(false), cl::Hidden);
+
static RegisterRegAlloc
linearscanRegAlloc("linearscan", "linear scan register allocator",
createLinearScanRegisterAllocator);
std::auto_ptr<VirtRegRewriter> rewriter_;
+ std::auto_ptr<Spiller> spiller_;
+
public:
virtual const char* getPassName() const {
return "Linear Scan Register Allocator";
vrm_ = &getAnalysis<VirtRegMap>();
if (!rewriter_.get()) rewriter_.reset(createVirtRegRewriter());
-
+
+ if (NewSpillFramework) {
+ spiller_.reset(createSpiller(mf_, li_, ls_, vrm_));
+ }
+
initIntervalSets();
linearScan();
NextReloadMap.clear();
DowngradedRegs.clear();
DowngradeMap.clear();
+ spiller_.reset(0);
return true;
}
// Ignore splited live intervals.
if (!isPhys && vrm_->getPreSplitReg(cur.reg))
continue;
+
+ // A register defined by an implicit_def can be liveout the def BB and livein
+ // to a use BB. Add it to the livein set of the use BB's.
+ if (!isPhys && cur.empty()) {
+ if (MachineInstr *DefMI = mri_->getVRegDef(cur.reg)) {
+ assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF);
+ MachineBasicBlock *DefMBB = DefMI->getParent();
+ SmallPtrSet<MachineBasicBlock*, 4> Seen;
+ Seen.insert(DefMBB);
+ for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(cur.reg),
+ re = mri_->reg_end(); ri != re; ++ri) {
+ MachineInstr *UseMI = &*ri;
+ MachineBasicBlock *UseMBB = UseMI->getParent();
+ if (Seen.insert(UseMBB))
+ UseMBB->addLiveIn(Reg);
+ }
+ }
+ }
for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end();
I != E; ++I) {
const LiveRange &LR = *I;
if (cur->weight != HUGE_VALF && cur->weight <= minWeight) {
DOUT << "\t\t\tspilling(c): " << *cur << '\n';
SmallVector<LiveInterval*, 8> spillIs;
- std::vector<LiveInterval*> added =
- li_->addIntervalsForSpills(*cur, spillIs, loopInfo, *vrm_);
+ std::vector<LiveInterval*> added;
+
+ if (!NewSpillFramework) {
+ added = li_->addIntervalsForSpills(*cur, spillIs, loopInfo, *vrm_);
+ } else {
+ added = spiller_->spill(cur);
+ }
+
std::sort(added.begin(), added.end(), LISorter());
addStackInterval(cur, ls_, li_, mri_, *vrm_);
if (added.empty())
// The earliest start of a Spilled interval indicates up to where
// in handled we need to roll back
- unsigned earliestStart = cur->beginNumber();
+
+ LiveInterval *earliestStartInterval = cur;
// Spill live intervals of virtual regs mapped to the physical register we
// want to clear (and its aliases). We only spill those that overlap with the
// mark our rollback point.
std::vector<LiveInterval*> added;
while (!spillIs.empty()) {
+ bool epicFail = false;
LiveInterval *sli = spillIs.back();
spillIs.pop_back();
DOUT << "\t\t\tspilling(a): " << *sli << '\n';
- earliestStart = std::min(earliestStart, sli->beginNumber());
- std::vector<LiveInterval*> newIs =
- li_->addIntervalsForSpills(*sli, spillIs, loopInfo, *vrm_);
+ earliestStartInterval =
+ (earliestStartInterval->beginNumber() < sli->beginNumber()) ?
+ earliestStartInterval : sli;
+
+ std::vector<LiveInterval*> newIs;
+ if (!NewSpillFramework) {
+ newIs = li_->addIntervalsForSpills(*sli, spillIs, loopInfo, *vrm_);
+ } else {
+ newIs = spiller_->spill(sli);
+ }
addStackInterval(sli, ls_, li_, mri_, *vrm_);
std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
spilled.insert(sli->reg);
+
+ if (epicFail) {
+ //abort();
+ }
}
+ unsigned earliestStart = earliestStartInterval->beginNumber();
+
DOUT << "\t\trolling back to: " << earliestStart << '\n';
// Scan handled in reverse order up to the earliest start of a