added register allocation code
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@585 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/SparcV9/SparcV9TargetMachine.cpp b/lib/Target/SparcV9/SparcV9TargetMachine.cpp
index f1be406..2070af7 100644
--- a/lib/Target/SparcV9/SparcV9TargetMachine.cpp
+++ b/lib/Target/SparcV9/SparcV9TargetMachine.cpp
@@ -14,6 +14,10 @@
#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)
//
@@ -85,6 +89,327 @@
}
+
+//---------------------------------------------------------------------------
+// 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
//
@@ -97,13 +422,47 @@
//---------------------------------------------------------------------------
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()
@@ -116,6 +475,10 @@
<< M->getName() << "\n\n";
return true;
}
+
+ AllocateRegisters(M, *this); // allocate registers
+
+
return false;
}