diff options
author | Lang Hames <lhames@gmail.com> | 2010-10-04 12:13:07 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2010-10-04 12:13:07 +0000 |
commit | ab62b7e8618bda8063b49afab181bc7ed5546104 (patch) | |
tree | bf83214bd2e382e0e53d41d3879c6ca2947425ec | |
parent | 3af96330a554f9bd63089cb142469c5e96ba08e9 (diff) | |
download | external_llvm-ab62b7e8618bda8063b49afab181bc7ed5546104.zip external_llvm-ab62b7e8618bda8063b49afab181bc7ed5546104.tar.gz external_llvm-ab62b7e8618bda8063b49afab181bc7ed5546104.tar.bz2 |
Removed the older style (in-allocator) problem construction system from the PBQP allocator. Problem construction is now done exclusively with the new builders.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115502 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/RegAllocPBQP.cpp | 637 |
1 files changed, 9 insertions, 628 deletions
diff --git a/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp index a45ead8..6907321 100644 --- a/lib/CodeGen/RegAllocPBQP.cpp +++ b/lib/CodeGen/RegAllocPBQP.cpp @@ -68,12 +68,6 @@ pbqpCoalescing("pbqp-coalescing", cl::init(false), cl::Hidden); static cl::opt<bool> -pbqpBuilder("pbqp-builder", - cl::desc("Use new builder system."), - cl::init(true), cl::Hidden); - - -static cl::opt<bool> pbqpPreSplitting("pbqp-pre-splitting", cl::desc("Pre-split before PBQP register allocation."), cl::init(false), cl::Hidden); @@ -129,76 +123,17 @@ private: 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); @@ -510,306 +445,6 @@ void RegAllocPBQP::getAnalysisUsage(AnalysisUsage &au) const { MachineFunctionPass::getAnalysisUsage(au); } -template <typename RegContainer> -PBQP::Vector RegAllocPBQP::buildCostVector(unsigned vReg, - const RegContainer &allowed, - const CoalesceMap &coalesces, - PBQP::PBQPNum spillCost) const { - - typedef typename RegContainer::const_iterator AllowedItr; - - // Allocate vector. Additional element (0th) used for spill option - PBQP::Vector v(allowed.size() + 1, 0); - - v[0] = spillCost; - - // Iterate over the allowed registers inserting coalesce benefits if there - // are any. - unsigned ai = 0; - for (AllowedItr itr = allowed.begin(), end = allowed.end(); - itr != end; ++itr, ++ai) { - - unsigned pReg = *itr; - - CoalesceMap::const_iterator cmItr = - coalesces.find(RegPair(vReg, pReg)); - - // No coalesce - on to the next preg. - if (cmItr == coalesces.end()) - continue; - - // We have a coalesce - insert the benefit. - v[ai + 1] = -cmItr->second; - } - - return v; -} - -template <typename RegContainer> -PBQP::Matrix* RegAllocPBQP::buildInterferenceMatrix( - const RegContainer &allowed1, const RegContainer &allowed2) const { - - typedef typename RegContainer::const_iterator RegContainerIterator; - - // Construct a PBQP matrix representing the cost of allocation options. The - // rows and columns correspond to the allocation options for the two live - // intervals. Elements will be infinite where corresponding registers alias, - // since we cannot allocate aliasing registers to interfering live intervals. - // All other elements (non-aliasing combinations) will have zero cost. Note - // that the spill option (element 0,0) has zero cost, since we can allocate - // both intervals to memory safely (the cost for each individual allocation - // to memory is accounted for by the cost vectors for each live interval). - PBQP::Matrix *m = - new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0); - - // Assume this is a zero matrix until proven otherwise. Zero matrices occur - // between interfering live ranges with non-overlapping register sets (e.g. - // non-overlapping reg classes, or disjoint sets of allowed regs within the - // same class). The term "overlapping" is used advisedly: sets which do not - // intersect, but contain registers which alias, will have non-zero matrices. - // We optimize zero matrices away to improve solver speed. - bool isZeroMatrix = true; - - - // Row index. Starts at 1, since the 0th row is for the spill option, which - // is always zero. - unsigned ri = 1; - - // Iterate over allowed sets, insert infinities where required. - for (RegContainerIterator a1Itr = allowed1.begin(), a1End = allowed1.end(); - a1Itr != a1End; ++a1Itr) { - - // Column index, starts at 1 as for row index. - unsigned ci = 1; - unsigned reg1 = *a1Itr; - - for (RegContainerIterator a2Itr = allowed2.begin(), a2End = allowed2.end(); - a2Itr != a2End; ++a2Itr) { - - unsigned reg2 = *a2Itr; - - // If the row/column regs are identical or alias insert an infinity. - if (tri->regsOverlap(reg1, reg2)) { - (*m)[ri][ci] = std::numeric_limits<PBQP::PBQPNum>::infinity(); - isZeroMatrix = false; - } - - ++ci; - } - - ++ri; - } - - // If this turns out to be a zero matrix... - if (isZeroMatrix) { - // free it and return null. - delete m; - return 0; - } - - // ...otherwise return the cost matrix. - return m; -} - -template <typename RegContainer> -PBQP::Matrix* RegAllocPBQP::buildCoalescingMatrix( - const RegContainer &allowed1, const RegContainer &allowed2, - PBQP::PBQPNum cBenefit) const { - - typedef typename RegContainer::const_iterator RegContainerIterator; - - // Construct a PBQP Matrix representing the benefits of coalescing. As with - // interference matrices the rows and columns represent allowed registers - // for the LiveIntervals which are (potentially) to be coalesced. The amount - // -cBenefit will be placed in any element representing the same register - // for both intervals. - PBQP::Matrix *m = - new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0); - - // Reset costs to zero. - m->reset(0); - - // Assume the matrix is zero till proven otherwise. Zero matrices will be - // optimized away as in the interference case. - bool isZeroMatrix = true; - - // Row index. Starts at 1, since the 0th row is for the spill option, which - // is always zero. - unsigned ri = 1; - - // Iterate over the allowed sets, insert coalescing benefits where - // appropriate. - for (RegContainerIterator a1Itr = allowed1.begin(), a1End = allowed1.end(); - a1Itr != a1End; ++a1Itr) { - - // Column index, starts at 1 as for row index. - unsigned ci = 1; - unsigned reg1 = *a1Itr; - - for (RegContainerIterator a2Itr = allowed2.begin(), a2End = allowed2.end(); - a2Itr != a2End; ++a2Itr) { - - // If the row and column represent the same register insert a beneficial - // cost to preference this allocation - it would allow us to eliminate a - // move instruction. - if (reg1 == *a2Itr) { - (*m)[ri][ci] = -cBenefit; - isZeroMatrix = false; - } - - ++ci; - } - - ++ri; - } - - // If this turns out to be a zero matrix... - if (isZeroMatrix) { - // ...free it and return null. - delete m; - return 0; - } - - return m; -} - -RegAllocPBQP::CoalesceMap RegAllocPBQP::findCoalesces() { - - typedef MachineFunction::const_iterator MFIterator; - typedef MachineBasicBlock::const_iterator MBBIterator; - typedef LiveInterval::const_vni_iterator VNIIterator; - - CoalesceMap coalescesFound; - - // To find coalesces we need to iterate over the function looking for - // copy instructions. - for (MFIterator bbItr = mf->begin(), bbEnd = mf->end(); - bbItr != bbEnd; ++bbItr) { - - const MachineBasicBlock *mbb = &*bbItr; - - for (MBBIterator iItr = mbb->begin(), iEnd = mbb->end(); - iItr != iEnd; ++iItr) { - - const MachineInstr *instr = &*iItr; - - // If this isn't a copy then continue to the next instruction. - if (!instr->isCopy()) - continue; - - unsigned srcReg = instr->getOperand(1).getReg(); - unsigned dstReg = instr->getOperand(0).getReg(); - - // If the registers are already the same our job is nice and easy. - if (dstReg == srcReg) - continue; - - bool srcRegIsPhysical = TargetRegisterInfo::isPhysicalRegister(srcReg), - dstRegIsPhysical = TargetRegisterInfo::isPhysicalRegister(dstReg); - - // If both registers are physical then we can't coalesce. - if (srcRegIsPhysical && dstRegIsPhysical) - continue; - - // If it's a copy that includes two virtual register but the source and - // destination classes differ then we can't coalesce. - if (!srcRegIsPhysical && !dstRegIsPhysical && - mri->getRegClass(srcReg) != mri->getRegClass(dstReg)) - continue; - - // If one is physical and one is virtual, check that the physical is - // allocatable in the class of the virtual. - if (srcRegIsPhysical && !dstRegIsPhysical) { - const TargetRegisterClass *dstRegClass = mri->getRegClass(dstReg); - if (std::find(dstRegClass->allocation_order_begin(*mf), - dstRegClass->allocation_order_end(*mf), srcReg) == - dstRegClass->allocation_order_end(*mf)) - continue; - } - if (!srcRegIsPhysical && dstRegIsPhysical) { - const TargetRegisterClass *srcRegClass = mri->getRegClass(srcReg); - if (std::find(srcRegClass->allocation_order_begin(*mf), - srcRegClass->allocation_order_end(*mf), dstReg) == - srcRegClass->allocation_order_end(*mf)) - continue; - } - - // If we've made it here we have a copy with compatible register classes. - // We can probably coalesce, but we need to consider overlap. - const LiveInterval *srcLI = &lis->getInterval(srcReg), - *dstLI = &lis->getInterval(dstReg); - - if (srcLI->overlaps(*dstLI)) { - // Even in the case of an overlap we might still be able to coalesce, - // but we need to make sure that no definition of either range occurs - // while the other range is live. - - // Otherwise start by assuming we're ok. - bool badDef = false; - - // Test all defs of the source range. - for (VNIIterator - vniItr = srcLI->vni_begin(), vniEnd = srcLI->vni_end(); - vniItr != vniEnd; ++vniItr) { - - // If we find a poorly defined def we err on the side of caution. - if (!(*vniItr)->def.isValid()) { - badDef = true; - break; - } - - // If we find a def that kills the coalescing opportunity then - // record it and break from the loop. - if (dstLI->liveAt((*vniItr)->def)) { - badDef = true; - break; - } - } - - // If we have a bad def give up, continue to the next instruction. - if (badDef) - continue; - - // Otherwise test definitions of the destination range. - for (VNIIterator - vniItr = dstLI->vni_begin(), vniEnd = dstLI->vni_end(); - vniItr != vniEnd; ++vniItr) { - - // We want to make sure we skip the copy instruction itself. - if ((*vniItr)->getCopy() == instr) - continue; - - if (!(*vniItr)->def.isValid()) { - badDef = true; - break; - } - - if (srcLI->liveAt((*vniItr)->def)) { - badDef = true; - break; - } - } - - // As before a bad def we give up and continue to the next instr. - if (badDef) - continue; - } - - // If we make it to here then either the ranges didn't overlap, or they - // did, but none of their definitions would prevent us from coalescing. - // We're good to go with the coalesce. - - float cBenefit = std::pow(10.0f, (float)loopInfo->getLoopDepth(mbb)) / 5.0; - - coalescesFound[RegPair(srcReg, dstReg)] = cBenefit; - coalescesFound[RegPair(dstReg, srcReg)] = cBenefit; - } - - } - - return coalescesFound; -} - void RegAllocPBQP::findVRegIntervalsToAlloc() { // Iterate over all live ranges. @@ -834,171 +469,6 @@ void RegAllocPBQP::findVRegIntervalsToAlloc() { } } -PBQP::Graph RegAllocPBQP::constructPBQPProblemOld() { - - typedef std::vector<const LiveInterval*> LIVector; - typedef std::vector<unsigned> RegVector; - - // This will store the physical intervals for easy reference. - LIVector physIntervals; - - // Start by clearing the old node <-> live interval mappings & allowed sets - li2Node.clear(); - node2LI.clear(); - allowedSets.clear(); - - // Populate physIntervals, update preg use: - for (LiveIntervals::iterator itr = lis->begin(), end = lis->end(); - itr != end; ++itr) { - - if (TargetRegisterInfo::isPhysicalRegister(itr->first)) { - physIntervals.push_back(itr->second); - mri->setPhysRegUsed(itr->second->reg); - } - } - - // Iterate over vreg intervals, construct live interval <-> node number - // mappings. - for (RegSet::const_iterator itr = vregsToAlloc.begin(), - end = vregsToAlloc.end(); - itr != end; ++itr) { - const LiveInterval *li = &lis->getInterval(*itr); - - li2Node[li] = node2LI.size(); - node2LI.push_back(li); - } - - // Get the set of potential coalesces. - CoalesceMap coalesces; - - if (pbqpCoalescing) { - coalesces = findCoalesces(); - } - - // Construct a PBQP solver for this problem - PBQP::Graph problem; - problemNodes.resize(vregsToAlloc.size()); - - // Resize allowedSets container appropriately. - allowedSets.resize(vregsToAlloc.size()); - - BitVector ReservedRegs = tri->getReservedRegs(*mf); - - // Iterate over virtual register intervals to compute allowed sets... - for (unsigned node = 0; node < node2LI.size(); ++node) { - - // Grab pointers to the interval and its register class. - const LiveInterval *li = node2LI[node]; - const TargetRegisterClass *liRC = mri->getRegClass(li->reg); - - // Start by assuming all allocable registers in the class are allowed... - RegVector liAllowed; - TargetRegisterClass::iterator aob = liRC->allocation_order_begin(*mf); - TargetRegisterClass::iterator aoe = liRC->allocation_order_end(*mf); - for (TargetRegisterClass::iterator it = aob; it != aoe; ++it) - if (!ReservedRegs.test(*it)) - liAllowed.push_back(*it); - - // Eliminate the physical registers which overlap with this range, along - // with all their aliases. - for (LIVector::iterator pItr = physIntervals.begin(), - pEnd = physIntervals.end(); pItr != pEnd; ++pItr) { - - if (!li->overlaps(**pItr)) - continue; - - unsigned pReg = (*pItr)->reg; - - // If we get here then the live intervals overlap, but we're still ok - // if they're coalescable. - if (coalesces.find(RegPair(li->reg, pReg)) != coalesces.end()) { - DEBUG(dbgs() << "CoalescingOverride: (" << li->reg << ", " << pReg << ")\n"); - continue; - } - - // If we get here then we have a genuine exclusion. - - // Remove the overlapping reg... - RegVector::iterator eraseItr = - std::find(liAllowed.begin(), liAllowed.end(), pReg); - - if (eraseItr != liAllowed.end()) - liAllowed.erase(eraseItr); - - const unsigned *aliasItr = tri->getAliasSet(pReg); - - if (aliasItr != 0) { - // ...and its aliases. - for (; *aliasItr != 0; ++aliasItr) { - RegVector::iterator eraseItr = - std::find(liAllowed.begin(), liAllowed.end(), *aliasItr); - - if (eraseItr != liAllowed.end()) { - liAllowed.erase(eraseItr); - } - } - } - } - - // Copy the allowed set into a member vector for use when constructing cost - // vectors & matrices, and mapping PBQP solutions back to assignments. - allowedSets[node] = AllowedSet(liAllowed.begin(), liAllowed.end()); - - // Set the spill cost to the interval weight, or epsilon if the - // interval weight is zero - PBQP::PBQPNum spillCost = (li->weight != 0.0) ? - li->weight : std::numeric_limits<PBQP::PBQPNum>::min(); - - // Build a cost vector for this interval. - problemNodes[node] = - problem.addNode( - buildCostVector(li->reg, allowedSets[node], coalesces, spillCost)); - - } - - - // Now add the cost matrices... - for (unsigned node1 = 0; node1 < node2LI.size(); ++node1) { - const LiveInterval *li = node2LI[node1]; - - // Test for live range overlaps and insert interference matrices. - for (unsigned node2 = node1 + 1; node2 < node2LI.size(); ++node2) { - const LiveInterval *li2 = node2LI[node2]; - - CoalesceMap::const_iterator cmItr = - coalesces.find(RegPair(li->reg, li2->reg)); - - PBQP::Matrix *m = 0; - - if (cmItr != coalesces.end()) { - m = buildCoalescingMatrix(allowedSets[node1], allowedSets[node2], - cmItr->second); - } - else if (li->overlaps(*li2)) { - m = buildInterferenceMatrix(allowedSets[node1], allowedSets[node2]); - } - - if (m != 0) { - problem.addEdge(problemNodes[node1], - problemNodes[node2], - *m); - - delete m; - } - } - } - - assert(problem.getNumNodes() == allowedSets.size()); -/* - std::cerr << "Allocating for " << problem.getNumNodes() << " nodes, " - << problem.getNumEdges() << " edges.\n"; - - problem.printDot(std::cerr); -*/ - // We're done, PBQP problem constructed - return it. - return problem; -} - void RegAllocPBQP::addStackInterval(const LiveInterval *spilled, MachineRegisterInfo* mri) { int stackSlot = vrm->getStackSlot(spilled->reg); @@ -1020,77 +490,6 @@ void RegAllocPBQP::addStackInterval(const LiveInterval *spilled, stackInterval.MergeRangesInAsValue(rhsInterval, vni); } -bool RegAllocPBQP::mapPBQPToRegAllocOld(const PBQP::Solution &solution) { - - // Set to true if we have any spills - bool anotherRoundNeeded = false; - - // Clear the existing allocation. - vrm->clearAllVirt(); - - // Iterate over the nodes mapping the PBQP solution to a register assignment. - for (unsigned node = 0; node < node2LI.size(); ++node) { - unsigned virtReg = node2LI[node]->reg, - allocSelection = solution.getSelection(problemNodes[node]); - - - // If the PBQP solution is non-zero it's a physical register... - if (allocSelection != 0) { - // Get the physical reg, subtracting 1 to account for the spill option. - unsigned physReg = allowedSets[node][allocSelection - 1]; - - DEBUG(dbgs() << "VREG " << virtReg << " -> " - << tri->getName(physReg) << " (Option: " << allocSelection << ")\n"); - - assert(physReg != 0); - - // Add to the virt reg map and update the used phys regs. - vrm->assignVirt2Phys(virtReg, physReg); - } - // ...Otherwise it's a spill. - else { - - // Make sure we ignore this virtual reg on the next round - // of allocation - vregsToAlloc.erase(virtReg); - - // Insert spill ranges for this live range - const LiveInterval *spillInterval = node2LI[node]; - double oldSpillWeight = spillInterval->weight; - SmallVector<LiveInterval*, 8> spillIs; - rmf->rememberUseDefs(spillInterval); - std::vector<LiveInterval*> newSpills = - lis->addIntervalsForSpills(*spillInterval, spillIs, loopInfo, *vrm); - addStackInterval(spillInterval, mri); - rmf->rememberSpills(spillInterval, newSpills); - - (void) oldSpillWeight; - DEBUG(dbgs() << "VREG " << virtReg << " -> SPILLED (Option: 0, Cost: " - << oldSpillWeight << ", New vregs: "); - - // Copy any newly inserted live intervals into the list of regs to - // allocate. - for (std::vector<LiveInterval*>::const_iterator - itr = newSpills.begin(), end = newSpills.end(); - itr != end; ++itr) { - - assert(!(*itr)->empty() && "Empty spill range."); - - DEBUG(dbgs() << (*itr)->reg << " "); - - vregsToAlloc.insert((*itr)->reg); - } - - DEBUG(dbgs() << ")\n"); - - // We need another round if spill intervals were added. - anotherRoundNeeded |= !newSpills.empty(); - } - } - - return !anotherRoundNeeded; -} - bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAProblem &problem, const PBQP::Solution &solution) { // Set to true if we have any spills @@ -1255,32 +654,18 @@ bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) { bool pbqpAllocComplete = false; unsigned round = 0; - if (!pbqpBuilder) { - while (!pbqpAllocComplete) { - DEBUG(dbgs() << " PBQP Regalloc round " << round << ":\n"); + while (!pbqpAllocComplete) { + DEBUG(dbgs() << " PBQP Regalloc round " << round << ":\n"); - PBQP::Graph problem = constructPBQPProblemOld(); - PBQP::Solution solution = - PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(problem); + std::auto_ptr<PBQPRAProblem> problem = + builder->build(mf, lis, loopInfo, vregsToAlloc); + PBQP::Solution solution = + PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve( + problem->getGraph()); - pbqpAllocComplete = mapPBQPToRegAllocOld(solution); + pbqpAllocComplete = mapPBQPToRegAlloc(*problem, solution); - ++round; - } - } else { - while (!pbqpAllocComplete) { - DEBUG(dbgs() << " PBQP Regalloc round " << round << ":\n"); - - std::auto_ptr<PBQPRAProblem> problem = - builder->build(mf, lis, loopInfo, vregsToAlloc); - PBQP::Solution solution = - PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve( - problem->getGraph()); - - pbqpAllocComplete = mapPBQPToRegAlloc(*problem, solution); - - ++round; - } + ++round; } } @@ -1291,10 +676,6 @@ bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) { vregsToAlloc.clear(); emptyIntervalVRegs.clear(); - li2Node.clear(); - node2LI.clear(); - allowedSets.clear(); - problemNodes.clear(); DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *vrm << "\n"); |