X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=lib%2FTarget%2FSparcV9%2FSparcV9RegClassInfo.cpp;h=fdd53bc18439320bd281a0a1dfc02a34e4070944;hb=db7c40db100926e78b4af89760c86b41179b9839;hp=1640dcab6c68d3c405e136dc6d388093878ad81a;hpb=786833ad3498036db72776f9b708ff08a6f8e29a;p=oota-llvm.git diff --git a/lib/Target/SparcV9/SparcV9RegClassInfo.cpp b/lib/Target/SparcV9/SparcV9RegClassInfo.cpp index 1640dcab6c6..fdd53bc1843 100644 --- a/lib/Target/SparcV9/SparcV9RegClassInfo.cpp +++ b/lib/Target/SparcV9/SparcV9RegClassInfo.cpp @@ -1,12 +1,27 @@ -//===-- SparcRegClassInfo.cpp - Register class def'ns for Sparc -----------===// +//===-- SparcV9RegClassInfo.cpp - Register class def'ns for SparcV9 -------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// // -// This file defines the register classes used by the Sparc target description. +// This file defines the methods used by the SparcV9 register allocator +// to pick registers of various classes. Most of this code should be +// considered part of the register allocator. // //===----------------------------------------------------------------------===// -#include "SparcRegClassInfo.h" #include "llvm/Type.h" -#include "../../CodeGen/RegAlloc/RegAllocCommon.h" // FIXME! +#include "SparcV9RegClassInfo.h" +#include "SparcV9Internals.h" +#include "SparcV9RegInfo.h" +#include "RegAlloc/RegAllocCommon.h" +#include "RegAlloc/IGNode.h" +#include + +namespace llvm { //----------------------------------------------------------------------------- // Int Register Class - method for coloring a node in the interference graph. @@ -21,15 +36,14 @@ // If both above fail, spill. // //----------------------------------------------------------------------------- -void SparcIntRegClass::colorIGNode(IGNode * Node, - std::vector &IsColorUsedArr) const +void SparcV9IntRegClass::colorIGNode(IGNode * Node, + const std::vector &IsColorUsedArr) const { LiveRange *LR = Node->getParentLR(); - if (DEBUG_RA) { - std::cerr << "\nColoring LR [CallInt=" << LR->isCallInterference() <<"]:"; - printSet(*LR); - } + if (DEBUG_RA) + std::cerr << "\nColoring LR [CallInt=" << LR->isCallInterference() <<"]:" + << *LR << "\n"; if (LR->hasSuggestedColor()) { unsigned SugCol = LR->getSuggestedColor(); @@ -46,8 +60,8 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, std::cerr << "\n Couldn't alloc Sug col - LR volatile & calls interf"; } } else if (DEBUG_RA) { // can't allocate the suggested col - std::cerr << "\n Could NOT allocate the suggested color (already used) "; - printSet(*LR); std::cerr << "\n"; + std::cerr << "\n Could NOT allocate the suggested color (already used) " + << *LR << "\n"; } } @@ -57,16 +71,16 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, //if this Node is between calls if (! LR->isCallInterference()) { // start with volatiles (we can allocate volatiles safely) - SearchStart = SparcIntRegClass::StartOfAllRegs; + SearchStart = SparcV9IntRegClass::StartOfAllRegs; } else { // start with non volatiles (no non-volatiles) - SearchStart = SparcIntRegClass::StartOfNonVolatileRegs; + SearchStart = SparcV9IntRegClass::StartOfNonVolatileRegs; } unsigned c=0; // color // find first unused color - for (c=SearchStart; c < SparcIntRegClass::NumOfAvailRegs; c++) { + for (c=SearchStart; c < SparcV9IntRegClass::NumOfAvailRegs; c++) { if (!IsColorUsedArr[c]) { ColorFound = true; break; @@ -74,7 +88,7 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, } if (ColorFound) { - LR->setColor(c); // first color found in preffered order + LR->setColor(c); // first color found in preferred order if (DEBUG_RA) std::cerr << "\n Colored after first search with col " << c; } @@ -83,10 +97,10 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, // else if (LR->isCallInterference()) { // start from 0 - try to find even a volatile this time - SearchStart = SparcIntRegClass::StartOfAllRegs; + SearchStart = SparcV9IntRegClass::StartOfAllRegs; // find first unused volatile color - for(c=SearchStart; c < SparcIntRegClass::StartOfNonVolatileRegs; c++) { + for(c=SearchStart; c < SparcV9IntRegClass::StartOfNonVolatileRegs; c++) { if (! IsColorUsedArr[c]) { ColorFound = true; break; @@ -98,7 +112,6 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, // get the live range corresponding to live var // since LR span across calls, must save across calls // - LR->markForSaveAcrossCalls(); if (DEBUG_RA) std::cerr << "\n Colored after SECOND search with col " << c; } @@ -117,7 +130,8 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, // // Algorithm: // -// If the single int CC register is used (either as icc or xcc) +// If (node has any interferences) +// /* all interference operations can use only one register! */ // mark the LR for spilling // else { // if (the LR is a 64-bit comparison) use %xcc @@ -127,33 +141,52 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, // Note: The third name (%ccr) is essentially an assembly mnemonic and // depends solely on the opcode, so the name can be chosen in EmitAssembly. //----------------------------------------------------------------------------- -void SparcIntCCRegClass::colorIGNode(IGNode *Node, - std::vector &IsColorUsedArr) const +void SparcV9IntCCRegClass::colorIGNode(IGNode *Node, + const std::vector &IsColorUsedArr) const { - if (IsColorUsedArr[xcc] && IsColorUsedArr[icc]) + if (Node->getNumOfNeighbors() > 0) Node->getParentLR()->markForSpill(); - else { - // Choose whether to use %xcc or %icc based on type of value compared - const LiveRange* ccLR = Node->getParentLR(); - const Type* setCCType = (* ccLR->begin())->getType(); // any Value in LR - assert(setCCType->isIntegral()); - int ccReg = (setCCType == Type::LongTy)? xcc : icc; + + // Mark the appropriate register in any case (even if it needs to be spilled) + // because there is only one possible register, but more importantly, the + // spill algorithm cannot find it. In particular, we have to choose + // whether to use %xcc or %icc based on type of value compared + // + const LiveRange* ccLR = Node->getParentLR(); + const Type* setCCType = (* ccLR->begin())->getType(); // any Value in LR + assert(setCCType->isIntegral() || isa(setCCType)); + int ccReg = ((isa(setCCType) || setCCType == Type::LongTy) + ? xcc : icc); #ifndef NDEBUG - // Let's just make sure values of two different types have not been - // coalesced into this LR. - for (ValueSet::const_iterator I=ccLR->begin(), E=ccLR->end(); I != E; ++I) - assert(setCCType->isIntegral() && - ((ccReg == xcc && (*I)->getType() == Type::LongTy) || - (ccReg == icc && (*I)->getType() != Type::LongTy)) - && "Comparisons needing different intCC regs coalesced in LR!"); + // Let's just make sure values of two different types have not been + // coalesced into this LR. + for (LiveRange::const_iterator I=ccLR->begin(), E=ccLR->end(); I!=E; ++I) { + const Type* ccType = (*I)->getType(); + assert((ccReg == xcc && (isa(ccType) + || ccType == Type::LongTy)) || + (ccReg == icc && ccType->isIntegral() && ccType != Type::LongTy) + && "Comparisons needing different intCC regs coalesced in LR!"); + } #endif - Node->setColor(ccReg); // only one int cc reg is available - } + Node->setColor(ccReg); // only one int cc reg is available } +void SparcV9FloatCCRegClass::colorIGNode(IGNode *Node, + const std::vector &IsColorUsedArr) const { + for(unsigned c = 0; c != 4; ++c) + if (!IsColorUsedArr[c]) { // find unused color + Node->setColor(c); + return; + } + + Node->getParentLR()->markForSpill(); +} + + + //----------------------------------------------------------------------------- // Float Register Class - method for coloring a node in the interference graph. // @@ -169,46 +202,56 @@ void SparcIntCCRegClass::colorIGNode(IGNode *Node, // If a color is still not fond, mark for spilling // //---------------------------------------------------------------------------- -void SparcFloatRegClass::colorIGNode(IGNode * Node, - std::vector &IsColorUsedArr) const +void SparcV9FloatRegClass::colorIGNode(IGNode * Node, + const std::vector &IsColorUsedArr) const { LiveRange *LR = Node->getParentLR(); - // Mark the second color for double-precision registers: - // This is UGLY and should be merged into nearly identical code - // in RegClass::colorIGNode that handles the first color. +#ifndef NDEBUG + // Check that the correct colors have been are marked for fp-doubles. + // + // FIXME: This is old code that is no longer needed. Temporarily converting + // it into a big assertion just to check that the replacement logic + // (invoking SparcV9FloatRegClass::markColorsUsed() directly from + // RegClass::colorIGNode) works correctly. + // + // In fact, this entire function should be identical to + // SparcV9IntRegClass::colorIGNode(), and perhaps can be + // made into a general case in CodeGen/RegAlloc/RegClass.cpp. // unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh IGNode *NeighIGNode = Node->getAdjIGNode(n); LiveRange *NeighLR = NeighIGNode->getParentLR(); - if (NeighLR->hasColor() && - NeighLR->getType() == Type::DoubleTy) { - IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true; + if (NeighLR->hasColor()) { + assert(IsColorUsedArr[ NeighLR->getColor() ]); + if (NeighLR->getType() == Type::DoubleTy) + assert(IsColorUsedArr[ NeighLR->getColor()+1 ]); } else if (NeighLR->hasSuggestedColor() && NeighLR-> isSuggestedColorUsable() ) { // if the neighbour can use the suggested color - IsColorUsedArr[ NeighLR->getSuggestedColor() ] = true; + assert(IsColorUsedArr[ NeighLR->getSuggestedColor() ]); if (NeighLR->getType() == Type::DoubleTy) - IsColorUsedArr[ (NeighLR->getSuggestedColor()) + 1 ] = true; + assert(IsColorUsedArr[ NeighLR->getSuggestedColor()+1 ]); } } +#endif // **NOTE: We don't check for call interferences in allocating suggested // color in this class since ALL registers are volatile. If this fact // changes, we should change the following part - //- see SparcIntRegClass::colorIGNode() + //- see SparcV9IntRegClass::colorIGNode() // if( LR->hasSuggestedColor() ) { if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) { LR->setColor( LR->getSuggestedColor() ); return; } else if (DEBUG_RA) { // can't allocate the suggested col - std::cerr << " Could NOT allocate the suggested color for LR "; - printSet(*LR); std::cerr << "\n"; + std::cerr << " Could NOT allocate the suggested color for LR " << *LR + << "\n"; } } @@ -229,7 +272,7 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node, return; } else { - // if we didn't find a color becuase the LR was single precision or + // if we didn't find a color because the LR was single precision or // all f32-f63 range is filled, we try to allocate a register from // the f0 - f31 region @@ -238,10 +281,10 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node, //if this Node is between calls (i.e., no call interferences ) if (! isCallInterf) { // start with volatiles (we can allocate volatiles safely) - SearchStart = SparcFloatRegClass::StartOfAllRegs; + SearchStart = SparcV9FloatRegClass::StartOfAllRegs; } else { // start with non volatiles (no non-volatiles) - SearchStart = SparcFloatRegClass::StartOfNonVolatileRegs; + SearchStart = SparcV9FloatRegClass::StartOfNonVolatileRegs; } ColorFound = findFloatColor(LR, SearchStart, 32, IsColorUsedArr); @@ -254,20 +297,71 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node, // We are here because there is a call interference and no non-volatile // color could be found. // Now try to allocate even a volatile color - ColorFound = findFloatColor(LR, SparcFloatRegClass::StartOfAllRegs, - SparcFloatRegClass::StartOfNonVolatileRegs, + ColorFound = findFloatColor(LR, SparcV9FloatRegClass::StartOfAllRegs, + SparcV9FloatRegClass::StartOfNonVolatileRegs, IsColorUsedArr); } if (ColorFound >= 0) { - LR->setColor(ColorFound); // first color found in prefered order - LR->markForSaveAcrossCalls(); + LR->setColor(ColorFound); // first color found in preferred order } else { // we are here because no color could be found LR->markForSpill(); // no color found - must spill } } +//----------------------------------------------------------------------------- +// This method marks the registers used for a given register number. +// This marks a single register for Float regs, but the R,R+1 pair +// for double-precision registers. +//----------------------------------------------------------------------------- + +void SparcV9FloatRegClass::markColorsUsed(unsigned RegInClass, + int UserRegType, + int RegTypeWanted, + std::vector &IsColorUsedArr) const +{ + if (UserRegType == SparcV9RegInfo::FPDoubleRegType || + RegTypeWanted == SparcV9RegInfo::FPDoubleRegType) { + // This register is used as or is needed as a double-precision reg. + // We need to mark the [even,odd] pair corresponding to this reg. + // Get the even numbered register corresponding to this reg. + unsigned EvenRegInClass = RegInClass & ~1u; + assert(EvenRegInClass+1 < NumOfAllRegs && + EvenRegInClass+1 < IsColorUsedArr.size()); + IsColorUsedArr[EvenRegInClass] = true; + IsColorUsedArr[EvenRegInClass+1] = true; + } + else { + assert(RegInClass < NumOfAllRegs && RegInClass < IsColorUsedArr.size()); + assert(UserRegType == RegTypeWanted + && "Something other than FP single/double types share a reg class?"); + IsColorUsedArr[RegInClass] = true; + } +} + +// This method finds unused registers of the specified register type, +// using the given "used" flag array IsColorUsedArr. It checks a single +// entry in the array directly for float regs, and checks the pair [R,R+1] +// for double-precision registers +// It returns -1 if no unused color is found. +// +int SparcV9FloatRegClass::findUnusedColor(int RegTypeWanted, + const std::vector &IsColorUsedArr) const +{ + if (RegTypeWanted == SparcV9RegInfo::FPDoubleRegType) { + unsigned NC = 2 * this->getNumOfAvailRegs(); + assert(IsColorUsedArr.size() == NC && "Invalid colors-used array"); + for (unsigned c = 0; c < NC; c+=2) + if (!IsColorUsedArr[c]) { + assert(!IsColorUsedArr[c+1] && "Incorrect used regs for FP double!"); + return c; + } + return -1; + } + else + return TargetRegClassInfo::findUnusedColor(RegTypeWanted, IsColorUsedArr); +} //----------------------------------------------------------------------------- // Helper method for coloring a node of Float Reg class. @@ -275,25 +369,29 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node, // type of the Node (i.e., float/double) //----------------------------------------------------------------------------- -int SparcFloatRegClass::findFloatColor(const LiveRange *LR, +int SparcV9FloatRegClass::findFloatColor(const LiveRange *LR, unsigned Start, unsigned End, - std::vector &IsColorUsedArr) const + const std::vector &IsColorUsedArr) const { - bool ColorFound = false; - unsigned c; - if (LR->getType() == Type::DoubleTy) { // find first unused color for a double - for (c=Start; c < End ; c+= 2) - if (!IsColorUsedArr[c] && !IsColorUsedArr[c+1]) + assert(Start % 2 == 0 && "Odd register number could be used for double!"); + for (unsigned c=Start; c < End ; c+= 2) + if (!IsColorUsedArr[c]) { + assert(!IsColorUsedArr[c+1] && + "Incorrect marking of used regs for SparcV9 FP double!"); return c; + } } else { // find first unused color for a single - for (c = Start; c < End; c++) + for (unsigned c = Start; c < End; c++) if (!IsColorUsedArr[c]) return c; } - + return -1; + } + +} // End llvm namespace