X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparcV9%2FSparcV9RegInfo.cpp;h=0a88e07fd359110a2ba85c80a73bf7f831eae4a7;hb=635df00b02e7b0483712ed2bf232980b9dc0977d;hp=b660e89805fb1b218ab16f97b1ff4002381769a7;hpb=c6f3ae5c66c8e0dab6a2bd9601d0e253ef9ba794;p=oota-llvm.git diff --git a/lib/Target/SparcV9/SparcV9RegInfo.cpp b/lib/Target/SparcV9/SparcV9RegInfo.cpp index b660e89805f..0a88e07fd35 100644 --- a/lib/Target/SparcV9/SparcV9RegInfo.cpp +++ b/lib/Target/SparcV9/SparcV9RegInfo.cpp @@ -1,36 +1,51 @@ -//===-- SparcRegInfo.cpp - Sparc Target Register Information --------------===// +//===-- SparcV9RegInfo.cpp - SparcV9 Target Register Information ----------===// // -// This file contains implementation of Sparc specific helper methods +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains implementations of SparcV9 specific helper methods // used for register allocation. // //===----------------------------------------------------------------------===// -#include "SparcInternals.h" -#include "SparcRegClassInfo.h" -#include "llvm/Target/Sparc.h" -#include "llvm/CodeGen/MachineCodeForMethod.h" -#include "llvm/CodeGen/PhyRegAlloc.h" -#include "llvm/CodeGen/MachineInstr.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/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "MachineFunctionInfo.h" +#include "MachineCodeForInstruction.h" +#include "MachineInstrAnnot.h" +#include "RegAlloc/LiveRangeInfo.h" +#include "RegAlloc/LiveRange.h" #include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "SparcV9Internals.h" +#include "SparcV9RegClassInfo.h" +#include "SparcV9RegInfo.h" +#include "SparcV9FrameInfo.h" +#include "SparcV9TargetMachine.h" +#include "SparcV9TmpInstr.h" #include -#include -using std::cerr; - -UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc &tgt) - : MachineRegInfo(tgt), UltraSparcInfo(&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 && + +namespace llvm { + +enum { + BadRegClass = ~0 +}; + +SparcV9RegInfo::SparcV9RegInfo(const SparcV9TargetMachine &tgt) + : target (tgt), NumOfIntArgRegs (6), NumOfFloatArgRegs (32) +{ + MachineRegClassArr.push_back(new SparcV9IntRegClass(IntRegClassID)); + MachineRegClassArr.push_back(new SparcV9FloatRegClass(FloatRegClassID)); + MachineRegClassArr.push_back(new SparcV9IntCCRegClass(IntCCRegClassID)); + MachineRegClassArr.push_back(new SparcV9FloatCCRegClass(FloatCCRegClassID)); + MachineRegClassArr.push_back(new SparcV9SpecialRegClass(SpecialRegClassID)); + + assert(SparcV9FloatRegClass::StartOfNonVolatileRegs == 32 && "32 Float regs are used for float arg passing"); } @@ -38,57 +53,97 @@ UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc &tgt) // getZeroRegNum - returns the register that contains always zero. // this is the unified register number // -int UltraSparcRegInfo::getZeroRegNum() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::g0); +unsigned SparcV9RegInfo::getZeroRegNum() const { + return getUnifiedRegNum(SparcV9RegInfo::IntRegClassID, + SparcV9IntRegClass::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); +unsigned SparcV9RegInfo::getCallAddressReg() const { + return getUnifiedRegNum(SparcV9RegInfo::IntRegClassID, + SparcV9IntRegClass::o7); } // Returns the register containing the return address. -// It should be made sure that this register contains the return +// It should be made sure that this register contains the return // value when a return instruction is reached. // -unsigned UltraSparcRegInfo::getReturnAddressReg() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::i7); +unsigned SparcV9RegInfo::getReturnAddressReg() const { + return getUnifiedRegNum(SparcV9RegInfo::IntRegClassID, + SparcV9IntRegClass::i7); } -// given the unified register number, this gives the name -// for generating assembly code or debugging. -// -const std::string UltraSparcRegInfo::getUnifiedRegName(int reg) const { - if( reg < 32 ) - return SparcIntRegOrder::getRegName(reg); - else if ( reg < (64 + 32) ) - return SparcFloatRegOrder::getRegName( reg - 32); - else if( reg < (64+32+4) ) - return SparcFloatCCRegOrder::getRegName( reg -32 - 64); - else if( reg < (64+32+4+2) ) // two names: %xcc and %ccr - return SparcIntCCRegOrder::getRegName( reg -32 - 64 - 4); - else if (reg== InvalidRegNum) //****** TODO: Remove */ - return "<*NoReg*>"; - else - assert(0 && "Invalid register number"); - return ""; +// Register get name implementations... + +// Int register names in same order as enum in class SparcV9IntRegClass +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 SparcV9IntRegClass::getRegName(unsigned reg) const { + 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 SparcV9FloatRegClass::getRegName(unsigned reg) const { + assert (reg < NumOfAllRegs); + return FloatRegNames[reg]; +} + +static const char * const IntCCRegNames[] = { + "xcc", "icc", "ccr" +}; + +const char * const SparcV9IntCCRegClass::getRegName(unsigned reg) const { + assert(reg < 3); + return IntCCRegNames[reg]; +} + +static const char * const FloatCCRegNames[] = { + "fcc0", "fcc1", "fcc2", "fcc3" +}; + +const char * const SparcV9FloatCCRegClass::getRegName(unsigned reg) const { + assert (reg < 4); + return FloatCCRegNames[reg]; +} + +static const char * const SpecialRegNames[] = { + "fsr" +}; + +const char * const SparcV9SpecialRegClass::getRegName(unsigned reg) const { + assert (reg < 1); + return SpecialRegNames[reg]; } // Get unified reg number for frame pointer -unsigned UltraSparcRegInfo::getFramePointer() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::i6); +unsigned SparcV9RegInfo::getFramePointer() const { + return getUnifiedRegNum(SparcV9RegInfo::IntRegClassID, + SparcV9IntRegClass::i6); } // Get unified reg number for stack pointer -unsigned UltraSparcRegInfo::getStackPointer() const { - return this->getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, - SparcIntRegOrder::o6); +unsigned SparcV9RegInfo::getStackPointer() const { + return getUnifiedRegNum(SparcV9RegInfo::IntRegClassID, + SparcV9IntRegClass::o6); } @@ -112,321 +167,230 @@ isVarArgsCall(const MachineInstr *CallMI) { } -// 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. -// +// Get the register number for the specified argument #argNo, +// // 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 +// getInvalidRegNum(), if there is no int register available for the arg. +// regNum, otherwise (this is NOT the unified reg. num). +// regClassId is set to the register class ID. +// +int +SparcV9RegInfo::regNumForIntArg(bool inCallee, bool isVarArgsCall, + unsigned argNo, unsigned& regClassId) const { - int firstArgReg = inCallee? SparcIntRegOrder::i0 : SparcIntRegOrder::o0; + regClassId = IntRegClassID; if (argNo >= NumOfIntArgRegs) - return InvalidRegNum; - else { - regClassId = IntRegClassID; - return isVarArgsCall? firstArgReg + argNo - : firstArgReg + intArgNo; - } + return getInvalidRegNum(); + else + return argNo + (inCallee? SparcV9IntRegClass::i0 : SparcV9IntRegClass::o0); } -// 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. +// Get the register number for the specified FP argument #argNo, // 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, +// getInvalidRegNum(), if there is no int register available for the arg. +// regNum, otherwise (this is NOT the unified reg. num). +// regClassId is set to the register class ID. +// +int +SparcV9RegInfo::regNumForFPArg(unsigned regType, bool inCallee, bool isVarArgsCall, - unsigned argNo, - unsigned intArgNo, unsigned fpArgNo, - unsigned& regClassId) const + unsigned argNo, unsigned& regClassId) const { - if (isVarArgsCall) { - assert(! isVarArgsCall && - "FP arguments to a varargs function should be explicitly copied " - "to/from int registers by instruction selection!"); - return InvalidRegNum; - } - else { - regClassId = FloatRegClassID; - if (regType == FPSingleRegType) - return (fpArgNo*2+1 >= NumOfFloatArgRegs)? - InvalidRegNum : SparcFloatRegOrder::f0 + (fpArgNo * 2 + 1); - else if (regType == FPDoubleRegType) - return (fpArgNo*2 >= NumOfFloatArgRegs)? - InvalidRegNum : SparcFloatRegOrder::f0 + (fpArgNo * 2); - else - assert(0 && "Illegal FP register type"); - } -} - -//--------------------------------------------------------------------------- -// Finds the return value of a sparc specific call instruction -//--------------------------------------------------------------------------- - -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); - - } else if (OpCode == JMPLCALL) { - - // 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; -} - - -const Value * -UltraSparcRegInfo::getCallInstIndirectAddrVal(const MachineInstr *CallMI) const -{ - return (CallMI->getOpCode() == JMPLCALL)? - CallMI->getOperand(0).getVRegValue() : NULL; + if (isVarArgsCall) + return regNumForIntArg(inCallee, isVarArgsCall, argNo, regClassId); + else + { + regClassId = FloatRegClassID; + if (regType == FPSingleRegType) + return (argNo*2+1 >= NumOfFloatArgRegs)? + getInvalidRegNum() : SparcV9FloatRegClass::f0 + (argNo * 2 + 1); + else if (regType == FPDoubleRegType) + return (argNo*2 >= NumOfFloatArgRegs)? + getInvalidRegNum() : SparcV9FloatRegClass::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(); +// The following 4 methods are used to find the RegType (SparcV9Internals.h) +// of a V9LiveRange, a Value, and for a given register unified reg number. +// +int SparcV9RegInfo::getRegTypeForClassAndType(unsigned regClassID, + const Type* type) const +{ + switch (regClassID) { + case IntRegClassID: return IntRegType; + case FloatRegClassID: + if (type == Type::FloatTy) return FPSingleRegType; + else if (type == Type::DoubleTy) return FPDoubleRegType; + assert(0 && "Unknown type in FloatRegClass"); return 0; + case IntCCRegClassID: return IntCCRegType; + case FloatCCRegClassID: return FloatCCRegType; + case SpecialRegClassID: return SpecialRegType; + default: assert( 0 && "Unknown reg class ID"); return 0; } - - 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 -// -int UltraSparcRegInfo::getRegType(const LiveRange *LR) const { - switch (LR->getRegClass()->getID()) { - case IntRegClassID: return IntRegType; - case FloatRegClassID: { - const Type *Typ = LR->getType(); - if (Typ == Type::FloatTy) - return FPSingleRegType; - else if (Typ == Type::DoubleTy) - 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; - } +int SparcV9RegInfo::getRegTypeForDataType(const Type* type) const +{ + return getRegTypeForClassAndType(getRegClassIDOfType(type), type); } -int UltraSparcRegInfo::getRegType(const Value *Val) const { - unsigned Typ; - - switch (getRegClassIDOfValue(Val)) { - case IntRegClassID: return IntRegType; - case FloatRegClassID: - if (Val->getType() == Type::FloatTy) - return FPSingleRegType; - else if (Val->getType() == Type::DoubleTy) - 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; - } +int SparcV9RegInfo::getRegTypeForLR(const V9LiveRange *LR) const +{ + return getRegTypeForClassAndType(LR->getRegClassID(), LR->getType()); } -int UltraSparcRegInfo::getRegType(int reg) const { - if (reg < 32) +int SparcV9RegInfo::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+3)) + return IntCCRegType; + else if (unifiedRegNum < (64+32+3+4)) return FloatCCRegType; - else if (reg < (64+32+4+2)) - return IntCCRegType; - else - assert(0 && "Invalid register number in getRegType"); + else if (unifiedRegNum < (64+32+3+4+1)) + return SpecialRegType; + else + 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 SparcV9RegInfo::getRegClassIDOfType(const Type *type, + bool isCCReg) const { + Type::TypeID ty = type->getTypeID(); + 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; // corresponding condition code register + else + return res; } - +unsigned SparcV9RegInfo::getRegClassIDOfRegType(int regType) const { + switch(regType) { + case IntRegType: return IntRegClassID; + case FPSingleRegType: + case FPDoubleRegType: return FloatRegClassID; + case IntCCRegType: return IntCCRegClassID; + case FloatCCRegType: return FloatCCRegClassID; + case SpecialRegType: return SpecialRegClassID; + 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, - LiveRangeInfo& LRI) const { +void SparcV9RegInfo::suggestReg4RetAddr(MachineInstr *RetMI, + LiveRangeInfo& LRI) const { - assert( (RetMI->getNumOperands() >= 2) - && "JMPL/RETURN must have 3 and 2 operands respectively"); - - MachineOperand & MO = ( MachineOperand &) RetMI->getOperand(0); + assert(target.getInstrInfo()->isReturn(RetMI->getOpcode())); - // return address is always mapped to i7 - // - MO.setRegForValue( getUnifiedRegNum( IntRegClassID, SparcIntRegOrder::i7) ); - - // Possible Optimization: + // return address is always mapped to i7 so set it immediately + RetMI->SetRegForOperand(0, getUnifiedRegNum(IntRegClassID, + SparcV9IntRegClass::i7)); + + // 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): + // 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) ); + // V9LiveRange * RetAddrLR = LRI.getLiveRangeForValue( RetAddrVal); + // RetAddrLR->setSuggestedColor(getUnifiedRegNum( IntRegClassID, + // SparcV9IntRegOrdr::i7) ); } //--------------------------------------------------------------------------- // Suggests a register for the ret address in the JMPL/CALL machine instr. -// Sparc ABI dictates that %o7 be used for this purpose. +// SparcV9 ABI dictates that %o7 be used for this purpose. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestReg4CallAddr(const MachineInstr * CallMI, - LiveRangeInfo& LRI, - std::vector RCList) const { - - - const Value *RetAddrVal = getCallInstRetAddr( CallMI ); - - // 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); - -} +void +SparcV9RegInfo::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"); + // A LR must already exist for the return address. + V9LiveRange *RetAddrLR = LRI.getLiveRangeForValue(RetAddrVal); + assert(RetAddrLR && "INTERNAL ERROR: No LR for return address of call!"); + + unsigned RegClassID = RetAddrLR->getRegClassID(); + RetAddrLR->setColor(getUnifiedRegNum(IntRegClassID, SparcV9IntRegClass::o7)); +} //--------------------------------------------------------------------------- -// This method will suggest colors to incoming args to a method. -// According to the Sparc ABI, the first 6 incoming args are in +// This method will suggest colors to incoming args to a method. +// According to the SparcV9 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 live range. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth, - LiveRangeInfo& LRI) const +void SparcV9RegInfo::suggestRegs4MethodArgs(const Function *Meth, + LiveRangeInfo& LRI) const { - // check if this is a varArgs function. needed for choosing regs. + // Check if this is a varArgs function. needed for choosing regs. bool isVarArgs = isVarArgsFunction(Meth->getType()); - - // get the argument list - const Function::ArgumentListType& ArgList = Meth->getArgumentList(); - - // for each argument. count INT and FP arguments separately. - for( unsigned argNo=0, intArgNo=0, fpArgNo=0; - argNo != ArgList.size(); ++argNo) - { - // get the LR of arg - LiveRange *LR = LRI.getLiveRangeForValue((const Value *)ArgList[argNo]); - assert( LR && "No live range found for method arg"); - - unsigned regType = getRegType( LR ); - unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg (unused) - - int regNum = (regType == IntRegType) - ? regNumForIntArg(true, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg) - : regNumForFPArg(regType, true, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); - - if(regNum != InvalidRegNum) - LR->setSuggestedColor(regNum); - } -} + // Count the arguments, *ignoring* whether they are int or FP args. + // Use this common arg numbering to pick the right int or fp register. + unsigned argNo=0; + for(Function::const_arg_iterator I = Meth->arg_begin(), E = Meth->arg_end(); + I != E; ++I, ++argNo) { + V9LiveRange *LR = LRI.getLiveRangeForValue(I); + assert(LR && "No live range found for method arg"); + + unsigned regType = getRegTypeForLR(LR); + unsigned regClassIDOfArgReg = BadRegClass; // for chosen reg (unused) + + int regNum = (regType == IntRegType) + ? regNumForIntArg(/*inCallee*/ true, isVarArgs, argNo, regClassIDOfArgReg) + : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs, argNo, + regClassIDOfArgReg); + + if (regNum != getInvalidRegNum()) + LR->setSuggestedColor(regNum); + } +} //--------------------------------------------------------------------------- @@ -434,107 +398,113 @@ void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth, // the correct hardware registers if they did not receive the correct // (suggested) color through graph coloring. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::colorMethodArgs(const Function *Meth, - LiveRangeInfo &LRI, - AddedInstrns *FirstAI) const { +void SparcV9RegInfo::colorMethodArgs(const Function *Meth, + LiveRangeInfo &LRI, + std::vector& InstrnsBefore, + std::vector& InstrnsAfter) const { // check if this is a varArgs function. needed for choosing regs. bool isVarArgs = isVarArgsFunction(Meth->getType()); - // get the argument list - const Function::ArgumentListType& ArgList = Meth->getArgumentList(); - // get an iterator to arg list MachineInstr *AdMI; // for each argument - for( unsigned argNo=0, intArgNo=0, fpArgNo=0; - argNo != ArgList.size(); ++argNo) { + // for each argument. count INT and FP arguments separately. + unsigned argNo=0, intArgNo=0, fpArgNo=0; + for(Function::const_arg_iterator I = Meth->arg_begin(), E = Meth->arg_end(); + I != E; ++I, ++argNo) { // get the LR of arg - LiveRange *LR = LRI.getLiveRangeForValue((Value*)ArgList[argNo]); + V9LiveRange *LR = LRI.getLiveRangeForValue(I); assert( LR && "No live range found for method arg"); - unsigned regType = getRegType( LR ); - unsigned RegClassID = (LR->getRegClass())->getID(); - + unsigned regType = getRegTypeForLR(LR); + unsigned RegClassID = LR->getRegClassID(); + // 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 - unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg - + unsigned UniArgReg = getInvalidRegNum(); // reg that LR MUST be colored with + unsigned regClassIDOfArgReg = BadRegClass; // reg class of chosen reg + int regNum = (regType == IntRegType) - ? regNumForIntArg(true, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg) - : regNumForFPArg(regType, true, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); - - if(regNum != InvalidRegNum) { + ? regNumForIntArg(/*inCallee*/ true, isVarArgs, + argNo, regClassIDOfArgReg) + : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs, + argNo, regClassIDOfArgReg); + + if(regNum != getInvalidRegNum()) { isArgInReg = true; UniArgReg = getUnifiedRegNum( regClassIDOfArgReg, regNum); } - - if( LR->hasColor() ) { // if this arg received a register + + if( ! LR->isMarkedForSpill() ) { // 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; + continue; - // We are here because the LR did not receive the suggested + // 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) + // 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, it MUST go into // the UniLRReg register // if( isArgInReg ) { - AdMI = cpReg2RegMI( UniArgReg, UniLRReg, regType ); + if( regClassIDOfArgReg != RegClassID ) { + // NOTE: This code has not been well-tested. - if( regClassIDOfArgReg != RegClassID ) { - assert(0 && - "FP arguments to a varargs function should be explicitly " - "copied to/from int registers by instruction selection!"); - - // 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. - // + // 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 && + RegClassID == FloatRegClassID && regClassIDOfArgReg == IntRegClassID && "This should only be an Int register for an FP argument"); - - int TmpOff = MachineCodeForMethod::get(Meth).pushTempValue(target, + + int TmpOff = MachineFunction::get(Meth).getInfo()->pushTempValue( getSpilledRegSize(regType)); - AdMI = cpReg2MemMI(UniArgReg, getFramePointer(), TmpOff, IntRegType); - FirstAI->InstrnsBefore.push_back(AdMI); - - AdMI = cpMem2RegMI(getFramePointer(), TmpOff, UniLRReg, regType); - FirstAI->InstrnsBefore.push_back(AdMI); - } - else { - AdMI = cpReg2RegMI(UniArgReg, UniLRReg, regType ); - FirstAI->InstrnsBefore.push_back( AdMI ); - } + cpReg2MemMI(InstrnsBefore, + UniArgReg, getFramePointer(), TmpOff, IntRegType); + + cpMem2RegMI(InstrnsBefore, + getFramePointer(), TmpOff, UniLRReg, regType); + } + else { + cpReg2RegMI(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(); - int offsetFromFP = - frameInfo.getIncomingArgOffset(MachineCodeForMethod::get(Meth), + // Now the arg is coming on stack. Since the LR received a register, + // we just have to load the arg on stack into that register + // + const TargetFrameInfo& frameInfo = *target.getFrameInfo(); + int offsetFromFP = + frameInfo.getIncomingArgOffset(MachineFunction::get(Meth), argNo); - - AdMI = cpMem2RegMI(getFramePointer(), offsetFromFP, - UniLRReg, regType ); - FirstAI->InstrnsBefore.push_back( AdMI ); + + // float arguments on stack are right justified so adjust the offset! + // int arguments are also right justified but they are always loaded as + // a full double-word so the offset does not need to be adjusted. + if (regType == FPSingleRegType) { + unsigned argSize = target.getTargetData().getTypeSize(LR->getType()); + unsigned slotSize = SparcV9FrameInfo::SizeOfEachArgOnStack; + assert(argSize <= slotSize && "Insufficient slot size!"); + offsetFromFP += slotSize - argSize; + } + + cpMem2RegMI(InstrnsBefore, + getFramePointer(), offsetFromFP, UniLRReg, regType); } - + } // if LR received a color - else { + else { // Now, the LR did not receive a color. But it has a stack offset for // spilling. @@ -542,43 +512,51 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth, // that on to the stack pos of LR if( isArgInReg ) { - - if( regClassIDOfArgReg != RegClassID ) { + + 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 + + // 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"); - - AdMI = cpReg2MemMI(UniArgReg, getFramePointer(), - LR->getSpillOffFromFP(), IntRegType ); + + cpReg2MemMI(InstrnsBefore, UniArgReg, + getFramePointer(), LR->getSpillOffFromFP(), IntRegType); } else { - AdMI = cpReg2MemMI(UniArgReg, getFramePointer(), - LR->getSpillOffFromFP(), regType ); + cpReg2MemMI(InstrnsBefore, UniArgReg, + getFramePointer(), LR->getSpillOffFromFP(), regType); } - - FirstAI->InstrnsBefore.push_back( AdMI ); } 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 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(); - int offsetFromFP = - frameInfo.getIncomingArgOffset(MachineCodeForMethod::get(Meth), + // Now the arg is coming on stack. Since the LR did NOT + // received a register as well, it is allocated a stack position. We + // 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 TargetFrameInfo& frameInfo = *target.getFrameInfo(); + int offsetFromFP = + frameInfo.getIncomingArgOffset(MachineFunction::get(Meth), argNo); - - LR->modifySpillOffFromFP( offsetFromFP ); + + // FP arguments on stack are right justified so adjust offset! + // int arguments are also right justified but they are always loaded as + // a full double-word so the offset does not need to be adjusted. + if (regType == FPSingleRegType) { + unsigned argSize = target.getTargetData().getTypeSize(LR->getType()); + unsigned slotSize = SparcV9FrameInfo::SizeOfEachArgOnStack; + assert(argSize <= slotSize && "Insufficient slot size!"); + offsetFromFP += slotSize - argSize; + } + + LR->modifySpillOffFromFP( offsetFromFP ); } } @@ -593,1173 +571,403 @@ 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()) ); - - // check if this is a varArgs function. needed for choosing regs. - bool isVarArgs = isVarArgsCall(CallMI); - - 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. +void SparcV9RegInfo::suggestRegs4CallArgs(MachineInstr *CallMI, + LiveRangeInfo& LRI) const { + assert ( (target.getInstrInfo())->isCall(CallMI->getOpcode()) ); - // the return value cannot have a LR in machine instruction since it is - // only defined by the call instruction + CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); - // if type is not void, create a new live range and set its - // register class and add to LRI - - - const Value *RetVal = getCallInstRetVal( CallMI ); + suggestReg4CallAddr(CallMI, LRI); + // 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()) { + V9LiveRange *RetValLR = LRI.getLiveRangeForValue(RetVal); + assert(RetValLR && "No LR for return Value of call!"); - if (RetVal) { - assert ((!LRI.getLiveRangeForValue(RetVal)) && - "LR for ret Value of call already definded!"); + unsigned RegClassID = RetValLR->getRegClassID(); - // 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); - else if (RegClassID == FloatRegClassID ) - RetValLR->setSuggestedColor(SparcFloatRegOrder::f0 ); + if( RegClassID == IntRegClassID ) + RetValLR->setSuggestedColor(SparcV9IntRegClass::o0); + else if (RegClassID == FloatRegClassID ) + RetValLR->setSuggestedColor(SparcV9FloatRegClass::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, intArgNo=0, fpArgNo=0; - i < NumOfCallArgs; ++i, ++argNo) { + i < NumOfCallArgs; ++i, ++argNo) { + + const Value *CallArg = argDesc->getArgInfo(i).getArgVal(); - const Value *CallArg = CallMI->getImplicitRef(i); - // get the LR of call operand (parameter) - LiveRange *const LR = LRI.getLiveRangeForValue(CallArg); + V9LiveRange *const LR = LRI.getLiveRangeForValue(CallArg); + if (!LR) + continue; // no live ranges for constants and labels - // 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"); - } - - unsigned regType = getRegType( LR ); - unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg (unused) + unsigned regType = getRegTypeForLR(LR); + unsigned regClassIDOfArgReg = BadRegClass; // chosen reg class (unused) // Choose a register for this arg depending on whether it is - // an INT or FP value, and if it is a varargs call + // 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(false, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg) - : regNumForFPArg(regType, false, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); - + ? regNumForIntArg(/*inCallee*/ false, /*isVarArgs*/ false, + argNo, regClassIDOfArgReg) + : regNumForFPArg(regType, /*inCallee*/ false, /*isVarArgs*/ false, + argNo, regClassIDOfArgReg); + // If a register could be allocated, use it. // If not, do NOTHING as this will be colored as a normal value. - if(regNum != InvalidRegNum) + if(regNum != getInvalidRegNum()) LR->setSuggestedColor(regNum); - } // for all call arguments - } //--------------------------------------------------------------------------- -// After graph coloring, we have call this method to see whehter the return -// value and the call args received the correct colors. If not, we have -// to instert copy instructions. +// this method is called for an LLVM return instruction to identify which +// values will be returned from this method and to suggest colors. //--------------------------------------------------------------------------- +void SparcV9RegInfo::suggestReg4RetValue(MachineInstr *RetMI, + LiveRangeInfo& LRI) const { -void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI, - LiveRangeInfo &LRI, - AddedInstrns *CallAI, - PhyRegAlloc &PRA, - const BasicBlock *BB) const { - - assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) ); - - // First color the return value of the call. - // If there is a LR for the return value, it means this - // method returns a value - - MachineInstr *AdMI; - - const Value *RetVal = getCallInstRetVal( CallMI ); - - 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"); - } - - unsigned RegClassID = (RetValLR->getRegClass())->getID(); - bool recvCorrectColor = false; + assert( target.getInstrInfo()->isReturn( RetMI->getOpcode() ) ); - unsigned CorrectCol; // correct color for ret value - if(RegClassID == IntRegClassID) - CorrectCol = SparcIntRegOrder::o0; - else if(RegClassID == FloatRegClassID) - CorrectCol = SparcFloatRegOrder::f0; - else { - assert( 0 && "Unknown RegClass"); - return; - } - - // if the LR received the correct color, NOTHING to do - - if( RetValLR->hasColor() ) - if( RetValLR->getColor() == CorrectCol ) - recvCorrectColor = true; - - - // if we didn't receive the correct color for some reason, - // put copy instruction - - if( !recvCorrectColor ) { + suggestReg4RetAddr(RetMI, LRI); - unsigned regType = getRegType( RetValLR ); - - // the reg that LR must be colored with - unsigned UniRetReg = getUnifiedRegNum( RegClassID, CorrectCol); - - if( RetValLR->hasColor() ) { - - 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 ); - - } // if LR has color - else { - - // 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 ); - } - - CallAI->InstrnsAfter.push_back( AdMI ); - - } // the LR didn't receive the suggested color - - } // if there a return value - - - //------------------------------------------- - // Now color all args of the call instruction - //------------------------------------------- - - std::vector AddedInstrnsBefore; - - unsigned NumOfCallArgs = getCallInstNumArgs( CallMI ); - - bool isVarArgs = isVarArgsCall(CallMI); - if (DEBUG_RA && isVarArgs) cerr << "\nVar arg call found!!\n"; - - for(unsigned argNo=0, i=0, intArgNo=0, fpArgNo=0; - i < NumOfCallArgs; ++i, ++argNo) { - - const Value *CallArg = CallMI->getImplicitRef(i); - - // get the LR of call operand (parameter) - LiveRange *const LR = LRI.getLiveRangeForValue(CallArg); - - unsigned regType = getRegType( CallArg ); - unsigned RegClassID = getRegClassIDOfValue( CallArg); - - // 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 - unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg - - int regNum = (regType == IntRegType) - ? regNumForIntArg(false, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg) - : regNumForFPArg(regType, false, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); - - if(regNum != InvalidRegNum) { - isArgInReg = true; - UniArgReg = getUnifiedRegNum( regClassIDOfArgReg, regNum); - } - - // 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"); - } - - 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( 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. - // We have to move a float reg to an int reg via memory. - // - assert(isVarArgs && - RegClassID == FloatRegClassID && - regClassIDOfArgReg == IntRegClassID && - "This should only be an Int register for an FP argument"); - - // 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 - - const MachineFrameInfo& frameInfo = target.getFrameInfo(); - int argOffset = - frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo); - - 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( regClassIDOfArgReg != RegClassID ) { - assert(isVarArgs && regClassIDOfArgReg == IntRegClassID && - "This should only be an Int register for an FP argument"); - - 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. - - // Optimize: 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)) ); - - - const MachineFrameInfo& frameInfo = target.getFrameInfo(); - int argOffset = - frameInfo.getOutgoingArgOffset(PRA.mcInfo, 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) - - 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. - - 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 ; - } - } - } // for each parameter in call instruction - - - // if we added any instruction before the call instruction, verify - // that they are in the proper order and if not, reorder them - - if (!AddedInstrnsBefore.empty()) { - - if (DEBUG_RA) { - cerr << "\nCalling reorder with instrns: \n"; - for(unsigned i=0; i < AddedInstrnsBefore.size(); i++) - cerr << *(AddedInstrnsBefore[i]); - } - - std::vector TmpVec; - OrderAddedInstrns(AddedInstrnsBefore, TmpVec, PRA); - - if (DEBUG_RA) { - cerr << "\nAfter reordering instrns: \n"; - for(unsigned i = 0; i < TmpVec.size(); i++) - cerr << *TmpVec[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 - // - insertCallerSavingCode(CallMI, BB, PRA); + // To find the return value (if any), we can get the LLVM return instr. + // from the return address register, which is the first operand + Value* tmpI = RetMI->getOperand(0).getVRegValue(); + ReturnInst* retI=cast(cast(tmpI)->getOperand(0)); + if (const Value *RetVal = retI->getReturnValue()) + if (V9LiveRange *const LR = LRI.getLiveRangeForValue(RetVal)) + LR->setSuggestedColor(LR->getRegClassID() == IntRegClassID + ? (unsigned) SparcV9IntRegClass::i0 + : (unsigned) SparcV9FloatRegClass::f0); } //--------------------------------------------------------------------------- -// This method is called for an LLVM return instruction to identify which -// values will be returned from this method and to suggest colors. +// 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. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestReg4RetValue(const MachineInstr *RetMI, - LiveRangeInfo &LRI) const { - - assert( (UltraSparcInfo->getInstrInfo()).isReturn( RetMI->getOpCode() ) ); - - suggestReg4RetAddr(RetMI, LRI); - // if there is an implicit ref, that has to be the ret value - if( RetMI->getNumImplicitRefs() > 0 ) { - - // The first implicit operand is the return value of a return instr - const Value *RetVal = RetMI->getImplicitRef(0); - - LiveRange *const LR = LRI.getLiveRangeForValue( RetVal ); - - if (!LR) { - cerr << "\nNo LR for:" << RAV(RetVal) << "\n"; - assert(0 && "No LR for return value of non-void method"); +bool +SparcV9RegInfo::regTypeNeedsScratchReg(int RegType, + int& scratchRegType) const +{ + if (RegType == IntCCRegType) + { + scratchRegType = IntRegType; + return true; } - - unsigned RegClassID = (LR->getRegClass())->getID(); - - if (RegClassID == IntRegClassID) - LR->setSuggestedColor(SparcIntRegOrder::i0); - else if (RegClassID == FloatRegClassID) - LR->setSuggestedColor(SparcFloatRegOrder::f0); - } + return false; } - - //--------------------------------------------------------------------------- -// Colors the return value of a method to %i0 or %f0, if possible. If it is -// not possilbe to directly color the LR, insert a copy instruction to move -// the LR to %i0 or %f0. When the LR is spilled, instead of the copy, we -// have to put a load instruction. +// Copy from a register to register. Register number must be the unified +// register number. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI, - LiveRangeInfo &LRI, - AddedInstrns *RetAI) const { - - assert((UltraSparcInfo->getInstrInfo()).isReturn( RetMI->getOpCode())); - - // if there is an implicit ref, that has to be the ret value - if(RetMI->getNumImplicitRefs() > 0) { - - // The first implicit operand is the return value of a return instr - const Value *RetVal = RetMI->getImplicitRef(0); - - LiveRange *LR = LRI.getLiveRangeForValue(RetVal); - - if (!LR) { - cerr << "\nNo LR for:" << RAV(RetVal) << "\n"; - // assert( LR && "No LR for return value of non-void method"); - return; - } - - unsigned RegClassID = getRegClassIDOfValue(RetVal); - unsigned regType = getRegType( RetVal ); - - unsigned CorrectCol; - if(RegClassID == IntRegClassID) - CorrectCol = SparcIntRegOrder::i0; - else if(RegClassID == FloatRegClassID) - CorrectCol = SparcFloatRegOrder::f0; - else { - assert (0 && "Unknown RegClass"); - return; - } - - // 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 - // It may be the suggested register or not +void +SparcV9RegInfo::cpReg2RegMI(std::vector& mvec, + unsigned SrcReg, + unsigned DestReg, + int RegType) const { + assert( ((int)SrcReg != getInvalidRegNum()) && + ((int)DestReg != getInvalidRegNum()) && + "Invalid Register"); - // copy the LR of retun value to i0 or f0 + MachineInstr * MI = NULL; - unsigned UniLRReg =getUnifiedRegNum( RegClassID, LR->getColor()); + switch( RegType ) { - // the LR received UniLRReg but must be colored with UniRetReg - // to pass as the return value - RetAI->InstrnsBefore.push_back(cpReg2RegMI(UniLRReg, UniRetReg, regType)); - } - else { // if the LR is spilled - MachineInstr *AdMI = cpMem2RegMI(getFramePointer(), - LR->getSpillOffFromFP(), - UniRetReg, regType); - RetAI->InstrnsBefore.push_back(AdMI); - cerr << "\nCopied the return value from stack\n"; + case IntCCRegType: + if (getRegType(DestReg) == IntRegType) { + // copy intCC reg to int reg + MI = (BuildMI(V9::RDCCR, 2) + .addMReg(getUnifiedRegNum(SparcV9RegInfo::IntCCRegClassID, + SparcV9IntCCRegClass::ccr)) + .addMReg(DestReg,MachineOperand::Def)); + } else { + // copy int reg to intCC reg + assert(getRegType(SrcReg) == IntRegType + && "Can only copy CC reg to/from integer reg"); + MI = (BuildMI(V9::WRCCRr, 3) + .addMReg(SrcReg) + .addMReg(SparcV9IntRegClass::g0) + .addMReg(getUnifiedRegNum(SparcV9RegInfo::IntCCRegClassID, + SparcV9IntCCRegClass::ccr), + MachineOperand::Def)); } - - } // if there is a return value - -} - - -//--------------------------------------------------------------------------- -// Copy from a register to register. Register number must be the unified -// register number -//--------------------------------------------------------------------------- + break; -MachineInstr * UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg, - unsigned DestReg, - int RegType) const { - assert( ((int)SrcReg != InvalidRegNum) && ((int)DestReg != InvalidRegNum) && - "Invalid Register"); - - MachineInstr * MI = NULL; + case FloatCCRegType: + assert(0 && "Cannot copy FPCC register to any other register"); + break; - switch( RegType ) { - case IntRegType: - case IntCCRegType: - case FloatCCRegType: - MI = new MachineInstr(ADD, 3); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, this->getZeroRegNum(), false); - MI->SetMachineOperandReg(2, DestReg, true); + MI = BuildMI(V9::ADDr, 3).addMReg(SrcReg).addMReg(getZeroRegNum()) + .addMReg(DestReg, MachineOperand::Def); break; case FPSingleRegType: - MI = new MachineInstr(FMOVS, 2); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestReg, true); + MI = BuildMI(V9::FMOVS, 2).addMReg(SrcReg) + .addMReg(DestReg, MachineOperand::Def); break; case FPDoubleRegType: - MI = new MachineInstr(FMOVD, 2); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestReg, true); + MI = BuildMI(V9::FMOVD, 2).addMReg(SrcReg) + .addMReg(DestReg, MachineOperand::Def); break; default: - assert(0 && "Unknow RegType"); + assert(0 && "Unknown RegType"); + break; } - return MI; -} - -//--------------------------------------------------------------------------- -// Copy from a register to memory (i.e., Store). Register number must -// be the unified register number -//--------------------------------------------------------------------------- - + if (MI) + mvec.push_back(MI); +} + +/// cpReg2MemMI - Generate SparcV9 MachineInstrs to store a register +/// (SrcReg) to memory, at [PtrReg + Offset]. Register numbers must be the +/// unified register numbers. RegType must be the SparcV9 register type +/// of SrcReg. When SrcReg is %ccr, scratchReg must be the +/// number of a free integer register. The newly-generated MachineInstrs +/// are appended to mvec. +/// +void SparcV9RegInfo::cpReg2MemMI(std::vector& mvec, + unsigned SrcReg, unsigned PtrReg, int Offset, + int RegType, int scratchReg) const { + unsigned OffReg = SparcV9::g4; // Use register g4 for holding large offsets + bool useImmediateOffset = true; + + // If the Offset will not fit in the signed-immediate field, we put it in + // register g4. This takes advantage of the fact that all the opcodes + // used below have the same size immed. field. + if (RegType != IntCCRegType + && !target.getInstrInfo()->constantFitsInImmedField(V9::LDXi, Offset)) { + // Put the offset into a register. We could do this in fewer steps, + // in some cases (see CreateSETSWConst()) but we're being lazy. + MachineInstr *MI = BuildMI(V9::SETHI, 2).addZImm(Offset).addMReg(OffReg, + MachineOperand::Def); + MI->getOperand(0).markHi32(); + mvec.push_back(MI); + MI = BuildMI(V9::ORi,3).addMReg(OffReg).addZImm(Offset).addMReg(OffReg, + MachineOperand::Def); + MI->getOperand(1).markLo32(); + mvec.push_back(MI); + MI = BuildMI(V9::SRAi5,3).addMReg(OffReg).addZImm(0).addMReg(OffReg, + MachineOperand::Def); + mvec.push_back(MI); + useImmediateOffset = false; + } -MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg, - unsigned DestPtrReg, - int Offset, int RegType) const { - MachineInstr * MI = NULL; - switch( RegType ) { + MachineInstr *MI = 0; + switch (RegType) { case IntRegType: - case FloatCCRegType: - MI = new MachineInstr(STX, 3); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestPtrReg, false); - MI->SetMachineOperandConst(2, MachineOperand:: MO_SignExtendedImmed, - (int64_t) Offset); + if (useImmediateOffset) + MI = BuildMI(V9::STXi,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset); + else + MI = BuildMI(V9::STXr,3).addMReg(SrcReg).addMReg(PtrReg).addMReg(OffReg); break; case FPSingleRegType: - MI = new MachineInstr(ST, 3); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestPtrReg, false); - MI->SetMachineOperandConst(2, MachineOperand:: MO_SignExtendedImmed, - (int64_t) Offset); + if (useImmediateOffset) + MI = BuildMI(V9::STFi, 3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset); + else + MI = BuildMI(V9::STFr, 3).addMReg(SrcReg).addMReg(PtrReg).addMReg(OffReg); break; case FPDoubleRegType: - MI = new MachineInstr(STD, 3); - MI->SetMachineOperandReg(0, SrcReg, false); - MI->SetMachineOperandReg(1, DestPtrReg, false); - MI->SetMachineOperandConst(2, MachineOperand:: MO_SignExtendedImmed, - (int64_t) Offset); + if (useImmediateOffset) + MI = BuildMI(V9::STDFi,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset); + else + MI = BuildMI(V9::STDFr,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(OffReg); break; case IntCCRegType: - assert( 0 && "Cannot directly store %ccr to memory"); - + assert(scratchReg >= 0 && getRegType(scratchReg) == IntRegType + && "Need a scratch reg of integer type to load or store %ccr"); + MI = BuildMI(V9::RDCCR, 2).addMReg(SparcV9::ccr) + .addMReg(scratchReg, MachineOperand::Def); + mvec.push_back(MI); + cpReg2MemMI(mvec, scratchReg, PtrReg, Offset, IntRegType); + return; + + case SpecialRegType: // used only for %fsr itself. + case FloatCCRegType: { + if (useImmediateOffset) + MI = BuildMI(V9::STXFSRi,3).addMReg(SparcV9::fsr).addMReg(PtrReg) + .addSImm(Offset); + else + MI = BuildMI(V9::STXFSRr,3).addMReg(SparcV9::fsr).addMReg(PtrReg) + .addMReg(OffReg); + break; + } default: - assert(0 && "Unknow RegType in cpReg2MemMI"); + assert(0 && "Unknown RegType in cpReg2MemMI"); + } + mvec.push_back(MI); +} + +/// cpMem2RegMI - Generate SparcV9 MachineInstrs to load a register +/// (DestReg) from memory, at [PtrReg + Offset]. Register numbers must be the +/// unified register numbers. RegType must be the SparcV9 register type +/// of DestReg. When DestReg is %ccr, scratchReg must be the +/// number of a free integer register. The newly-generated MachineInstrs +/// are appended to mvec. +/// +void SparcV9RegInfo::cpMem2RegMI(std::vector& mvec, + unsigned PtrReg, int Offset, unsigned DestReg, + int RegType, int scratchReg) const { + unsigned OffReg = SparcV9::g4; // Use register g4 for holding large offsets + bool useImmediateOffset = true; + + // If the Offset will not fit in the signed-immediate field, we put it in + // register g4. This takes advantage of the fact that all the opcodes + // used below have the same size immed. field. + if (RegType != IntCCRegType + && !target.getInstrInfo()->constantFitsInImmedField(V9::LDXi, Offset)) { + MachineInstr *MI = BuildMI(V9::SETHI, 2).addZImm(Offset).addMReg(OffReg, + MachineOperand::Def); + MI->getOperand(0).markHi32(); + mvec.push_back(MI); + MI = BuildMI(V9::ORi,3).addMReg(OffReg).addZImm(Offset).addMReg(OffReg, + MachineOperand::Def); + MI->getOperand(1).markLo32(); + mvec.push_back(MI); + MI = BuildMI(V9::SRAi5,3).addMReg(OffReg).addZImm(0).addMReg(OffReg, + MachineOperand::Def); + mvec.push_back(MI); + useImmediateOffset = false; } - return MI; -} - - -//--------------------------------------------------------------------------- -// Copy from memory to a reg (i.e., Load) Register number must be the unified -// register number -//--------------------------------------------------------------------------- - - -MachineInstr * UltraSparcRegInfo::cpMem2RegMI(unsigned SrcPtrReg, - int Offset, - unsigned DestReg, - int RegType) const { - MachineInstr * MI = NULL; + MachineInstr *MI = 0; switch (RegType) { case IntRegType: - case FloatCCRegType: - MI = new MachineInstr(LDX, 3); - MI->SetMachineOperandReg(0, SrcPtrReg, false); - MI->SetMachineOperandConst(1, MachineOperand:: MO_SignExtendedImmed, - (int64_t) Offset); - MI->SetMachineOperandReg(2, DestReg, true); + if (useImmediateOffset) + MI = BuildMI(V9::LDXi, 3).addMReg(PtrReg).addSImm(Offset) + .addMReg(DestReg, MachineOperand::Def); + else + MI = BuildMI(V9::LDXr, 3).addMReg(PtrReg).addMReg(OffReg) + .addMReg(DestReg, MachineOperand::Def); break; case FPSingleRegType: - MI = new MachineInstr(LD, 3); - MI->SetMachineOperandReg(0, SrcPtrReg, false); - MI->SetMachineOperandConst(1, MachineOperand:: MO_SignExtendedImmed, - (int64_t) Offset); - MI->SetMachineOperandReg(2, DestReg, true); - + if (useImmediateOffset) + MI = BuildMI(V9::LDFi, 3).addMReg(PtrReg).addSImm(Offset) + .addMReg(DestReg, MachineOperand::Def); + else + MI = BuildMI(V9::LDFr, 3).addMReg(PtrReg).addMReg(OffReg) + .addMReg(DestReg, MachineOperand::Def); break; case FPDoubleRegType: - MI = new MachineInstr(LDD, 3); - MI->SetMachineOperandReg(0, SrcPtrReg, false); - MI->SetMachineOperandConst(1, MachineOperand:: MO_SignExtendedImmed, - (int64_t) Offset); - MI->SetMachineOperandReg(2, DestReg, true); + if (useImmediateOffset) + MI= BuildMI(V9::LDDFi, 3).addMReg(PtrReg).addSImm(Offset) + .addMReg(DestReg, MachineOperand::Def); + else + MI= BuildMI(V9::LDDFr, 3).addMReg(PtrReg).addMReg(OffReg) + .addMReg(DestReg, MachineOperand::Def); break; case IntCCRegType: - assert( 0 && "Cannot directly load into %ccr from memory"); + assert(scratchReg >= 0 && getRegType(scratchReg) == IntRegType + && "Need a scratch reg of integer type to load or store %ccr"); + cpMem2RegMI(mvec, PtrReg, Offset, scratchReg, IntRegType); + MI = BuildMI(V9::WRCCRr, 3).addMReg(scratchReg).addMReg(SparcV9::g0) + .addMReg(SparcV9::ccr, MachineOperand::Def); + break; + case SpecialRegType: // used only for %fsr itself + case FloatCCRegType: { + if (useImmediateOffset) + MI = BuildMI(V9::LDXFSRi, 3).addMReg(PtrReg).addSImm(Offset) + .addMReg(SparcV9::fsr, MachineOperand::Def); + else + MI = BuildMI(V9::LDXFSRr, 3).addMReg(PtrReg).addMReg(OffReg) + .addMReg(SparcV9::fsr, MachineOperand::Def); + break; + } default: assert(0 && "Unknown RegType in cpMem2RegMI"); } - - return MI; + mvec.push_back(MI); } - - - //--------------------------------------------------------------------------- // Generate a copy instruction to copy a value to another. Temporarily // used by PhiElimination code. //--------------------------------------------------------------------------- -MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const { - int RegType = getRegType( Src ); - - assert( (RegType==getRegType(Src)) && "Src & Dest are diff types"); - +void +SparcV9RegInfo::cpValue2Value(Value *Src, Value *Dest, + std::vector& mvec) const { + int RegType = getRegTypeForDataType(Src->getType()); MachineInstr * MI = NULL; - switch( RegType ) { + 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 = BuildMI(V9::ADDr, 3).addReg(Src).addMReg(getZeroRegNum()) + .addRegDef(Dest); 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 = BuildMI(V9::FMOVS, 2).addReg(Src).addRegDef(Dest); 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 = BuildMI(V9::FMOVD, 2).addReg(Src).addRegDef(Dest); break; - default: - assert(0 && "Unknow RegType in CpValu2Value"); - } - - return MI; -} - - - - - - -//---------------------------------------------------------------------------- -// This method inserts caller saving/restoring instructons before/after -// a call machine instruction. The caller saving/restoring instructions are -// inserted like: -// -// ** caller saving instructions -// other instructions inserted for the call by ColorCallArg -// CALL instruction -// other instructions inserted for the call ColorCallArg -// ** caller restoring instructions -// -//---------------------------------------------------------------------------- - - -void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, - const BasicBlock *BB, - PhyRegAlloc &PRA) const { - - // has set to record which registers were saved/restored - // - std::hash_set PushedRegSet; - - // 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 - // and restore it after the call. - // We do this because, we look at the LV set *after* the instruction - // 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 ); - - if (RetVal) { - LiveRange *RetValLR = PRA.LRI.getLiveRangeForValue( RetVal ); - assert(RetValLR && "No LR for RetValue of call"); - - if (RetValLR->hasColor()) - PushedRegSet.insert( - getUnifiedRegNum((RetValLR->getRegClass())->getID(), - RetValLR->getColor() ) ); + assert(0 && "Unknown RegType in cpValue2Value"); } - - const ValueSet &LVSetAft = PRA.LVI->getLiveVarSetAfterMInst(MInst, BB); - ValueSet::const_iterator LIt = LVSetAft.begin(); - - // for each live var in live variable set after machine inst - for( ; LIt != LVSetAft.end(); ++LIt) { - - // get the live range corresponding to live var - LiveRange *const LR = PRA.LRI.getLiveRangeForValue(*LIt ); - - // LR can be null if it is a const since a const - // doesn't have a dominating def - see Assumptions above - if( LR ) { - - if( LR->hasColor() ) { - - unsigned RCID = (LR->getRegClass())->getID(); - unsigned Color = LR->getColor(); - - if ( isRegVolatile(RCID, Color) ) { - - // 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() ) { - - // if we haven't already pushed that register - - unsigned RegType = getRegType( LR ); - - // 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)); - - - 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); - } - - - //---- 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); - } - - 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; - } - } - } // if not already pushed - - } // if LR has a volatile color - - } // if LR has color - - } // if there is a LR for Var - - } // for each value in the LV set after instruction - + mvec.push_back(MI); } -//--------------------------------------------------------------------------- -// 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 //--------------------------------------------------------------------------- -void UltraSparcRegInfo::printReg(const LiveRange *LR) { - unsigned RegClassID = (LR->getRegClass())->getID(); - cerr << " *Node " << (LR->getUserIGNode())->getIndex(); +void SparcV9RegInfo::printReg(const V9LiveRange *LR) const { + unsigned RegClassID = LR->getRegClassID(); + std::cerr << " Node "; if (!LR->hasColor()) { - cerr << " - could not find a color\n"; + std::cerr << " - could not find a color\n"; return; } - - // if a color is found - - cerr << " colored with color "<< LR->getColor(); - - if (RegClassID == IntRegClassID) { - cerr<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) << "]\n"; - - } else if (RegClassID == FloatRegClassID) { - cerr << "[" << SparcFloatRegOrder::getRegName(LR->getColor()); - if( LR->getType() == Type::DoubleTy) - cerr << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1); - cerr << "]\n"; - } -} - -//--------------------------------------------------------------------------- -// This method examines instructions inserted by RegAlloc code before a -// machine instruction to detect invalid orders that destroy values before -// they are used. If it detects such conditions, it reorders the instructions. -// -// 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. + // if a color is found -// All the uses are before THE def to a register + std::cerr << " colored with color "<< LR->getColor(); + unsigned uRegName = getUnifiedRegNum(RegClassID, LR->getColor()); -//--------------------------------------------------------------------------- -void UltraSparcRegInfo::OrderAddedInstrns(std::vector &UnordVec, - std::vector &OrdVec, - PhyRegAlloc &PRA) const{ - - /* - Problem: We can have instructions inserted by RegAlloc like - 1. add %ox %g0 %oy - 2. add %oy %g0 %oz, where z!=x or z==x - - This is wrong since %oy used by 2 is overwritten by 1 - - Solution: - We re-order the instructions so that the uses are before the defs - - Algorithm: - - do - for each instruction 'DefInst' in the UnOrdVec - for each instruction 'UseInst' that follows the DefInst - if the reg defined by DefInst is used by UseInst - mark DefInst as not movable in this iteration - If DefInst is not marked as not-movable, move DefInst to OrdVec - while all instructions in DefInst are moved to OrdVec - - For moving, we call the move2OrdVec(). It checks whether there is a def - in it for the uses in the instruction to be added to OrdVec. If there - are no preceding defs, it just appends the instruction. If there is a - preceding def, it puts two instructions to save the reg on stack before - the load and puts a restore at use. - - */ - - bool CouldMoveAll; - bool DebugPrint = false; - - do { - CouldMoveAll = true; - std::vector::iterator DefIt = UnordVec.begin(); - - for( ; DefIt != UnordVec.end(); ++DefIt ) { - - // for each instruction in the UnordVec do ... - - MachineInstr *DefInst = *DefIt; - - if( DefInst == NULL) continue; - - //cerr << "\nInst in UnordVec = " << *DefInst; - - // 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 the operand in DefInst is a def ... - - bool DefEqUse = false; - - std::vector::iterator UseIt = DefIt; - UseIt++; - - for( ; UseIt != UnordVec.end(); ++UseIt ) { - - MachineInstr *UseInst = *UseIt; - if( UseInst == NULL) continue; - - // for each inst (UseInst) that is below the DefInst do ... - MachineOperand& UseOp = UseInst->getOperand(0); - - if( ! UseOp.opIsDef() && - UseOp.getOperandType() == MachineOperand::MO_MachineRegister) { - - // if use is a register ... - - if( DefOp.getMachineRegNum() == UseOp.getMachineRegNum() ) { - - // if Def and this use are the same, it means that this use - // is destroyed by a def before it is used - - // cerr << "\nCouldn't move " << *DefInst; - - DefEqUse = true; - CouldMoveAll = false; - DebugPrint = true; - break; - } // if two registers are equal - - } // if use is a register - - }// for all use instructions - - if( ! DefEqUse ) { - - // after examining all the instructions that follow the DefInst - // if there are no dependencies, we can move it to the OrdVec - - // cerr << "Moved to Ord: " << *DefInst; - - moveInst2OrdVec(OrdVec, DefInst, PRA); - - //OrdVec.push_back(DefInst); - - // mark the pos of DefInst with NULL to indicate that it is - // empty - *DefIt = NULL; - } - - } // if Def is a machine register - - } // for all instructions in the UnordVec - - - } while(!CouldMoveAll); - - if (DebugPrint) { - cerr << "\nAdded instructions were reordered to:\n"; - for(unsigned int i=0; i < OrdVec.size(); i++) - cerr << *(OrdVec[i]); - } + std::cerr << "["; + std::cerr<< getUnifiedRegName(uRegName); + if (RegClassID == FloatRegClassID && LR->getType() == Type::DoubleTy) + std::cerr << "+" << getUnifiedRegName(uRegName+1); + std::cerr << "]\n"; } - - - - -void UltraSparcRegInfo::moveInst2OrdVec(std::vector &OrdVec, - MachineInstr *UnordInst, - PhyRegAlloc &PRA) const { - MachineOperand& UseOp = UnordInst->getOperand(0); - - if( ! UseOp.opIsDef() && - UseOp.getOperandType() == MachineOperand::MO_MachineRegister) { - - // for the use of UnordInst, see whether there is a defining instr - // before in the OrdVec - bool DefEqUse = false; - - std::vector::iterator OrdIt = OrdVec.begin(); - - for( ; OrdIt != OrdVec.end(); ++OrdIt ) { - - MachineInstr *OrdInst = *OrdIt ; - - MachineOperand& DefOp = - OrdInst->getOperand(OrdInst->getNumOperands()-1); - - if( DefOp.opIsDef() && - DefOp.getOperandType() == MachineOperand::MO_MachineRegister) { - - //cerr << "\nDefining Ord Inst: " << *OrdInst; - - if( DefOp.getMachineRegNum() == UseOp.getMachineRegNum() ) { - - // we are here because there is a preceding def in the OrdVec - // for the use in this intr we are going to insert. This - // happened because the original code was like: - // 1. add %ox %g0 %oy - // 2. add %oy %g0 %ox - // In Round1, we added 2 to OrdVec but 1 remained in UnordVec - // Now we are processing %ox of 1. - // We have to - - const int UReg = DefOp.getMachineRegNum(); - const int RegType = getRegType(UReg); - MachineInstr *AdIBef, *AdIAft; - - 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); - OrdIt = OrdVec.insert( OrdIt, AdIBef); - OrdIt++; // points to current instr we processed - - // Load directly into DReg (%oy) - MachineOperand& DOp= - (UnordInst->getOperand(UnordInst->getNumOperands()-1)); - assert(DOp.opIsDef() && "Last operand is not the def"); - const int DReg = DOp.getMachineRegNum(); - - AdIAft=cpMem2RegMI(getFramePointer(), StackOff, DReg, RegType); - OrdVec.push_back(AdIAft); - - cerr << "\nFixed CIRCULAR references by reordering"; - - if( DEBUG_RA ) { - cerr << "\nBefore CIRCULAR Reordering:\n"; - cerr << *UnordInst; - cerr << *OrdInst; - - cerr << "\nAfter CIRCULAR Reordering - All Inst so far:\n"; - for(unsigned i=0; i < OrdVec.size(); i++) - cerr << *(OrdVec[i]); - } - - // Do not copy the UseInst to OrdVec - DefEqUse = true; - break; - - }// if two registers are equal - - } // if Def is a register - - } // for each instr in OrdVec - - if(!DefEqUse) { - - // We didn't find a def in the OrdVec, so just append this inst - OrdVec.push_back( UnordInst ); - //cerr << "Reordered Inst (Moved Dn): " << *UnordInst; - } - - }// if the operand in UnordInst is a use -} +} // End llvm namespace