mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-30 04:37:20 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121234 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6171ab69f4
commit
cba2e06d52
@ -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
|
||||
|
214
lib/CodeGen/RegAllocGreedy.cpp
Normal file
214
lib/CodeGen/RegAllocGreedy.cpp
Normal file
@ -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…
x
Reference in New Issue
Block a user