};
+
//---------------------------------------------------------------------------
-// class UltraSparcInstrInfo
+// class UltraSparcRegInfo
//
// Purpose:
// This class provides info about sparc register classes.
//---------------------------------------------------------------------------
class LiveRange;
+class UltraSparc;
+
class UltraSparcRegInfo : public MachineRegInfo
{
private:
- enum RegClassIDs { IntRegClassID, FloatRegClassID, FloatCCREgClassID };
+
+ enum RegClassIDs {
+ IntRegClassID,
+ FloatRegClassID,
+ IntCCRegClassID,
+ FloatCCRegClassID
+ };
+
+ // WARNING: If the above enum order must be changed, also modify
+ // getRegisterClassOfValue method below since it assumes this particular
+ // order for efficiency.
+
// reverse pointer to get info about the ultra sparc machine
const UltraSparc *const UltraSparcInfo;
public:
- UltraSparcRegInfo(const UltraSparc *USI ) : UltraSparcInfo(USI),
- NumOfIntArgRegs(6),
- NumOfFloatArgRegs(6)
- {
+ UltraSparcRegInfo(const UltraSparc *const USI ) : UltraSparcInfo(USI),
+ NumOfIntArgRegs(6),
+ NumOfFloatArgRegs(6)
+ {
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 == 6 &&
"6 Float regs are used for float arg passing");
-
}
+ // ***** TODO Delete
+ ~UltraSparcRegInfo(void) { } // empty destructor
+
+
inline const UltraSparc & getUltraSparcInfo() const {
return *UltraSparcInfo;
}
- inline unsigned getRegClassIDOfValue (const Value *const Val) const {
+
+
+ inline unsigned getRegClassIDOfValue (const Value *const Val,
+ bool isCCReg = false) const {
+
Type::PrimitiveID ty = (Val->getType())->getPrimitiveID();
+
+ unsigned res;
if( ty && ty <= Type::LongTyID || (ty == Type::PointerTyID) )
- return IntRegClassID; // sparc int reg (ty=0: void)
+ res = IntRegClassID; // sparc int reg (ty=0: void)
else if( ty <= Type::DoubleTyID)
- return FloatRegClassID; // sparc float reg class
+ res = FloatRegClassID; // sparc float reg class
else {
cout << "TypeID: " << ty << endl;
assert(0 && "Cannot resolve register class for type");
}
+
+ if(isCCReg)
+ return res + 2; // corresponidng condition code regiser
+
+ else
+ return res;
+
}
-
+
+
+#if 0
+ unsigned getRCIDOfMachineOp (const MachineOperand & Op) const {
+
+ unsigned Type = getRegClassIDOfValue( Op.getVRegValue() );
+
+ if( Op.getOperandType() == MachineOperand::MO_CCRegister )
+ return Type + 2; // because of the order of CC classes
+ else return Type;
+ }
+
+#endif
+
+
+
void colorArgs(const Method *const Meth, LiveRangeInfo& LRI) const;
static void printReg(const LiveRange *const LR) ;
return reg;
else if ( RegClassID == FloatRegClassID && reg < 64)
return reg + 32; // we have 32 int regs
- else if( RegClassID == FloatCCREgClassID && reg < 4)
+ else if( RegClassID == FloatCCRegClassID && reg < 4)
return reg + 32 + 64; // 32 int, 64 float
- else
+ else if( RegClassID == IntCCRegClassID )
+ return 4+ 32 + 64; // only int cc reg
+ else
assert(0 && "Invalid register class or reg number");
}
else if ( reg < (64 + 32) )
return SparcFloatRegOrder::getRegName( reg - 32);
else if( reg < (64+32+4) )
- assert( 0 && "no float condition reg class yet");
- // return reg + 32 + 64;
+ return SparcFloatCCRegOrder::getRegName( reg -32 - 64);
+ else if ( reg == 64+32+4)
+ return "xcc"; // only integer cc reg
else
assert(0 && "Invalid register number");
}
-
-
-
/*---------------------------------------------------------------------------
Scheduling guidelines for SPARC IIi:
class UltraSparc : public TargetMachine {
UltraSparcInstrInfo InstInfo;
UltraSparcSchedInfo InstSchedulingInfo;
+ UltraSparcRegInfo RegInfo;
public:
UltraSparc();
virtual ~UltraSparc() {}
virtual const MachineInstrInfo& getInstrInfo() const { return InstInfo; }
+ virtual const MachineRegInfo& getRegInfo() const { return RegInfo; }
+
// compileMethod - For the sparc, we do instruction selection, followed by
// delay slot scheduling, then register allocation.
//
Purpose: Contains the description of integer register class of Sparc
*/
-#ifndef SPARC_INT_REG_CLASS_H
-#define SPARC_INT_REG_CLASS_H
+
+#ifndef SPARC_REG_INFO_CLASS_H
+#define SPARC_REG_INFO_CLASS_H
#include "llvm/Target/RegInfo.h"
+#include "llvm/CodeGen/IGNode.h"
//-----------------------------------------------------------------------------
// Integer Register Class
//-----------------------------------------------------------------------------
+
// Int register names in same order as enum in class SparcIntRegOrder
-//
+
static string const IntRegNames[] =
{ "g1", "g2", "g3", "g4", "g5", "g6", "g7",
"o0", "o1", "o2", "o3", "o4", "o5", "o7",
public:
SparcIntRegClass(unsigned ID)
- : MachineRegClassInfo(0,
+ : MachineRegClassInfo(ID,
SparcIntRegOrder::NumOfAvailRegs,
SparcIntRegOrder::NumOfAllRegs)
{ }
};
+
class SparcFloatRegClass : public MachineRegClassInfo
{
private:
public:
SparcFloatRegClass(unsigned ID)
- : MachineRegClassInfo(1,
+ : MachineRegClassInfo(ID,
SparcFloatRegOrder::NumOfAvailRegs,
SparcFloatRegOrder::NumOfAllRegs)
{ }
+
+//-----------------------------------------------------------------------------
+// Int CC Register Class
+// Only one integer cc register is available
+//-----------------------------------------------------------------------------
+
+
+class SparcIntCCRegClass : public MachineRegClassInfo
+{
+public:
+
+ SparcIntCCRegClass(unsigned ID)
+ : MachineRegClassInfo(ID,1, 1) { }
+
+ inline void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
+ Node->setColor(0); // only one int cc reg is available
+ }
+
+};
+
+
+
+//-----------------------------------------------------------------------------
+// Float CC Register Class
+// Only 4 Float CC registers are available
+//-----------------------------------------------------------------------------
+
+
+static string const FloatCCRegNames[] =
+ {
+ "fcc0", "fcc1", "fcc2", "fcc3"
+ };
+
+
+class SparcFloatCCRegOrder{
+
+ public:
+
+ enum RegsInPrefOrder {
+
+ fcc0, fcc1, fcc2, fcc3
+ };
+
+ static const string getRegName(const unsigned reg) {
+ assert( reg < 4 );
+ return FloatCCRegNames[reg];
+ }
+
+};
+
+
+
+class SparcFloatCCRegClass : public MachineRegClassInfo
+{
+public:
+
+ SparcFloatCCRegClass(unsigned ID)
+ : MachineRegClassInfo(ID, 4, 4) { }
+
+ void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
+ int c;
+ for(c=0; c < 4 && IsColorUsedArr[c] ; ++c) ; // find color
+ assert( (c < 4) && "Can allocate only 4 float cc registers");
+ Node->setColor(c);
+ }
+
+};
+
+
+
+
#endif
#include "llvm/CodeGen/InstrScheduling.h"
#include "llvm/CodeGen/InstrSelection.h"
+#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
+#include "llvm/CodeGen/PhyRegAlloc.h"
+
+
// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
//
}
+
+//---------------------------------------------------------------------------
+// class UltraSparcRegInfo
+//
+// Purpose:
+// This class provides info about sparc register classes.
+//--------------------------------------------------------------------------
+
+#if 0
+UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc *const USI ) :
+ UltraSparcInfo(USI),
+ NumOfIntArgRegs(6),
+ NumOfFloatArgRegs(6)
+ {
+ 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 == 6 &&
+ "6 Float regs are used for float arg passing");
+ }
+
+ // ***** TODO insert deletes for reg classes
+UltraSparcRegInfo::~UltraSparcRegInfo(void) { } // empty destructor
+
+#endif
+
+//---------------------------------------------------------------------------
+// UltraSparcRegInfo
+// Purpose:
+// This method will color incoming args to a method. If there are more
+// args than that can fit in regs, code will be inserted to pop them from
+// stack
+//---------------------------------------------------------------------------
+
+
+void UltraSparcRegInfo::colorArgs(const Method *const Meth,
+ LiveRangeInfo& LRI) const
+{
+
+ // get the argument list
+ const Method::ArgumentListType& ArgList = Meth->getArgumentList();
+ // get an iterator to arg list
+ Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
+ unsigned intArgNo=0;
+
+ // to keep track of which float regs are allocated for argument passing
+ bool FloatArgUsedArr[NumOfFloatArgRegs];
+
+ // init float arg used array
+ for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
+ FloatArgUsedArr[i] = false;
+
+ // for each argument
+ for( ; ArgIt != ArgList.end() ; ++ArgIt) {
+
+ // get the LR of arg
+ LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt);
+ unsigned RegClassID = (LR->getRegClass())->getID();
+
+ // if the arg is in int class - allocate a reg for an int arg
+ if( RegClassID == IntRegClassID ) {
+
+ if( intArgNo < NumOfIntArgRegs) {
+ LR->setColor( SparcIntRegOrder::i0 + intArgNo );
+
+ if( DEBUG_RA) printReg( LR );
+ }
+
+ else {
+ // TODO: Insert push code here
+ assert( 0 && "Insert push code here!");
+ }
+ ++intArgNo;
+ }
+
+ // if the arg is float/double
+ else if ( RegClassID == FloatRegClassID) {
+
+ if( LR->getTypeID() == Type::DoubleTyID ) {
+
+ // find the first reg # we can pass a double arg
+ for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
+ if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
+ LR->setColor( SparcFloatRegOrder::f0 + i );
+ FloatArgUsedArr[i] = true;
+ FloatArgUsedArr[i+1] = true;
+ if( DEBUG_RA) printReg( LR );
+ break;
+ }
+ }
+ if( ! LR->hasColor() ) { // if LR was not colored above
+
+ assert(0 && "insert push code here for a double");
+
+ }
+
+ }
+ else if( LR->getTypeID() == Type::FloatTyID ) {
+
+ // find the first reg # we can pass a float arg
+ for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
+ if ( !FloatArgUsedArr[i] ) {
+ LR->setColor( SparcFloatRegOrder::f0 + i );
+ FloatArgUsedArr[i] = true;
+ if( DEBUG_RA) printReg( LR );
+ break;
+ }
+ }
+ if( ! LR->hasColor() ) { // if LR was not colored above
+ assert(0 && "insert push code here for a float");
+ }
+
+ }
+ else
+ assert(0 && "unknown float type in method arg");
+
+ } // float register class
+
+ else
+ assert(0 && "Unknown RegClassID");
+ }
+
+}
+
+
+
+
+
+
+void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
+
+ unsigned RegClassID = (LR->getRegClass())->getID();
+
+ cout << " *Node " << (LR->getUserIGNode())->getIndex();
+
+ if( ! LR->hasColor() ) {
+ cout << " - could not find a color" << endl;
+ return;
+ }
+
+ // if a color is found
+
+ cout << " colored with color "<< LR->getColor();
+
+ if( RegClassID == IntRegClassID ) {
+
+ cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
+ cout << "]" << endl;
+ }
+ else if ( RegClassID == FloatRegClassID) {
+ cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
+ if( LR->getTypeID() == Type::DoubleTyID )
+ cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
+ cout << "]" << endl;
+ }
+
+
+}
+
+
+void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
+ CallInstrList, LiveRangeInfo& LRI,
+ AddedInstrMapType &AddedInstrMap) const
+{
+
+ vector<const Instruction *>::const_iterator InstIt = CallInstrList.begin();
+
+ for( ; InstIt != CallInstrList.end(); ++InstIt) {
+
+ // Inst = LLVM call instruction
+ const Instruction *const CallI = *InstIt;
+
+ MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec();
+ MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
+
+ // find the CALL/JMMPL machine instruction
+ for( ; MIIt != MInstVec.end() &&
+ ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
+ ++MIIt );
+
+ assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
+
+ // CallMI = CALL/JMPL machine isntruction
+ const MachineInstr *const CallMI = *MIIt;
+
+ Instruction::op_const_iterator OpIt = CallI->op_begin();
+
+ unsigned intArgNo=0;
+ //unsigned NumOfCallInterfs = LR->getNumOfCallInterferences();
+
+ // to keep track of which float regs are allocated for argument passing
+ bool FloatArgUsedArr[NumOfFloatArgRegs];
+
+ // init float arg used array
+ for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
+ FloatArgUsedArr[i] = false;
+
+ // go thru all the operands of LLVM instruction
+ for( ; OpIt != CallI->op_end(); ++OpIt ) {
+
+ // get the LR of call operand (parameter)
+ LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt);
+
+ if ( !LR ) {
+ cout << " Warning: In call instr, no LR for arg: " ;
+ printValue(*OpIt);
+ cout << endl;
+ continue;
+ }
+
+ unsigned RegClassID = (LR->getRegClass())->getID();
+
+ // if the arg is in int class - allocate a reg for an int arg
+ if( RegClassID == IntRegClassID ) {
+
+ if( intArgNo < NumOfIntArgRegs) {
+ setCallArgColor( LR, SparcIntRegOrder::o0 + intArgNo );
+ }
+
+ else {
+ // TODO: Insert push code here
+ assert( 0 && "Insert push code here!");
+
+ AddedInstrns * AI = AddedInstrMap[ CallMI ];
+ if( ! AI ) AI = new AddedInstrns();
+
+ // AI->InstrnsBefore.push_back( getStackPushInstr(LR) );
+ AddedInstrMap[ CallMI ] = AI;
+
+ }
+ ++intArgNo;
+ }
+
+ // if the arg is float/double
+ else if ( RegClassID == FloatRegClassID) {
+
+ if( LR->getTypeID() == Type::DoubleTyID ) {
+
+ // find the first reg # we can pass a double arg
+ for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
+ if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
+ setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
+ FloatArgUsedArr[i] = true;
+ FloatArgUsedArr[i+1] = true;
+ //if( DEBUG_RA) printReg( LR );
+ break;
+ }
+ }
+ if( ! LR->hasColor() ) { // if LR was not colored above
+
+ assert(0 && "insert push code here for a double");
+
+ }
+
+ }
+ else if( LR->getTypeID() == Type::FloatTyID ) {
+
+ // find the first reg # we can pass a float arg
+ for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
+ if ( !FloatArgUsedArr[i] ) {
+ setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
+ FloatArgUsedArr[i] = true;
+ // LR->setColor( SparcFloatRegOrder::f0 + i );
+ // if( DEBUG_RA) printReg( LR );
+ break;
+ }
+ }
+ if( ! LR->hasColor() ) { // if LR was not colored above
+ assert(0 && "insert push code here for a float");
+ }
+
+ }
+ else
+ assert(0 && "unknown float type in method arg");
+
+ } // float register class
+
+ else
+ assert(0 && "Unknown RegClassID");
+
+
+ } // for each operand in a call instruction
+
+
+
+
+ } // for all call instrctions in CallInstrList
+
+}
+
+
+void UltraSparcRegInfo::setCallArgColor(LiveRange *const LR,
+ const unsigned RegNo) const {
+
+ // if no call interference and LR is NOT previously colored (e.g., as an
+ // incoming arg)
+ if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) {
+ // we can directly allocate a %o register
+ LR->setColor( RegNo);
+ if( DEBUG_RA) printReg( LR );
+ }
+ else { // there are call interferences
+
+ /*
+ // insert a copy machine instr to copy from LR to %o(reg)
+ PreMInstrMap[ CallMI ] =
+ getNewCopyMInstr( LR->, SparcIntRegOrder::o0 + intArgNo );
+ */
+ cout << " $$$ TODO: Insert a copy for call argument!: " << endl;
+
+ // We don't color LR here. It's colored as any other normal LR
+ }
+
+}
+
+
+
+
+
//---------------------------------------------------------------------------
// class UltraSparcMachine
//
//---------------------------------------------------------------------------
UltraSparc::UltraSparc() : TargetMachine("UltraSparc-Native"),
- InstSchedulingInfo(&InstInfo) {
+ InstSchedulingInfo(&InstInfo),
+ RegInfo( this ) {
optSizeForSubWordData = 4;
minMemOpWordSize = 8;
maxAtomicMemOpWordSize = 8;
zeroRegNum = 0; // %g0 always gives 0 on Sparc
}
+
+
+//----------------------------------------------------------------------------
+// Entry point for register allocation for a module
+//----------------------------------------------------------------------------
+
+void AllocateRegisters(Method *M, TargetMachine &TM)
+{
+
+ if ( (M)->isExternal() ) // don't process prototypes
+ return;
+
+ if( DEBUG_RA ) {
+ cout << endl << "******************** Method "<< (M)->getName();
+ cout << " ********************" <<endl;
+ }
+
+ MethodLiveVarInfo LVI(M ); // Analyze live varaibles
+ LVI.analyze();
+
+
+ PhyRegAlloc PRA(M, TM , &LVI); // allocate registers
+ PRA.allocateRegisters();
+
+
+ if( DEBUG_RA ) cout << endl << "Register allocation complete!" << endl;
+
+}
+
+
+
+
+
bool UltraSparc::compileMethod(Method *M) {
if (SelectInstructionsForMethod(M, *this)) {
cerr << "Instruction selection failed for method " << M->getName()
<< M->getName() << "\n\n";
return true;
}
+
+ AllocateRegisters(M, *this); // allocate registers
+
+
return false;
}