diff options
author | Lang Hames <lhames@gmail.com> | 2010-09-23 04:28:54 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2010-09-23 04:28:54 +0000 |
commit | f70e7cc7a2871d498dbecbec2d1c3beb3da2af33 (patch) | |
tree | e6a449843c5993f31c5bed3b0f8802b53e400c0d /lib/CodeGen/RegAllocPBQP.cpp | |
parent | 38a9288f78d76ad8f43a0398230c7c420390e606 (diff) | |
download | external_llvm-f70e7cc7a2871d498dbecbec2d1c3beb3da2af33.zip external_llvm-f70e7cc7a2871d498dbecbec2d1c3beb3da2af33.tar.gz external_llvm-f70e7cc7a2871d498dbecbec2d1c3beb3da2af33.tar.bz2 |
Moved the PBQP allocator class out of the header and back in to the cpp file to hide the gory details.
Allocator instances can now be created by calling createPBQPRegisterAllocator.
Tidied up use of CoalescerPair as per Jakob's suggestions.
Made the new PBQPBuilder based construction process the default. The internal construction process
remains in-place and available via -pbqp-builder=false for now. It will be removed shortly if the new
process doesn't cause any regressions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114626 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/RegAllocPBQP.cpp')
-rw-r--r-- | lib/CodeGen/RegAllocPBQP.cpp | 250 |
1 files changed, 190 insertions, 60 deletions
diff --git a/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp index 6353835..0db5053 100644 --- a/lib/CodeGen/RegAllocPBQP.cpp +++ b/lib/CodeGen/RegAllocPBQP.cpp @@ -56,11 +56,11 @@ #include <set> #include <vector> -namespace llvm { +using namespace llvm; static RegisterRegAlloc registerPBQPRepAlloc("pbqp", "PBQP register allocator", - llvm::createPBQPRegisterAllocator); + createDefaultPBQPRegisterAllocator); static cl::opt<bool> pbqpCoalescing("pbqp-coalescing", @@ -69,17 +69,149 @@ pbqpCoalescing("pbqp-coalescing", static cl::opt<bool> pbqpBuilder("pbqp-builder", - cl::desc("Use new builder system."), - cl::init(false), cl::Hidden); + cl::desc("Use new builder system."), + cl::init(true), cl::Hidden); static cl::opt<bool> pbqpPreSplitting("pbqp-pre-splitting", - cl::desc("Pre-splite before PBQP register allocation."), + cl::desc("Pre-split before PBQP register allocation."), cl::init(false), cl::Hidden); +namespace { + +/// +/// PBQP based allocators solve the register allocation problem by mapping +/// register allocation problems to Partitioned Boolean Quadratic +/// Programming problems. +class RegAllocPBQP : public MachineFunctionPass { +public: + + static char ID; + + /// Construct a PBQP register allocator. + RegAllocPBQP(std::auto_ptr<PBQPBuilder> b) : MachineFunctionPass(ID), builder(b) {} + + /// Return the pass name. + virtual const char* getPassName() const { + return "PBQP Register Allocator"; + } + + /// PBQP analysis usage. + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + /// Perform register allocation + virtual bool runOnMachineFunction(MachineFunction &MF); + +private: + + typedef std::map<const LiveInterval*, unsigned> LI2NodeMap; + typedef std::vector<const LiveInterval*> Node2LIMap; + typedef std::vector<unsigned> AllowedSet; + typedef std::vector<AllowedSet> AllowedSetMap; + typedef std::pair<unsigned, unsigned> RegPair; + typedef std::map<RegPair, PBQP::PBQPNum> CoalesceMap; + typedef std::vector<PBQP::Graph::NodeItr> NodeVector; + typedef std::set<unsigned> RegSet; + + + std::auto_ptr<PBQPBuilder> builder; + + MachineFunction *mf; + const TargetMachine *tm; + const TargetRegisterInfo *tri; + const TargetInstrInfo *tii; + const MachineLoopInfo *loopInfo; + MachineRegisterInfo *mri; + RenderMachineFunction *rmf; + + LiveIntervals *lis; + LiveStacks *lss; + VirtRegMap *vrm; + + LI2NodeMap li2Node; + Node2LIMap node2LI; + AllowedSetMap allowedSets; + RegSet vregsToAlloc, emptyIntervalVRegs; + NodeVector problemNodes; + + + /// Builds a PBQP cost vector. + template <typename RegContainer> + PBQP::Vector buildCostVector(unsigned vReg, + const RegContainer &allowed, + const CoalesceMap &cealesces, + PBQP::PBQPNum spillCost) const; + + /// \brief Builds a PBQP interference matrix. + /// + /// @return Either a pointer to a non-zero PBQP matrix representing the + /// allocation option costs, or a null pointer for a zero matrix. + /// + /// Expects allowed sets for two interfering LiveIntervals. These allowed + /// sets should contain only allocable registers from the LiveInterval's + /// register class, with any interfering pre-colored registers removed. + template <typename RegContainer> + PBQP::Matrix* buildInterferenceMatrix(const RegContainer &allowed1, + const RegContainer &allowed2) const; + + /// + /// Expects allowed sets for two potentially coalescable LiveIntervals, + /// and an estimated benefit due to coalescing. The allowed sets should + /// contain only allocable registers from the LiveInterval's register + /// classes, with any interfering pre-colored registers removed. + template <typename RegContainer> + PBQP::Matrix* buildCoalescingMatrix(const RegContainer &allowed1, + const RegContainer &allowed2, + PBQP::PBQPNum cBenefit) const; + + /// \brief Finds coalescing opportunities and returns them as a map. + /// + /// Any entries in the map are guaranteed coalescable, even if their + /// corresponding live intervals overlap. + CoalesceMap findCoalesces(); + + /// \brief Finds the initial set of vreg intervals to allocate. + void findVRegIntervalsToAlloc(); + + /// \brief Constructs a PBQP problem representation of the register + /// allocation problem for this function. + /// + /// Old Construction Process - this functionality has been subsumed + /// by PBQPBuilder. This function will only be hanging around for a little + /// while until the new system has been fully tested. + /// + /// @return a PBQP solver object for the register allocation problem. + PBQP::Graph constructPBQPProblemOld(); + + /// \brief Adds a stack interval if the given live interval has been + /// spilled. Used to support stack slot coloring. + void addStackInterval(const LiveInterval *spilled,MachineRegisterInfo* mri); + + /// \brief Given a solved PBQP problem maps this solution back to a register + /// assignment. + /// + /// Old Construction Process - this functionality has been subsumed + /// by PBQPBuilder. This function will only be hanging around for a little + /// while until the new system has been fully tested. + /// + bool mapPBQPToRegAllocOld(const PBQP::Solution &solution); + + /// \brief Given a solved PBQP problem maps this solution back to a register + /// assignment. + bool mapPBQPToRegAlloc(const PBQPRAProblem &problem, + const PBQP::Solution &solution); + + /// \brief Postprocessing before final spilling. Sets basic block "live in" + /// variables. + void finalizeAlloc() const; + +}; + char RegAllocPBQP::ID = 0; +} // End anonymous namespace. + unsigned PBQPRAProblem::getVRegForNode(PBQP::Graph::ConstNodeItr node) const { Node2VReg::const_iterator vregItr = node2VReg.find(node); assert(vregItr != node2VReg.end() && "No vreg for node."); @@ -277,58 +409,54 @@ std::auto_ptr<PBQPRAProblem> PBQPBuilderWithCoalescing::build( miItr != miEnd; ++miItr) { const MachineInstr *mi = &*miItr; - if (!mi->isCopy() && !mi->isSubregToReg()) - continue; // Not coalescable. - if (!cp.setRegisters(mi)) continue; // Not coalescable. if (cp.getSrcReg() == cp.getDstReg()) continue; // Already coalesced. - if (cp.isCoalescable(mi)) { - - unsigned dst = cp.getDstReg(), - src = cp.getSrcReg(); - + unsigned dst = cp.getDstReg(), + src = cp.getSrcReg(); + const float copyFactor = 0.5; // Cost of copy relative to load. Current + // value plucked randomly out of the air. + + PBQP::PBQPNum cBenefit = + copyFactor * LiveIntervals::getSpillWeight(false, true, + loopInfo->getLoopDepth(mbb)); - PBQP::PBQPNum cBenefit = - std::pow(10.0f, (float)loopInfo->getLoopDepth(mbb)); - - if (cp.isPhys()) { - if (!lis->isAllocatable(dst)) - continue; + if (cp.isPhys()) { + if (!lis->isAllocatable(dst)) + continue; - const PBQPRAProblem::AllowedSet &allowed = p->getAllowedSet(src); - unsigned pregOpt = 0; - while (pregOpt < allowed.size() && allowed[pregOpt] != dst) - ++pregOpt; - if (pregOpt < allowed.size()) { - ++pregOpt; // +1 to account for spill option. - PBQP::Graph::NodeItr node = p->getNodeForVReg(src); - addPhysRegCoalesce(g.getNodeCosts(node), pregOpt, cBenefit); - } + const PBQPRAProblem::AllowedSet &allowed = p->getAllowedSet(src); + unsigned pregOpt = 0; + while (pregOpt < allowed.size() && allowed[pregOpt] != dst) + ++pregOpt; + if (pregOpt < allowed.size()) { + ++pregOpt; // +1 to account for spill option. + PBQP::Graph::NodeItr node = p->getNodeForVReg(src); + addPhysRegCoalesce(g.getNodeCosts(node), pregOpt, cBenefit); + } + } else { + const PBQPRAProblem::AllowedSet *allowed1 = &p->getAllowedSet(dst); + const PBQPRAProblem::AllowedSet *allowed2 = &p->getAllowedSet(src); + PBQP::Graph::NodeItr node1 = p->getNodeForVReg(dst); + PBQP::Graph::NodeItr node2 = p->getNodeForVReg(src); + PBQP::Graph::EdgeItr edge = g.findEdge(node1, node2); + if (edge == g.edgesEnd()) { + edge = g.addEdge(node1, node2, PBQP::Matrix(allowed1->size() + 1, + allowed2->size() + 1, + 0)); } else { - const PBQPRAProblem::AllowedSet *allowed1 = &p->getAllowedSet(dst); - const PBQPRAProblem::AllowedSet *allowed2 = &p->getAllowedSet(src); - PBQP::Graph::NodeItr node1 = p->getNodeForVReg(dst); - PBQP::Graph::NodeItr node2 = p->getNodeForVReg(src); - PBQP::Graph::EdgeItr edge = g.findEdge(node1, node2); - if (edge == g.edgesEnd()) { - edge = g.addEdge(node1, node2, PBQP::Matrix(allowed1->size() + 1, - allowed2->size() + 1, - 0)); - } else { - if (g.getEdgeNode1(edge) == node2) { - std::swap(node1, node2); - std::swap(allowed1, allowed2); - } + if (g.getEdgeNode1(edge) == node2) { + std::swap(node1, node2); + std::swap(allowed1, allowed2); } - - addVirtRegCoalesce(g.getEdgeCosts(edge), *allowed1, *allowed2, - cBenefit); } + + addVirtRegCoalesce(g.getEdgeCosts(edge), *allowed1, *allowed2, + cBenefit); } } } @@ -336,7 +464,6 @@ std::auto_ptr<PBQPRAProblem> PBQPBuilderWithCoalescing::build( return p; } - void PBQPBuilderWithCoalescing::addPhysRegCoalesce(PBQP::Vector &costVec, unsigned pregOption, PBQP::PBQPNum benefit) { @@ -707,7 +834,7 @@ void RegAllocPBQP::findVRegIntervalsToAlloc() { } } -PBQP::Graph RegAllocPBQP::constructPBQPProblem() { +PBQP::Graph RegAllocPBQP::constructPBQPProblemOld() { typedef std::vector<const LiveInterval*> LIVector; typedef std::vector<unsigned> RegVector; @@ -893,7 +1020,7 @@ void RegAllocPBQP::addStackInterval(const LiveInterval *spilled, stackInterval.MergeRangesInAsValue(rhsInterval, vni); } -bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQP::Solution &solution) { +bool RegAllocPBQP::mapPBQPToRegAllocOld(const PBQP::Solution &solution) { // Set to true if we have any spills bool anotherRoundNeeded = false; @@ -964,8 +1091,8 @@ bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQP::Solution &solution) { return !anotherRoundNeeded; } -bool RegAllocPBQP::mapPBQPToRegAlloc2(const PBQPRAProblem &problem, - const PBQP::Solution &solution) { +bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAProblem &problem, + const PBQP::Solution &solution) { // Set to true if we have any spills bool anotherRoundNeeded = false; @@ -1132,11 +1259,11 @@ bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) { while (!pbqpAllocComplete) { DEBUG(dbgs() << " PBQP Regalloc round " << round << ":\n"); - PBQP::Graph problem = constructPBQPProblem(); + PBQP::Graph problem = constructPBQPProblemOld(); PBQP::Solution solution = PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(problem); - pbqpAllocComplete = mapPBQPToRegAlloc(solution); + pbqpAllocComplete = mapPBQPToRegAllocOld(solution); ++round; } @@ -1150,7 +1277,7 @@ bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) { PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve( problem->getGraph()); - pbqpAllocComplete = mapPBQPToRegAlloc2(*problem, solution); + pbqpAllocComplete = mapPBQPToRegAlloc(*problem, solution); ++round; } @@ -1179,15 +1306,18 @@ bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) { return true; } -FunctionPass* createPBQPRegisterAllocator() { - if (pbqpCoalescing) { - return new RegAllocPBQP( - std::auto_ptr<PBQPBuilder>(new PBQPBuilderWithCoalescing())); - } // else - return new RegAllocPBQP( - std::auto_ptr<PBQPBuilder>(new PBQPBuilder())); +FunctionPass* llvm::createPBQPRegisterAllocator( + std::auto_ptr<PBQPBuilder> builder) { + return new RegAllocPBQP(builder); } +FunctionPass* llvm::createDefaultPBQPRegisterAllocator() { + if (pbqpCoalescing) { + return createPBQPRegisterAllocator( + std::auto_ptr<PBQPBuilder>(new PBQPBuilderWithCoalescing())); + } // else + return createPBQPRegisterAllocator( + std::auto_ptr<PBQPBuilder>(new PBQPBuilder())); } #undef DEBUG_TYPE |