diff --git a/llvm/lib/Target/Sparc/Sparc.cpp b/llvm/lib/Target/Sparc/Sparc.cpp index 20bad83dfc65..9524e8051599 100644 --- a/llvm/lib/Target/Sparc/Sparc.cpp +++ b/llvm/lib/Target/Sparc/Sparc.cpp @@ -291,14 +291,17 @@ UltraSparc::compileMethod(Method *method) << "\n\n"; return true; } - + + /* if (ScheduleInstructionsWithSSA(method, *this)) { cerr << "Instruction scheduling before allocation failed for method " << method->getName() << "\n\n"; return true; } + */ + AllocateRegisters(method, *this); // allocate registers ApplyPeepholeOptimizations(method, *this); // machine-dependent peephole opts diff --git a/llvm/lib/Target/Sparc/SparcInternals.h b/llvm/lib/Target/Sparc/SparcInternals.h index c24b9bd38419..45aa029e8774 100644 --- a/llvm/lib/Target/Sparc/SparcInternals.h +++ b/llvm/lib/Target/Sparc/SparcInternals.h @@ -180,7 +180,6 @@ class PhyRegAlloc; class UltraSparcRegInfo : public MachineRegInfo { - private: // The actual register classes in the Sparc @@ -336,20 +335,21 @@ class UltraSparcRegInfo : public MachineRegInfo - + bool isVarArgCall(const MachineInstr *CallMI) const; public: - UltraSparcRegInfo(const TargetMachine& tgt ) : MachineRegInfo(tgt), - UltraSparcInfo(& (const UltraSparc&) tgt), - NumOfIntArgRegs(6), - NumOfFloatArgRegs(32), - InvalidRegNum(1000), - SizeOfOperandOnStack(8) - { + UltraSparcRegInfo(const TargetMachine& tgt ) : + MachineRegInfo(tgt), + UltraSparcInfo(& (const UltraSparc&) tgt), + NumOfIntArgRegs(6), + NumOfFloatArgRegs(32), + InvalidRegNum(1000), + SizeOfOperandOnStack(8) { + MachineRegClassArr.push_back( new SparcIntRegClass(IntRegClassID) ); MachineRegClassArr.push_back( new SparcFloatRegClass(FloatRegClassID) ); MachineRegClassArr.push_back( new SparcIntCCRegClass(IntCCRegClassID) ); @@ -421,7 +421,8 @@ class UltraSparcRegInfo : public MachineRegInfo AddedInstrns *const FirstAI) const; void colorCallArgs(const MachineInstr *const CallMI, LiveRangeInfo& LRI, - AddedInstrns *const CallAI, PhyRegAlloc &PRA) const; + AddedInstrns *const CallAI, PhyRegAlloc &PRA, + const BasicBlock *BB) const; void colorRetValue(const MachineInstr *const RetI, LiveRangeInfo& LRI, AddedInstrns *const RetAI) const; @@ -478,6 +479,14 @@ class UltraSparcRegInfo : public MachineRegInfo return (reg != InvalidRegNum && reg < 32); } + + + inline int getSpilledRegSize(const int RegType) const { + return 8; + // + // for Sparc, we allocate 8 bytes on stack for all register types + } + const Value * getCallInstRetVal(const MachineInstr *CallMI) const; MachineInstr * cpReg2RegMI(const unsigned SrcReg, const unsigned DestReg, diff --git a/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp b/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp index f79dd5817bbf..6b39d61f5e1d 100644 --- a/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp @@ -4,23 +4,20 @@ #include "llvm/Target/Sparc.h" //----------------------------------------------------------------------------- -// Int Register Class +// Int Register Class - method for coloring a node in the interference graph. +// +// Algorithm: +// Record the colors/suggested colors of all neighbors. +// +// If there is a suggested color, try to allocate it +// If there is no call interf, try to allocate volatile, then non volatile +// If there is call interf, try to allocate non-volatile. If that fails +// try to allocate a volatile and insert save across calls +// If both above fail, spill. +// //----------------------------------------------------------------------------- - void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const { - - /* Algorithm: - Record the colors/suggested colors of all neighbors. - - If there is a suggested color, try to allocate it - If there is no call interf, try to allocate volatile, then non volatile - If there is call interf, try to allocate non-volatile. If that fails - try to allocate a volatile and insert save across calls - If both above fail, spill. - - */ - LiveRange * LR = Node->getParentLR(); unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors @@ -37,7 +34,6 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const if( NeighLR-> isSuggestedColorUsable() ) IsColorUsedArr[ NeighLR->getSuggestedColor() ] = true; } - } if( DEBUG_RA ) { @@ -49,8 +45,6 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const unsigned SugCol = LR->getSuggestedColor(); - // cout << "\n -Has sug color: " << SugCol; - if( ! IsColorUsedArr[ SugCol ] ) { if( LR->isSuggestedColorUsable() ) { @@ -102,6 +96,7 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const // if color is not found because of call interference // try even finding a volatile color and insert save across calls + // else if( LR->isCallInterference() ) { // start from 0 - try to find even a volatile this time @@ -116,16 +111,16 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const LR->setColor(c); // get the live range corresponding to live var // since LR span across calls, must save across calls + // LR->markForSaveAcrossCalls(); - if(DEBUG_RA) cout << "\n Colored after SECOND search with col " << c ; } - } // If we couldn't find a color regardless of call interference - i.e., we // don't have either a volatile or non-volatile color left + // if( !ColorFound ) LR->markForSpill(); // no color found - must spill @@ -141,61 +136,23 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const //----------------------------------------------------------------------------- -// Float Register Class -//----------------------------------------------------------------------------- - -// find the first available color in the range [Start,End] depending on the -// type of the Node (i.e., float/double) - -int SparcFloatRegClass::findFloatColor(const LiveRange *const LR, - unsigned Start, - unsigned End, - bool IsColorUsedArr[] ) const -{ - - bool ColorFound = false; - unsigned c; - - if( LR->getTypeID() == Type::DoubleTyID ) { - - // find first unused color for a double - for( c=Start; c < End ;c+= 2){ - if( ! IsColorUsedArr[ c ] && ! IsColorUsedArr[ c+1 ]) - { ColorFound=true; break; } - } - - } else { - - // find first unused color for a single - for( c=Start; c < End; c++) { - if( ! IsColorUsedArr[ c ] ) { ColorFound=true; break; } - } - } - - if( ColorFound ) return c; - else return -1; -} - - - - - +// Float Register Class - method for coloring a node in the interference graph. +// +// Algorithm: +// +// If the LR is a double try to allocate f32 - f63 +// If the above fails or LR is single precision +// If the LR does not interfere with a call +// start allocating from f0 +// Else start allocating from f6 +// If a color is still not found because LR interferes with a call +// Search in f0 - f6. If found mark for spill across calls. +// If a color is still not fond, mark for spilling +// +//---------------------------------------------------------------------------- void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const { - /* Algorithm: - - If the LR is a double try to allocate f32 - f63 - If the above fails or LR is single precision - If the LR does not interfere with a call - start allocating from f0 - Else start allocating from f6 - If a color is still not found because LR interferes with a call - Search in f0 - f6. If found mark for spill across calls. - If a color is still not fond, mark for spilling - */ - - LiveRange * LR = Node->getParentLR(); unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors @@ -245,17 +202,24 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const bool isCallInterf = LR->isCallInterference(); // if value is a double - search the double only reigon (f32 - f63) + // i.e. we try to allocate f32 - f63 first for doubles since singles + // cannot go there. By doing that, we provide more space for singles + // in f0 - f31 + // if( LR->getTypeID() == Type::DoubleTyID ) ColorFound = findFloatColor( LR, 32, 64, IsColorUsedArr ); - if( ColorFound >= 0 ) { + if( ColorFound >= 0 ) { // if we could find a color LR->setColor(ColorFound); if( DEBUG_RA) UltraSparcRegInfo::printReg( LR ); return; } + else { - else { // the above fails or LR is single precision + // if we didn't find a color becuase the LR was single precision or + // all f32-f63 range is filled, we try to allocate a register from + // the f0 - f31 region unsigned SearchStart; // start pos of color in pref-order @@ -270,16 +234,15 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const } ColorFound = findFloatColor( LR, SearchStart, 32, IsColorUsedArr ); - } - if( ColorFound >= 0 ) { + + + if( ColorFound >= 0 ) { // if we could find a color LR->setColor(ColorFound); if( DEBUG_RA) UltraSparcRegInfo::printReg( LR ); return; } - - else if( isCallInterf ) { // We are here because there is a call interference and no non-volatile @@ -306,7 +269,41 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const LR->markForSpill(); // no color found - must spill if( DEBUG_RA) UltraSparcRegInfo::printReg( LR ); +} + + +//----------------------------------------------------------------------------- +// Helper method for coloring a node of Float Reg class. +// Finds the first available color in the range [Start,End] depending on the +// type of the Node (i.e., float/double) +//----------------------------------------------------------------------------- +int SparcFloatRegClass::findFloatColor(const LiveRange *const LR, + unsigned Start, + unsigned End, + bool IsColorUsedArr[] ) const { + + bool ColorFound = false; + unsigned c; + + if( LR->getTypeID() == Type::DoubleTyID ) { + + // find first unused color for a double + for( c=Start; c < End ;c+= 2){ + if( ! IsColorUsedArr[ c ] && ! IsColorUsedArr[ c+1 ]) + { ColorFound=true; break; } + } + + } else { + + // find first unused color for a single + for( c=Start; c < End; c++) { + if( ! IsColorUsedArr[ c ] ) { ColorFound=true; break; } + } + } + + if( ColorFound ) return c; + else return -1; } @@ -322,5 +319,3 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const - - diff --git a/llvm/lib/Target/Sparc/SparcRegInfo.cpp b/llvm/lib/Target/Sparc/SparcRegInfo.cpp index 1876e458a0a1..6a0460de7415 100644 --- a/llvm/lib/Target/Sparc/SparcRegInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegInfo.cpp @@ -5,23 +5,22 @@ #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" +#include "llvm/DerivedTypes.h" - +//--------------------------------------------------------------------------- +// Purpose: +// This file contains implementation of Sparc specific helper methods +// used for register allocation. +//--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -// UltraSparcRegInfo +// Finds the return value of a sparc specific call instruction //--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Finds the return value of a call instruction -//--------------------------------------------------------------------------- - const Value * -UltraSparcRegInfo::getCallInstRetVal(const MachineInstr *CallMI) const{ +UltraSparcRegInfo::getCallInstRetVal(const MachineInstr *CallMI) const { unsigned OpCode = CallMI->getOpCode(); unsigned NumOfImpRefs = CallMI->getNumImplicitRefs(); @@ -30,6 +29,7 @@ UltraSparcRegInfo::getCallInstRetVal(const MachineInstr *CallMI) const{ // 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); @@ -37,7 +37,8 @@ UltraSparcRegInfo::getCallInstRetVal(const MachineInstr *CallMI) const{ } else if( OpCode == JMPLCALL) { - // The last implicit operand is the return value of a JMPL in + // The last implicit operand is the return value of a JMPL + // if( NumOfImpRefs > 0 ) if( CallMI->implicitRefIsDefined(NumOfImpRefs-1) ) return CallMI->getImplicitRef(NumOfImpRefs-1); @@ -46,13 +47,13 @@ UltraSparcRegInfo::getCallInstRetVal(const MachineInstr *CallMI) const{ assert(0 && "OpCode must be CALL/JMPL for a call instr"); return NULL; - } -//--------------------------------------------------------------------------- -// Finds the return address of a call instruction -//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Finds the return address of a call sparc specific call instruction +//--------------------------------------------------------------------------- const Value * UltraSparcRegInfo::getCallInstRetAddr(const MachineInstr *CallMI)const { @@ -63,7 +64,9 @@ UltraSparcRegInfo::getCallInstRetAddr(const MachineInstr *CallMI)const { 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); } @@ -79,14 +82,13 @@ UltraSparcRegInfo::getCallInstRetAddr(const MachineInstr *CallMI)const { assert(0 && "There must be a return addr for a call instr"); return NULL; - } + //--------------------------------------------------------------------------- // Finds the # of actual arguments of the call instruction //--------------------------------------------------------------------------- - const unsigned UltraSparcRegInfo::getCallInstNumArgs(const MachineInstr *CallMI) const { @@ -128,15 +130,33 @@ UltraSparcRegInfo::getCallInstNumArgs(const MachineInstr *CallMI) const { assert( (NumArgs != -1) && "Internal error in getCallInstNumArgs" ); return (unsigned) NumArgs; - - } -//--------------------------------------------------------------------------- -// Suggests a register for the ret address in the RET machine instruction -//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// 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()); + MethodType *MT = cast(PT->getElementType()); + + return MT->isVarArg(); +} + + + + +//--------------------------------------------------------------------------- +// Suggests a register for the ret address in the RET machine instruction. +// We always suggest %i7 by convention. +//--------------------------------------------------------------------------- void UltraSparcRegInfo::suggestReg4RetAddr(const MachineInstr * RetMI, LiveRangeInfo& LRI) const { @@ -145,30 +165,27 @@ void UltraSparcRegInfo::suggestReg4RetAddr(const MachineInstr * RetMI, MachineOperand & MO = ( MachineOperand &) RetMI->getOperand(0); + // return address is always mapped to i7 + // MO.setRegForValue( getUnifiedRegNum( IntRegClassID, SparcIntRegOrder::i7) ); - // TODO (Optimize): + // Possible Optimization: // Instead of setting the color, we can suggest one. In that case, // we have to test later whether it received the suggested color. // 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): - /* - 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) ); - */ - - + // 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) ); } //--------------------------------------------------------------------------- -// Suggests a register for the ret address in the JMPL/CALL machine instr +// 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, @@ -187,18 +204,6 @@ void UltraSparcRegInfo::suggestReg4CallAddr(const MachineInstr * CallMI, RetAddrLR->setColor(getUnifiedRegNum(IntRegClassID,SparcIntRegOrder::o7)); LRI.addLRToMap( RetAddrVal, RetAddrLR); - - /* - assert( (CallMI->getNumOperands() == 3) && "JMPL must have 3 operands"); - - // directly set color since the LR of ret address (if there were one) - // will not extend after the call instr - - MachineOperand & MO = ( MachineOperand &) CallMI->getOperand(2); - MO.setRegForValue( getUnifiedRegNum( IntRegClassID,SparcIntRegOrder::o7) ); - - */ - } @@ -206,10 +211,11 @@ void UltraSparcRegInfo::suggestReg4CallAddr(const MachineInstr * CallMI, //--------------------------------------------------------------------------- // This method will suggest colors to incoming args to a method. +// According to the Sparc ABI, the first 6 incoming args are in +// %i0 - %i5 (if they are integer) OR in %f0 - %f31 (if they are float). // 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. +// done - it will be colored (or spilled) as a normal live range. //--------------------------------------------------------------------------- - void UltraSparcRegInfo::suggestRegs4MethodArgs(const Method *const Meth, LiveRangeInfo& LRI) const { @@ -230,13 +236,12 @@ void UltraSparcRegInfo::suggestRegs4MethodArgs(const Method *const Meth, // 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"; @@ -250,15 +255,16 @@ void UltraSparcRegInfo::suggestRegs4MethodArgs(const Method *const Meth, else if( RegType == FPDoubleRegType && (argNo*2) < NumOfFloatArgRegs) LR->setSuggestedColor( SparcFloatRegOrder::f0 + (argNo * 2) ); - } - } -//--------------------------------------------------------------------------- -// -//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// This method is called after graph coloring to move incoming args to +// the correct hardware registers if they did not receive the correct +// (suggested) color through graph coloring. +//--------------------------------------------------------------------------- void UltraSparcRegInfo::colorMethodArgs(const Method *const Meth, LiveRangeInfo& LRI, AddedInstrns *const FirstAI) const { @@ -282,11 +288,11 @@ void UltraSparcRegInfo::colorMethodArgs(const Method *const Meth, unsigned RegType = getRegType( LR ); unsigned RegClassID = (LR->getRegClass())->getID(); - - // 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 that the argument must go (UniArgReg) + // bool isArgInReg = false; - unsigned UniArgReg = InvalidRegNum; // reg that LR MUST be colored with + unsigned UniArgReg = InvalidRegNum; // reg that LR MUST be colored with if( (RegType== IntRegType && argNo < NumOfIntArgRegs)) { isArgInReg = true; @@ -303,21 +309,23 @@ void UltraSparcRegInfo::colorMethodArgs(const Method *const Meth, } - if( LR->hasColor() ) { + if( LR->hasColor() ) { // if this arg received a register unsigned UniLRReg = getUnifiedRegNum( RegClassID, LR->getColor() ); // if LR received the correct color, nothing to do + // if( UniLRReg == UniArgReg ) continue; - // 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. + // We are here because the LR did not receive the suggested + // but LR received another register. + // Now we have to copy the %i reg (or stack pos of arg) + // to the register the LR was colored with. - // if the arg is coming in UniArgReg register MUST go into + // if the arg is coming in UniArgReg register, it MUST go into // the UniLRReg register + // if( isArgInReg ) AdMI = cpReg2RegMI( UniArgReg, UniLRReg, RegType ); @@ -325,12 +333,14 @@ void UltraSparcRegInfo::colorMethodArgs(const Method *const Meth, // 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; + bool growUp; // find the offset of arg in stack frame int firstArg = - frameInfo.getFirstIncomingArgOffset(MachineCodeForMethod::get(Meth), growUp); + frameInfo.getFirstIncomingArgOffset(MachineCodeForMethod::get(Meth), + growUp); int offsetFromFP = growUp? firstArg + argNo * frameInfo.getSizeOfEachArgOnStack() : firstArg - argNo * frameInfo.getSizeOfEachArgOnStack(); @@ -347,11 +357,9 @@ void UltraSparcRegInfo::colorMethodArgs(const Method *const Meth, // Now, the LR did not receive a color. But it has a stack offset for // spilling. - // So, if the arg is coming in UniArgReg register, we can just move // that on to the stack pos of LR - if( isArgInReg ) { MachineInstr *AdIBef = @@ -502,7 +510,8 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *const CallMI, void UltraSparcRegInfo::colorCallArgs(const MachineInstr *const CallMI, LiveRangeInfo& LRI, AddedInstrns *const CallAI, - PhyRegAlloc &PRA) const { + PhyRegAlloc &PRA, + const BasicBlock *BB) const { assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) ); @@ -588,12 +597,18 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *const CallMI, } // if there a return value + //------------------------------------------- // Now color all args of the call instruction + //------------------------------------------- vector AddedInstrnsBefore; 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); @@ -615,14 +630,32 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *const CallMI, } else if(RegType == FPSingleRegType && argNo < NumOfFloatArgRegs) { isArgInReg = true; - UniArgReg = getUnifiedRegNum(RegClassID, - SparcFloatRegOrder::f0 + (argNo*2 + 1) ); + + 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) { isArgInReg = true; - UniArgReg = getUnifiedRegNum(RegClassID, SparcFloatRegOrder::f0+argNo*2); - } + 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; + } + } // not possible to have a null LR since all args (even consts) // must be defined before @@ -636,9 +669,6 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *const CallMI, } - // if the LR received the suggested color, NOTHING to do - - if( LR->hasColor() ) { @@ -656,8 +686,30 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *const CallMI, // to pass it as an argument if( isArgInReg ) { - AdMI = cpReg2RegMI(UniLRReg, UniArgReg, RegType ); - AddedInstrnsBefore.push_back( AdMI ); + + 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 { @@ -688,9 +740,12 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *const CallMI, // Since, the outgoing arg goes in a register we just have to insert // a load instruction to load the LR to outgoing register - - AdMI = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(), - UniArgReg, RegType ); + 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 @@ -709,9 +764,9 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *const CallMI, int TReg = PRA.getUniRegNotUsedByThisInst( LR->getRegClass(), CallMI ); - /**** NOTE: THIS SHOULD USE THE RIGHT SIZE FOR THE REG BEING PUSHED ****/ - int TmpOff = PRA.mcInfo.pushTempValue(target, 8); - // target.findOptimalStorageSize(LR->getType())); + int TmpOff = PRA.mcInfo.pushTempValue(target, + getSpilledRegSize(getRegType(LR)) ); + int argOffset = PRA.mcInfo.allocateOptionalArg(target, LR->getType()); @@ -772,6 +827,11 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *const CallMI, } + // 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); @@ -1112,7 +1172,7 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, // Clear the temp area of the stack //PRA.mcInfo.popAllTempValues(target); - // TODO*** Don't do this since we can have a situation lik + // TODO*** Don't do this since we can have a situation like /* stx %o1 %i6 1999 <--- inserted by this code @@ -1185,9 +1245,10 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, // and add them to InstrnsBefore and InstrnsAfter of the // call instruction - /**** NOTE: THIS SHOULD USE THE RIGHT SIZE FOR THE REG BEING PUSHED ****/ - int StackOff = PRA.mcInfo.pushTempValue(target, 8); - // target.findOptimalStorageSize(LR->getType())); + + int StackOff = PRA.mcInfo.pushTempValue(target, + getSpilledRegSize(RegType)); + MachineInstr *AdIBefCC, *AdIAftCC, *AdICpCC; MachineInstr *AdIBef, *AdIAft; @@ -1561,9 +1622,8 @@ void UltraSparcRegInfo::moveInst2OrdVec(vector &OrdVec, const int RegType = getRegType(UReg); MachineInstr *AdIBef, *AdIAft; - // TODO: Change 8 below - /**** NOTE: THIS SHOULD USE THE RIGHT SIZE FOR THE REG BEING PUSHED ****/ - const int StackOff = PRA.mcInfo.pushTempValue(target, 8); + const int StackOff = PRA.mcInfo.pushTempValue(target, + getSpilledRegSize(RegType)); // Save the UReg (%ox) on stack before it's destroyed AdIBef=cpReg2MemMI(UReg, getFramePointer(), StackOff, RegType);