added support for suggesting colors
llvm-svn: 671
diff --git a/llvm/lib/Target/Sparc/SparcRegInfo.cpp b/llvm/lib/Target/Sparc/SparcRegInfo.cpp
index 8254b00..0a2570e 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,
+ vector<RegClass *>RCList) 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<RegClass *> RCList) const {
-void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
- CallInstrList, LiveRangeInfo& LRI,
- AddedInstrMapType &AddedInstrMap) const
-{
+ assert( (CallI->getOpcode() == Instruction::Call) && "Not a call instr");
- vector<const Instruction *>::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
- 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;
- }
+ 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");
+
}
- 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<const Instruction *> &
- RetInstrList, LiveRangeInfo& LRI,
- AddedInstrMapType &AddedInstrMap) const
-{
-
- vector<const Instruction *>::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 {
-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);
+ 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
+ }
+
+
+
}
- 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 @@
}
+
+
+
+
+