From 5867c7ae808d9fd4b4b61ff2c12e47e18272f9f9 Mon Sep 17 00:00:00 2001 From: Ruchira Sasanka Date: Sun, 30 Sep 2001 23:16:47 +0000 Subject: [PATCH] added support for suggesting colors llvm-svn: 671 --- llvm/lib/Target/Sparc/SparcRegClassInfo.cpp | 118 ++- llvm/lib/Target/Sparc/SparcRegClassInfo.h | 18 +- llvm/lib/Target/Sparc/SparcRegInfo.cpp | 992 +++++++++++++------- 3 files changed, 736 insertions(+), 392 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp b/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp index a6d7f9e060c3..883ed52d0fc3 100644 --- a/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp @@ -11,31 +11,48 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const { /* Algorithm: - Record the color of all neighbors. + Record the colors/suggested colors 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 + If there is a suggested color, try to allocate it + 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. + If both above fail, spill. */ + LiveRange * LR = Node->getParentLR(); 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 - } + LiveRange *NeighLR = NeighIGNode->getParentLR(); + + if( NeighLR->hasColor() ) // if has a color + IsColorUsedArr[ NeighLR->getColor() ] = true; // record that color + + else if( NeighLR->hasSuggestedColor() ) // or has a suggest col + IsColorUsedArr[ NeighLR->getSuggestedColor() ] = true; + } + if( LR->hasSuggestedColor() ) { + if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) { + LR->setColor( LR->getSuggestedColor() ); + return; + } + else { // can't allocate the suggested col + cout << " Coud NOT allocate the suggested color for LR "; + LR->printSet(); cout << endl; + } + } 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) { + if( LR->getNumOfCallInterferences() == 0) { // start with volatiles (we can allocate volatiles safely) SearchStart = SparcIntRegOrder::StartOfAllRegs; @@ -53,11 +70,12 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const } if( ColorFound) - Node->setColor(c); // first color found in preffered order + LR->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() ) + else if( LR->getNumOfCallInterferences() ) { // start from 0 - try to find even a volatile this time SearchStart = SparcIntRegOrder::StartOfAllRegs; @@ -68,21 +86,22 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const } if( ColorFound) { - Node->setColor(c); + LR->setColor(c); // since LR span across calls, must save across calls - Node->markForSaveAcrossCalls(); + LR->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 + LR->markForSpill(); // no color found - must spill if( DEBUG_RA) - UltraSparcRegInfo::printReg( Node->getParentLR() ); + UltraSparcRegInfo::printReg( LR ); } @@ -98,7 +117,8 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const // 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, +int SparcFloatRegClass::findFloatColor(const LiveRange *const LR, + unsigned Start, unsigned End, bool IsColorUsedArr[] ) const { @@ -106,7 +126,7 @@ int SparcFloatRegClass::findFloatColor(const IGNode *const Node, unsigned Start, bool ColorFound = false; unsigned c; - if( Node->getTypeID() == Type::DoubleTyID ) { + if( LR->getTypeID() == Type::DoubleTyID ) { // find first unused color for a double for( c=Start; c < End ;c+= 2){ @@ -146,28 +166,50 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const */ + LiveRange * LR = Node->getParentLR(); 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; + LiveRange *NeighLR = NeighIGNode->getParentLR(); + + if( NeighLR->hasColor() ) { // if neigh has a color + IsColorUsedArr[ NeighLR->getColor() ] = true; // record that color + if( NeighLR->getTypeID() == Type::DoubleTyID ) + IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true; + } + else if( NeighLR->hasSuggestedColor() ) { // if neigh has sugg color + IsColorUsedArr[ NeighLR->getSuggestedColor() ] = true; + if( NeighLR->getTypeID() == Type::DoubleTyID ) + IsColorUsedArr[ (NeighLR->getSuggestedColor()) + 1 ] = true; + } + + } + + + if( LR->hasSuggestedColor() ) { + if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) { + LR->setColor( LR->getSuggestedColor() ); + return; + } + else { // can't allocate the suggested col + cout << " Coud NOT allocate the suggested color for LR "; + LR->printSet(); cout << endl; } } + int ColorFound = -1; // have we found a color yet? - unsigned NumOfCallInterf = Node->getNumOfCallInterferences(); + unsigned NumOfCallInterf = LR->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( LR->getTypeID() == Type::DoubleTyID ) + ColorFound = findFloatColor( LR, 32, 64, IsColorUsedArr ); if( ColorFound >= 0 ) { - Node->setColor(ColorFound); - if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() ); + LR->setColor(ColorFound); + if( DEBUG_RA) UltraSparcRegInfo::printReg( LR ); return; } @@ -185,38 +227,42 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const SearchStart = SparcFloatRegOrder::StartOfNonVolatileRegs; } - ColorFound = findFloatColor( Node, SearchStart, 32, IsColorUsedArr ); + ColorFound = findFloatColor( LR, SearchStart, 32, IsColorUsedArr ); } if( ColorFound >= 0 ) { - Node->setColor(ColorFound); - if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() ); + LR->setColor(ColorFound); + if( DEBUG_RA) UltraSparcRegInfo::printReg( LR ); 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, + ColorFound = findFloatColor( LR, 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() ); + LR->setColor(ColorFound); // first color found in preffered order + LR->markForSaveAcrossCalls(); + if( DEBUG_RA) UltraSparcRegInfo::printReg( LR ); return; } - else { - Node->markForSpill(); // no color found - must spill - if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() ); - } + + // we are here because no color could be found + + LR->markForSpill(); // no color found - must spill + if( DEBUG_RA) UltraSparcRegInfo::printReg( LR ); } diff --git a/llvm/lib/Target/Sparc/SparcRegClassInfo.h b/llvm/lib/Target/Sparc/SparcRegClassInfo.h index 4a00cb560ca7..d613582c87af 100644 --- a/llvm/lib/Target/Sparc/SparcRegClassInfo.h +++ b/llvm/lib/Target/Sparc/SparcRegClassInfo.h @@ -19,11 +19,11 @@ // Int register names in same order as enum in class SparcIntRegOrder static string const IntRegNames[] = - { "g1", "g2", "g3", "g4", "g5", "g6", "g7", + { "g1", "g2", "g3", "g4", "g5", "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" }; + "i0", "i1", "i2", "i3", "i4", "i5", "i7", + "g0", "g6", "g7", "i6", "o6" }; @@ -36,7 +36,7 @@ class SparcIntRegOrder{ // --- 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 + g1, g2, g3, g4, g5, //%g1-%g5 (g6-7 are reserved for system) o0, o1, o2, o3, o4, o5, o7, // %o0-%o5, // %o6 is sp, @@ -45,17 +45,17 @@ class SparcIntRegOrder{ // --- 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 + i0, i1, i2, i3, i4, i5, i7, // %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 + // %i7 is the ret address by convention - can be used for others // 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 + g0, g6, g7, i6, o6 @@ -130,7 +130,7 @@ class SparcFloatRegOrder{ static unsigned int const NumOfAvailRegs = 32; static unsigned int const NumOfAllRegs = 64; - static unsigned int const StartOfNonVolatileRegs = f6; + static unsigned int const StartOfNonVolatileRegs = f32; static unsigned int const StartOfAllRegs = f0; @@ -149,7 +149,7 @@ class SparcFloatRegClass : public MachineRegClassInfo { private: - int findFloatColor(const IGNode *const Node, unsigned Start, + int findFloatColor(const LiveRange *const LR, unsigned Start, unsigned End, bool IsColorUsedArr[] ) const; public: diff --git a/llvm/lib/Target/Sparc/SparcRegInfo.cpp b/llvm/lib/Target/Sparc/SparcRegInfo.cpp index 8254b00a5b09..0a2570e5a422 100644 --- a/llvm/lib/Target/Sparc/SparcRegInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegInfo.cpp @@ -2,6 +2,7 @@ #include "SparcInternals.h" #include "llvm/Method.h" #include "llvm/iTerminators.h" +#include "llvm/iOther.h" #include "llvm/CodeGen/InstrScheduling.h" #include "llvm/CodeGen/InstrSelection.h" @@ -15,448 +16,740 @@ // 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 +// This method sets the hidden operand for return address in RETURN and +// JMPL machine instructions. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::colorArgs(const Method *const Meth, - LiveRangeInfo& LRI) const +bool UltraSparcRegInfo::handleSpecialMInstr(const MachineInstr * MInst, + LiveRangeInfo& LRI, + vectorRCList) const { + + unsigned OpCode = MInst->getOpCode(); + + + // if the instruction is a RETURN instruction, suggest %i7 + + if( (UltraSparcInfo->getInstrInfo()).isReturn( OpCode ) ) { + + const Value *RetAddrVal = getValue4ReturnAddr(MInst); + + if( (getRegClassIDOfValue( RetAddrVal) == IntRegClassID) ) { + if( DEBUG_RA) { + cout << "\n$?$Return Address Value is not of Integer Type. Type ="; + cout << (RetAddrVal->getType())->getPrimitiveID() << endl; + } + } + + + LiveRange * RetAddrLR = new LiveRange(); + RetAddrLR->add(RetAddrVal); + RetAddrLR->setRegClass( RCList[IntRegClassID] ); + LRI.addLRToMap( RetAddrVal, RetAddrLR); + + RetAddrLR->setSuggestedColor(SparcIntRegOrder::i7); + + return true; + } + + // else if the instruction is a JMPL instruction, color it with %o7 + // this can be permenently colored since the LR is very short (one instr) + // TODO: Directly change the machine register instead of creating a LR + + else if( (UltraSparcInfo->getInstrInfo()).isCall(MInst->getOpCode() ) ) { + + const Value *RetAddrVal = getValue4ReturnAddr(MInst); + + if( (getRegClassIDOfValue( RetAddrVal) == IntRegClassID) ) { + if( DEBUG_RA) { + cout << "\n$?$Return Address Value is not of Integer Type. Type ="; + cout << (RetAddrVal->getType())->getPrimitiveID() << endl; + } + } + + LiveRange * RetAddrLR = new LiveRange(); + RetAddrLR->add(RetAddrVal); + RetAddrLR->setRegClass( RCList[IntRegClassID] ); + LRI.addLRToMap( RetAddrVal, RetAddrLR); + + RetAddrLR->setColor(SparcIntRegOrder::o7); + + return true; + + } + + else return false; // not a special machine instruction + +} + + +//--------------------------------------------------------------------------- +// This gets the hidden value in a return register which is used to +// pass the return address. +//--------------------------------------------------------------------------- + +Value * +UltraSparcRegInfo::getValue4ReturnAddr( const MachineInstr * MInst ) const { + + if( (UltraSparcInfo->getInstrInfo()).isReturn(MInst->getOpCode()) ) { + + assert( (MInst->getNumOperands() == 2) && "RETURN must have 2 operands"); + const MachineOperand & MO = MInst->getOperand(0); + return MO.getVRegValue(); + + } + else if( (UltraSparcInfo->getInstrInfo()).isCall(MInst->getOpCode()) ) { + + assert( (MInst->getNumOperands() == 3) && "JMPL must have 3 operands"); + const MachineOperand & MO = MInst->getOperand(2); + return MO.getVRegValue(); + } + + else + assert(0 && "Machine Instr is not a CALL/RET"); +} + + + +//--------------------------------------------------------------------------- +// This method will suggest colors to incoming args to a method. +// If the arg is passed on stack due to the lack of regs, NOTHING will be +// done - it will be colored (or spilled) as a normal value. +//--------------------------------------------------------------------------- + +void UltraSparcRegInfo::suggestRegs4MethodArgs(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) { + for( unsigned argNo=0; ArgIt != ArgList.end() ; ++ArgIt, ++argNo) { // get the LR of arg LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt); - unsigned RegClassID = (LR->getRegClass())->getID(); + assert( LR && "No live range found for method arg"); + + unsigned RegType = getRegType( LR ); + // if the arg is in int class - allocate a reg for an int arg - if( RegClassID == IntRegClassID ) { + if( RegType == IntRegType ) { - if( intArgNo < NumOfIntArgRegs) { - LR->setColor( SparcIntRegOrder::i0 + intArgNo ); + if( argNo < NumOfIntArgRegs) { + LR->setSuggestedColor( SparcIntRegOrder::i0 + argNo ); - if( DEBUG_RA) printReg( LR ); } else { - // TODO: Insert push code here - assert( 0 && "Insert push code here!"); + // Do NOTHING as this will be colored as a normal value. + if (DEBUG_RA) cout << " Int Regr not suggested for method arg\n"; } - ++intArgNo; + } + else if( RegType==FPSingleRegType && (argNo*2+1) < NumOfFloatArgRegs) + LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2 + 1) ); + + + else if( RegType == FPDoubleRegType && (argNo*2) < NumOfFloatArgRegs) + LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2) ); + - // 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::colorMethodArgs(const Method *const Meth, + LiveRangeInfo& LRI, + AddedInstrns *const FirstAI) const { + + // get the argument list + const Method::ArgumentListType& ArgList = Meth->getArgumentList(); + // get an iterator to arg list + Method::ArgumentListType::const_iterator ArgIt = ArgList.begin(); + + MachineInstr *AdMI; + + + // for each argument + for( unsigned argNo=0; ArgIt != ArgList.end() ; ++ArgIt, ++argNo) { + + // get the LR of arg + LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt); + assert( LR && "No live range found for method arg"); + + + // if the LR received the suggested color, NOTHING to be done + if( LR->hasSuggestedColor() && LR->hasColor() ) + if( LR->getSuggestedColor() == LR->getColor() ) + continue; + + // We are here because the LR did not have a suggested + // color or did not receive the suggested color. Now handle + // individual cases. + + + unsigned RegType = getRegType( LR ); + unsigned RegClassID = (LR->getRegClass())->getID(); + + + // find whether this argument is coming in a register (if not, on stack) + + bool isArgInReg = false; + unsigned UniArgReg = InvalidRegNum; + + if( (RegType== IntRegType && argNo < NumOfIntArgRegs)) { + isArgInReg = true; + UniArgReg = getUnifiedRegNum( RegClassID, SparcIntRegOrder::o0 + argNo ); + } + else if(RegType == FPSingleRegType && argNo < NumOfFloatArgRegs) { + isArgInReg = true; + UniArgReg = getUnifiedRegNum( RegClassID, + SparcFloatRegOrder::f0 + argNo*2 + 1 ) ; + } + else if(RegType == FPDoubleRegType && argNo < NumOfFloatArgRegs) { + isArgInReg = true; + UniArgReg = getUnifiedRegNum(RegClassID, SparcFloatRegOrder::f0+argNo*2); + } + + + if( LR->hasColor() ) { + + // We are here because the LR did not have a suggested + // color or did not receive the suggested color but LR got a register. + // Now we have to copy %ix reg (or stack pos of arg) + // to the register it was colored with. + + unsigned UniLRReg = getUnifiedRegNum( RegClassID, LR->getColor() ); + + // if the arg is coming in a register and goes into a register + if( isArgInReg ) + AdMI = cpReg2RegMI(UniArgReg, UniLRReg, RegType ); + + else + assert(0 && "TODO: Color an Incoming arg on stack"); + + // Now add the instruction + FirstAI->InstrnsBefore.push_back( AdMI ); + + } + + else { // LR is not colored (i.e., spilled) + + assert(0 && "TODO: Color a spilled arg "); + + } + + + } // for each incoming argument + +} + +//--------------------------------------------------------------------------- +// This method is called before graph coloring to suggest colors to the +// outgoing call args and the return value of the call. +//--------------------------------------------------------------------------- +void UltraSparcRegInfo::suggestRegs4CallArgs(const CallInst *const CallI, + LiveRangeInfo& LRI, + vector RCList) const { -void UltraSparcRegInfo::colorCallArgs(vector & - CallInstrList, LiveRangeInfo& LRI, - AddedInstrMapType &AddedInstrMap) const -{ + assert( (CallI->getOpcode() == Instruction::Call) && "Not a call instr"); - vector::const_iterator InstIt; - - // First color the return value of all call instructions. The return value + // First color the return value of the call instruction. 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) { + // the return value cannot have a LR in machine instruction since it is + // only defined by the call instruction - const Instruction *const CallI = *InstIt; + assert( (! LRI.getLiveRangeForValue( CallI ) ) && + "LR for ret Value of call already definded!"); - // get the live range of return value of this call - LiveRange *const LR = LRI.getLiveRangeForValue( CallI ); + // if type is not void, create a new live range and set its + // register class and add to LRI - if ( LR ) { + if( ! ((CallI->getType())->getPrimitiveID() == Type::VoidTyID) ) { + + // create a new LR for the return value - // 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. + LiveRange * RetValLR = new LiveRange(); + RetValLR->add( CallI ); + unsigned RegClassID = getRegClassIDOfValue( CallI ); + RetValLR->setRegClass( RCList[RegClassID] ); + LRI.addLRToMap( CallI, RetValLR); - assert( ! LR->hasColor() && "Can't have a color since this is a def"); + // now suggest a register depending on the register class of ret arg + + if( RegClassID == IntRegClassID ) + RetValLR->setSuggestedColor(SparcIntRegOrder::o0); + else if (RegClassID == FloatRegClassID ) + RetValLR->setSuggestedColor(SparcFloatRegOrder::f0 ); + else assert( 0 && "Unknown reg class for return value of call\n"); - unsigned RegClassID = (LR->getRegClass())->getID(); - - if( RegClassID == IntRegClassID ) { - LR->setColor(SparcIntRegOrder::o0); - } - else if (RegClassID == FloatRegClassID ) { - LR->setColor(SparcFloatRegOrder::f0 ); - } - } - else { - cout << "Warning: No Live Range for return value of CALL" << endl; - } } - for( InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) { + // Now suggest colors for arguments (operands) of the call instruction. + // Colors are suggested only if the arg number is smaller than the + // the number of registers allocated for argument passing. - // Inst = LLVM call instruction - const Instruction *const CallI = *InstIt; + Instruction::op_const_iterator OpIt = CallI->op_begin(); + ++OpIt; // first operand is the called method - skip it + + // go thru all the operands of LLVM instruction + for(unsigned argNo=0; OpIt != CallI->op_end(); ++OpIt, ++argNo ) { + + // get the LR of call operand (parameter) + LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt); - // 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; + if( !LR ) { // possible because arg can be a const + if( DEBUG_RA) { + cout << " Warning: In call instr, no LR for arg: " ; + printValue(*OpIt); cout << endl; } + continue; + } + + unsigned RegType = getRegType( LR ); - unsigned RegClassID = (LR->getRegClass())->getID(); + // if the arg is in int class - allocate a reg for an int arg + if( RegType == IntRegType ) { + + if( argNo < NumOfIntArgRegs) + LR->setSuggestedColor( SparcIntRegOrder::o0 + argNo ); + + else if (DEBUG_RA) + // Do NOTHING as this will be colored as a normal value. + cout << " Regr not suggested for int call arg" << endl; - // 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!"); + } + else if( RegType == FPSingleRegType && (argNo*2 +1)< NumOfFloatArgRegs) + LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2 + 1) ); + + + else if( RegType == FPDoubleRegType && (argNo*2) < NumOfFloatArgRegs) + LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2) ); + - 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 + } // for all call arguments } +//--------------------------------------------------------------------------- +// After graph coloring, we have call this method to see whehter the return +// value and the call args received the correct colors. If not, we have +// to instert copy instructions. +//--------------------------------------------------------------------------- - -void UltraSparcRegInfo::colorRetArg(vector & - RetInstrList, LiveRangeInfo& LRI, - AddedInstrMapType &AddedInstrMap) const -{ - - vector::const_iterator InstIt; +void UltraSparcRegInfo::colorCallArgs(const CallInst *const CallI, + LiveRangeInfo& LRI, + AddedInstrns *const CallAI) const { - for(InstIt=RetInstrList.begin(); InstIt != RetInstrList.end(); ++InstIt) { + // First color the return value of the call. + // If there is a LR for the return value, it means this + // method returns a value + + MachineInstr *AdMI; + LiveRange * RetValLR = LRI.getLiveRangeForValue( CallI ); - const ReturnInst *const RetI = (ReturnInst *) *InstIt; + if( RetValLR ) { - // get the return value of this return instruction - const Value *RetVal = (RetI)->getReturnValue(); + bool recvSugColor = false; - if( RetVal ) { + if( RetValLR->hasSuggestedColor() && RetValLR->hasColor() ) + if( RetValLR->getSuggestedColor() == RetValLR->getColor()) + recvSugColor = true; - // find the CALL/JMMPL machine instruction - MachineCodeForVMInstr & MInstVec = RetI->getMachineInstrVec(); - MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin(); + // if we didn't receive the suggested color for some reason, + // put copy instruction + if( !recvSugColor ) { + + if( RetValLR->hasColor() ) { + + unsigned RegType = getRegType( RetValLR ); + unsigned RegClassID = (RetValLR->getRegClass())->getID(); + + unsigned UniRetLRReg=getUnifiedRegNum(RegClassID,RetValLR->getColor()); + unsigned UniRetReg = InvalidRegNum; + + // find where we receive the return value depending on + // register class + + if(RegClassID == IntRegClassID) + UniRetReg = getUnifiedRegNum( RegClassID, SparcIntRegOrder::o0); + else if(RegClassID == FloatRegClassID) + UniRetReg = getUnifiedRegNum( RegClassID, SparcFloatRegOrder::f0); + + + AdMI = cpReg2RegMI(UniRetLRReg, UniRetReg, RegType ); + CallAI->InstrnsAfter.push_back( AdMI ); - /* - for( ; MIIt != MInstVec.end() && - !getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode()); - ++MIIt ) { - - cout << "Inst = "<< TargetInstrDescriptors[(*MIIt)->getOpCode()].opCodeString << endl; - - - } - assert((MIIt != MInstVec.end()) &&"No return machine instruction found"); - - */ - - - assert(getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode()) - && "First machine inst is not a RETURN 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); - } - } + } // if LR has color else { - cout << "Warning: No LR for return value" << endl; + + assert(0 && "LR of return value is splilled"); } + + } // the LR didn't receive the suggested color + + } // if there is a LR - i.e., return value is not void + + + + // Now color all the operands of the call instruction + + Instruction::op_const_iterator OpIt = CallI->op_begin(); + ++OpIt; // first operand is the called method - skip it + + // go thru all the operands of LLVM instruction + for(unsigned argNo=0; OpIt != CallI->op_end(); ++OpIt, ++argNo ) { + + // get the LR of call operand (parameter) + LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt); + + Value *ArgVal = (Value *) *OpIt; + + unsigned RegType = getRegType( ArgVal ); + unsigned RegClassID = getRegClassIDOfValue( ArgVal ); + + // find whether this argument is coming in a register (if not, on stack) + + bool isArgInReg = false; + unsigned UniArgReg = InvalidRegNum; + + if( (RegType== IntRegType && argNo < NumOfIntArgRegs)) { + isArgInReg = true; + UniArgReg = getUnifiedRegNum(RegClassID, SparcIntRegOrder::o0 + argNo ); + } + else if(RegType == FPSingleRegType && argNo < NumOfFloatArgRegs) { + isArgInReg = true; + UniArgReg = getUnifiedRegNum(RegClassID, + SparcFloatRegOrder::f0 + (argNo*2 + 1) ); + } + else if(RegType == FPDoubleRegType && argNo < NumOfFloatArgRegs) { + isArgInReg = true; + UniArgReg = getUnifiedRegNum(RegClassID, SparcFloatRegOrder::f0+argNo*2); } - } -} + + if( !LR ) { // possible because arg can be a const + + if( DEBUG_RA) { + cout << " Warning: In call instr, no LR for arg: " ; + printValue(*OpIt); cout << endl; + } + + //AdMI = cpValue2RegMI( ArgVal, UniArgReg, RegType); + //(CallAI->InstrnsBefore).push_back( AdMI ); + //cout << " *Constant moved to an output register\n"; + + continue; + } + + + // if the LR received the suggested color, NOTHING to do + + if( LR->hasSuggestedColor() && LR->hasColor() ) + if( LR->getSuggestedColor() == LR->getColor() ) + continue; + -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; + if( LR->hasColor() ) { - // 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. - } + // We are here because though the LR is allocated a register, it + // was not allocated the suggested register. So, we have to copy %ix reg + // (or stack pos of arg) to the register it was colored with + + + unsigned UniLRReg = getUnifiedRegNum( RegClassID, LR->getColor() ); + + if( isArgInReg ) + AdMI = cpReg2RegMI(UniLRReg, UniArgReg, RegType ); + + else + assert(0 && "TODO: Push an outgoing arg on stack"); + + // Now add the instruction + CallAI->InstrnsBefore.push_back( AdMI ); + + } + + else { // LR is not colored (i.e., spilled) + + assert(0 && "TODO: Copy a spilled call arg to an output reg "); + + } + + } // for each parameter in call instruction } -// Generates a copy machine instruction to copy a value to a given -// register. +//--------------------------------------------------------------------------- +// This method is called for an LLVM return instruction to identify which +// values will be returned from this method and to suggest colors. +//--------------------------------------------------------------------------- +void UltraSparcRegInfo::suggestReg4RetValue(const ReturnInst *const RetI, + LiveRangeInfo& LRI) const { + + + + assert( (RetI->getOpcode() == Instruction::Ret) && "Not a ret instr"); + + // get the return value of this return instruction + + const Value *RetVal = (RetI)->getReturnValue(); + + // if the method returns a value + if( RetVal ) { + + MachineInstr *AdMI; + LiveRange *const LR = LRI.getLiveRangeForValue( RetVal ); + + + if ( LR ) { + + unsigned RegClassID = (LR->getRegClass())->getID(); + + if( RegClassID == IntRegClassID ) + LR->setSuggestedColor(SparcIntRegOrder::i0); + + else if ( RegClassID == FloatRegClassID ) + LR->setSuggestedColor(SparcFloatRegOrder::f0); + + } + else { + if( DEBUG_RA ) + cout << "Warning: No LR for return value" << endl; + // possible since this can be returning a constant + } -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); + +} + +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +void UltraSparcRegInfo::colorRetValue(const ReturnInst *const RetI, + LiveRangeInfo& LRI, + AddedInstrns *const RetAI) const { + + + // get the return value of this return instruction + Value *RetVal = (Value *) (RetI)->getReturnValue(); + + // if the method returns a value + if( RetVal ) { + + MachineInstr *AdMI; + LiveRange *const LR = LRI.getLiveRangeForValue( RetVal ); + + unsigned RegClassID = getRegClassIDOfValue(RetVal); + unsigned RegType = getRegType( RetVal ); + unsigned UniRetReg = InvalidRegNum; + + if(RegClassID == IntRegClassID) + UniRetReg = getUnifiedRegNum( RegClassID, SparcIntRegOrder::i0 ); + else if(RegClassID == FloatRegClassID) + UniRetReg = getUnifiedRegNum( RegClassID, SparcFloatRegOrder::f0); + + if ( LR ) { + + // if the LR received the suggested color, NOTHING to do + + if( LR->hasSuggestedColor() && LR->hasColor() ) + if( LR->getSuggestedColor() == LR->getColor() ) + return; + + if( LR->hasColor() ) { + + // We are here because the LR was allocted a regiter, but NOT + // the correct register. + + // copy the LR of retun value to i0 or f0 + + unsigned UniLRReg =getUnifiedRegNum( RegClassID, LR->getColor()); + + if(RegClassID == IntRegClassID) + UniRetReg = getUnifiedRegNum( RegClassID, SparcIntRegOrder::i0); + else if(RegClassID == FloatRegClassID) + UniRetReg = getUnifiedRegNum( RegClassID, SparcFloatRegOrder::f0); + + AdMI = cpReg2RegMI( UniLRReg, UniRetReg, RegType); + + } + else + assert(0 && "TODO: Copy the return value from stack\n"); + + } else { + + // if NO LR we have to add an explicit copy to move the value to + // the return register. + + //AdMI = cpValue2RegMI( RetVal, UniRetReg, RegType); + //(RetAI->InstrnsBefore).push_back( AdMI ); + + // assert( 0 && "Returned constant must be moved to the ret reg\n"); + } + + + } // if there is a return value + +} + + +//--------------------------------------------------------------------------- +// Copy from a register to register. Register number must be the unified +// register number +//--------------------------------------------------------------------------- + + +MachineInstr * UltraSparcRegInfo::cpReg2RegMI(const unsigned SrcReg, + const unsigned DestReg, + const int RegType) const { + + assert( (SrcReg != InvalidRegNum) && (DestReg != InvalidRegNum) && + "Invalid Register"); + + MachineInstr * MI = NULL; + + switch( RegType ) { + + case IntRegType: + MI = new MachineInstr(ADD, 3); + MI->SetMachineOperand(0, SrcReg, false); + MI->SetMachineOperand(1, SparcIntRegOrder::g0, false); + MI->SetMachineOperand(2, DestReg, true); + break; + + case FPSingleRegType: + MI = new MachineInstr(FMOVS, 2); + MI->SetMachineOperand(0, SrcReg, false); + MI->SetMachineOperand(1, DestReg, true); + break; + + case FPDoubleRegType: + MI = new MachineInstr(FMOVD, 2); + MI->SetMachineOperand(0, SrcReg, false); + MI->SetMachineOperand(1, DestReg, true); + break; + + default: + assert(0 && "Unknow RegType"); } return MI; - } + + +//--------------------------------------------------------------------------- +// Only constant/label values are accepted. +// ***This code is temporary *** +//--------------------------------------------------------------------------- + + +MachineInstr * UltraSparcRegInfo::cpValue2RegMI(Value * Val, + const unsigned DestReg, + const int RegType) const { + + assert( (DestReg != InvalidRegNum) && "Invalid Register"); + + /* + unsigned MReg; + int64_t Imm; + + MachineOperand::MachineOperandType MOTypeInt = + ChooseRegOrImmed(Val, ADD, *UltraSparcInfo, true, MReg, Imm); + */ + + MachineOperand::MachineOperandType MOType; + + switch( Val->getValueType() ) { + + case Value::ConstantVal: + case Value::GlobalVal: + MOType = MachineOperand:: MO_UnextendedImmed; // TODO**** correct??? + break; + + case Value::BasicBlockVal: + case Value::MethodVal: + MOType = MachineOperand::MO_PCRelativeDisp; + break; + + default: + cout << "Value Type: " << Val->getValueType() << endl; + assert(0 && "Unknown val type - Only constants/globals/labels are valid"); + } + + + + MachineInstr * MI = NULL; + + switch( RegType ) { + + case IntRegType: + MI = new MachineInstr(ADD); + MI->SetMachineOperand(0, MOType, Val, false); + MI->SetMachineOperand(1, SparcIntRegOrder::g0, false); + MI->SetMachineOperand(2, DestReg, true); + break; + + case FPSingleRegType: + assert(0 && "FP const move not yet implemented"); + MI = new MachineInstr(FMOVS); + MI->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, Val, false); + MI->SetMachineOperand(1, DestReg, true); + break; + + case FPDoubleRegType: + assert(0 && "FP const move not yet implemented"); + MI = new MachineInstr(FMOVD); + MI->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, Val, false); + MI->SetMachineOperand(1, DestReg, true); + break; + + default: + assert(0 && "Unknow RegType"); + } + + return MI; +} + + + + + + + //--------------------------------------------------------------------------- // Print the register assigned to a LR //--------------------------------------------------------------------------- @@ -490,3 +783,8 @@ void UltraSparcRegInfo::printReg(const LiveRange *const LR) { } + + + + +