forked from OSchip/llvm-project
Stub out RegAllocGreedy.
This new register allocator is initially identical to RegAllocBasic, but it will receive all of the tricks that RegAllocBasic won't get. RegAllocGreedy will eventually replace linear scan. llvm-svn: 121234
This commit is contained in:
parent
7a05f00ade
commit
b8812a1c15
|
@ -36,6 +36,7 @@ namespace {
|
|||
(void) llvm::createFastRegisterAllocator();
|
||||
(void) llvm::createBasicRegisterAllocator();
|
||||
(void) llvm::createLinearScanRegisterAllocator();
|
||||
(void) llvm::createGreedyRegisterAllocator();
|
||||
(void) llvm::createDefaultPBQPRegisterAllocator();
|
||||
|
||||
(void) llvm::createSimpleRegisterCoalescer();
|
||||
|
|
|
@ -103,6 +103,11 @@ namespace llvm {
|
|||
///
|
||||
FunctionPass *createBasicRegisterAllocator();
|
||||
|
||||
/// Greedy register allocation pass - This pass implements a global register
|
||||
/// allocator for optimized builds.
|
||||
///
|
||||
FunctionPass *createGreedyRegisterAllocator();
|
||||
|
||||
/// LinearScanRegisterAllocation Pass - This pass implements the linear scan
|
||||
/// register allocation algorithm, a global register allocator.
|
||||
///
|
||||
|
|
|
@ -61,6 +61,7 @@ add_llvm_library(LLVMCodeGen
|
|||
PseudoSourceValue.cpp
|
||||
RegAllocBasic.cpp
|
||||
RegAllocFast.cpp
|
||||
RegAllocGreedy.cpp
|
||||
RegAllocLinearScan.cpp
|
||||
RegAllocPBQP.cpp
|
||||
RegisterCoalescer.cpp
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
//===-- RegAllocGreedy.cpp - greedy 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 RAGreedy function pass for register allocation in
|
||||
// optimized builds.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "regalloc"
|
||||
#include "LiveIntervalUnion.h"
|
||||
#include "RegAllocBase.h"
|
||||
#include "Spiller.h"
|
||||
#include "VirtRegMap.h"
|
||||
#include "VirtRegRewriter.h"
|
||||
#include "llvm/ADT/OwningPtr.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/CodeGen/RegisterCoalescer.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator",
|
||||
createGreedyRegisterAllocator);
|
||||
|
||||
namespace {
|
||||
class RAGreedy : public MachineFunctionPass, public RegAllocBase {
|
||||
// context
|
||||
MachineFunction *MF;
|
||||
const TargetMachine *TM;
|
||||
MachineRegisterInfo *MRI;
|
||||
|
||||
BitVector ReservedRegs;
|
||||
|
||||
// analyses
|
||||
LiveStacks *LS;
|
||||
|
||||
// state
|
||||
std::auto_ptr<Spiller> SpillerInstance;
|
||||
|
||||
public:
|
||||
RAGreedy();
|
||||
|
||||
/// Return the pass name.
|
||||
virtual const char* getPassName() const {
|
||||
return "Basic Register Allocator";
|
||||
}
|
||||
|
||||
/// RAGreedy analysis usage.
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
virtual void releaseMemory();
|
||||
|
||||
virtual Spiller &spiller() { return *SpillerInstance; }
|
||||
|
||||
virtual unsigned selectOrSplit(LiveInterval &VirtReg,
|
||||
SmallVectorImpl<LiveInterval*> &SplitVRegs);
|
||||
|
||||
/// Perform register allocation.
|
||||
virtual bool runOnMachineFunction(MachineFunction &mf);
|
||||
|
||||
static char ID;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
char RAGreedy::ID = 0;
|
||||
|
||||
FunctionPass* llvm::createGreedyRegisterAllocator() {
|
||||
return new RAGreedy();
|
||||
}
|
||||
|
||||
RAGreedy::RAGreedy(): MachineFunctionPass(ID) {
|
||||
initializeLiveIntervalsPass(*PassRegistry::getPassRegistry());
|
||||
initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
|
||||
initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry());
|
||||
initializeRegisterCoalescerAnalysisGroup(*PassRegistry::getPassRegistry());
|
||||
initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry());
|
||||
initializeLiveStacksPass(*PassRegistry::getPassRegistry());
|
||||
initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry());
|
||||
initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
|
||||
initializeVirtRegMapPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addRequired<LiveIntervals>();
|
||||
AU.addPreserved<SlotIndexes>();
|
||||
if (StrongPHIElim)
|
||||
AU.addRequiredID(StrongPHIEliminationID);
|
||||
AU.addRequiredTransitive<RegisterCoalescer>();
|
||||
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>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
void RAGreedy::releaseMemory() {
|
||||
SpillerInstance.reset(0);
|
||||
RegAllocBase::releaseMemory();
|
||||
}
|
||||
|
||||
unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,
|
||||
SmallVectorImpl<LiveInterval*> &SplitVRegs) {
|
||||
// Populate a list of physical register spill candidates.
|
||||
SmallVector<unsigned, 8> PhysRegSpillCands;
|
||||
|
||||
// Check for an available register in this class.
|
||||
const TargetRegisterClass *TRC = MRI->getRegClass(VirtReg.reg);
|
||||
DEBUG(dbgs() << "RegClass: " << TRC->getName() << ' ');
|
||||
|
||||
for (TargetRegisterClass::iterator I = TRC->allocation_order_begin(*MF),
|
||||
E = TRC->allocation_order_end(*MF);
|
||||
I != E; ++I) {
|
||||
|
||||
unsigned PhysReg = *I;
|
||||
if (ReservedRegs.test(PhysReg)) continue;
|
||||
|
||||
// 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;
|
||||
}
|
||||
LiveInterval *interferingVirtReg =
|
||||
Queries[interfReg].firstInterference().liveUnionPos().value();
|
||||
|
||||
// The current VirtReg must either 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.
|
||||
//
|
||||
// FIXME: RAGreedy will sort this list by 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;
|
||||
}
|
||||
// No other spill candidates were found, so spill the current VirtReg.
|
||||
DEBUG(dbgs() << "spilling: " << VirtReg << '\n');
|
||||
SmallVector<LiveInterval*, 1> pendingSpills;
|
||||
|
||||
spiller().spill(&VirtReg, SplitVRegs, pendingSpills);
|
||||
|
||||
// The live virtual register requesting allocation was spilled, so tell
|
||||
// the caller not to allocate anything during this round.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
|
||||
DEBUG(dbgs() << "********** GREEDY REGISTER ALLOCATION **********\n"
|
||||
<< "********** Function: "
|
||||
<< ((Value*)mf.getFunction())->getName() << '\n');
|
||||
|
||||
MF = &mf;
|
||||
TM = &mf.getTarget();
|
||||
MRI = &mf.getRegInfo();
|
||||
|
||||
const TargetRegisterInfo *TRI = TM->getRegisterInfo();
|
||||
RegAllocBase::init(*TRI, getAnalysis<VirtRegMap>(),
|
||||
getAnalysis<LiveIntervals>());
|
||||
|
||||
ReservedRegs = TRI->getReservedRegs(*MF);
|
||||
SpillerInstance.reset(createSpiller(*this, *MF, *VRM));
|
||||
allocatePhysRegs();
|
||||
addMBBLiveIns(MF);
|
||||
|
||||
// Run rewriter
|
||||
std::auto_ptr<VirtRegRewriter> rewriter(createVirtRegRewriter());
|
||||
rewriter->runOnMachineFunction(*MF, *VRM, LIS);
|
||||
|
||||
// The pass output is in VirtRegMap. Release all the transient data.
|
||||
releaseMemory();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue