#include "VirtRegRewriter.h"
#include "Spiller.h"
#include "llvm/Function.h"
+#include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
cl::desc("Pre-register allocation live interval splitting"),
cl::init(false), cl::Hidden);
+static cl::opt<bool>
+TrivCoalesceEnds("trivial-coalesce-ends",
+ cl::desc("Attempt trivial coalescing of interval ends"),
+ cl::init(false), cl::Hidden);
+
static RegisterRegAlloc
linearscanRegAlloc("linearscan", "linear scan register allocator",
createLinearScanRegisterAllocator);
// Make sure PassManager knows which analyses to make available
// to coalescing and which analyses coalescing invalidates.
AU.addRequiredTransitive<RegisterCoalescer>();
+ AU.addRequired<CalculateSpillWeights>();
if (PreSplitIntervals)
AU.addRequiredID(PreAllocSplittingID);
AU.addRequired<LiveStacks>();
if ((Preference && Preference == Reg) || !cur.containsOneValue())
return Reg;
- VNInfo *vni = cur.begin()->valno;
+ // We cannot handle complicated live ranges. Simple linear stuff only.
+ if (cur.ranges.size() != 1)
+ return Reg;
+
+ const LiveRange &range = cur.ranges.front();
+
+ VNInfo *vni = range.valno;
if (vni->isUnused())
return Reg;
+
unsigned CandReg;
- bool forward; // extending physreg forward
{
MachineInstr *CopyMI;
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
(CopyMI = li_->getInstructionFromIndex(vni->def)) &&
tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg))
// Defined by a copy, try to extend SrcReg forward
- CandReg = SrcReg, forward = true;
- else if (cur.ranges.size()==1 &&
+ CandReg = SrcReg;
+ else if (TrivCoalesceEnds &&
(CopyMI =
- li_->getInstructionFromIndex(cur.begin()->end.getBaseIndex())) &&
+ li_->getInstructionFromIndex(range.end.getBaseIndex())) &&
tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
cur.reg == SrcReg)
// Only used by a copy, try to extend DstReg backwards
- CandReg = DstReg, forward = false;
+ CandReg = DstReg;
else
return Reg;
}
if (!RC->contains(CandReg))
return Reg;
- if (forward) {
- if (li_->conflictsWithPhysRegDef(cur, *vrm_, CandReg))
- return Reg;
- } else {
- if (li_->conflictsWithPhysRegUse(cur, *vrm_, CandReg))
- return Reg;
- }
+ if (li_->conflictsWithPhysReg(cur, *vrm_, CandReg))
+ return Reg;
// Try to coalesce.
DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(CandReg)
const RALinScan &Allocator;
public:
- WeightCompare(const RALinScan &Alloc) : Allocator(Alloc) {};
+ WeightCompare(const RALinScan &Alloc) : Allocator(Alloc) {}
typedef std::pair<unsigned, float> RegWeightPair;
bool operator()(const RegWeightPair &LHS, const RegWeightPair &RHS) const {
// The earliest start of a Spilled interval indicates up to where
// in handled we need to roll back
+ assert(!spillIs.empty() && "No spill intervals?");
+ SlotIndex earliestStart = spillIs[0]->beginIndex();
- 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
// current interval as the rest do not affect its allocation. we also keep
LiveInterval *sli = spillIs.back();
spillIs.pop_back();
DEBUG(errs() << "\t\t\tspilling(a): " << *sli << '\n');
- earliestStartInterval =
- (earliestStartInterval->beginIndex() < sli->beginIndex()) ?
- earliestStartInterval : sli;
+ if (sli->beginIndex() < earliestStart)
+ earliestStart = sli->beginIndex();
std::vector<LiveInterval*> newIs;
- newIs = spiller_->spill(sli, spillIs);
+ newIs = spiller_->spill(sli, spillIs, &earliestStart);
addStackInterval(sli, ls_, li_, mri_, *vrm_);
std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
spilled.insert(sli->reg);
}
- SlotIndex earliestStart = earliestStartInterval->beginIndex();
-
DEBUG(errs() << "\t\trolling back to: " << earliestStart << '\n');
// Scan handled in reverse order up to the earliest start of a
while (!handled_.empty()) {
LiveInterval* i = handled_.back();
// If this interval starts before t we are done.
- if (i->beginIndex() < earliestStart)
+ if (!i->empty() && i->beginIndex() < earliestStart)
break;
DEBUG(errs() << "\t\t\tundo changes for: " << *i << '\n');
handled_.pop_back();