#include "llvm/Target/Sparc.h" #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" #include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h" #include "llvm/CodeGen/PhyRegAlloc.h" //--------------------------------------------------------------------------- // UltraSparcRegInfo //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // This method sets the hidden operand for return address in RETURN and // JMPL machine instructions. //--------------------------------------------------------------------------- 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(); // 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"); 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::i0 + argNo ); } else { // Do NOTHING as this will be colored as a normal value. if (DEBUG_RA) cout << " Int Regr not suggested for method arg\n"; } } 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) ); } } //--------------------------------------------------------------------------- // //--------------------------------------------------------------------------- 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 { 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. // the return value cannot have a LR in machine instruction since it is // only defined by the call instruction assert( (! LRI.getLiveRangeForValue( CallI ) ) && "LR for ret Value of call already definded!"); // if type is not void, create a new live range and set its // register class and add to LRI if( ! ((CallI->getType())->getPrimitiveID() == Type::VoidTyID) ) { // create a new LR for the return value LiveRange * RetValLR = new LiveRange(); RetValLR->add( CallI ); unsigned RegClassID = getRegClassIDOfValue( CallI ); RetValLR->setRegClass( RCList[RegClassID] ); LRI.addLRToMap( CallI, RetValLR); // 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"); } // 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; } 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 } //--------------------------------------------------------------------------- // 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::colorCallArgs(const CallInst *const CallI, LiveRangeInfo& LRI, AddedInstrns *const CallAI) const { // 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 ); if( RetValLR ) { bool recvSugColor = false; if( RetValLR->hasSuggestedColor() && RetValLR->hasColor() ) if( RetValLR->getSuggestedColor() == RetValLR->getColor()) recvSugColor = true; // 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 ); } // if LR has color else { 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; if( LR->hasColor() ) { // 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 } //--------------------------------------------------------------------------- // 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 { // 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::GlobalVariableVal: 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 //--------------------------------------------------------------------------- void UltraSparcRegInfo::printReg(const LiveRange *const LR) { unsigned RegClassID = (LR->getRegClass())->getID(); cout << " *Node " << (LR->getUserIGNode())->getIndex(); if( ! LR->hasColor() ) { cout << " - could not find a color" << endl; return; } // if a color is found cout << " colored with color "<< LR->getColor(); if( RegClassID == IntRegClassID ) { cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ; cout << "]" << endl; } else if ( RegClassID == FloatRegClassID) { cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor()); if( LR->getTypeID() == Type::DoubleTyID ) cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1); cout << "]" << endl; } }