From dfc6c887dac4cb2fe4c0da6b5a053eba4c7a33f5 Mon Sep 17 00:00:00 2001 From: Ruchira Sasanka Date: Tue, 18 Sep 2001 22:52:44 +0000 Subject: [PATCH] -- ruchira llvm-svn: 632 --- llvm/lib/Target/Sparc/Makefile | 1 + llvm/lib/Target/Sparc/Sparc.cpp | 324 +---------- llvm/lib/Target/Sparc/SparcInternals.h | 58 +- llvm/lib/Target/Sparc/SparcRegClassInfo.cpp | 238 ++++++++ llvm/lib/Target/Sparc/SparcRegClassInfo.h | 240 ++++++++ llvm/lib/Target/Sparc/SparcRegInfo.cpp | 608 ++++++++++++++------ 6 files changed, 954 insertions(+), 515 deletions(-) create mode 100644 llvm/lib/Target/Sparc/SparcRegClassInfo.cpp create mode 100644 llvm/lib/Target/Sparc/SparcRegClassInfo.h diff --git a/llvm/lib/Target/Sparc/Makefile b/llvm/lib/Target/Sparc/Makefile index a2b8c2abd78c..aa1f0dc4a284 100644 --- a/llvm/lib/Target/Sparc/Makefile +++ b/llvm/lib/Target/Sparc/Makefile @@ -6,6 +6,7 @@ Source = \ Sparc.o \ Sparc.burm.o \ SparcInstrSelection.o \ + SparcRegClassInfo.o \ SparcRegInfo.o include $(LEVEL)/Makefile.common diff --git a/llvm/lib/Target/Sparc/Sparc.cpp b/llvm/lib/Target/Sparc/Sparc.cpp index 37052568cd13..f2caf3884231 100644 --- a/llvm/lib/Target/Sparc/Sparc.cpp +++ b/llvm/lib/Target/Sparc/Sparc.cpp @@ -29,16 +29,16 @@ TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); } + //---------------------------------------------------------------------------- // Entry point for register allocation for a module //---------------------------------------------------------------------------- -bool -AllocateRegisters(Method *M, TargetMachine &TM) +void AllocateRegisters(Method *M, TargetMachine &TM) { if ( (M)->isExternal() ) // don't process prototypes - return false; + return; if( DEBUG_RA ) { cout << endl << "******************** Method "<< (M)->getName(); @@ -55,9 +55,11 @@ AllocateRegisters(Method *M, TargetMachine &TM) if( DEBUG_RA ) cout << endl << "Register allocation complete!" << endl; - return false; } + + + //***************************** External Classes **************************/ @@ -128,300 +130,6 @@ UltraSparcSchedInfo::initializeResources() - -//--------------------------------------------------------------------------- -// UltraSparcRegInfo -// Purpose: -// 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 -//--------------------------------------------------------------------------- - - -void UltraSparcRegInfo::colorArgs(const Method *const Meth, - LiveRangeInfo& LRI) const -{ - - // 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; - - // 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; - - // 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"); - } - -} - - - - - - -void UltraSparcRegInfo::printReg(const LiveRange *const LR) { - - unsigned RegClassID = (LR->getRegClass())->getID(); - - cout << " *Node " << (LR->getUserIGNode())->getIndex(); - - if( ! LR->hasColor() ) { - cout << " - could not find a color" << endl; - return; - } - - // if a color is found - - cout << " colored with color "<< LR->getColor(); - - if( RegClassID == IntRegClassID ) { - - cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ; - cout << "]" << endl; - } - else if ( RegClassID == FloatRegClassID) { - cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor()); - if( LR->getTypeID() == Type::DoubleTyID ) - cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1); - cout << "]" << endl; - } - - -} - - -void UltraSparcRegInfo::colorCallArgs(vector & - CallInstrList, LiveRangeInfo& LRI, - AddedInstrMapType &AddedInstrMap) const -{ - - vector::const_iterator InstIt = CallInstrList.begin(); - - for( ; InstIt != CallInstrList.end(); ++InstIt) { - - // Inst = LLVM call instruction - const Instruction *const CallI = *InstIt; - - MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec(); - MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin(); - - // find the CALL/JMMPL machine instruction - for( ; MIIt != MInstVec.end() && - ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode()); - ++MIIt ); - - assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found"); - - // CallMI = CALL/JMPL machine isntruction - const MachineInstr *const CallMI = *MIIt; - - Instruction::op_const_iterator OpIt = CallI->op_begin(); - - unsigned intArgNo=0; - //unsigned NumOfCallInterfs = LR->getNumOfCallInterferences(); - - // 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) { - setCallArgColor( LR, SparcIntRegOrder::o0 + intArgNo ); - } - - 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] ) { - setCallArgColor(LR, 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] ) { - setCallArgColor(LR, SparcFloatRegOrder::f0 + i ); - 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 UltraSparcRegInfo::setCallArgColor(LiveRange *const LR, - const unsigned RegNo) const { - - // if no call interference and LR is NOT previously colored (e.g., as an - // incoming arg) - if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) { - // we can directly allocate a %o register - LR->setColor( RegNo); - if( DEBUG_RA) printReg( LR ); - } - else { // there are call interferences - - /* - // insert a copy machine instr to copy from LR to %o(reg) - PreMInstrMap[ CallMI ] = - getNewCopyMInstr( LR->, SparcIntRegOrder::o0 + intArgNo ); - */ - cout << " $$$ TODO: Insert a copy for call argument!: " << endl; - - // We don't color LR here. It's colored as any other normal LR - } - -} - - - - - //--------------------------------------------------------------------------- // class UltraSparcMachine // @@ -445,9 +153,11 @@ UltraSparc::UltraSparc() } -bool -UltraSparc::compileMethod(Method *M) -{ + + + +bool UltraSparc::compileMethod(Method *M) { + if (SelectInstructionsForMethod(M, *this)) { cerr << "Instruction selection failed for method " << M->getName() @@ -462,13 +172,11 @@ UltraSparc::compileMethod(Method *M) return true; } - // if (AllocateRegisters(M, *this)) // allocate registers - // { - // cerr << "Register allocation failed for method " - // << M->getName() << "\n\n"; - // return true; - // } - + AllocateRegisters(M, *this); // allocate registers + + return false; } + + diff --git a/llvm/lib/Target/Sparc/SparcInternals.h b/llvm/lib/Target/Sparc/SparcInternals.h index c63c7c5f6b5a..1980c2e803af 100644 --- a/llvm/lib/Target/Sparc/SparcInternals.h +++ b/llvm/lib/Target/Sparc/SparcInternals.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 & + 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/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp b/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp new file mode 100644 index 000000000000..a6d7f9e060c3 --- /dev/null +++ b/llvm/lib/Target/Sparc/SparcRegClassInfo.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/llvm/lib/Target/Sparc/SparcRegClassInfo.h b/llvm/lib/Target/Sparc/SparcRegClassInfo.h new file mode 100644 index 000000000000..4a00cb560ca7 --- /dev/null +++ b/llvm/lib/Target/Sparc/SparcRegClassInfo.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/llvm/lib/Target/Sparc/SparcRegInfo.cpp b/llvm/lib/Target/Sparc/SparcRegInfo.cpp index 0b30e5c1af6e..ec4868b938dc 100644 --- a/llvm/lib/Target/Sparc/SparcRegInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegInfo.cpp @@ -1,90 +1,140 @@ -#include "llvm/CodeGen/IGNode.h" -#include "SparcRegInfo.h" -#include "SparcInternals.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" -//----------------------------------------------------------------------------- -// Int Register Class -//----------------------------------------------------------------------------- +#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h" +#include "llvm/CodeGen/PhyRegAlloc.h" -void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const + + + +//--------------------------------------------------------------------------- +// UltraSparcRegInfo +//--------------------------------------------------------------------------- + +/* +Rules for coloring values with sepcial registers: +================================================= + +The following are the cases we color values with special regs: + +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. + +*/ + + + +//--------------------------------------------------------------------------- +// 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 +//--------------------------------------------------------------------------- + +void UltraSparcRegInfo::colorArgs(const Method *const Meth, + LiveRangeInfo& LRI) const { - /* Algorithm: - Record the color of all neighbors. + // 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; - 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. + // 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; - unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors + // for each argument + for( ; ArgIt != ArgList.end() ; ++ArgIt) { - 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 - } - } + // 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 ); - 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( DEBUG_RA) printReg( LR ); + } + + else { + // TODO: Insert push code here + assert( 0 && "Insert push code here!"); + } + ++intArgNo; } - if( ColorFound) { - Node->setColor(c); - // since LR span across calls, must save across calls - Node->markForSaveAcrossCalls(); - } + // 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() ); - + } @@ -92,148 +142,334 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const -//----------------------------------------------------------------------------- -// 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 +void UltraSparcRegInfo::colorCallArgs(vector & + CallInstrList, LiveRangeInfo& LRI, + AddedInstrMapType &AddedInstrMap) const { - bool ColorFound = false; - unsigned c; + vector::const_iterator InstIt; - if( Node->getTypeID() == Type::DoubleTyID ) { + // 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) { + + const Instruction *const CallI = *InstIt; + + // get the live range of return value of this call + LiveRange *const LR = LRI.getLiveRangeForValue( CallI ); + + if ( LR ) { + + // 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. + + 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 & + RetInstrList, LiveRangeInfo& LRI, + AddedInstrMapType &AddedInstrMap) 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 - */ + vector::const_iterator InstIt; - unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors + for(InstIt=RetInstrList.begin(); InstIt != RetInstrList.end(); ++InstIt) { + + const ReturnInst *const RetI = (ReturnInst *) *InstIt; + + // get the return value of this return instruction + const Value *RetVal = (RetI)->getReturnValue(); + + if( RetVal ) { + + // find the CALL/JMMPL machine instruction + MachineCodeForVMInstr & MInstVec = RetI->getMachineInstrVec(); + MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin(); + + assert(getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode()) + && "First machine instruction is not a RET Machine Instr"); + // RET machine isntruction + const MachineInstr *const RetMI = *MIIt; + + LiveRange *const LR = LRI.getLiveRangeForValue( RetVal ); + unsigned RegClassID = (LR->getRegClass())->getID(); + + if ( LR ) { + if( RegClassID == IntRegClassID ) { + setCallOrRetArgCol( LR, SparcIntRegOrder::i0, RetMI, AddedInstrMap); + } + else if (RegClassID==FloatRegClassID ) { + setCallOrRetArgCol(LR, SparcFloatRegOrder::f0, RetMI, AddedInstrMap); + } + + } + else { + cout << "Warning: No LR for return value" << endl; + } - 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() ); - } - - } +void UltraSparcRegInfo::setCallOrRetArgCol(LiveRange *const LR, + const unsigned RegNo, + const MachineInstr *MI, + AddedInstrMapType &AIMap) const { + + // if no call interference and LR is NOT previously colored (e.g., as an + // incoming arg) + if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) { + // we can directly allocate a %o register + LR->setColor( RegNo); + if( DEBUG_RA) printReg( LR ); + } + else { + + // there are call interferences (e.g., live across a call or produced + // by a call instr) or this LR is already colored as an incoming argument + + MachineInstr *MI = getCopy2RegMI((*(LR->begin())), RegNo, + (LR->getRegClass())->getID()); + + AddedInstrns * AI = AIMap[ MI ]; // get already added instrns for MI + if( ! AI ) AI = new AddedInstrns(); + + AI->InstrnsBefore.push_back( MI ); // add the new MI yp AMI + AIMap[ MI ] = AI; + + + cout << "Inserted a copy instr for a RET/CALL instr " << endl; + + // We don't color LR here. It's colored as any other normal LR or + // as an incoming arg or a return value of a call. + } + +} + +// Generates a copy machine instruction to copy a value to a given +// register. + +MachineInstr * UltraSparcRegInfo::getCopy2RegMI(const Value *SrcVal, + const unsigned Reg, + unsigned RegClassID) const { + MachineInstr * MI; + + if( RegClassID == IntRegClassID ) { // if integer move + + MI = new MachineInstr(ADD, 3); + + MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal); + MI->SetMachineOperand(1, SparcIntRegOrder::g0, false); + MI->SetMachineOperand(2, Reg, true); + } + else { // if FP move + + if(SrcVal->getType()-> getPrimitiveID() == Type::FloatTyID ) + MI = new MachineInstr(FMOVS, 2); + else if(SrcVal->getType()-> getPrimitiveID() == Type::DoubleTyID) + MI = new MachineInstr(FMOVD, 2); + else assert( 0 && "Unknown Type"); + + MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal); + MI->SetMachineOperand(1, Reg, true); + } + + return MI; + +} +//--------------------------------------------------------------------------- +// Print the register assigned to a LR +//--------------------------------------------------------------------------- + +void UltraSparcRegInfo::printReg(const LiveRange *const LR) { + + unsigned RegClassID = (LR->getRegClass())->getID(); + + cout << " *Node " << (LR->getUserIGNode())->getIndex(); + + if( ! LR->hasColor() ) { + cout << " - could not find a color" << endl; + return; + } + + // if a color is found + + cout << " colored with color "<< LR->getColor(); + + if( RegClassID == IntRegClassID ) { + + cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ; + cout << "]" << endl; + } + else if ( RegClassID == FloatRegClassID) { + cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor()); + if( LR->getTypeID() == Type::DoubleTyID ) + cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1); + cout << "]" << endl; + } - - - - - - - - - +}