X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparcV9%2FSparcV9RegInfo.cpp;h=f6ad9c69387ca1a5f97d5854e517242bf7600d97;hb=a2bae305fb5a870c4ef753ed290a7ddea73ec82b;hp=89f699b368f8090f744fe9e51de6255b343a7b1a;hpb=0b0ffa0800c51589a3b2f2371c9f6a0092bddaeb;p=oota-llvm.git diff --git a/lib/Target/SparcV9/SparcV9RegInfo.cpp b/lib/Target/SparcV9/SparcV9RegInfo.cpp index 89f699b368f..f6ad9c69387 100644 --- a/lib/Target/SparcV9/SparcV9RegInfo.cpp +++ b/lib/Target/SparcV9/SparcV9RegInfo.cpp @@ -8,26 +8,33 @@ #include "SparcInternals.h" #include "SparcRegClassInfo.h" #include "llvm/Target/Sparc.h" -#include "llvm/CodeGen/MachineCodeForMethod.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/PhyRegAlloc.h" +#include "llvm/CodeGen/InstrSelection.h" +#include "llvm/CodeGen/InstrSelectionSupport.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h" +#include "llvm/CodeGen/MachineInstrAnnot.h" +#include "llvm/CodeGen/RegAllocCommon.h" +#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h" #include "llvm/iTerminators.h" #include "llvm/iOther.h" +#include "llvm/Function.h" #include "llvm/DerivedTypes.h" #include +#include using std::cerr; +using std::vector; UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc &tgt) - : MachineRegInfo(tgt), UltraSparcInfo(&tgt), NumOfIntArgRegs(6), + : MachineRegInfo(tgt), NumOfIntArgRegs(6), NumOfFloatArgRegs(32), InvalidRegNum(1000) { MachineRegClassArr.push_back(new SparcIntRegClass(IntRegClassID)); MachineRegClassArr.push_back(new SparcFloatRegClass(FloatRegClassID)); MachineRegClassArr.push_back(new SparcIntCCRegClass(IntCCRegClassID)); MachineRegClassArr.push_back(new SparcFloatCCRegClass(FloatCCRegClassID)); - - assert(SparcFloatRegOrder::StartOfNonVolatileRegs == 32 && + + assert(SparcFloatRegClass::StartOfNonVolatileRegs == 32 && "32 Float regs are used for float arg passing"); } @@ -36,16 +43,16 @@ UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc &tgt) // this is the unified register number // int UltraSparcRegInfo::getZeroRegNum() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::g0); + return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, + SparcIntRegClass::g0); } // getCallAddressReg - returns the reg used for pushing the address when a // method is called. This can be used for other purposes between calls // unsigned UltraSparcRegInfo::getCallAddressReg() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::o7); + return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, + SparcIntRegClass::o7); } // Returns the register containing the return address. @@ -53,22 +60,73 @@ unsigned UltraSparcRegInfo::getCallAddressReg() const { // value when a return instruction is reached. // unsigned UltraSparcRegInfo::getReturnAddressReg() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::i7); + return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, + SparcIntRegClass::i7); +} + +// Register get name implementations... + +// Int register names in same order as enum in class SparcIntRegClass +static const char * const IntRegNames[] = { + "o0", "o1", "o2", "o3", "o4", "o5", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", + "i6", "i7", + "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o6" +}; + +const char * const SparcIntRegClass::getRegName(unsigned reg) { + assert(reg < NumOfAllRegs); + return IntRegNames[reg]; +} + +static const char * const FloatRegNames[] = { + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", + "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", + "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", + "f30", "f31", "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39", + "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", "f48", "f49", + "f50", "f51", "f52", "f53", "f54", "f55", "f56", "f57", "f58", "f59", + "f60", "f61", "f62", "f63" +}; + +const char * const SparcFloatRegClass::getRegName(unsigned reg) { + assert (reg < NumOfAllRegs); + return FloatRegNames[reg]; +} + + +static const char * const IntCCRegNames[] = { + "xcc", "ccr" +}; + +const char * const SparcIntCCRegClass::getRegName(unsigned reg) { + assert(reg < 2); + return IntCCRegNames[reg]; +} + +static const char * const FloatCCRegNames[] = { + "fcc0", "fcc1", "fcc2", "fcc3" +}; + +const char * const SparcFloatCCRegClass::getRegName(unsigned reg) { + assert (reg < 4); + return FloatCCRegNames[reg]; } // given the unified register number, this gives the name // for generating assembly code or debugging. // -const std::string UltraSparcRegInfo::getUnifiedRegName(int reg) const { +const char * const UltraSparcRegInfo::getUnifiedRegName(int reg) const { if( reg < 32 ) - return SparcIntRegOrder::getRegName(reg); + return SparcIntRegClass::getRegName(reg); else if ( reg < (64 + 32) ) - return SparcFloatRegOrder::getRegName( reg - 32); + return SparcFloatRegClass::getRegName( reg - 32); else if( reg < (64+32+4) ) - return SparcFloatCCRegOrder::getRegName( reg -32 - 64); + return SparcFloatCCRegClass::getRegName( reg -32 - 64); else if( reg < (64+32+4+2) ) // two names: %xcc and %ccr - return SparcIntCCRegOrder::getRegName( reg -32 - 64 - 4); + return SparcIntCCRegClass::getRegName( reg -32 - 64 - 4); else if (reg== InvalidRegNum) //****** TODO: Remove */ return "<*NoReg*>"; else @@ -78,214 +136,201 @@ const std::string UltraSparcRegInfo::getUnifiedRegName(int reg) const { // Get unified reg number for frame pointer unsigned UltraSparcRegInfo::getFramePointer() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::i6); + return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, + SparcIntRegClass::i6); } // Get unified reg number for stack pointer unsigned UltraSparcRegInfo::getStackPointer() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::o6); + return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, + SparcIntRegClass::o6); } - //--------------------------------------------------------------------------- -// Finds the return value of a sparc specific call instruction +// Finds whether a call is an indirect call //--------------------------------------------------------------------------- -const Value * -UltraSparcRegInfo::getCallInstRetVal(const MachineInstr *CallMI) const { - unsigned OpCode = CallMI->getOpCode(); - unsigned NumOfImpRefs = CallMI->getNumImplicitRefs(); - - if (OpCode == CALL) { - - // The one before the last implicit operand is the return value of - // a CALL instr - // - if( NumOfImpRefs > 1 ) - if (CallMI->implicitRefIsDefined(NumOfImpRefs-2)) - return CallMI->getImplicitRef(NumOfImpRefs-2); +inline bool +isVarArgsFunction(const Type *funcType) { + return cast(cast(funcType) + ->getElementType())->isVarArg(); +} - } else if (OpCode == JMPLCALL) { +inline bool +isVarArgsCall(const MachineInstr *CallMI) { + Value* callee = CallMI->getOperand(0).getVRegValue(); + // const Type* funcType = isa(callee)? callee->getType() + // : cast(callee->getType())->getElementType(); + const Type* funcType = callee->getType(); + return isVarArgsFunction(funcType); +} - // The last implicit operand is the return value of a JMPL - // - if(NumOfImpRefs > 0) - if (CallMI->implicitRefIsDefined(NumOfImpRefs-1)) - return CallMI->getImplicitRef(NumOfImpRefs-1); - } else - assert(0 && "OpCode must be CALL/JMPL for a call instr"); - return NULL; +// Get the register number for the specified integer arg#, +// assuming there are argNum total args, intArgNum int args, +// and fpArgNum FP args preceding (and not including) this one. +// Use INT regs for FP args if this is a varargs call. +// +// Return value: +// InvalidRegNum, if there is no int register available for the arg. +// regNum, otherwise (this is NOT the unified reg. num). +// +inline int +UltraSparcRegInfo::regNumForIntArg(bool inCallee, bool isVarArgsCall, + unsigned argNo, + unsigned intArgNo, unsigned fpArgNo, + unsigned& regClassId) const +{ + regClassId = IntRegClassID; + if (argNo >= NumOfIntArgRegs) + return InvalidRegNum; + else + return argNo + (inCallee? SparcIntRegClass::i0 : SparcIntRegClass::o0); } - -const Value * -UltraSparcRegInfo::getCallInstIndirectAddrVal(const MachineInstr *CallMI) const +// Get the register number for the specified FP arg#, +// assuming there are argNum total args, intArgNum int args, +// and fpArgNum FP args preceding (and not including) this one. +// Use INT regs for FP args if this is a varargs call. +// +// Return value: +// InvalidRegNum, if there is no int register available for the arg. +// regNum, otherwise (this is NOT the unified reg. num). +// +inline int +UltraSparcRegInfo::regNumForFPArg(unsigned regType, + bool inCallee, bool isVarArgsCall, + unsigned argNo, + unsigned intArgNo, unsigned fpArgNo, + unsigned& regClassId) const { - return (CallMI->getOpCode() == JMPLCALL)? - CallMI->getOperand(0).getVRegValue() : NULL; + if (isVarArgsCall) + return regNumForIntArg(inCallee, isVarArgsCall, argNo, intArgNo, fpArgNo, + regClassId); + else + { + regClassId = FloatRegClassID; + if (regType == FPSingleRegType) + return (argNo*2+1 >= NumOfFloatArgRegs)? + InvalidRegNum : SparcFloatRegClass::f0 + (argNo * 2 + 1); + else if (regType == FPDoubleRegType) + return (argNo*2 >= NumOfFloatArgRegs)? + InvalidRegNum : SparcFloatRegClass::f0 + (argNo * 2); + else + assert(0 && "Illegal FP register type"); + return 0; + } } //--------------------------------------------------------------------------- // Finds the return address of a call sparc specific call instruction //--------------------------------------------------------------------------- -const Value * -UltraSparcRegInfo::getCallInstRetAddr(const MachineInstr *CallMI) const { - unsigned OpCode = CallMI->getOpCode(); - - if (OpCode == CALL) { - unsigned NumOfImpRefs = CallMI->getNumImplicitRefs(); - assert( NumOfImpRefs && "CALL instr must have at least on ImpRef"); - - // The last implicit operand is the return address of a CALL instr - // - return CallMI->getImplicitRef(NumOfImpRefs-1); - - } else if(OpCode == JMPLCALL) { - MachineOperand &MO = (MachineOperand &)CallMI->getOperand(2); - return MO.getVRegValue(); - } - - assert(0 && "OpCode must be CALL/JMPL for a call instr"); - return 0; -} - -// The following 3 methods are used to find the RegType (see enum above) -// of a LiveRange, Value and using the unified RegClassID +// The following 4 methods are used to find the RegType (SparcInternals.h) +// of a LiveRange, a Value, and for a given register unified reg number. // -int UltraSparcRegInfo::getRegType(const LiveRange *LR) const { - switch (LR->getRegClass()->getID()) { +int UltraSparcRegInfo::getRegType(unsigned regClassID, + const Type* type) const { + switch (regClassID) { case IntRegClassID: return IntRegType; case FloatRegClassID: { - const Type *Typ = LR->getType(); - if (Typ == Type::FloatTy) + if (type == Type::FloatTy) return FPSingleRegType; - else if (Typ == Type::DoubleTy) + else if (type == Type::DoubleTy) return FPDoubleRegType; assert(0 && "Unknown type in FloatRegClass"); } - case IntCCRegClassID: return IntCCRegType; + case IntCCRegClassID: return IntCCRegType; case FloatCCRegClassID: return FloatCCRegType; - default: assert( 0 && "Unknown reg class ID"); - return 0; + default: assert( 0 && "Unknown reg class ID"); return 0; } } +int UltraSparcRegInfo::getRegType(const LiveRange *LR) const { + return getRegType(LR->getRegClass()->getID(), LR->getType()); +} + int UltraSparcRegInfo::getRegType(const Value *Val) const { - unsigned Typ; - - switch (getRegClassIDOfValue(Val)) { - case IntRegClassID: return IntRegType; - case FloatRegClassID: - Typ = Val->getType()->getPrimitiveID(); - if (Typ == Type::FloatTyID) - return FPSingleRegType; - else if (Typ == Type::DoubleTyID) - return FPDoubleRegType; - assert(0 && "Unknown type in FloatRegClass"); - - case IntCCRegClassID: return IntCCRegType; - case FloatCCRegClassID: return FloatCCRegType ; - default: assert(0 && "Unknown reg class ID"); - return 0; - } + return getRegType(getRegClassIDOfValue(Val), Val->getType()); } -int UltraSparcRegInfo::getRegType(int reg) const { - if (reg < 32) +int UltraSparcRegInfo::getRegType(int unifiedRegNum) const { + if (unifiedRegNum < 32) return IntRegType; - else if (reg < (32 + 32)) + else if (unifiedRegNum < (32 + 32)) return FPSingleRegType; - else if (reg < (64 + 32)) + else if (unifiedRegNum < (64 + 32)) return FPDoubleRegType; - else if (reg < (64+32+4)) + else if (unifiedRegNum < (64+32+4)) return FloatCCRegType; - else if (reg < (64+32+4+2)) + else if (unifiedRegNum < (64+32+4+2)) return IntCCRegType; else - assert(0 && "Invalid register number in getRegType"); + assert(0 && "Invalid unified register number in getRegType"); return 0; } - - - -//--------------------------------------------------------------------------- -// Finds the # of actual arguments of the call instruction -//--------------------------------------------------------------------------- -unsigned -UltraSparcRegInfo::getCallInstNumArgs(const MachineInstr *CallMI) const { - - unsigned OpCode = CallMI->getOpCode(); - unsigned NumOfImpRefs = CallMI->getNumImplicitRefs(); - - if (OpCode == CALL) { - switch (NumOfImpRefs) { - case 0: assert(0 && "A CALL inst must have at least one ImpRef (RetAddr)"); - case 1: return 0; - default: // two or more implicit refs - if (CallMI->implicitRefIsDefined(NumOfImpRefs-2)) - return NumOfImpRefs - 2; - else - return NumOfImpRefs - 1; - } - } else if (OpCode == JMPLCALL) { - - // The last implicit operand is the return value of a JMPL instr - if( NumOfImpRefs > 0 ) { - if (CallMI->implicitRefIsDefined(NumOfImpRefs-1)) - return NumOfImpRefs - 1; - else - return NumOfImpRefs; - } - else - return NumOfImpRefs; +// To find the register class used for a specified Type +// +unsigned UltraSparcRegInfo::getRegClassIDOfType(const Type *type, + bool isCCReg) const { + Type::PrimitiveID ty = type->getPrimitiveID(); + unsigned res; + + // FIXME: Comparing types like this isn't very safe... + if ((ty && ty <= Type::LongTyID) || (ty == Type::LabelTyID) || + (ty == Type::FunctionTyID) || (ty == Type::PointerTyID) ) + res = IntRegClassID; // sparc int reg (ty=0: void) + else if (ty <= Type::DoubleTyID) + res = FloatRegClassID; // sparc float reg class + else { + //std::cerr << "TypeID: " << ty << "\n"; + assert(0 && "Cannot resolve register class for type"); + return 0; } - - assert(0 && "OpCode must be CALL/JMPL for a call instr"); - return 0; + + if(isCCReg) + return res + 2; // corresponidng condition code regiser + else + return res; } - - -//--------------------------------------------------------------------------- -// Finds whether a call is an indirect call -//--------------------------------------------------------------------------- -bool UltraSparcRegInfo::isVarArgCall(const MachineInstr *CallMI) const { - - assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) ); - - const MachineOperand & calleeOp = CallMI->getOperand(0); - Value *calleeVal = calleeOp.getVRegValue(); - - PointerType *PT = cast(calleeVal->getType()); - return cast(PT->getElementType())->isVarArg(); +// To find the register class to which a specified register belongs +// +unsigned UltraSparcRegInfo::getRegClassIDOfReg(int unifiedRegNum) const { + unsigned classId = 0; + (void) getClassRegNum(unifiedRegNum, classId); + return classId; } - - +unsigned UltraSparcRegInfo::getRegClassIDOfRegType(int regType) const { + switch(regType) { + case IntRegType: return IntRegClassID; + case FPSingleRegType: + case FPDoubleRegType: return FloatRegClassID; + case IntCCRegType: return IntCCRegClassID; + case FloatCCRegType: return FloatCCRegClassID; + default: + assert(0 && "Invalid register type in getRegClassIDOfRegType"); + return 0; + } +} //--------------------------------------------------------------------------- // Suggests a register for the ret address in the RET machine instruction. // We always suggest %i7 by convention. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestReg4RetAddr(const MachineInstr *RetMI, +void UltraSparcRegInfo::suggestReg4RetAddr(MachineInstr *RetMI, LiveRangeInfo& LRI) const { - assert( (RetMI->getNumOperands() >= 2) - && "JMPL/RETURN must have 3 and 2 operands respectively"); + assert(target.getInstrInfo().isReturn(RetMI->getOpCode())); - MachineOperand & MO = ( MachineOperand &) RetMI->getOperand(0); - - // return address is always mapped to i7 - // - MO.setRegForValue( getUnifiedRegNum( IntRegClassID, SparcIntRegOrder::i7) ); + // return address is always mapped to i7 so set it immediately + RetMI->SetRegForOperand(0, getUnifiedRegNum(IntRegClassID, + SparcIntRegClass::i7)); // Possible Optimization: // Instead of setting the color, we can suggest one. In that case, @@ -293,11 +338,12 @@ void UltraSparcRegInfo::suggestReg4RetAddr(const MachineInstr *RetMI, // In that case, a LR has to be created at the start of method. // It has to be done as follows (remove the setRegVal above): + // MachineOperand & MO = RetMI->getOperand(0); // const Value *RetAddrVal = MO.getVRegValue(); // assert( RetAddrVal && "LR for ret address must be created at start"); // LiveRange * RetAddrLR = LRI.getLiveRangeForValue( RetAddrVal); // RetAddrLR->setSuggestedColor(getUnifiedRegNum( IntRegClassID, - // SparcIntRegOrdr::i7) ); + // SparcIntRegOrdr::i7) ); } @@ -305,28 +351,24 @@ void UltraSparcRegInfo::suggestReg4RetAddr(const MachineInstr *RetMI, // Suggests a register for the ret address in the JMPL/CALL machine instr. // Sparc ABI dictates that %o7 be used for this purpose. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestReg4CallAddr(const MachineInstr * CallMI, - LiveRangeInfo& LRI, - std::vector RCList) const { - +void +UltraSparcRegInfo::suggestReg4CallAddr(MachineInstr * CallMI, + LiveRangeInfo& LRI) const +{ + CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); + const Value *RetAddrVal = argDesc->getReturnAddrReg(); + assert(RetAddrVal && "INTERNAL ERROR: Return address value is required"); - const Value *RetAddrVal = getCallInstRetAddr( CallMI ); + // A LR must already exist for the return address. + LiveRange *RetAddrLR = LRI.getLiveRangeForValue(RetAddrVal); + assert(RetAddrLR && "INTERNAL ERROR: No LR for return address of call!"); - // RetAddrVal cannot be NULL (asserted in getCallInstRetAddr) - // create a new LR for the return address and color it - - LiveRange * RetAddrLR = new LiveRange(); - RetAddrLR->insert( RetAddrVal ); - unsigned RegClassID = getRegClassIDOfValue( RetAddrVal ); - RetAddrLR->setRegClass( RCList[RegClassID] ); - RetAddrLR->setColor(getUnifiedRegNum(IntRegClassID,SparcIntRegOrder::o7)); - LRI.addLRToMap( RetAddrVal, RetAddrLR); - + unsigned RegClassID = RetAddrLR->getRegClass()->getID(); + RetAddrLR->setColor(getUnifiedRegNum(IntRegClassID, SparcIntRegClass::o7)); } - //--------------------------------------------------------------------------- // This method will suggest colors to incoming args to a method. // According to the Sparc ABI, the first 6 incoming args are in @@ -337,47 +379,32 @@ void UltraSparcRegInfo::suggestReg4CallAddr(const MachineInstr * CallMI, void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth, LiveRangeInfo& LRI) const { - - // get the argument list - const Function::ArgumentListType& ArgList = Meth->getArgumentList(); - // get an iterator to arg list - Function::ArgumentListType::const_iterator ArgIt = ArgList.begin(); - - // for each argument - for( unsigned argNo=0; ArgIt != ArgList.end() ; ++ArgIt, ++argNo) { - + // check if this is a varArgs function. needed for choosing regs. + bool isVarArgs = isVarArgsFunction(Meth->getType()); + + // for each argument. count INT and FP arguments separately. + unsigned argNo=0, intArgNo=0, fpArgNo=0; + for(Function::const_aiterator I = Meth->abegin(), E = Meth->aend(); + I != E; ++I, ++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) cerr << " Int Regr not suggested for method arg\n"; - } - - } - else if( RegType==FPSingleRegType && (argNo*2+1) < NumOfFloatArgRegs) - LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2 + 1) ); + LiveRange *LR = LRI.getLiveRangeForValue(I); + assert(LR && "No live range found for method arg"); - - else if( RegType == FPDoubleRegType && (argNo*2) < NumOfFloatArgRegs) - LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2) ); + unsigned regType = getRegType(LR); + unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg (unused) + int regNum = (regType == IntRegType) + ? regNumForIntArg(/*inCallee*/ true, isVarArgs, + argNo, intArgNo++, fpArgNo, regClassIDOfArgReg) + : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs, + argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); + + if(regNum != InvalidRegNum) + LR->setSuggestedColor(regNum); } } - //--------------------------------------------------------------------------- // This method is called after graph coloring to move incoming args to // the correct hardware registers if they did not receive the correct @@ -387,44 +414,39 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth, LiveRangeInfo &LRI, AddedInstrns *FirstAI) const { - // get the argument list - const Function::ArgumentListType& ArgList = Meth->getArgumentList(); - // get an iterator to arg list - Function::ArgumentListType::const_iterator ArgIt = ArgList.begin(); + // check if this is a varArgs function. needed for choosing regs. + bool isVarArgs = isVarArgsFunction(Meth->getType()); MachineInstr *AdMI; - // for each argument - for( unsigned argNo=0; ArgIt != ArgList.end() ; ++ArgIt, ++argNo) { - + // for each argument. count INT and FP arguments separately. + unsigned argNo=0, intArgNo=0, fpArgNo=0; + for(Function::const_aiterator I = Meth->abegin(), E = Meth->aend(); + I != E; ++I, ++argNo) { // get the LR of arg - LiveRange *LR = LRI.getLiveRangeForValue(*ArgIt); + LiveRange *LR = LRI.getLiveRangeForValue(I); assert( LR && "No live range found for method arg"); - - unsigned RegType = getRegType( LR ); + unsigned regType = getRegType( LR ); unsigned RegClassID = (LR->getRegClass())->getID(); - + // Find whether this argument is coming in a register (if not, on stack) - // Also find the correct register that the argument must go (UniArgReg) + // Also find the correct register the argument must use (UniArgReg) // bool isArgInReg = false; unsigned UniArgReg = InvalidRegNum; // reg that LR MUST be colored with - - if( (RegType== IntRegType && argNo < NumOfIntArgRegs)) { - isArgInReg = true; - UniArgReg = getUnifiedRegNum( RegClassID, SparcIntRegOrder::i0 + argNo ); - } - else if(RegType == FPSingleRegType && argNo < NumOfFloatArgRegs) { - isArgInReg = true; - UniArgReg = getUnifiedRegNum( RegClassID, - SparcFloatRegOrder::f0 + argNo*2 + 1 ) ; - } - else if(RegType == FPDoubleRegType && argNo < NumOfFloatArgRegs) { + unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg + + int regNum = (regType == IntRegType) + ? regNumForIntArg(/*inCallee*/ true, isVarArgs, + argNo, intArgNo++, fpArgNo, regClassIDOfArgReg) + : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs, + argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); + + if(regNum != InvalidRegNum) { isArgInReg = true; - UniArgReg = getUnifiedRegNum(RegClassID, SparcFloatRegOrder::f0+argNo*2); + UniArgReg = getUnifiedRegNum( regClassIDOfArgReg, regNum); } - if( LR->hasColor() ) { // if this arg received a register @@ -443,30 +465,43 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth, // if the arg is coming in UniArgReg register, it MUST go into // the UniLRReg register // - if( isArgInReg ) - AdMI = cpReg2RegMI( UniArgReg, UniLRReg, RegType ); - + if( isArgInReg ) { + if( regClassIDOfArgReg != RegClassID ) { + assert(0 && "This could should work but it is not tested yet"); + + // It is a variable argument call: the float reg must go in a %o reg. + // We have to move an int reg to a float reg via memory. + // + assert(isVarArgs && + RegClassID == FloatRegClassID && + regClassIDOfArgReg == IntRegClassID && + "This should only be an Int register for an FP argument"); + + int TmpOff = MachineFunction::get(Meth).pushTempValue(target, + getSpilledRegSize(regType)); + cpReg2MemMI(FirstAI->InstrnsBefore, + UniArgReg, getFramePointer(), TmpOff, IntRegType); + + cpMem2RegMI(FirstAI->InstrnsBefore, + getFramePointer(), TmpOff, UniLRReg, regType); + } + else { + cpReg2RegMI(FirstAI->InstrnsBefore, UniArgReg, UniLRReg, regType); + } + } else { // Now the arg is coming on stack. Since the LR recieved a register, // we just have to load the arg on stack into that register // const MachineFrameInfo& frameInfo = target.getFrameInfo(); - assert(frameInfo.argsOnStackHaveFixedSize()); - - bool growUp; // find the offset of arg in stack frame - int firstArg = - frameInfo.getFirstIncomingArgOffset(MachineCodeForMethod::get(Meth), - growUp); int offsetFromFP = - growUp? firstArg + argNo * frameInfo.getSizeOfEachArgOnStack() - : firstArg - argNo * frameInfo.getSizeOfEachArgOnStack(); + frameInfo.getIncomingArgOffset(MachineFunction::get(Meth), + argNo); - AdMI = cpMem2RegMI(getFramePointer(), offsetFromFP, - UniLRReg, RegType ); + cpMem2RegMI(FirstAI->InstrnsBefore, + getFramePointer(), offsetFromFP, UniLRReg, regType); } - - FirstAI->InstrnsBefore.push_back( AdMI ); } // if LR received a color @@ -478,28 +513,39 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth, // that on to the stack pos of LR if( isArgInReg ) { - cpReg2MemMI(UniArgReg, getFramePointer(), - LR->getSpillOffFromFP(), RegType ); - - FirstAI->InstrnsBefore.push_back( AdMI ); + + if( regClassIDOfArgReg != RegClassID ) { + assert(0 && + "FP arguments to a varargs function should be explicitly " + "copied to/from int registers by instruction selection!"); + + // It must be a float arg for a variable argument call, which + // must come in a %o reg. Move the int reg to the stack. + // + assert(isVarArgs && regClassIDOfArgReg == IntRegClassID && + "This should only be an Int register for an FP argument"); + + cpReg2MemMI(FirstAI->InstrnsBefore, UniArgReg, + getFramePointer(), LR->getSpillOffFromFP(), IntRegType); + } + else { + cpReg2MemMI(FirstAI->InstrnsBefore, UniArgReg, + getFramePointer(), LR->getSpillOffFromFP(), regType); + } } else { // Now the arg is coming on stack. Since the LR did NOT // recieved a register as well, it is allocated a stack position. We - // can simply change the stack poistion of the LR. We can do this, + // can simply change the stack position of the LR. We can do this, // since this method is called before any other method that makes // uses of the stack pos of the LR (e.g., updateMachineInstr) const MachineFrameInfo& frameInfo = target.getFrameInfo(); - assert(frameInfo.argsOnStackHaveFixedSize()); - - bool growUp; - int firstArg = frameInfo.getFirstIncomingArgOffset(MachineCodeForMethod::get(Meth), growUp); int offsetFromFP = - growUp? firstArg + argNo * frameInfo.getSizeOfEachArgOnStack() - : firstArg - argNo * frameInfo.getSizeOfEachArgOnStack(); + frameInfo.getIncomingArgOffset(MachineFunction::get(Meth), + argNo); LR->modifySpillOffFromFP( offsetFromFP ); } @@ -516,115 +562,197 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth, // 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 MachineInstr *CallMI, - LiveRangeInfo& LRI, - std::vector RCList) const { - - assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) ); - - suggestReg4CallAddr(CallMI, LRI, RCList); - - - // 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 - - // if type is not void, create a new live range and set its - // register class and add to LRI +void UltraSparcRegInfo::suggestRegs4CallArgs(MachineInstr *CallMI, + LiveRangeInfo& LRI) const { + assert ( (target.getInstrInfo()).isCall(CallMI->getOpCode()) ); + CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); + + suggestReg4CallAddr(CallMI, LRI); - const Value *RetVal = getCallInstRetVal( CallMI ); + // First color the return value of the call instruction, if any. + // The return value will be in %o0 if the value is an integer type, + // or in %f0 if the value is a float type. + // + if (const Value *RetVal = argDesc->getReturnValue()) { + LiveRange *RetValLR = LRI.getLiveRangeForValue(RetVal); + assert(RetValLR && "No LR for return Value of call!"); + unsigned RegClassID = RetValLR->getRegClass()->getID(); - if (RetVal) { - assert ((!LRI.getLiveRangeForValue(RetVal)) && - "LR for ret Value of call already definded!"); - - // create a new LR for the return value - LiveRange *RetValLR = new LiveRange(); - RetValLR->insert(RetVal); - unsigned RegClassID = getRegClassIDOfValue(RetVal); - RetValLR->setRegClass(RCList[RegClassID]); - LRI.addLRToMap(RetVal, RetValLR); - // now suggest a register depending on the register class of ret arg - if( RegClassID == IntRegClassID ) - RetValLR->setSuggestedColor(SparcIntRegOrder::o0); + RetValLR->setSuggestedColor(SparcIntRegClass::o0); else if (RegClassID == FloatRegClassID ) - RetValLR->setSuggestedColor(SparcFloatRegOrder::f0 ); + RetValLR->setSuggestedColor(SparcFloatRegClass::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. // Now, go thru call args - implicit operands of the call MI - unsigned NumOfCallArgs = getCallInstNumArgs( CallMI ); + unsigned NumOfCallArgs = argDesc->getNumArgs(); - for(unsigned argNo=0, i=0; i < NumOfCallArgs; ++i, ++argNo ) { + for(unsigned argNo=0, i=0, intArgNo=0, fpArgNo=0; + i < NumOfCallArgs; ++i, ++argNo) { - const Value *CallArg = CallMI->getImplicitRef(i); + const Value *CallArg = argDesc->getArgInfo(i).getArgVal(); // get the LR of call operand (parameter) LiveRange *const LR = LRI.getLiveRangeForValue(CallArg); - - // not possible to have a null LR since all args (even consts) - // must be defined before - if (!LR) { - cerr << " ERROR: In call instr, no LR for arg: " << RAV(CallArg) << "\n"; - assert(0 && "NO LR for call arg"); - } + assert (LR && "Must have a LR for all arguments since " + "all args (even consts) must be defined before"); + + unsigned regType = getRegType( LR ); + unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg (unused) + + // Choose a register for this arg depending on whether it is + // an INT or FP value. Here we ignore whether or not it is a + // varargs calls, because FP arguments will be explicitly copied + // to an integer Value and handled under (argCopy != NULL) below. + int regNum = (regType == IntRegType) + ? regNumForIntArg(/*inCallee*/ false, /*isVarArgs*/ false, + argNo, intArgNo++, fpArgNo, regClassIDOfArgReg) + : regNumForFPArg(regType, /*inCallee*/ false, /*isVarArgs*/ false, + argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); - unsigned RegType = getRegType( LR ); + // If a register could be allocated, use it. + // If not, do NOTHING as this will be colored as a normal value. + if(regNum != InvalidRegNum) + LR->setSuggestedColor(regNum); + + // Repeat for the second copy of the argument, which would be + // an FP argument being passed to a function with no prototype + const Value *argCopy = argDesc->getArgInfo(i).getArgCopy(); + if (argCopy != NULL) + { + assert(regType != IntRegType && argCopy->getType()->isInteger() + && "Must be passing copy of FP argument in int register"); + int copyRegNum = regNumForIntArg(/*inCallee*/false, /*isVarArgs*/false, + argNo, intArgNo, fpArgNo-1, + regClassIDOfArgReg); + assert(copyRegNum != InvalidRegNum); + LiveRange *const copyLR = LRI.getLiveRangeForValue(argCopy); + copyLR->setSuggestedColor(copyRegNum); + } + + } // for all call arguments - // 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. - cerr << " Regr not suggested for int call arg\n"; - +//--------------------------------------------------------------------------- +// Helper method for UltraSparcRegInfo::colorCallArgs(). +//--------------------------------------------------------------------------- + +void +UltraSparcRegInfo::InitializeOutgoingArg(MachineInstr* CallMI, + AddedInstrns *CallAI, + PhyRegAlloc &PRA, LiveRange* LR, + unsigned regType, unsigned RegClassID, + int UniArgRegOrNone, unsigned int argNo, + std::vector& AddedInstrnsBefore) + const +{ + MachineInstr *AdMI; + bool isArgInReg = false; + unsigned UniArgReg = MAXINT; // unused unless initialized below + if (UniArgRegOrNone != InvalidRegNum) + { + isArgInReg = true; + UniArgReg = (unsigned) UniArgRegOrNone; + CallMI->insertUsedReg(UniArgReg); // mark the reg as used } - else if( RegType == FPSingleRegType && (argNo*2 +1)< NumOfFloatArgRegs) - LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2 + 1) ); + + if (LR->hasColor()) { + unsigned UniLRReg = getUnifiedRegNum(RegClassID, LR->getColor()); - - else if( RegType == FPDoubleRegType && (argNo*2) < NumOfFloatArgRegs) - LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2) ); + // if LR received the correct color, nothing to do + if( isArgInReg && UniArgReg == UniLRReg ) + return; + // The LR is allocated to a register UniLRReg and must be copied + // to UniArgReg or to the stack slot. + // + if( isArgInReg ) { + // Copy UniLRReg to UniArgReg + cpReg2RegMI(AddedInstrnsBefore, UniLRReg, UniArgReg, regType); + } + else { + // Copy UniLRReg to the stack to pass the arg on stack. + const MachineFrameInfo& frameInfo = target.getFrameInfo(); + int argOffset = frameInfo.getOutgoingArgOffset(PRA.MF, argNo); + cpReg2MemMI(CallAI->InstrnsBefore, + UniLRReg, getStackPointer(), argOffset, regType); + } - } // for all call arguments - + } else { // LR is not colored (i.e., spilled) + + if( isArgInReg ) { + // Insert a load instruction to load the LR to UniArgReg + cpMem2RegMI(AddedInstrnsBefore, getFramePointer(), + LR->getSpillOffFromFP(), UniArgReg, regType); + // Now add the instruction + } + + else { + // Now, we have to pass the arg on stack. Since LR also did NOT + // receive a register we have to move an argument in memory to + // outgoing parameter on stack. + // Use TReg to load and store the value. + // Use TmpOff to save TReg, since that may have a live value. + // + int TReg = PRA.getUniRegNotUsedByThisInst( LR->getRegClass(), CallMI ); + int TmpOff = PRA.MF.pushTempValue(target, + getSpilledRegSize(getRegType(LR))); + const MachineFrameInfo& frameInfo = target.getFrameInfo(); + int argOffset = frameInfo.getOutgoingArgOffset(PRA.MF, argNo); + + MachineInstr *Ad1, *Ad2, *Ad3, *Ad4; + + // Sequence: + // (1) Save TReg on stack + // (2) Load LR value into TReg from stack pos of LR + // (3) Store Treg on outgoing Arg pos on stack + // (4) Load the old value of TReg from stack to TReg (restore it) + // + // OPTIMIZE THIS: + // When reverse pointers in MahineInstr are introduced: + // Call PRA.getUnusedRegAtMI(....) to get an unused reg. Step 1 is + // needed only if this fails. Currently, we cannot call the + // above method since we cannot find LVSetBefore without the BB + // + // NOTE: We directly add to CallAI->InstrnsBefore instead of adding to + // AddedInstrnsBefore since these instructions must not be reordered. + cpReg2MemMI(CallAI->InstrnsBefore, + TReg, getFramePointer(), TmpOff, regType); + cpMem2RegMI(CallAI->InstrnsBefore, + getFramePointer(), LR->getSpillOffFromFP(), TReg, regType); + cpReg2MemMI(CallAI->InstrnsBefore, + TReg, getStackPointer(), argOffset, regType); + cpMem2RegMI(CallAI->InstrnsBefore, + getFramePointer(), TmpOff, TReg, regType); + } + } } - //--------------------------------------------------------------------------- // 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 MachineInstr *CallMI, +void UltraSparcRegInfo::colorCallArgs(MachineInstr *CallMI, LiveRangeInfo &LRI, AddedInstrns *CallAI, PhyRegAlloc &PRA, const BasicBlock *BB) const { - assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) ); + assert ( (target.getInstrInfo()).isCall(CallMI->getOpCode()) ); - // Reset the optional args area in the stack frame - // since that is reused for each call - // - PRA.mcInfo.resetOptionalArgs(target); + CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); // First color the return value of the call. // If there is a LR for the return value, it means this @@ -632,55 +760,54 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI, MachineInstr *AdMI; - const Value *RetVal = getCallInstRetVal( CallMI ); + const Value *RetVal = argDesc->getReturnValue(); if (RetVal) { LiveRange *RetValLR = LRI.getLiveRangeForValue( RetVal ); if (!RetValLR) { cerr << "\nNo LR for:" << RAV(RetVal) << "\n"; - assert(0 && "ERR:No LR for non-void return value"); + assert(RetValLR && "ERR:No LR for non-void return value"); } unsigned RegClassID = (RetValLR->getRegClass())->getID(); - bool recvCorrectColor = false; - + bool recvCorrectColor; unsigned CorrectCol; // correct color for ret value + unsigned UniRetReg; // unified number for CorrectCol + if(RegClassID == IntRegClassID) - CorrectCol = SparcIntRegOrder::o0; + CorrectCol = SparcIntRegClass::o0; else if(RegClassID == FloatRegClassID) - CorrectCol = SparcFloatRegOrder::f0; + CorrectCol = SparcFloatRegClass::f0; else { assert( 0 && "Unknown RegClass"); return; } + + // convert to unified number + UniRetReg = getUnifiedRegNum(RegClassID, CorrectCol); + // Mark the register as used by this instruction + CallMI->insertUsedReg(UniRetReg); + // if the LR received the correct color, NOTHING to do - - if( RetValLR->hasColor() ) - if( RetValLR->getColor() == CorrectCol ) - recvCorrectColor = true; - - + recvCorrectColor = RetValLR->hasColor()? RetValLR->getColor() == CorrectCol + : false; + // if we didn't receive the correct color for some reason, // put copy instruction - if( !recvCorrectColor ) { - - unsigned RegType = getRegType( RetValLR ); - - // the reg that LR must be colored with - unsigned UniRetReg = getUnifiedRegNum( RegClassID, CorrectCol); + unsigned regType = getRegType( RetValLR ); + if( RetValLR->hasColor() ) { - unsigned - UniRetLRReg=getUnifiedRegNum(RegClassID,RetValLR->getColor()); + unsigned UniRetLRReg=getUnifiedRegNum(RegClassID,RetValLR->getColor()); // the return value is coming in UniRetReg but has to go into // the UniRetLRReg - AdMI = cpReg2RegMI( UniRetReg, UniRetLRReg, RegType ); + cpReg2RegMI(CallAI->InstrnsAfter, UniRetReg, UniRetLRReg, regType); } // if LR has color else { @@ -688,12 +815,10 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI, // if the LR did NOT receive a color, we have to move the return // value coming in UniRetReg to the stack pos of spilled LR - AdMI = cpReg2MemMI(UniRetReg, getFramePointer(), - RetValLR->getSpillOffFromFP(), RegType ); + cpReg2MemMI(CallAI->InstrnsAfter, UniRetReg, + getFramePointer(),RetValLR->getSpillOffFromFP(), regType); } - CallAI->InstrnsAfter.push_back( AdMI ); - } // the LR didn't receive the suggested color } // if there a return value @@ -704,196 +829,95 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI, //------------------------------------------- std::vector AddedInstrnsBefore; + + unsigned NumOfCallArgs = argDesc->getNumArgs(); + + for(unsigned argNo=0, i=0, intArgNo=0, fpArgNo=0; + i < NumOfCallArgs; ++i, ++argNo) { - unsigned NumOfCallArgs = getCallInstNumArgs( CallMI ); - - bool VarArgCall = isVarArgCall( CallMI ); - - if(VarArgCall) cerr << "\nVar arg call found!!\n"; - - for(unsigned argNo=0, i=0; i < NumOfCallArgs; ++i, ++argNo ) { - - const Value *CallArg = CallMI->getImplicitRef(i); - + const Value *CallArg = argDesc->getArgInfo(i).getArgVal(); + // get the LR of call operand (parameter) LiveRange *const LR = LRI.getLiveRangeForValue(CallArg); - unsigned RegType = getRegType( CallArg ); - unsigned RegClassID = getRegClassIDOfValue( CallArg); + unsigned RegClassID = getRegClassIDOfValue( CallArg); + unsigned regType = getRegType( RegClassID, CallArg->getType() ); - // find whether this argument is coming in a register (if not, on stack) - + // Find whether this argument is coming in a register (if not, on stack) + // Also find the correct register the argument must use (UniArgReg) + // bool isArgInReg = false; - unsigned UniArgReg = InvalidRegNum; // reg that LR must be colored with - - if( (RegType== IntRegType && argNo < NumOfIntArgRegs)) { - isArgInReg = true; - UniArgReg = getUnifiedRegNum(RegClassID, SparcIntRegOrder::o0 + argNo ); - } - else if(RegType == FPSingleRegType && argNo < NumOfFloatArgRegs) { - isArgInReg = true; - - if( !VarArgCall ) - UniArgReg = getUnifiedRegNum(RegClassID, - SparcFloatRegOrder::f0 + (argNo*2 + 1) ); - else { - // a variable argument call - must pass float arg in %o's - if( argNo < NumOfIntArgRegs) - UniArgReg=getUnifiedRegNum(IntRegClassID,SparcIntRegOrder::o0+argNo); - else - isArgInReg = false; - } - - } - else if(RegType == FPDoubleRegType && argNo < NumOfFloatArgRegs) { + unsigned UniArgReg = InvalidRegNum; // reg that LR MUST be colored with + unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg + + // Find the register that must be used for this arg, depending on + // whether it is an INT or FP value. Here we ignore whether or not it + // is a varargs calls, because FP arguments will be explicitly copied + // to an integer Value and handled under (argCopy != NULL) below. + int regNum = (regType == IntRegType) + ? regNumForIntArg(/*inCallee*/ false, /*isVarArgs*/ false, + argNo, intArgNo++, fpArgNo, regClassIDOfArgReg) + : regNumForFPArg(regType, /*inCallee*/ false, /*isVarArgs*/ false, + argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); + + if(regNum != InvalidRegNum) { isArgInReg = true; - - if( !VarArgCall ) - UniArgReg =getUnifiedRegNum(RegClassID,SparcFloatRegOrder::f0+argNo*2); - else { - // a variable argument call - must pass float arg in %o's - if( argNo < NumOfIntArgRegs) - UniArgReg=getUnifiedRegNum(IntRegClassID,SparcIntRegOrder::o0+argNo); - else - isArgInReg = false; - } + UniArgReg = getUnifiedRegNum( regClassIDOfArgReg, regNum); + assert(regClassIDOfArgReg == RegClassID && + "Moving values between reg classes must happen during selection"); } - + // not possible to have a null LR since all args (even consts) // must be defined before if (!LR) { - cerr << " ERROR: In call instr, no LR for arg: " << RAV(CallArg) << "\n"; - assert(0 && "NO LR for call arg"); + cerr << " ERROR: In call instr, no LR for arg: " << RAV(CallArg) <<"\n"; + assert(LR && "NO LR for call arg"); } - - - if (LR->hasColor()) { - unsigned UniLRReg = getUnifiedRegNum( RegClassID, LR->getColor() ); - - // if LR received the correct color, nothing to do - if( UniLRReg == UniArgReg ) - continue; - - // 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 - - // the LR is colored with UniLRReg but has to go into UniArgReg - // to pass it as an argument - - if( isArgInReg ) { - - if( VarArgCall && RegClassID == FloatRegClassID ) { - - - // for a variable argument call, the float reg must go in a %o reg. - // We have to move a float reg to an int reg via memory. - // The store instruction will be directly added to - // CallAI->InstrnsBefore since it does not need reordering - // - int TmpOff = PRA.mcInfo.pushTempValue(target, - getSpilledRegSize(RegType)); - - AdMI = cpReg2MemMI(UniLRReg, getFramePointer(), TmpOff, RegType ); - CallAI->InstrnsBefore.push_back( AdMI ); - - AdMI = cpMem2RegMI(getFramePointer(), TmpOff, UniArgReg, IntRegType); - AddedInstrnsBefore.push_back( AdMI ); - } - - else { - AdMI = cpReg2RegMI(UniLRReg, UniArgReg, RegType ); - AddedInstrnsBefore.push_back( AdMI ); - } - - } else { - // Now, we have to pass the arg on stack. Since LR received a register - // we just have to move that register to the stack position where - // the argument must be passed - - int argOffset = PRA.mcInfo.allocateOptionalArg(target, LR->getType()); - - AdMI = cpReg2MemMI(UniLRReg, getStackPointer(), argOffset, RegType ); - - // Now add the instruction. We can directly add to - // CallAI->InstrnsBefore since we are just saving a reg on stack - // - CallAI->InstrnsBefore.push_back( AdMI ); - - //cerr << "\nCaution: Passing a reg on stack"; - } - - - } else { // LR is not colored (i.e., spilled) - - if( isArgInReg ) { - - // Now the LR did NOT recieve a register but has a stack poistion. - // Since, the outgoing arg goes in a register we just have to insert - // a load instruction to load the LR to outgoing register - - if( VarArgCall && RegClassID == FloatRegClassID ) - AdMI = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(), - UniArgReg, IntRegType ); - else - AdMI = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(), - UniArgReg, RegType ); - - cerr << "\nCaution: Loading a spilled val to a reg as a call arg"; - AddedInstrnsBefore.push_back( AdMI ); // Now add the instruction - } - - else { - // Now, we have to pass the arg on stack. Since LR also did NOT - // receive a register we have to move an argument in memory to - // outgoing parameter on stack. - - // Optoimize: Optimize when reverse pointers in MahineInstr are - // introduced. - // call PRA.getUnusedRegAtMI(....) to get an unused reg. Only if this - // fails, then use the following code. Currently, we cannot call the - // above method since we cannot find LVSetBefore without the BB - - int TReg = PRA.getUniRegNotUsedByThisInst( LR->getRegClass(), CallMI ); - - int TmpOff = PRA.mcInfo.pushTempValue(target, - getSpilledRegSize(getRegType(LR)) ); - - - int argOffset = PRA.mcInfo.allocateOptionalArg(target, LR->getType()); + + InitializeOutgoingArg(CallMI, CallAI, PRA, LR, regType, RegClassID, + UniArgReg, argNo, AddedInstrnsBefore); + + // Repeat for the second copy of the argument, which would be + // an FP argument being passed to a function with no prototype. + // It may either be passed as a copy in an integer register + // (in argCopy), or on the stack (useStackSlot). + const Value *argCopy = argDesc->getArgInfo(i).getArgCopy(); + if (argCopy != NULL) + { + assert(regType != IntRegType && argCopy->getType()->isInteger() + && "Must be passing copy of FP argument in int register"); - MachineInstr *Ad1, *Ad2, *Ad3, *Ad4; + unsigned copyRegClassID = getRegClassIDOfValue(argCopy); + unsigned copyRegType = getRegType(copyRegClassID, argCopy->getType()); - // Sequence: - // (1) Save TReg on stack - // (2) Load LR value into TReg from stack pos of LR - // (3) Store Treg on outgoing Arg pos on stack - // (4) Load the old value of TReg from stack to TReg (restore it) - - Ad1 = cpReg2MemMI(TReg, getFramePointer(), TmpOff, RegType ); - Ad2 = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(), - TReg, RegType ); - Ad3 = cpReg2MemMI(TReg, getStackPointer(), argOffset, RegType ); - Ad4 = cpMem2RegMI(getFramePointer(), TmpOff, TReg, RegType ); - - // We directly add to CallAI->InstrnsBefore instead of adding to - // AddedInstrnsBefore since these instructions must not be - // reordered. + int copyRegNum = regNumForIntArg(/*inCallee*/false, /*isVarArgs*/false, + argNo, intArgNo, fpArgNo-1, + regClassIDOfArgReg); + assert(copyRegNum != InvalidRegNum); + assert(regClassIDOfArgReg == copyRegClassID && + "Moving values between reg classes must happen during selection"); - CallAI->InstrnsBefore.push_back( Ad1 ); - CallAI->InstrnsBefore.push_back( Ad2 ); - CallAI->InstrnsBefore.push_back( Ad3 ); - CallAI->InstrnsBefore.push_back( Ad4 ); - - cerr << "\nCaution: Call arg moved from stack2stack for: " << *CallMI ; + InitializeOutgoingArg(CallMI, CallAI, PRA, + LRI.getLiveRangeForValue(argCopy), copyRegType, + copyRegClassID, copyRegNum, argNo, + AddedInstrnsBefore); + } + + if (regNum != InvalidRegNum && + argDesc->getArgInfo(i).usesStackSlot()) + { + // Pass the argument via the stack in addition to regNum + assert(regType != IntRegType && "Passing an integer arg. twice?"); + assert(!argCopy && "Passing FP arg in FP reg, INT reg, and stack?"); + InitializeOutgoingArg(CallMI, CallAI, PRA, LR, regType, RegClassID, + InvalidRegNum, argNo, AddedInstrnsBefore); } - } } // for each parameter in call instruction - - // if we added any instruction before the call instruction, verify + // If we added any instruction before the call instruction, verify // that they are in the proper order and if not, reorder them - + // + std::vector ReorderedVec; if (!AddedInstrnsBefore.empty()) { if (DEBUG_RA) { @@ -902,39 +926,38 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI, cerr << *(AddedInstrnsBefore[i]); } - std::vector TmpVec; - OrderAddedInstrns(AddedInstrnsBefore, TmpVec, PRA); - + OrderAddedInstrns(AddedInstrnsBefore, ReorderedVec, PRA); + assert(ReorderedVec.size() >= AddedInstrnsBefore.size() + && "Dropped some instructions when reordering!"); + if (DEBUG_RA) { cerr << "\nAfter reordering instrns: \n"; - for(unsigned i = 0; i < TmpVec.size(); i++) - cerr << *TmpVec[i]; + for(unsigned i = 0; i < ReorderedVec.size(); i++) + cerr << *ReorderedVec[i]; } - - // copy the results back from TmpVec to InstrnsBefore - for(unsigned i=0; i < TmpVec.size(); i++) - CallAI->InstrnsBefore.push_back( TmpVec[i] ); } - - - // now insert caller saving code for this call instruction + + // Now insert caller saving code for this call instruction // - insertCallerSavingCode(CallMI, BB, PRA); - - // Reset optional args area again to be safe - PRA.mcInfo.resetOptionalArgs(target); + insertCallerSavingCode(CallAI->InstrnsBefore, CallAI->InstrnsAfter, + CallMI, BB, PRA); + + // Then insert the final reordered code for the call arguments. + // + for(unsigned i=0; i < ReorderedVec.size(); i++) + CallAI->InstrnsBefore.push_back( ReorderedVec[i] ); } //--------------------------------------------------------------------------- // 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 MachineInstr *RetMI, +void UltraSparcRegInfo::suggestReg4RetValue(MachineInstr *RetMI, LiveRangeInfo &LRI) const { - assert( (UltraSparcInfo->getInstrInfo()).isReturn( RetMI->getOpCode() ) ); + assert( (target.getInstrInfo()).isReturn( RetMI->getOpCode() ) ); - suggestReg4RetAddr(RetMI, LRI); + suggestReg4RetAddr(RetMI, LRI); // if there is an implicit ref, that has to be the ret value if( RetMI->getNumImplicitRefs() > 0 ) { @@ -952,9 +975,9 @@ void UltraSparcRegInfo::suggestReg4RetValue(const MachineInstr *RetMI, unsigned RegClassID = (LR->getRegClass())->getID(); if (RegClassID == IntRegClassID) - LR->setSuggestedColor(SparcIntRegOrder::i0); + LR->setSuggestedColor(SparcIntRegClass::i0); else if (RegClassID == FloatRegClassID) - LR->setSuggestedColor(SparcFloatRegOrder::f0); + LR->setSuggestedColor(SparcFloatRegClass::f0); } } @@ -966,11 +989,11 @@ void UltraSparcRegInfo::suggestReg4RetValue(const MachineInstr *RetMI, // the LR to %i0 or %f0. When the LR is spilled, instead of the copy, we // have to put a load instruction. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI, +void UltraSparcRegInfo::colorRetValue(MachineInstr *RetMI, LiveRangeInfo &LRI, AddedInstrns *RetAI) const { - assert((UltraSparcInfo->getInstrInfo()).isReturn( RetMI->getOpCode())); + assert((target.getInstrInfo()).isReturn( RetMI->getOpCode())); // if there is an implicit ref, that has to be the ret value if(RetMI->getNumImplicitRefs() > 0) { @@ -987,25 +1010,29 @@ void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI, } unsigned RegClassID = getRegClassIDOfValue(RetVal); - unsigned RegType = getRegType( RetVal ); + unsigned regType = getRegType( RetVal ); unsigned CorrectCol; if(RegClassID == IntRegClassID) - CorrectCol = SparcIntRegOrder::i0; + CorrectCol = SparcIntRegClass::i0; else if(RegClassID == FloatRegClassID) - CorrectCol = SparcFloatRegOrder::f0; + CorrectCol = SparcFloatRegClass::f0; else { assert (0 && "Unknown RegClass"); return; } - // if the LR received the correct color, NOTHING to do + // convert to unified number + unsigned UniRetReg = getUnifiedRegNum(RegClassID, CorrectCol); + // Mark the register as used by this instruction + RetMI->insertUsedReg(UniRetReg); + + // if the LR received the correct color, NOTHING to do + if (LR->hasColor() && LR->getColor() == CorrectCol) return; - - unsigned UniRetReg = getUnifiedRegNum(RegClassID, CorrectCol); - + if (LR->hasColor()) { // We are here because the LR was allocted a regiter @@ -1017,13 +1044,11 @@ void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI, // the LR received UniLRReg but must be colored with UniRetReg // to pass as the return value - RetAI->InstrnsBefore.push_back(cpReg2RegMI(UniLRReg, UniRetReg, RegType)); + cpReg2RegMI(RetAI->InstrnsBefore, UniLRReg, UniRetReg, regType); } else { // if the LR is spilled - MachineInstr *AdMI = cpMem2RegMI(getFramePointer(), - LR->getSpillOffFromFP(), - UniRetReg, RegType); - RetAI->InstrnsBefore.push_back(AdMI); + cpMem2RegMI(RetAI->InstrnsBefore, getFramePointer(), + LR->getSpillOffFromFP(), UniRetReg, regType); cerr << "\nCopied the return value from stack\n"; } @@ -1031,95 +1056,153 @@ void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI, } +//--------------------------------------------------------------------------- +// Check if a specified register type needs a scratch register to be +// copied to/from memory. If it does, the reg. type that must be used +// for scratch registers is returned in scratchRegType. +// +// Only the int CC register needs such a scratch register. +// The FP CC registers can (and must) be copied directly to/from memory. +//--------------------------------------------------------------------------- + +bool +UltraSparcRegInfo::regTypeNeedsScratchReg(int RegType, + int& scratchRegType) const +{ + if (RegType == IntCCRegType) + { + scratchRegType = IntRegType; + return true; + } + return false; +} //--------------------------------------------------------------------------- // Copy from a register to register. Register number must be the unified -// register number +// register number. //--------------------------------------------------------------------------- -MachineInstr * UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg, unsigned DestReg, - int RegType) const { - +void +UltraSparcRegInfo::cpReg2RegMI(vector& mvec, + unsigned SrcReg, + unsigned DestReg, + int RegType) const { assert( ((int)SrcReg != InvalidRegNum) && ((int)DestReg != InvalidRegNum) && "Invalid Register"); MachineInstr * MI = NULL; - + switch( RegType ) { - case IntRegType: case IntCCRegType: + if (getRegType(DestReg) == IntRegType) + { // copy intCC reg to int reg + // Use SrcReg+1 to get the name "%ccr" instead of "%xcc" for RDCCR + MI = Create2OperandInstr_Reg(RDCCR, SrcReg+1, DestReg); + } + else + { // copy int reg to intCC reg + // Use DestReg+1 to get the name "%ccr" instead of "%xcc" for WRCCR + assert(getRegType(SrcReg) == IntRegType + && "Can only copy CC reg to/from integer reg"); + MI = Create2OperandInstr_Reg(WRCCR, SrcReg, DestReg+1); + } + break; + case FloatCCRegType: - MI = new MachineInstr(ADD, 3); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, this->getZeroRegNum(), false); - MI->SetMachineOperandReg(2, DestReg, true); + assert(0 && "Cannot copy FPCC register to any other register"); break; - + + case IntRegType: + MI = Create3OperandInstr_Reg(ADD, SrcReg, getZeroRegNum(), DestReg); + break; + case FPSingleRegType: - MI = new MachineInstr(FMOVS, 2); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestReg, true); + MI = Create2OperandInstr_Reg(FMOVS, SrcReg, DestReg); break; case FPDoubleRegType: - MI = new MachineInstr(FMOVD, 2); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestReg, true); + MI = Create2OperandInstr_Reg(FMOVD, SrcReg, DestReg); break; default: - assert(0 && "Unknow RegType"); + assert(0 && "Unknown RegType"); + break; } - - return MI; + + if (MI) + mvec.push_back(MI); } - //--------------------------------------------------------------------------- // Copy from a register to memory (i.e., Store). Register number must // be the unified register number //--------------------------------------------------------------------------- -MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg, - unsigned DestPtrReg, - int Offset, int RegType) const { +void +UltraSparcRegInfo::cpReg2MemMI(vector& mvec, + unsigned SrcReg, + unsigned DestPtrReg, + int Offset, int RegType, + int scratchReg) const { MachineInstr * MI = NULL; switch( RegType ) { case IntRegType: - case FloatCCRegType: + assert(target.getInstrInfo().constantFitsInImmedField(STX, Offset)); MI = new MachineInstr(STX, 3); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestPtrReg, false); + MI->SetMachineOperandReg(0, SrcReg); + MI->SetMachineOperandReg(1, DestPtrReg); MI->SetMachineOperandConst(2, MachineOperand:: MO_SignExtendedImmed, (int64_t) Offset); + mvec.push_back(MI); break; case FPSingleRegType: + assert(target.getInstrInfo().constantFitsInImmedField(ST, Offset)); MI = new MachineInstr(ST, 3); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestPtrReg, false); + MI->SetMachineOperandReg(0, SrcReg); + MI->SetMachineOperandReg(1, DestPtrReg); MI->SetMachineOperandConst(2, MachineOperand:: MO_SignExtendedImmed, (int64_t) Offset); + mvec.push_back(MI); break; case FPDoubleRegType: + assert(target.getInstrInfo().constantFitsInImmedField(STD, Offset)); MI = new MachineInstr(STD, 3); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestPtrReg, false); + MI->SetMachineOperandReg(0, SrcReg); + MI->SetMachineOperandReg(1, DestPtrReg); MI->SetMachineOperandConst(2, MachineOperand:: MO_SignExtendedImmed, (int64_t) Offset); + mvec.push_back(MI); break; case IntCCRegType: - assert( 0 && "Cannot directly store %ccr to memory"); + assert(scratchReg >= 0 && "Need scratch reg to store %ccr to memory"); + assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg"); + + // Use SrcReg+1 to get the name "%ccr" instead of "%xcc" for RDCCR + MI = Create2OperandInstr_Reg(RDCCR, SrcReg+1, scratchReg); + mvec.push_back(MI); + + cpReg2MemMI(mvec, scratchReg, DestPtrReg, Offset, IntRegType); + break; + + case FloatCCRegType: + assert(0 && "Tell Vikram if this assertion fails: we may have to mask out the other bits here"); + assert(target.getInstrInfo().constantFitsInImmedField(STXFSR, Offset)); + MI = new MachineInstr(STXFSR, 3); + MI->SetMachineOperandReg(0, SrcReg); + MI->SetMachineOperandReg(1, DestPtrReg); + MI->SetMachineOperandConst(2, MachineOperand:: MO_SignExtendedImmed, + (int64_t) Offset); + mvec.push_back(MI); + break; default: - assert(0 && "Unknow RegType in cpReg2MemMI"); + assert(0 && "Unknown RegType in cpReg2MemMI"); } - - return MI; } @@ -1129,59 +1212,83 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg, //--------------------------------------------------------------------------- -MachineInstr * UltraSparcRegInfo::cpMem2RegMI(unsigned SrcPtrReg, - int Offset, - unsigned DestReg, - int RegType) const { +void +UltraSparcRegInfo::cpMem2RegMI(vector& mvec, + unsigned SrcPtrReg, + int Offset, + unsigned DestReg, + int RegType, + int scratchReg) const { MachineInstr * MI = NULL; switch (RegType) { case IntRegType: - case FloatCCRegType: + assert(target.getInstrInfo().constantFitsInImmedField(LDX, Offset)); MI = new MachineInstr(LDX, 3); - MI->SetMachineOperandReg(0, SrcPtrReg, false); + MI->SetMachineOperandReg(0, SrcPtrReg); MI->SetMachineOperandConst(1, MachineOperand:: MO_SignExtendedImmed, (int64_t) Offset); MI->SetMachineOperandReg(2, DestReg, true); + mvec.push_back(MI); break; case FPSingleRegType: + assert(target.getInstrInfo().constantFitsInImmedField(LD, Offset)); MI = new MachineInstr(LD, 3); - MI->SetMachineOperandReg(0, SrcPtrReg, false); + MI->SetMachineOperandReg(0, SrcPtrReg); MI->SetMachineOperandConst(1, MachineOperand:: MO_SignExtendedImmed, (int64_t) Offset); MI->SetMachineOperandReg(2, DestReg, true); - + mvec.push_back(MI); break; case FPDoubleRegType: + assert(target.getInstrInfo().constantFitsInImmedField(LDD, Offset)); MI = new MachineInstr(LDD, 3); - MI->SetMachineOperandReg(0, SrcPtrReg, false); + MI->SetMachineOperandReg(0, SrcPtrReg); MI->SetMachineOperandConst(1, MachineOperand:: MO_SignExtendedImmed, (int64_t) Offset); MI->SetMachineOperandReg(2, DestReg, true); + mvec.push_back(MI); break; case IntCCRegType: - assert( 0 && "Cannot directly load into %ccr from memory"); + assert(scratchReg >= 0 && "Need scratch reg to load %ccr from memory"); + assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg"); + cpMem2RegMI(mvec, SrcPtrReg, Offset, scratchReg, IntRegType); + + // Use DestReg+1 to get the name "%ccr" instead of "%xcc" for WRCCR + MI = Create2OperandInstr_Reg(WRCCR, scratchReg, DestReg+1); + mvec.push_back(MI); + + break; + + case FloatCCRegType: + assert(0 && "Tell Vikram if this assertion fails: we may have to mask out the other bits here"); + assert(target.getInstrInfo().constantFitsInImmedField(LDXFSR, Offset)); + MI = new MachineInstr(LDXFSR, 3); + MI->SetMachineOperandReg(0, SrcPtrReg); + MI->SetMachineOperandConst(1, MachineOperand:: MO_SignExtendedImmed, + (int64_t) Offset); + MI->SetMachineOperandReg(2, DestReg, true); + mvec.push_back(MI); + break; default: assert(0 && "Unknown RegType in cpMem2RegMI"); } - - return MI; } - - - //--------------------------------------------------------------------------- // Generate a copy instruction to copy a value to another. Temporarily // used by PhiElimination code. //--------------------------------------------------------------------------- -MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const { +void +UltraSparcRegInfo::cpValue2Value(Value *Src, + Value *Dest, + vector& mvec) const { int RegType = getRegType( Src ); assert( (RegType==getRegType(Src)) && "Src & Dest are diff types"); @@ -1191,29 +1298,29 @@ MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const { switch( RegType ) { case IntRegType: MI = new MachineInstr(ADD, 3); - MI->SetMachineOperandVal(0, MachineOperand:: MO_VirtualRegister, Src, false); - MI->SetMachineOperandReg(1, this->getZeroRegNum(), false); - MI->SetMachineOperandVal(2, MachineOperand:: MO_VirtualRegister, Dest, true); + MI->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, Src); + MI->SetMachineOperandReg(1, getZeroRegNum()); + MI->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, Dest, true); break; case FPSingleRegType: MI = new MachineInstr(FMOVS, 2); - MI->SetMachineOperandVal(0, MachineOperand:: MO_VirtualRegister, Src, false); - MI->SetMachineOperandVal(1, MachineOperand:: MO_VirtualRegister, Dest, true); + MI->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, Src); + MI->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, Dest, true); break; case FPDoubleRegType: MI = new MachineInstr(FMOVD, 2); - MI->SetMachineOperandVal(0, MachineOperand:: MO_VirtualRegister, Src, false); - MI->SetMachineOperandVal(1, MachineOperand:: MO_VirtualRegister, Dest, true); + MI->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, Src); + MI->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, Dest, true); break; default: assert(0 && "Unknow RegType in CpValu2Value"); } - return MI; + mvec.push_back(MI); } @@ -1235,14 +1342,21 @@ MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const { //---------------------------------------------------------------------------- -void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, - const BasicBlock *BB, - PhyRegAlloc &PRA) const { - +void +UltraSparcRegInfo::insertCallerSavingCode(vector& instrnsBefore, + vector& instrnsAfter, + MachineInstr *CallMI, + const BasicBlock *BB, + PhyRegAlloc &PRA) const +{ + assert ( (target.getInstrInfo()).isCall(CallMI->getOpCode()) ); + // has set to record which registers were saved/restored // - std::hash_set PushedRegSet; + hash_set PushedRegSet; + CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); + // Now find the LR of the return value of the call // The last *implicit operand* is the return value of a call // Insert it to to he PushedRegSet since we must not save that register @@ -1251,8 +1365,7 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, // to determine, which LRs must be saved across calls. The return value // of the call is live in this set - but we must not save/restore it. - - const Value *RetVal = getCallInstRetVal( MInst ); + const Value *RetVal = argDesc->getReturnValue(); if (RetVal) { LiveRange *RetValLR = PRA.LRI.getLiveRangeForValue( RetVal ); @@ -1264,8 +1377,7 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, RetValLR->getColor() ) ); } - - const ValueSet &LVSetAft = PRA.LVI->getLiveVarSetAfterMInst(MInst, BB); + const ValueSet &LVSetAft = PRA.LVI->getLiveVarSetAfterMInst(CallMI, BB); ValueSet::const_iterator LIt = LVSetAft.begin(); // for each live var in live variable set after machine inst @@ -1287,7 +1399,7 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, // if the value is in both LV sets (i.e., live before and after // the call machine instruction) - + unsigned Reg = getUnifiedRegNum(RCID, Color); if( PushedRegSet.find(Reg) == PushedRegSet.end() ) { @@ -1299,104 +1411,79 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, // Now get two instructions - to push on stack and pop from stack // and add them to InstrnsBefore and InstrnsAfter of the // call instruction - - - int StackOff = PRA.mcInfo.pushTempValue(target, - getSpilledRegSize(RegType)); - + // + int StackOff = PRA.MF.pushTempValue(target, + getSpilledRegSize(RegType)); + + vector AdIBef, AdIAft; - MachineInstr *AdIBefCC=NULL, *AdIAftCC=NULL, *AdICpCC; - MachineInstr *AdIBef=NULL, *AdIAft=NULL; - //---- Insert code for pushing the reg on stack ---------- - - if( RegType == IntCCRegType ) { - - // Handle IntCCRegType specially since we cannot directly - // push %ccr on to the stack - - const ValueSet &LVSetBef = - PRA.LVI->getLiveVarSetBeforeMInst(MInst, BB); - - // get a free INTEGER register - int FreeIntReg = - PRA.getUsableUniRegAtMI(PRA.getRegClassByID(IntRegClassID) /*LR->getRegClass()*/, - IntRegType, MInst, &LVSetBef, AdIBefCC, AdIAftCC); - - // insert the instructions in reverse order since we are - // adding them to the front of InstrnsBefore - - if(AdIAftCC) - PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIAftCC); - - AdICpCC = cpCCR2IntMI(FreeIntReg); - PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdICpCC); - - if(AdIBefCC) - PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIBefCC); - - if(DEBUG_RA) { - cerr << "\n!! Inserted caller saving (push) inst for %ccr:"; - if(AdIBefCC) cerr << "\t" << *(AdIBefCC); - cerr << "\t" << *AdICpCC; - if(AdIAftCC) cerr << "\t" << *(AdIAftCC); - } - - } else { - // for any other register type, just add the push inst - AdIBef = cpReg2MemMI(Reg, getFramePointer(), StackOff, RegType ); - PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIBef); - } - - + + // We may need a scratch register to copy the saved value + // to/from memory. This may itself have to insert code to + // free up a scratch register. Any such code should go before + // the save code. + int scratchRegType = -1; + int scratchReg = -1; + if (regTypeNeedsScratchReg(RegType, scratchRegType)) + { // Find a register not live in the LVSet before CallMI + const ValueSet &LVSetBef = + PRA.LVI->getLiveVarSetBeforeMInst(CallMI, BB); + scratchReg = PRA.getUsableUniRegAtMI(scratchRegType, &LVSetBef, + CallMI, AdIBef, AdIAft); + assert(scratchReg != getInvalidRegNum()); + CallMI->insertUsedReg(scratchReg); + } + + if (AdIBef.size() > 0) + instrnsBefore.insert(instrnsBefore.end(), + AdIBef.begin(), AdIBef.end()); + + cpReg2MemMI(instrnsBefore, Reg,getFramePointer(),StackOff,RegType, + scratchReg); + + if (AdIAft.size() > 0) + instrnsBefore.insert(instrnsBefore.end(), + AdIAft.begin(), AdIAft.end()); + //---- Insert code for popping the reg from the stack ---------- - if (RegType == IntCCRegType) { - - // Handle IntCCRegType specially since we cannot directly - // pop %ccr on from the stack - - // get a free INT register - int FreeIntReg = - PRA.getUsableUniRegAtMI(PRA.getRegClassByID(IntRegClassID) /* LR->getRegClass()*/, - IntRegType, MInst, &LVSetAft, AdIBefCC, AdIAftCC); - - if(AdIBefCC) - PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIBefCC); - - AdICpCC = cpInt2CCRMI(FreeIntReg); - PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdICpCC); - - if(AdIAftCC) - PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIAftCC); - - if(DEBUG_RA) { - - cerr << "\n!! Inserted caller saving (pop) inst for %ccr:"; - if(AdIBefCC) cerr << "\t" << *(AdIBefCC); - cerr << "\t" << *AdICpCC; - if(AdIAftCC) cerr << "\t" << *(AdIAftCC); - } - - } else { - // for any other register type, just add the pop inst - AdIAft = cpMem2RegMI(getFramePointer(), StackOff, Reg, RegType ); - PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIAft); - } + // We may need a scratch register to copy the saved value + // from memory. This may itself have to insert code to + // free up a scratch register. Any such code should go + // after the save code. + // + scratchRegType = -1; + scratchReg = -1; + if (regTypeNeedsScratchReg(RegType, scratchRegType)) + { // Find a register not live in the LVSet after CallMI + scratchReg = PRA.getUsableUniRegAtMI(scratchRegType, &LVSetAft, + CallMI, AdIBef, AdIAft); + assert(scratchReg != getInvalidRegNum()); + CallMI->insertUsedReg(scratchReg); + } + + if (AdIBef.size() > 0) + instrnsAfter.insert(instrnsAfter.end(), + AdIBef.begin(), AdIBef.end()); + + cpMem2RegMI(instrnsAfter, getFramePointer(), StackOff,Reg,RegType, + scratchReg); + + if (AdIAft.size() > 0) + instrnsAfter.insert(instrnsAfter.end(), + AdIAft.begin(), AdIAft.end()); PushedRegSet.insert(Reg); - + if(DEBUG_RA) { - cerr << "\nFor call inst:" << *MInst; - cerr << " -inserted caller saving instrs:\n\t "; - if( RegType == IntCCRegType ) { - if(AdIBefCC) cerr << *AdIBefCC << "\t"; - if(AdIAftCC) cerr << *AdIAftCC; - } - else { - if(AdIBef) cerr << *AdIBef << "\t"; - if(AdIAft) cerr << *AdIAft; - } + cerr << "\nFor call inst:" << *CallMI; + cerr << " -inserted caller saving instrs: Before:\n\t "; + for_each(instrnsBefore.begin(), instrnsBefore.end(), + std::mem_fun(&MachineInstr::dump)); + cerr << " -and After:\n\t "; + for_each(instrnsAfter.begin(), instrnsAfter.end(), + std::mem_fun(&MachineInstr::dump)); } } // if not already pushed @@ -1407,40 +1494,9 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, } // if there is a LR for Var } // for each value in the LV set after instruction - -} - -//--------------------------------------------------------------------------- -// Copies %ccr into an integer register. IntReg is the UNIFIED register -// number. -//--------------------------------------------------------------------------- - -MachineInstr * UltraSparcRegInfo::cpCCR2IntMI(unsigned IntReg) const { - MachineInstr * MI = new MachineInstr(RDCCR, 2); - MI->SetMachineOperandReg(0, this->getUnifiedRegNum(UltraSparcRegInfo::IntCCRegClassID, - SparcIntCCRegOrder::ccr), - false, true); - MI->SetMachineOperandReg(1, IntReg, true); - return MI; -} - -//--------------------------------------------------------------------------- -// Copies an integer register into %ccr. IntReg is the UNIFIED register -// number. -//--------------------------------------------------------------------------- - -MachineInstr *UltraSparcRegInfo::cpInt2CCRMI(unsigned IntReg) const { - MachineInstr *MI = new MachineInstr(WRCCR, 3); - MI->SetMachineOperandReg(0, IntReg, false); - MI->SetMachineOperandReg(1, this->getZeroRegNum(), false); - MI->SetMachineOperandReg(2, this->getUnifiedRegNum(UltraSparcRegInfo::IntCCRegClassID, SparcIntCCRegOrder::ccr), - true, true); - return MI; } - - //--------------------------------------------------------------------------- // Print the register assigned to a LR //--------------------------------------------------------------------------- @@ -1459,12 +1515,12 @@ void UltraSparcRegInfo::printReg(const LiveRange *LR) { cerr << " colored with color "<< LR->getColor(); if (RegClassID == IntRegClassID) { - cerr<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) << "]\n"; + cerr<< " [" << SparcIntRegClass::getRegName(LR->getColor()) << "]\n"; } else if (RegClassID == FloatRegClassID) { - cerr << "[" << SparcFloatRegOrder::getRegName(LR->getColor()); + cerr << "[" << SparcFloatRegClass::getRegName(LR->getColor()); if( LR->getType() == Type::DoubleTy) - cerr << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1); + cerr << "+" << SparcFloatRegClass::getRegName(LR->getColor()+1); cerr << "]\n"; } } @@ -1477,21 +1533,21 @@ void UltraSparcRegInfo::printReg(const LiveRange *LR) { // The unordered instructions come in the UnordVec. These instructions are // instructions inserted by RegAlloc. All such instruction MUST have // their USES BEFORE THE DEFS after reordering. - +// // The UnordVec & OrdVec must be DISTINCT. The OrdVec must be empty when // this method is called. - +// // This method uses two vectors for efficiency in accessing - +// // Since instructions are inserted in RegAlloc, this assumes that the // first operand is the source reg and the last operand is the dest reg. - +// It also does not consider operands that are both use and def. +// // All the uses are before THE def to a register - - //--------------------------------------------------------------------------- -void UltraSparcRegInfo::OrderAddedInstrns(std::vector &UnordVec, - std::vector &OrdVec, + +void UltraSparcRegInfo::OrderAddedInstrns(std::vector &UnordVec, + std::vector &OrdVec, PhyRegAlloc &PRA) const{ /* @@ -1542,11 +1598,10 @@ void UltraSparcRegInfo::OrderAddedInstrns(std::vector &UnordVec, // last operand is the def (unless for a store which has no def reg) MachineOperand& DefOp = DefInst->getOperand(DefInst->getNumOperands()-1); - if( DefOp.opIsDef() && - DefOp.getOperandType() == MachineOperand::MO_MachineRegister) { + if (DefOp.opIsDef() && + DefOp.getType() == MachineOperand::MO_MachineRegister) { // If the operand in DefInst is a def ... - bool DefEqUse = false; std::vector::iterator UseIt = DefIt; @@ -1560,8 +1615,8 @@ void UltraSparcRegInfo::OrderAddedInstrns(std::vector &UnordVec, // for each inst (UseInst) that is below the DefInst do ... MachineOperand& UseOp = UseInst->getOperand(0); - if( ! UseOp.opIsDef() && - UseOp.getOperandType() == MachineOperand::MO_MachineRegister) { + if (!UseOp.opIsDef() && + UseOp.getType() == MachineOperand::MO_MachineRegister) { // if use is a register ... @@ -1605,7 +1660,7 @@ void UltraSparcRegInfo::OrderAddedInstrns(std::vector &UnordVec, } while(!CouldMoveAll); - if (DebugPrint) { + if (DebugPrint && DEBUG_RA) { cerr << "\nAdded instructions were reordered to:\n"; for(unsigned int i=0; i < OrdVec.size(); i++) cerr << *(OrdVec[i]); @@ -1621,8 +1676,8 @@ void UltraSparcRegInfo::moveInst2OrdVec(std::vector &OrdVec, PhyRegAlloc &PRA) const { MachineOperand& UseOp = UnordInst->getOperand(0); - if( ! UseOp.opIsDef() && - UseOp.getOperandType() == MachineOperand::MO_MachineRegister) { + if (!UseOp.opIsDef() && + UseOp.getType() == MachineOperand::MO_MachineRegister) { // for the use of UnordInst, see whether there is a defining instr // before in the OrdVec @@ -1638,7 +1693,7 @@ void UltraSparcRegInfo::moveInst2OrdVec(std::vector &OrdVec, OrdInst->getOperand(OrdInst->getNumOperands()-1); if( DefOp.opIsDef() && - DefOp.getOperandType() == MachineOperand::MO_MachineRegister) { + DefOp.getType() == MachineOperand::MO_MachineRegister) { //cerr << "\nDefining Ord Inst: " << *OrdInst; @@ -1653,17 +1708,20 @@ void UltraSparcRegInfo::moveInst2OrdVec(std::vector &OrdVec, // Now we are processing %ox of 1. // We have to - const int UReg = DefOp.getMachineRegNum(); - const int RegType = getRegType(UReg); + int UReg = DefOp.getMachineRegNum(); + int RegType = getRegType(UReg); MachineInstr *AdIBef, *AdIAft; - const int StackOff = PRA.mcInfo.pushTempValue(target, - getSpilledRegSize(RegType)); + const int StackOff = PRA.MF.pushTempValue(target, + getSpilledRegSize(RegType)); // Save the UReg (%ox) on stack before it's destroyed - AdIBef=cpReg2MemMI(UReg, getFramePointer(), StackOff, RegType); - OrdIt = OrdVec.insert( OrdIt, AdIBef); - OrdIt++; // points to current instr we processed + vector mvec; + cpReg2MemMI(mvec, UReg, getFramePointer(), StackOff, RegType); + for (vector::iterator MI=mvec.begin(); MI != mvec.end(); ++MI) { + OrdIt = OrdVec.insert(OrdIt, *MI); + ++OrdIt; // OrdIt must still point to current instr we processed + } // Load directly into DReg (%oy) MachineOperand& DOp= @@ -1671,12 +1729,10 @@ void UltraSparcRegInfo::moveInst2OrdVec(std::vector &OrdVec, assert(DOp.opIsDef() && "Last operand is not the def"); const int DReg = DOp.getMachineRegNum(); - AdIAft=cpMem2RegMI(getFramePointer(), StackOff, DReg, RegType); - OrdVec.push_back(AdIAft); + cpMem2RegMI(OrdVec, getFramePointer(), StackOff, DReg, RegType); - cerr << "\nFixed CIRCULAR references by reordering"; - if( DEBUG_RA ) { + cerr << "\nFixed CIRCULAR references by reordering:"; cerr << "\nBefore CIRCULAR Reordering:\n"; cerr << *UnordInst; cerr << *OrdInst;