Newer
Older
//===-- RegAllocBasic.cpp - Basic Register Allocator ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the RABasic function pass, which provides a minimal
// implementation of the basic register allocator.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "regalloc"
Jakob Stoklund Olesen
committed
#include "RegAllocBase.h"
#include "LiveDebugVariables.h"
#include "LiveRangeEdit.h"
#include "RenderMachineFunction.h"
#include "Spiller.h"
#include "VirtRegMap.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Function.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
Jakob Stoklund Olesen
committed
#include <queue>
using namespace llvm;
static RegisterRegAlloc basicRegAlloc("basic", "basic register allocator",
createBasicRegisterAllocator);
Jakob Stoklund Olesen
committed
namespace {
struct CompSpillWeight {
bool operator()(LiveInterval *A, LiveInterval *B) const {
return A->weight < B->weight;
}
};
}
/// RABasic provides a minimal implementation of the basic register allocation
/// algorithm. It prioritizes live virtual registers by spill weight and spills
/// whenever a register is unavailable. This is not practical in production but
/// provides a useful baseline both for measuring other allocators and comparing
/// the speed of the basic algorithm against other styles of allocators.
class RABasic : public MachineFunctionPass, public RegAllocBase
{
// context
MachineFunction *MF;
LiveStacks *LS;
RenderMachineFunction *RMF;
std::auto_ptr<Spiller> SpillerInstance;
Jakob Stoklund Olesen
committed
std::priority_queue<LiveInterval*, std::vector<LiveInterval*>,
CompSpillWeight> Queue;
public:
RABasic();
/// Return the pass name.
virtual const char* getPassName() const {
return "Basic Register Allocator";
}
/// RABasic analysis usage.
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual void releaseMemory();
virtual Spiller &spiller() { return *SpillerInstance; }
Jakob Stoklund Olesen
committed
virtual float getPriority(LiveInterval *LI) { return LI->weight; }
Jakob Stoklund Olesen
committed
virtual void enqueue(LiveInterval *LI) {
Queue.push(LI);
}
virtual LiveInterval *dequeue() {
if (Queue.empty())
return 0;
LiveInterval *LI = Queue.top();
Queue.pop();
return LI;
}
virtual unsigned selectOrSplit(LiveInterval &VirtReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs);
/// Perform register allocation.
virtual bool runOnMachineFunction(MachineFunction &mf);
// Helper for spilling all live virtual registers currently unified under preg
// that interfere with the most recently queried lvr. Return true if spilling
// was successful, and append any new spilled/split intervals to splitLVRs.
bool spillInterferences(LiveInterval &VirtReg, unsigned PhysReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs);
void spillReg(LiveInterval &VirtReg, unsigned PhysReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs);
static char ID;
};
char RABasic::ID = 0;
} // end anonymous namespace
RABasic::RABasic(): MachineFunctionPass(ID) {
initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry());
initializeLiveIntervalsPass(*PassRegistry::getPassRegistry());
initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry());
initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry());
initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry());
initializeLiveStacksPass(*PassRegistry::getPassRegistry());
Jakob Stoklund Olesen
committed
initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry());
initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
initializeVirtRegMapPass(*PassRegistry::getPassRegistry());
initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry());
}
void RABasic::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<AliasAnalysis>();
AU.addPreserved<AliasAnalysis>();
AU.addRequired<LiveIntervals>();
AU.addPreserved<SlotIndexes>();
AU.addRequired<LiveDebugVariables>();
AU.addPreserved<LiveDebugVariables>();
if (StrongPHIElim)
AU.addRequiredID(StrongPHIEliminationID);
AU.addRequiredTransitiveID(RegisterCoalescerPassID);
AU.addRequired<CalculateSpillWeights>();
AU.addRequired<LiveStacks>();
AU.addPreserved<LiveStacks>();
AU.addRequiredID(MachineDominatorsID);
AU.addPreservedID(MachineDominatorsID);
AU.addRequired<MachineLoopInfo>();
AU.addPreserved<MachineLoopInfo>();
AU.addRequired<VirtRegMap>();
AU.addPreserved<VirtRegMap>();
DEBUG(AU.addRequired<RenderMachineFunction>());
MachineFunctionPass::getAnalysisUsage(AU);
}
void RABasic::releaseMemory() {
SpillerInstance.reset(0);
RegAllocBase::releaseMemory();
}
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
// Helper for spillInterferences() that spills all interfering vregs currently
// assigned to this physical register.
void RABasic::spillReg(LiveInterval& VirtReg, unsigned PhysReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs) {
LiveIntervalUnion::Query &Q = query(VirtReg, PhysReg);
assert(Q.seenAllInterferences() && "need collectInterferences()");
const SmallVectorImpl<LiveInterval*> &PendingSpills = Q.interferingVRegs();
for (SmallVectorImpl<LiveInterval*>::const_iterator I = PendingSpills.begin(),
E = PendingSpills.end(); I != E; ++I) {
LiveInterval &SpilledVReg = **I;
DEBUG(dbgs() << "extracting from " <<
TRI->getName(PhysReg) << " " << SpilledVReg << '\n');
// Deallocate the interfering vreg by removing it from the union.
// A LiveInterval instance may not be in a union during modification!
unassign(SpilledVReg, PhysReg);
// Spill the extracted interval.
LiveRangeEdit LRE(SpilledVReg, SplitVRegs, 0, &PendingSpills);
spiller().spill(LRE);
}
// After extracting segments, the query's results are invalid. But keep the
// contents valid until we're done accessing pendingSpills.
Q.clear();
}
// Spill or split all live virtual registers currently unified under PhysReg
// that interfere with VirtReg. The newly spilled or split live intervals are
// returned by appending them to SplitVRegs.
bool RABasic::spillInterferences(LiveInterval &VirtReg, unsigned PhysReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs) {
// Record each interference and determine if all are spillable before mutating
// either the union or live intervals.
unsigned NumInterferences = 0;
// Collect interferences assigned to any alias of the physical register.
for (const unsigned *asI = TRI->getOverlaps(PhysReg); *asI; ++asI) {
LiveIntervalUnion::Query &QAlias = query(VirtReg, *asI);
NumInterferences += QAlias.collectInterferingVRegs();
if (QAlias.seenUnspillableVReg()) {
return false;
}
}
DEBUG(dbgs() << "spilling " << TRI->getName(PhysReg) <<
" interferences with " << VirtReg << "\n");
assert(NumInterferences > 0 && "expect interference");
// Spill each interfering vreg allocated to PhysReg or an alias.
for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI)
spillReg(VirtReg, *AliasI, SplitVRegs);
return true;
}
// Driver for the register assignment and splitting heuristics.
// Manages iteration over the LiveIntervalUnions.
// This is a minimal implementation of register assignment and splitting that
// spills whenever we run out of registers.
//
// selectOrSplit can only be called once per live virtual register. We then do a
// single interference test for each register the correct class until we find an
// available register. So, the number of interference tests in the worst case is
// |vregs| * |machineregs|. And since the number of interference tests is
// minimal, there is no value in caching them outside the scope of
// selectOrSplit().
unsigned RABasic::selectOrSplit(LiveInterval &VirtReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs) {
// Populate a list of physical register spill candidates.
SmallVector<unsigned, 8> PhysRegSpillCands;
Jakob Stoklund Olesen
committed
ArrayRef<unsigned> Order =
RegClassInfo.getOrder(MRI->getRegClass(VirtReg.reg));
for (ArrayRef<unsigned>::iterator I = Order.begin(), E = Order.end(); I != E;
++I) {
unsigned PhysReg = *I;
// Check interference and as a side effect, intialize queries for this
// VirtReg and its aliases.
unsigned interfReg = checkPhysRegInterference(VirtReg, PhysReg);
if (interfReg == 0) {
// Found an available register.
return PhysReg;
LiveIntervalUnion::Query &IntfQ = query(VirtReg, interfReg);
IntfQ.collectInterferingVRegs(1);
LiveInterval *interferingVirtReg = IntfQ.interferingVRegs().front();
// The current VirtReg must either be spillable, or one of its interferences
// must have less spill weight.
if (interferingVirtReg->weight < VirtReg.weight ) {
PhysRegSpillCands.push_back(PhysReg);
// Try to spill another interfering reg with less spill weight.
for (SmallVectorImpl<unsigned>::iterator PhysRegI = PhysRegSpillCands.begin(),
PhysRegE = PhysRegSpillCands.end(); PhysRegI != PhysRegE; ++PhysRegI) {
if (!spillInterferences(VirtReg, *PhysRegI, SplitVRegs)) continue;
assert(checkPhysRegInterference(VirtReg, *PhysRegI) == 0 &&
"Interference after spill.");
// Tell the caller to allocate to this newly freed physical register.
return *PhysRegI;
Jakob Stoklund Olesen
committed
// No other spill candidates were found, so spill the current VirtReg.
DEBUG(dbgs() << "spilling: " << VirtReg << '\n');
Jakob Stoklund Olesen
committed
if (!VirtReg.isSpillable())
return ~0u;
LiveRangeEdit LRE(VirtReg, SplitVRegs);
spiller().spill(LRE);
// The live virtual register requesting allocation was spilled, so tell
// the caller not to allocate anything during this round.
return 0;
bool RABasic::runOnMachineFunction(MachineFunction &mf) {
DEBUG(dbgs() << "********** BASIC REGISTER ALLOCATION **********\n"
<< "********** Function: "
<< ((Value*)mf.getFunction())->getName() << '\n');
MF = &mf;
DEBUG(RMF = &getAnalysis<RenderMachineFunction>());
RegAllocBase::init(getAnalysis<VirtRegMap>(), getAnalysis<LiveIntervals>());
SpillerInstance.reset(createInlineSpiller(*this, *MF, *VRM));
Jakob Stoklund Olesen
committed
addMBBLiveIns(MF);
// Diagnostic output before rewriting
DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *VRM << "\n");
// optional HTML output
DEBUG(RMF->renderMachineFunction("After basic register allocation.", VRM));
// FIXME: Verification currently must run before VirtRegRewriter. We should
// make the rewriter a separate pass and override verifyAnalysis instead. When
// that happens, verification naturally falls under VerifyMachineCode.
#ifndef NDEBUG
Jakob Stoklund Olesen
committed
if (VerifyEnabled) {
// Verify accuracy of LiveIntervals. The standard machine code verifier
// ensures that each LiveIntervals covers all uses of the virtual reg.
// FIXME: MachineVerifier is badly broken when using the standard
// spiller. Always use -spiller=inline with -verify-regalloc. Even with the
// inline spiller, some tests fail to verify because the coalescer does not
// always generate verifiable code.
MF->verify(this, "In RABasic::verify");
// Verify that LiveIntervals are partitioned into unions and disjoint within
// the unions.
verify();
}
#endif // !NDEBUG
// Run rewriter
Jakob Stoklund Olesen
committed
VRM->rewrite(LIS->getSlotIndexes());
// Write out new DBG_VALUE instructions.
getAnalysis<LiveDebugVariables>().emitDebugValues(VRM);
// The pass output is in VirtRegMap. Release all the transient data.
releaseMemory();
return true;
}
{
return new RABasic();
}