diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/SparcV9/Makefile | 1 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9Internals.h | 58 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegClassInfo.cpp | 238 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegClassInfo.h | 240 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegInfo.cpp | 540 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9TargetMachine.cpp | 324 |
6 files changed, 920 insertions, 481 deletions
diff --git a/lib/Target/SparcV9/Makefile b/lib/Target/SparcV9/Makefile index a2b8c2abd7..aa1f0dc4a2 100644 --- a/lib/Target/SparcV9/Makefile +++ b/lib/Target/SparcV9/Makefile @@ -6,6 +6,7 @@ Source = \ Sparc.o \ Sparc.burm.o \ SparcInstrSelection.o \ + SparcRegClassInfo.o \ SparcRegInfo.o include $(LEVEL)/Makefile.common diff --git a/lib/Target/SparcV9/SparcV9Internals.h b/lib/Target/SparcV9/SparcV9Internals.h index c63c7c5f6b..1980c2e803 100644 --- a/lib/Target/SparcV9/SparcV9Internals.h +++ b/lib/Target/SparcV9/SparcV9Internals.h @@ -8,7 +8,11 @@ #ifndef SPARC_INTERNALS_H #define SPARC_INTERNALS_H -#include "SparcRegInfo.h" + +#include "SparcRegClassInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/MachineInstrInfo.h" + #include "llvm/Target/MachineSchedInfo.h" #include "llvm/Type.h" @@ -855,17 +859,12 @@ public: }; -//--------------------------------------------------------------------------- -// class UltraSparcRegInfo -// -// Purpose: -// This class provides info about sparc register classes. -//--------------------------------------------------------------------------- class LiveRange; class UltraSparc; + class UltraSparcRegInfo : public MachineRegInfo { @@ -893,27 +892,32 @@ class UltraSparcRegInfo : public MachineRegInfo // %f0 - %f5 are used (can hold 6 floats or 3 doubles) unsigned const NumOfFloatArgRegs; - void setCallArgColor(LiveRange *const LR, const unsigned RegNo) const; + //void setCallArgColor(LiveRange *const LR, const unsigned RegNo) const; + + void setCallOrRetArgCol(LiveRange *const LR, const unsigned RegNo, + const MachineInstr *MI,AddedInstrMapType &AIMap)const; + + MachineInstr * getCopy2RegMI(const Value *SrcVal, const unsigned Reg, + unsigned RegClassID) const ; + public: - UltraSparcRegInfo(const UltraSparc *const USI ) - : MachineRegInfo(), - UltraSparcInfo(USI), - NumOfIntArgRegs(6), - NumOfFloatArgRegs(6) + UltraSparcRegInfo(const UltraSparc *const USI ) : UltraSparcInfo(USI), + NumOfIntArgRegs(6), + NumOfFloatArgRegs(6) { MachineRegClassArr.push_back( new SparcIntRegClass(IntRegClassID) ); MachineRegClassArr.push_back( new SparcFloatRegClass(FloatRegClassID) ); MachineRegClassArr.push_back( new SparcIntCCRegClass(IntCCRegClassID) ); MachineRegClassArr.push_back( new SparcFloatCCRegClass(FloatCCRegClassID)); - + assert( SparcFloatRegOrder::StartOfNonVolatileRegs == 6 && "6 Float regs are used for float arg passing"); } - + // ***** TODO Delete ~UltraSparcRegInfo(void) { } // empty destructor @@ -922,11 +926,7 @@ class UltraSparcRegInfo : public MachineRegInfo return *UltraSparcInfo; } - // returns the register that is hardwired to zero - virtual inline int getZeroRegNum() const { - return (int) SparcIntRegOrder::g0; - } - + inline unsigned getRegClassIDOfValue (const Value *const Val, bool isCCReg = false) const { @@ -953,6 +953,18 @@ class UltraSparcRegInfo : public MachineRegInfo } + // returns the register tha contains always zero + inline int getZeroRegNum() const { return SparcIntRegOrder::g0; } + + // returns the reg used for pushing the address when a method is called. + // This can be used for other purposes between calls + unsigned getCallAddressReg() const { return SparcIntRegOrder::o7; } + + + // and when we return from a method. It should be made sure that this + // register contains the return value when a return instruction is reached. + unsigned getReturnAddressReg() const { return SparcIntRegOrder::i7; } + void colorArgs(const Method *const Meth, LiveRangeInfo& LRI) const; static void printReg(const LiveRange *const LR) ; @@ -961,6 +973,11 @@ class UltraSparcRegInfo : public MachineRegInfo LiveRangeInfo& LRI, AddedInstrMapType& AddedInstrMap ) const; + void colorRetArg(vector<const Instruction *> & + RetInstrList, LiveRangeInfo& LRI, + AddedInstrMapType &AddedInstrMap) const; + + // this method provides a unique number for each register inline int getUnifiedRegNum(int RegClassID, int reg) const { @@ -997,7 +1014,6 @@ class UltraSparcRegInfo : public MachineRegInfo - /*--------------------------------------------------------------------------- Scheduling guidelines for SPARC IIi: diff --git a/lib/Target/SparcV9/SparcV9RegClassInfo.cpp b/lib/Target/SparcV9/SparcV9RegClassInfo.cpp new file mode 100644 index 0000000000..a6d7f9e060 --- /dev/null +++ b/lib/Target/SparcV9/SparcV9RegClassInfo.cpp @@ -0,0 +1,238 @@ +#include "llvm/CodeGen/IGNode.h" +#include "SparcInternals.h" + +#include "llvm/Target/Sparc.h" + +//----------------------------------------------------------------------------- +// Int Register Class +//----------------------------------------------------------------------------- + +void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const +{ + + /* Algorithm: + Record the color of all neighbors. + + If there is no call interf, try to allocate volatile, then non volatile + If there is call interf, try to allocate non-volatile. If that fails + try to allocate a volatile and insert save across calls + If both above fail, spill. + + */ + + unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors + + for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh + IGNode *NeighIGNode = Node->getAdjIGNode(n); + if( NeighIGNode->hasColor() ) { // if neigh has a color + IsColorUsedArr[ NeighIGNode->getColor() ] = true; // record that color + } + } + + + + unsigned SearchStart; // start pos of color in pref-order + bool ColorFound= false; // have we found a color yet? + + //if this Node is between calls + if( Node->getNumOfCallInterferences() == 0) { + + // start with volatiles (we can allocate volatiles safely) + SearchStart = SparcIntRegOrder::StartOfAllRegs; + } + else { + // start with non volatiles (no non-volatiles) + SearchStart = SparcIntRegOrder::StartOfNonVolatileRegs; + } + + unsigned c=0; // color + + // find first unused color + for( c=SearchStart; c < SparcIntRegOrder::NumOfAvailRegs; c++) { + if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; } + } + + if( ColorFound) + Node->setColor(c); // first color found in preffered order + + // if color is not found because of call interference + // try even finding a volatile color and insert save across calls + else if( Node->getNumOfCallInterferences() ) + { + // start from 0 - try to find even a volatile this time + SearchStart = SparcIntRegOrder::StartOfAllRegs; + + // find first unused volatile color + for(c=SearchStart; c < SparcIntRegOrder::StartOfNonVolatileRegs; c++) { + if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; } + } + + if( ColorFound) { + Node->setColor(c); + // since LR span across calls, must save across calls + Node->markForSaveAcrossCalls(); + } + + } + + // If we couldn't find a color regardless of call interference - i.e., we + // don't have either a volatile or non-volatile color left + if( !ColorFound ) + Node->markForSpill(); // no color found - must spill + + + if( DEBUG_RA) + UltraSparcRegInfo::printReg( Node->getParentLR() ); + +} + + + + + + +//----------------------------------------------------------------------------- +// Float Register Class +//----------------------------------------------------------------------------- + +// find the first available color in the range [Start,End] depending on the +// type of the Node (i.e., float/double) + +int SparcFloatRegClass::findFloatColor(const IGNode *const Node, unsigned Start, + unsigned End, + bool IsColorUsedArr[] ) const +{ + + bool ColorFound = false; + unsigned c; + + if( Node->getTypeID() == Type::DoubleTyID ) { + + // find first unused color for a double + for( c=Start; c < End ;c+= 2){ + if( ! IsColorUsedArr[ c ] && ! IsColorUsedArr[ c+1 ]) + { ColorFound=true; break; } + } + + } else { + + // find first unused color for a single + for( c=Start; c < End; c++) { + if( ! IsColorUsedArr[ c ] ) { ColorFound=true; break; } + } + } + + if( ColorFound ) return c; + else return -1; +} + + + + + +void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const +{ + + /* Algorithm: + + If the LR is a double try to allocate f32 - f63 + If the above fails or LR is single precision + If the LR does not interfere with a call + start allocating from f0 + Else start allocating from f6 + If a color is still not found because LR interferes with a call + Search in f0 - f6. If found mark for spill across calls. + If a color is still not fond, mark for spilling + */ + + + unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors + + for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh + IGNode *NeighIGNode = Node->getAdjIGNode(n); + if( NeighIGNode->hasColor() ) { // if neigh has a color + IsColorUsedArr[ NeighIGNode->getColor() ] = true; // record that color + if( NeighIGNode->getTypeID() == Type::DoubleTyID ) + IsColorUsedArr[ (NeighIGNode->getColor()) + 1 ] = true; + } + } + + int ColorFound = -1; // have we found a color yet? + unsigned NumOfCallInterf = Node->getNumOfCallInterferences(); + + // if value is a double - search the double only reigon (f32 - f63) + if( Node->getTypeID() == Type::DoubleTyID ) + ColorFound = findFloatColor( Node, 32, 64, IsColorUsedArr ); + + + if( ColorFound >= 0 ) { + Node->setColor(ColorFound); + if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() ); + return; + } + + else { // the above fails or LR is single precision + + unsigned SearchStart; // start pos of color in pref-order + + //if this Node is between calls (i.e., no call interferences ) + if( ! NumOfCallInterf ) { + // start with volatiles (we can allocate volatiles safely) + SearchStart = SparcFloatRegOrder::StartOfAllRegs; + } + else { + // start with non volatiles (no non-volatiles) + SearchStart = SparcFloatRegOrder::StartOfNonVolatileRegs; + } + + ColorFound = findFloatColor( Node, SearchStart, 32, IsColorUsedArr ); + + } + + if( ColorFound >= 0 ) { + Node->setColor(ColorFound); + if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() ); + return; + } + + else if( NumOfCallInterf ) { + + // 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( Node, SparcFloatRegOrder::StartOfAllRegs, + SparcFloatRegOrder::StartOfNonVolatileRegs, + IsColorUsedArr); + } + + if( ColorFound >= 0 ) { + Node->setColor(ColorFound); // first color found in preffered order + Node->markForSaveAcrossCalls(); + if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() ); + return; + } + + else { + Node->markForSpill(); // no color found - must spill + if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() ); + } + + +} + + + + + + + + + + + + + + + + diff --git a/lib/Target/SparcV9/SparcV9RegClassInfo.h b/lib/Target/SparcV9/SparcV9RegClassInfo.h new file mode 100644 index 0000000000..4a00cb560c --- /dev/null +++ b/lib/Target/SparcV9/SparcV9RegClassInfo.h @@ -0,0 +1,240 @@ +/* Title: SparcRegClassInfo.h -*- C++ -*- + Author: Ruchira Sasanka + Date: Aug 20, 01 + Purpose: Contains the description of integer register class of Sparc +*/ + + +#ifndef SPARC_REG_INFO_CLASS_H +#define SPARC_REG_INFO_CLASS_H + +#include "llvm/Target/MachineRegInfo.h" +#include "llvm/CodeGen/IGNode.h" + +//----------------------------------------------------------------------------- +// Integer Register Class +//----------------------------------------------------------------------------- + + +// Int register names in same order as enum in class SparcIntRegOrder + +static string const IntRegNames[] = + { "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o0", "o1", "o2", "o3", "o4", "o5", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", + "g0", "i6", "i7", "o6" }; + + + +class SparcIntRegOrder{ + + public: + + enum RegsInPrefOrder // colors possible for a LR (in preferred order) + { + // --- following colors are volatile across function calls + // %g0 can't be used for coloring - always 0 + + g1, g2, g3, g4, g5, g6, g7, //%g1-%g7 + o0, o1, o2, o3, o4, o5, o7, // %o0-%o5, + + // %o6 is sp, + // all %0's can get modified by a call + + // --- following colors are NON-volatile across function calls + + l0, l1, l2, l3, l4, l5, l6, l7, // %l0-%l7 + i0, i1, i2, i3, i4, i5, // %i0-%i5: i's need not be preserved + + // %i6 is the fp - so not allocated + // %i7 is the ret address - can be used if saved + + // max # of colors reg coloring can allocate (NumOfAvailRegs) + + // --- following colors are not available for allocation within this phase + // --- but can appear for pre-colored ranges + + g0, i6, i7, o6 + + + + }; + + // max # of colors reg coloring can allocate + static unsigned int const NumOfAvailRegs = g0; + + static unsigned int const StartOfNonVolatileRegs = l0; + static unsigned int const StartOfAllRegs = g1; + static unsigned int const NumOfAllRegs = o6 + 1; + + + static const string getRegName(const unsigned reg) { + assert( reg < NumOfAllRegs ); + return IntRegNames[reg]; + } + +}; + + + +class SparcIntRegClass : public MachineRegClassInfo +{ + public: + + SparcIntRegClass(unsigned ID) + : MachineRegClassInfo(ID, + SparcIntRegOrder::NumOfAvailRegs, + SparcIntRegOrder::NumOfAllRegs) + { } + + void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const; + +}; + +//----------------------------------------------------------------------------- +// Float Register Class +//----------------------------------------------------------------------------- + +static string const FloatRegNames[] = + { + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", + "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", + "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", + "f30", "f31", "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39", + "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", "f48", "f49", + "f50", "f51", "f52", "f53", "f54", "f55", "f56", "f57", "f58", "f59", + "f60", "f61", "f62", "f63" + }; + + +class SparcFloatRegOrder{ + + public: + + enum RegsInPrefOrder { + + f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, + f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, + f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, + f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, + f40, f41, f42, f43, f44, f45, f46, f47, f48, f49, + f50, f51, f52, f53, f54, f55, f56, f57, f58, f59, + f60, f61, f62, f63 + + }; + + // there are 64 regs alltogether but only 32 regs can be allocated at + // a time. + + static unsigned int const NumOfAvailRegs = 32; + static unsigned int const NumOfAllRegs = 64; + + static unsigned int const StartOfNonVolatileRegs = f6; + static unsigned int const StartOfAllRegs = f0; + + + static const string getRegName(const unsigned reg) { + assert( reg < NumOfAllRegs ); + return FloatRegNames[reg]; + } + + + +}; + + + +class SparcFloatRegClass : public MachineRegClassInfo +{ + private: + + int findFloatColor(const IGNode *const Node, unsigned Start, + unsigned End, bool IsColorUsedArr[] ) const; + + public: + + SparcFloatRegClass(unsigned ID) + : MachineRegClassInfo(ID, + SparcFloatRegOrder::NumOfAvailRegs, + SparcFloatRegOrder::NumOfAllRegs) + { } + + void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const; + +}; + + + + +//----------------------------------------------------------------------------- +// Int CC Register Class +// Only one integer cc register is available +//----------------------------------------------------------------------------- + + +class SparcIntCCRegClass : public MachineRegClassInfo +{ +public: + + SparcIntCCRegClass(unsigned ID) + : MachineRegClassInfo(ID,1, 1) { } + + inline void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const { + Node->setColor(0); // only one int cc reg is available + } + +}; + + + +//----------------------------------------------------------------------------- +// Float CC Register Class +// Only 4 Float CC registers are available +//----------------------------------------------------------------------------- + + +static string const FloatCCRegNames[] = + { + "fcc0", "fcc1", "fcc2", "fcc3" + }; + + +class SparcFloatCCRegOrder{ + + public: + + enum RegsInPrefOrder { + + fcc0, fcc1, fcc2, fcc3 + }; + + static const string getRegName(const unsigned reg) { + assert( reg < 4 ); + return FloatCCRegNames[reg]; + } + +}; + + + +class SparcFloatCCRegClass : public MachineRegClassInfo +{ +public: + + SparcFloatCCRegClass(unsigned ID) + : MachineRegClassInfo(ID, 4, 4) { } + + void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const { + int c; + for(c=0; c < 4 && IsColorUsedArr[c] ; ++c) ; // find color + assert( (c < 4) && "Can allocate only 4 float cc registers"); + Node->setColor(c); + } + +}; + + + + +#endif diff --git a/lib/Target/SparcV9/SparcV9RegInfo.cpp b/lib/Target/SparcV9/SparcV9RegInfo.cpp index 0b30e5c1af..ec4868b938 100644 --- a/lib/Target/SparcV9/SparcV9RegInfo.cpp +++ b/lib/Target/SparcV9/SparcV9RegInfo.cpp @@ -1,239 +1,475 @@ -#include "llvm/CodeGen/IGNode.h" -#include "SparcRegInfo.h" +#include "llvm/Target/Sparc.h" #include "SparcInternals.h" +#include "llvm/Method.h" +#include "llvm/iTerminators.h" +#include "llvm/CodeGen/InstrScheduling.h" +#include "llvm/CodeGen/InstrSelection.h" -#include "llvm/Target/Sparc.h" +#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h" +#include "llvm/CodeGen/PhyRegAlloc.h" -//----------------------------------------------------------------------------- -// Int Register Class -//----------------------------------------------------------------------------- -void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const -{ - /* Algorithm: - Record the color of all neighbors. - If there is no call interf, try to allocate volatile, then non volatile - If there is call interf, try to allocate non-volatile. If that fails - try to allocate a volatile and insert save across calls - If both above fail, spill. +//--------------------------------------------------------------------------- +// UltraSparcRegInfo +//--------------------------------------------------------------------------- - */ +/* +Rules for coloring values with sepcial registers: +================================================= - unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors +The following are the cases we color values with special regs: - for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh - IGNode *NeighIGNode = Node->getAdjIGNode(n); - if( NeighIGNode->hasColor() ) { // if neigh has a color - IsColorUsedArr[ NeighIGNode->getColor() ] = true; // record that color - } - } +1) Incoming Method Arguements +2) Outgoing Call Arguments +3) Return Value of a call +4) Return Value of a return statement +Both 1 and 3 are defs. Therefore, they can be set directly. For case 1, +incoming args are colored to %i0-%i5 and %f0 - %fx. For case 3, the return +value of the call must be colored to %o0 or %f0. +For case 2 we can use %o0-%o6 and %f0- %fx and for case 4 we can use %i0 or +%f0. However, we cannot pre-color them directly to those regs +if there are call interferences or they can be already colred by case 1. +(Note that a return value is call is already colored and it is registered +as a call interference as well if it is live after the call). Otherwise, they +can be precolored. In cases where we cannot precolor, we just have to insert +a copy instruction to copy the LR to the required register. - unsigned SearchStart; // start pos of color in pref-order - bool ColorFound= false; // have we found a color yet? +*/ - //if this Node is between calls - if( Node->getNumOfCallInterferences() == 0) { - // start with volatiles (we can allocate volatiles safely) - SearchStart = SparcIntRegOrder::StartOfAllRegs; - } - else { - // start with non volatiles (no non-volatiles) - SearchStart = SparcIntRegOrder::StartOfNonVolatileRegs; - } - unsigned c=0; // color - - // find first unused color - for( c=SearchStart; c < SparcIntRegOrder::NumOfAvailRegs; c++) { - if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; } - } +//--------------------------------------------------------------------------- +// This method will color incoming args to a method. If there are more +// args than that can fit in regs, code will be inserted to pop them from +// stack +//--------------------------------------------------------------------------- - if( ColorFound) - Node->setColor(c); // first color found in preffered order +void UltraSparcRegInfo::colorArgs(const Method *const Meth, + LiveRangeInfo& LRI) const +{ - // if color is not found because of call interference - // try even finding a volatile color and insert save across calls - else if( Node->getNumOfCallInterferences() ) - { - // start from 0 - try to find even a volatile this time - SearchStart = SparcIntRegOrder::StartOfAllRegs; + // get the argument list + const Method::ArgumentListType& ArgList = Meth->getArgumentList(); + // get an iterator to arg list + Method::ArgumentListType::const_iterator ArgIt = ArgList.begin(); + unsigned intArgNo=0; - // find first unused volatile color - for(c=SearchStart; c < SparcIntRegOrder::StartOfNonVolatileRegs; c++) { - if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; } - } + // to keep track of which float regs are allocated for argument passing + bool FloatArgUsedArr[NumOfFloatArgRegs]; - if( ColorFound) { - Node->setColor(c); - // since LR span across calls, must save across calls - Node->markForSaveAcrossCalls(); + // init float arg used array + for(unsigned i=0; i < NumOfFloatArgRegs; ++i) + FloatArgUsedArr[i] = false; + + // for each argument + for( ; ArgIt != ArgList.end() ; ++ArgIt) { + + // get the LR of arg + LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt); + unsigned RegClassID = (LR->getRegClass())->getID(); + + // if the arg is in int class - allocate a reg for an int arg + if( RegClassID == IntRegClassID ) { + + if( intArgNo < NumOfIntArgRegs) { + LR->setColor( SparcIntRegOrder::i0 + intArgNo ); + + if( DEBUG_RA) printReg( LR ); + } + + else { + // TODO: Insert push code here + assert( 0 && "Insert push code here!"); + } + ++intArgNo; } + // if the arg is float/double + else if ( RegClassID == FloatRegClassID) { + + if( LR->getTypeID() == Type::DoubleTyID ) { + + // find the first reg # we can pass a double arg + for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) { + if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) { + LR->setColor( SparcFloatRegOrder::f0 + i ); + FloatArgUsedArr[i] = true; + FloatArgUsedArr[i+1] = true; + if( DEBUG_RA) printReg( LR ); + break; + } + } + if( ! LR->hasColor() ) { // if LR was not colored above + + assert(0 && "insert push code here for a double"); + + } + + } + else if( LR->getTypeID() == Type::FloatTyID ) { + + // find the first reg # we can pass a float arg + for(unsigned i=0; i < NumOfFloatArgRegs; ++i) { + if ( !FloatArgUsedArr[i] ) { + LR->setColor( SparcFloatRegOrder::f0 + i ); + FloatArgUsedArr[i] = true; + if( DEBUG_RA) printReg( LR ); + break; + } + } + if( ! LR->hasColor() ) { // if LR was not colored above + assert(0 && "insert push code here for a float"); + } + + } + else + assert(0 && "unknown float type in method arg"); + + } // float register class + + else + assert(0 && "Unknown RegClassID"); } + +} - // If we couldn't find a color regardless of call interference - i.e., we - // don't have either a volatile or non-volatile color left - if( !ColorFound ) - Node->markForSpill(); // no color found - must spill - if( DEBUG_RA) - UltraSparcRegInfo::printReg( Node->getParentLR() ); -} +void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> & + CallInstrList, LiveRangeInfo& LRI, + AddedInstrMapType &AddedInstrMap) const +{ + vector<const Instruction *>::const_iterator InstIt; + // First color the return value of all call instructions. The return value + // will be in %o0 if the value is an integer type, or in %f0 if the + // value is a float type. + for(InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) { -//----------------------------------------------------------------------------- -// Float Register Class -//----------------------------------------------------------------------------- + const Instruction *const CallI = *InstIt; -// find the first available color in the range [Start,End] depending on the -// type of the Node (i.e., float/double) + // get the live range of return value of this call + LiveRange *const LR = LRI.getLiveRangeForValue( CallI ); -int SparcFloatRegClass::findFloatColor(const IGNode *const Node, unsigned Start, - unsigned End, - bool IsColorUsedArr[] ) const -{ + if ( LR ) { - bool ColorFound = false; - unsigned c; + // Since the call is a def, it cannot be colored by some other instr. + // Therefore, we can definitely set a color here. + // However, this def can be used by some other instr like another call + // or return which places that in a special register. In that case + // it has to put a copy. Note that, the def will have a call interference + // with this call instr itself if it is live after this call. - if( Node->getTypeID() == Type::DoubleTyID ) { + assert( ! LR->hasColor() && "Can't have a color since this is a def"); + + unsigned RegClassID = (LR->getRegClass())->getID(); - // find first unused color for a double - for( c=Start; c < End ;c+= 2){ - if( ! IsColorUsedArr[ c ] && ! IsColorUsedArr[ c+1 ]) - { ColorFound=true; break; } + if( RegClassID == IntRegClassID ) { + LR->setColor(SparcIntRegOrder::o0); + } + else if (RegClassID == FloatRegClassID ) { + LR->setColor(SparcFloatRegOrder::f0 ); + } } - - } else { - - // find first unused color for a single - for( c=Start; c < End; c++) { - if( ! IsColorUsedArr[ c ] ) { ColorFound=true; break; } + else { + cout << "Warning: No Live Range for return value of CALL" << endl; } } - - if( ColorFound ) return c; - else return -1; + + + for( InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) { + + // Inst = LLVM call instruction + const Instruction *const CallI = *InstIt; + + // find the CALL/JMMPL machine instruction + MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec(); + MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin(); + + /* + for( ; MIIt != MInstVec.end() && + ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode()); + ++MIIt ); + + assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found"); + */ + + assert(getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode()) && + "First machine instruction is not a Call/JMPL Machine Instr"); + + // CallMI = CALL/JMPL machine isntruction + const MachineInstr *const CallMI = *MIIt; + + Instruction::op_const_iterator OpIt = CallI->op_begin(); + + unsigned intArgNo=0; + + + // to keep track of which float regs are allocated for argument passing + bool FloatArgUsedArr[NumOfFloatArgRegs]; + + // init float arg used array + for(unsigned i=0; i < NumOfFloatArgRegs; ++i) + FloatArgUsedArr[i] = false; + + // go thru all the operands of LLVM instruction + for( ; OpIt != CallI->op_end(); ++OpIt ) { + + // get the LR of call operand (parameter) + LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt); + + if ( !LR ) { + cout << " Warning: In call instr, no LR for arg: " ; + printValue(*OpIt); + cout << endl; + continue; + } + + unsigned RegClassID = (LR->getRegClass())->getID(); + + // if the arg is in int class - allocate a reg for an int arg + if( RegClassID == IntRegClassID ) { + + if( intArgNo < NumOfIntArgRegs) { + setCallOrRetArgCol( LR, SparcIntRegOrder::o0 + intArgNo, + CallMI, AddedInstrMap); + } + + else { + // TODO: Insert push code here + assert( 0 && "Insert push code here!"); + + AddedInstrns * AI = AddedInstrMap[ CallMI ]; + if( ! AI ) AI = new AddedInstrns(); + + // AI->InstrnsBefore.push_back( getStackPushInstr(LR) ); + AddedInstrMap[ CallMI ] = AI; + + } + ++intArgNo; + } + + // if the arg is float/double + else if ( RegClassID == FloatRegClassID) { + + if( LR->getTypeID() == Type::DoubleTyID ) { + + // find the first reg # we can pass a double arg + for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) { + if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) { + setCallOrRetArgCol(LR, SparcFloatRegOrder::f0 + i, + CallMI, AddedInstrMap); + FloatArgUsedArr[i] = true; + FloatArgUsedArr[i+1] = true; + //if( DEBUG_RA) printReg( LR ); + break; + } + } + if( ! LR->hasColor() ) { // if LR was not colored above + + assert(0 && "insert push code here for a double"); + + } + + } + else if( LR->getTypeID() == Type::FloatTyID ) { + + // find the first reg # we can pass a float arg + for(unsigned i=0; i < NumOfFloatArgRegs; ++i) { + if ( !FloatArgUsedArr[i] ) { + setCallOrRetArgCol(LR, SparcFloatRegOrder::f0 + i, + CallMI, AddedInstrMap); + FloatArgUsedArr[i] = true; + // LR->setColor( SparcFloatRegOrder::f0 + i ); + // if( DEBUG_RA) printReg( LR ); + break; + } + } + if( ! LR->hasColor() ) { // if LR was not colored above + assert(0 && "insert push code here for a float"); + } + + } + else + assert(0 && "unknown float type in method arg"); + + } // float register class + + else + assert(0 && "Unknown RegClassID"); + + + } // for each operand in a call instruction + + + + + + } // for all call instrctions in CallInstrList + } -void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const +void UltraSparcRegInfo::colorRetArg(vector<const Instruction *> & + RetInstrList, LiveRangeInfo& LRI, + AddedInstrMapType &AddedInstrMap) const { - /* Algorithm: + vector<const Instruction *>::const_iterator InstIt; - If the LR is a double try to allocate f32 - f63 - If the above fails or LR is single precision - If the LR does not interfere with a call - start allocating from f0 - Else start allocating from f6 - If a color is still not found because LR interferes with a call - Search in f0 - f6. If found mark for spill across calls. - If a color is still not fond, mark for spilling - */ + for(InstIt=RetInstrList.begin(); InstIt != RetInstrList.end(); ++InstIt) { - unsigned NumNeighbors = Node-> |