{
/* 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;
}
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;
}
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 );
}
// 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
{
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){
*/
+ 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;
}
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 );
}
#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"
// 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
+//---------------------------------------------------------------------------
+// This method sets the hidden operand for return address in RETURN and
+// JMPL machine instructions.
+//---------------------------------------------------------------------------
+
+bool UltraSparcRegInfo::handleSpecialMInstr(const MachineInstr * MInst,
+ LiveRangeInfo& LRI,
+ vector<RegClass *>RCList) const {
+
+ unsigned OpCode = MInst->getOpCode();
-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.
+ // 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 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 gets the hidden value in a return register which is used to
+// pass the return address.
//---------------------------------------------------------------------------
-void UltraSparcRegInfo::colorArgs(const Method *const Meth,
- LiveRangeInfo& LRI) const
+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 ) {
+void UltraSparcRegInfo::colorMethodArgs(const Method *const Meth,
+ LiveRangeInfo& LRI,
+ AddedInstrns *const FirstAI) const {
- // 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
+ // get the argument list
+ const Method::ArgumentListType& ArgList = Meth->getArgumentList();
+ // get an iterator to arg list
+ Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
- assert(0 && "insert push code here for a double");
+ MachineInstr *AdMI;
- }
- }
- 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");
- }
+ // 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 && "unknown float type in method arg");
+ assert(0 && "TODO: Color an Incoming arg on stack");
- } // float register class
+ // Now add the instruction
+ FirstAI->InstrnsBefore.push_back( AdMI );
- else
- assert(0 && "Unknown RegClassID");
- }
-
-}
+ }
+
+ else { // LR is not colored (i.e., spilled)
+
+ assert(0 && "TODO: Color a spilled arg ");
+
+ }
+ } // for each incoming argument
+}
-void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
- CallInstrList, LiveRangeInfo& LRI,
- AddedInstrMapType &AddedInstrMap) const
-{
- vector<const Instruction *>::const_iterator InstIt;
+//---------------------------------------------------------------------------
+// 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<RegClass *> RCList) const {
+
- // First color the return value of all call instructions. The return value
+ assert( (CallI->getOpcode() == Instruction::Call) && "Not a call instr");
+
+ // 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
- unsigned RegClassID = (LR->getRegClass())->getID();
-
- if( RegClassID == IntRegClassID ) {
- LR->setColor(SparcIntRegOrder::o0);
- }
- else if (RegClassID == FloatRegClassID ) {
- LR->setColor(SparcFloatRegOrder::f0 );
+ 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");
+
+ }
+
+
+ // 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.
+
+ 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);
+
+ 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;
}
- else {
- cout << "Warning: No Live Range for return value of CALL" << endl;
+
+ unsigned RegType = getRegType( LR );
+
+ // 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;
+
}
- }
+ 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) );
+
+ } // for all call arguments
- 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();
+//---------------------------------------------------------------------------
+// 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.
+//---------------------------------------------------------------------------
- /*
- for( ; MIIt != MInstVec.end() &&
- ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
- ++MIIt );
- assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
- */
+void UltraSparcRegInfo::colorCallArgs(const CallInst *const CallI,
+ LiveRangeInfo& LRI,
+ AddedInstrns *const CallAI) const {
- 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;
+ // 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 );
- Instruction::op_const_iterator OpIt = CallI->op_begin();
+ if( RetValLR ) {
- unsigned intArgNo=0;
+ bool recvSugColor = false;
+ if( RetValLR->hasSuggestedColor() && RetValLR->hasColor() )
+ if( RetValLR->getSuggestedColor() == RetValLR->getColor())
+ recvSugColor = true;
- // to keep track of which float regs are allocated for argument passing
- bool FloatArgUsedArr[NumOfFloatArgRegs];
+ // if we didn't receive the suggested color for some reason,
+ // put copy instruction
- // init float arg used array
- for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
- FloatArgUsedArr[i] = false;
+ if( !recvSugColor ) {
- // go thru all the operands of LLVM instruction
- for( ; OpIt != CallI->op_end(); ++OpIt ) {
+ if( RetValLR->hasColor() ) {
- // get the LR of call operand (parameter)
- LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt);
+ unsigned RegType = getRegType( RetValLR );
+ unsigned RegClassID = (RetValLR->getRegClass())->getID();
- if ( !LR ) {
- cout << " Warning: In call instr, no LR for arg: " ;
- printValue(*OpIt);
- cout << endl;
- continue;
- }
+ unsigned UniRetLRReg=getUnifiedRegNum(RegClassID,RetValLR->getColor());
+ unsigned UniRetReg = InvalidRegNum;
- unsigned RegClassID = (LR->getRegClass())->getID();
+ // 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 );
- // 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);
- }
+ } // if LR has color
+ else {
- 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;
+ assert(0 && "LR of return value is splilled");
}
- // 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");
+ } // the LR didn't receive the suggested color
+
+ } // if there is a LR - i.e., return value is not void
+
- } // for each operand in a call instruction
+ // 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;
- } // for all call instrctions in CallInstrList
+ 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;
+ }
-void UltraSparcRegInfo::colorRetArg(vector<const Instruction *> &
- RetInstrList, LiveRangeInfo& LRI,
- AddedInstrMapType &AddedInstrMap) const
-{
+ //AdMI = cpValue2RegMI( ArgVal, UniArgReg, RegType);
+ //(CallAI->InstrnsBefore).push_back( AdMI );
+ //cout << " *Constant moved to an output register\n";
- vector<const Instruction *>::const_iterator InstIt;
+ continue;
+ }
+
+ // if the LR received the suggested color, NOTHING to do
- for(InstIt=RetInstrList.begin(); InstIt != RetInstrList.end(); ++InstIt) {
+ if( LR->hasSuggestedColor() && LR->hasColor() )
+ if( LR->getSuggestedColor() == LR->getColor() )
+ continue;
+
- const ReturnInst *const RetI = (ReturnInst *) *InstIt;
- // get the return value of this return instruction
- const Value *RetVal = (RetI)->getReturnValue();
- if( RetVal ) {
+
+ if( LR->hasColor() ) {
- // find the CALL/JMMPL machine instruction
- MachineCodeForVMInstr & MInstVec = RetI->getMachineInstrVec();
- MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
+ // 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
-
- /*
- for( ; MIIt != MInstVec.end() &&
- !getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode());
- ++MIIt ) {
- cout << "Inst = "<< TargetInstrDescriptors[(*MIIt)->getOpCode()].opCodeString << endl;
+ unsigned UniLRReg = getUnifiedRegNum( RegClassID, LR->getColor() );
+ if( isArgInReg )
+ AdMI = cpReg2RegMI(UniLRReg, UniArgReg, RegType );
- }
- assert((MIIt != MInstVec.end()) &&"No return machine instruction found");
-
- */
+ 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(getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode())
- && "First machine inst is not a RETURN Machine Instr");
+ assert(0 && "TODO: Copy a spilled call arg to an output reg ");
+ }
- // RET machine isntruction
- const MachineInstr *const RetMI = *MIIt;
+ } // for each parameter in call instruction
- 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;
- }
+//---------------------------------------------------------------------------
+// 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
}
+
+
}
+
+
}
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+void UltraSparcRegInfo::colorRetValue(const ReturnInst *const RetI,
+ LiveRangeInfo& LRI,
+ AddedInstrns *const RetAI) const {
-void UltraSparcRegInfo::setCallOrRetArgCol(LiveRange *const LR,
- const unsigned RegNo,
- const MachineInstr *MI,
- AddedInstrMapType &AIMap) const {
+ // get the return value of this return instruction
+ Value *RetVal = (Value *) (RetI)->getReturnValue();
- // 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 {
+ // 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
- // 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
+ if( LR->hasSuggestedColor() && LR->hasColor() )
+ if( LR->getSuggestedColor() == LR->getColor() )
+ return;
- MachineInstr *MI = getCopy2RegMI((*(LR->begin())), RegNo,
- (LR->getRegClass())->getID());
+ if( LR->hasColor() ) {
- AddedInstrns * AI = AIMap[ MI ]; // get already added instrns for MI
- if( ! AI ) AI = new AddedInstrns();
+ // We are here because the LR was allocted a regiter, but NOT
+ // the correct register.
- AI->InstrnsBefore.push_back( MI ); // add the new MI yp AMI
- AIMap[ MI ] = AI;
+ // 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");
- cout << "Inserted a copy instr for a RET/CALL instr " << endl;
+ } else {
- // 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.
- }
+ // 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
}
-// 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;
+//---------------------------------------------------------------------------
+// Copy from a register to register. Register number must be the unified
+// register number
+//---------------------------------------------------------------------------
+
- if( RegClassID == IntRegClassID ) { // if integer move
+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, MachineOperand::MO_VirtualRegister, SrcVal);
+ MI->SetMachineOperand(0, SrcReg, false);
MI->SetMachineOperand(1, SparcIntRegOrder::g0, false);
- MI->SetMachineOperand(2, Reg, true);
+ 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");
}
- 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");
+ return MI;
+}
+
+
+
- MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
- MI->SetMachineOperand(1, Reg, true);
+//---------------------------------------------------------------------------
+// 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");
}
- return MI;
+
+ 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
//---------------------------------------------------------------------------
}
+
+
+
+
+