forked from OSchip/llvm-project
parent
1f331f258b
commit
dfc6c887da
|
@ -6,6 +6,7 @@ Source = \
|
|||
Sparc.o \
|
||||
Sparc.burm.o \
|
||||
SparcInstrSelection.o \
|
||||
SparcRegClassInfo.o \
|
||||
SparcRegInfo.o
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
|
|
@ -29,16 +29,16 @@
|
|||
TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); }
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Entry point for register allocation for a module
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
AllocateRegisters(Method *M, TargetMachine &TM)
|
||||
void AllocateRegisters(Method *M, TargetMachine &TM)
|
||||
{
|
||||
|
||||
if ( (M)->isExternal() ) // don't process prototypes
|
||||
return false;
|
||||
return;
|
||||
|
||||
if( DEBUG_RA ) {
|
||||
cout << endl << "******************** Method "<< (M)->getName();
|
||||
|
@ -55,9 +55,11 @@ AllocateRegisters(Method *M, TargetMachine &TM)
|
|||
|
||||
if( DEBUG_RA ) cout << endl << "Register allocation complete!" << endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//***************************** External Classes **************************/
|
||||
|
||||
|
||||
|
@ -128,300 +130,6 @@ UltraSparcSchedInfo::initializeResources()
|
|||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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
|
||||
//
|
||||
|
@ -445,9 +153,11 @@ UltraSparc::UltraSparc()
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
UltraSparc::compileMethod(Method *M)
|
||||
{
|
||||
|
||||
|
||||
|
||||
bool UltraSparc::compileMethod(Method *M) {
|
||||
|
||||
if (SelectInstructionsForMethod(M, *this))
|
||||
{
|
||||
cerr << "Instruction selection failed for method " << M->getName()
|
||||
|
@ -462,13 +172,11 @@ UltraSparc::compileMethod(Method *M)
|
|||
return true;
|
||||
}
|
||||
|
||||
// if (AllocateRegisters(M, *this)) // allocate registers
|
||||
// {
|
||||
// cerr << "Register allocation failed for method "
|
||||
// << M->getName() << "\n\n";
|
||||
// return true;
|
||||
// }
|
||||
|
||||
AllocateRegisters(M, *this); // allocate registers
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
#ifndef SPARC_INTERNALS_H
|
||||
#define SPARC_INTERNALS_H
|
||||
|
||||
#include "SparcRegInfo.h"
|
||||
|
||||
#include "SparcRegClassInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/MachineInstrInfo.h"
|
||||
|
||||
#include "llvm/Target/MachineSchedInfo.h"
|
||||
#include "llvm/Type.h"
|
||||
|
||||
|
@ -855,17 +859,12 @@ public:
|
|||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// class UltraSparcRegInfo
|
||||
//
|
||||
// Purpose:
|
||||
// This class provides info about sparc register classes.
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class LiveRange;
|
||||
class UltraSparc;
|
||||
|
||||
|
||||
|
||||
class UltraSparcRegInfo : public MachineRegInfo
|
||||
{
|
||||
|
||||
|
@ -893,27 +892,32 @@ class UltraSparcRegInfo : public MachineRegInfo
|
|||
// %f0 - %f5 are used (can hold 6 floats or 3 doubles)
|
||||
unsigned const NumOfFloatArgRegs;
|
||||
|
||||
void setCallArgColor(LiveRange *const LR, const unsigned RegNo) const;
|
||||
//void setCallArgColor(LiveRange *const LR, const unsigned RegNo) const;
|
||||
|
||||
void setCallOrRetArgCol(LiveRange *const LR, const unsigned RegNo,
|
||||
const MachineInstr *MI,AddedInstrMapType &AIMap)const;
|
||||
|
||||
MachineInstr * getCopy2RegMI(const Value *SrcVal, const unsigned Reg,
|
||||
unsigned RegClassID) const ;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
UltraSparcRegInfo(const UltraSparc *const USI )
|
||||
: MachineRegInfo(),
|
||||
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
|
||||
|
||||
|
@ -922,11 +926,7 @@ class UltraSparcRegInfo : public MachineRegInfo
|
|||
return *UltraSparcInfo;
|
||||
}
|
||||
|
||||
// returns the register that is hardwired to zero
|
||||
virtual inline int getZeroRegNum() const {
|
||||
return (int) SparcIntRegOrder::g0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline unsigned getRegClassIDOfValue (const Value *const Val,
|
||||
bool isCCReg = false) const {
|
||||
|
@ -953,6 +953,18 @@ class UltraSparcRegInfo : public MachineRegInfo
|
|||
|
||||
}
|
||||
|
||||
// returns the register tha contains always zero
|
||||
inline int getZeroRegNum() const { return SparcIntRegOrder::g0; }
|
||||
|
||||
// returns the reg used for pushing the address when a method is called.
|
||||
// This can be used for other purposes between calls
|
||||
unsigned getCallAddressReg() const { return SparcIntRegOrder::o7; }
|
||||
|
||||
|
||||
// and when we return from a method. It should be made sure that this
|
||||
// register contains the return value when a return instruction is reached.
|
||||
unsigned getReturnAddressReg() const { return SparcIntRegOrder::i7; }
|
||||
|
||||
void colorArgs(const Method *const Meth, LiveRangeInfo& LRI) const;
|
||||
|
||||
static void printReg(const LiveRange *const LR) ;
|
||||
|
@ -961,6 +973,11 @@ class UltraSparcRegInfo : public MachineRegInfo
|
|||
LiveRangeInfo& LRI,
|
||||
AddedInstrMapType& AddedInstrMap ) const;
|
||||
|
||||
void colorRetArg(vector<const Instruction *> &
|
||||
RetInstrList, LiveRangeInfo& LRI,
|
||||
AddedInstrMapType &AddedInstrMap) const;
|
||||
|
||||
|
||||
// this method provides a unique number for each register
|
||||
inline int getUnifiedRegNum(int RegClassID, int reg) const {
|
||||
|
||||
|
@ -997,7 +1014,6 @@ class UltraSparcRegInfo : public MachineRegInfo
|
|||
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Scheduling guidelines for SPARC IIi:
|
||||
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
#include "llvm/CodeGen/IGNode.h"
|
||||
#include "SparcInternals.h"
|
||||
|
||||
#include "llvm/Target/Sparc.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Int Register Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const
|
||||
{
|
||||
|
||||
/* Algorithm:
|
||||
Record the color of all neighbors.
|
||||
|
||||
If there is no call interf, try to allocate volatile, then non volatile
|
||||
If there is call interf, try to allocate non-volatile. If that fails
|
||||
try to allocate a volatile and insert save across calls
|
||||
If both above fail, spill.
|
||||
|
||||
*/
|
||||
|
||||
unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
|
||||
|
||||
for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh
|
||||
IGNode *NeighIGNode = Node->getAdjIGNode(n);
|
||||
if( NeighIGNode->hasColor() ) { // if neigh has a color
|
||||
IsColorUsedArr[ NeighIGNode->getColor() ] = true; // record that color
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned SearchStart; // start pos of color in pref-order
|
||||
bool ColorFound= false; // have we found a color yet?
|
||||
|
||||
//if this Node is between calls
|
||||
if( Node->getNumOfCallInterferences() == 0) {
|
||||
|
||||
// start with volatiles (we can allocate volatiles safely)
|
||||
SearchStart = SparcIntRegOrder::StartOfAllRegs;
|
||||
}
|
||||
else {
|
||||
// start with non volatiles (no non-volatiles)
|
||||
SearchStart = SparcIntRegOrder::StartOfNonVolatileRegs;
|
||||
}
|
||||
|
||||
unsigned c=0; // color
|
||||
|
||||
// find first unused color
|
||||
for( c=SearchStart; c < SparcIntRegOrder::NumOfAvailRegs; c++) {
|
||||
if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; }
|
||||
}
|
||||
|
||||
if( ColorFound)
|
||||
Node->setColor(c); // first color found in preffered order
|
||||
|
||||
// if color is not found because of call interference
|
||||
// try even finding a volatile color and insert save across calls
|
||||
else if( Node->getNumOfCallInterferences() )
|
||||
{
|
||||
// start from 0 - try to find even a volatile this time
|
||||
SearchStart = SparcIntRegOrder::StartOfAllRegs;
|
||||
|
||||
// find first unused volatile color
|
||||
for(c=SearchStart; c < SparcIntRegOrder::StartOfNonVolatileRegs; c++) {
|
||||
if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; }
|
||||
}
|
||||
|
||||
if( ColorFound) {
|
||||
Node->setColor(c);
|
||||
// since LR span across calls, must save across calls
|
||||
Node->markForSaveAcrossCalls();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we couldn't find a color regardless of call interference - i.e., we
|
||||
// don't have either a volatile or non-volatile color left
|
||||
if( !ColorFound )
|
||||
Node->markForSpill(); // no color found - must spill
|
||||
|
||||
|
||||
if( DEBUG_RA)
|
||||
UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Float Register Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// find the first available color in the range [Start,End] depending on the
|
||||
// type of the Node (i.e., float/double)
|
||||
|
||||
int SparcFloatRegClass::findFloatColor(const IGNode *const Node, unsigned Start,
|
||||
unsigned End,
|
||||
bool IsColorUsedArr[] ) const
|
||||
{
|
||||
|
||||
bool ColorFound = false;
|
||||
unsigned c;
|
||||
|
||||
if( Node->getTypeID() == Type::DoubleTyID ) {
|
||||
|
||||
// find first unused color for a double
|
||||
for( c=Start; c < End ;c+= 2){
|
||||
if( ! IsColorUsedArr[ c ] && ! IsColorUsedArr[ c+1 ])
|
||||
{ ColorFound=true; break; }
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// find first unused color for a single
|
||||
for( c=Start; c < End; c++) {
|
||||
if( ! IsColorUsedArr[ c ] ) { ColorFound=true; break; }
|
||||
}
|
||||
}
|
||||
|
||||
if( ColorFound ) return c;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const
|
||||
{
|
||||
|
||||
/* Algorithm:
|
||||
|
||||
If the LR is a double try to allocate f32 - f63
|
||||
If the above fails or LR is single precision
|
||||
If the LR does not interfere with a call
|
||||
start allocating from f0
|
||||
Else start allocating from f6
|
||||
If a color is still not found because LR interferes with a call
|
||||
Search in f0 - f6. If found mark for spill across calls.
|
||||
If a color is still not fond, mark for spilling
|
||||
*/
|
||||
|
||||
|
||||
unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
|
||||
|
||||
for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh
|
||||
IGNode *NeighIGNode = Node->getAdjIGNode(n);
|
||||
if( NeighIGNode->hasColor() ) { // if neigh has a color
|
||||
IsColorUsedArr[ NeighIGNode->getColor() ] = true; // record that color
|
||||
if( NeighIGNode->getTypeID() == Type::DoubleTyID )
|
||||
IsColorUsedArr[ (NeighIGNode->getColor()) + 1 ] = true;
|
||||
}
|
||||
}
|
||||
|
||||
int ColorFound = -1; // have we found a color yet?
|
||||
unsigned NumOfCallInterf = Node->getNumOfCallInterferences();
|
||||
|
||||
// if value is a double - search the double only reigon (f32 - f63)
|
||||
if( Node->getTypeID() == Type::DoubleTyID )
|
||||
ColorFound = findFloatColor( Node, 32, 64, IsColorUsedArr );
|
||||
|
||||
|
||||
if( ColorFound >= 0 ) {
|
||||
Node->setColor(ColorFound);
|
||||
if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
return;
|
||||
}
|
||||
|
||||
else { // the above fails or LR is single precision
|
||||
|
||||
unsigned SearchStart; // start pos of color in pref-order
|
||||
|
||||
//if this Node is between calls (i.e., no call interferences )
|
||||
if( ! NumOfCallInterf ) {
|
||||
// start with volatiles (we can allocate volatiles safely)
|
||||
SearchStart = SparcFloatRegOrder::StartOfAllRegs;
|
||||
}
|
||||
else {
|
||||
// start with non volatiles (no non-volatiles)
|
||||
SearchStart = SparcFloatRegOrder::StartOfNonVolatileRegs;
|
||||
}
|
||||
|
||||
ColorFound = findFloatColor( Node, SearchStart, 32, IsColorUsedArr );
|
||||
|
||||
}
|
||||
|
||||
if( ColorFound >= 0 ) {
|
||||
Node->setColor(ColorFound);
|
||||
if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
return;
|
||||
}
|
||||
|
||||
else if( NumOfCallInterf ) {
|
||||
|
||||
// We are here because there is a call interference and no non-volatile
|
||||
// color could be found.
|
||||
// Now try to allocate even a volatile color
|
||||
|
||||
ColorFound = findFloatColor( Node, SparcFloatRegOrder::StartOfAllRegs,
|
||||
SparcFloatRegOrder::StartOfNonVolatileRegs,
|
||||
IsColorUsedArr);
|
||||
}
|
||||
|
||||
if( ColorFound >= 0 ) {
|
||||
Node->setColor(ColorFound); // first color found in preffered order
|
||||
Node->markForSaveAcrossCalls();
|
||||
if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
return;
|
||||
}
|
||||
|
||||
else {
|
||||
Node->markForSpill(); // no color found - must spill
|
||||
if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
/* Title: SparcRegClassInfo.h -*- C++ -*-
|
||||
Author: Ruchira Sasanka
|
||||
Date: Aug 20, 01
|
||||
Purpose: Contains the description of integer register class of Sparc
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SPARC_REG_INFO_CLASS_H
|
||||
#define SPARC_REG_INFO_CLASS_H
|
||||
|
||||
#include "llvm/Target/MachineRegInfo.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",
|
||||
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
|
||||
"i0", "i1", "i2", "i3", "i4", "i5",
|
||||
"g0", "i6", "i7", "o6" };
|
||||
|
||||
|
||||
|
||||
class SparcIntRegOrder{
|
||||
|
||||
public:
|
||||
|
||||
enum RegsInPrefOrder // colors possible for a LR (in preferred order)
|
||||
{
|
||||
// --- following colors are volatile across function calls
|
||||
// %g0 can't be used for coloring - always 0
|
||||
|
||||
g1, g2, g3, g4, g5, g6, g7, //%g1-%g7
|
||||
o0, o1, o2, o3, o4, o5, o7, // %o0-%o5,
|
||||
|
||||
// %o6 is sp,
|
||||
// all %0's can get modified by a call
|
||||
|
||||
// --- following colors are NON-volatile across function calls
|
||||
|
||||
l0, l1, l2, l3, l4, l5, l6, l7, // %l0-%l7
|
||||
i0, i1, i2, i3, i4, i5, // %i0-%i5: i's need not be preserved
|
||||
|
||||
// %i6 is the fp - so not allocated
|
||||
// %i7 is the ret address - can be used if saved
|
||||
|
||||
// max # of colors reg coloring can allocate (NumOfAvailRegs)
|
||||
|
||||
// --- following colors are not available for allocation within this phase
|
||||
// --- but can appear for pre-colored ranges
|
||||
|
||||
g0, i6, i7, o6
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
// max # of colors reg coloring can allocate
|
||||
static unsigned int const NumOfAvailRegs = g0;
|
||||
|
||||
static unsigned int const StartOfNonVolatileRegs = l0;
|
||||
static unsigned int const StartOfAllRegs = g1;
|
||||
static unsigned int const NumOfAllRegs = o6 + 1;
|
||||
|
||||
|
||||
static const string getRegName(const unsigned reg) {
|
||||
assert( reg < NumOfAllRegs );
|
||||
return IntRegNames[reg];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SparcIntRegClass : public MachineRegClassInfo
|
||||
{
|
||||
public:
|
||||
|
||||
SparcIntRegClass(unsigned ID)
|
||||
: MachineRegClassInfo(ID,
|
||||
SparcIntRegOrder::NumOfAvailRegs,
|
||||
SparcIntRegOrder::NumOfAllRegs)
|
||||
{ }
|
||||
|
||||
void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const;
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Float Register Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static string 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"
|
||||
};
|
||||
|
||||
|
||||
class SparcFloatRegOrder{
|
||||
|
||||
public:
|
||||
|
||||
enum RegsInPrefOrder {
|
||||
|
||||
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
|
||||
|
||||
};
|
||||
|
||||
// there are 64 regs alltogether but only 32 regs can be allocated at
|
||||
// a time.
|
||||
|
||||
static unsigned int const NumOfAvailRegs = 32;
|
||||
static unsigned int const NumOfAllRegs = 64;
|
||||
|
||||
static unsigned int const StartOfNonVolatileRegs = f6;
|
||||
static unsigned int const StartOfAllRegs = f0;
|
||||
|
||||
|
||||
static const string getRegName(const unsigned reg) {
|
||||
assert( reg < NumOfAllRegs );
|
||||
return FloatRegNames[reg];
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SparcFloatRegClass : public MachineRegClassInfo
|
||||
{
|
||||
private:
|
||||
|
||||
int findFloatColor(const IGNode *const Node, unsigned Start,
|
||||
unsigned End, bool IsColorUsedArr[] ) const;
|
||||
|
||||
public:
|
||||
|
||||
SparcFloatRegClass(unsigned ID)
|
||||
: MachineRegClassInfo(ID,
|
||||
SparcFloatRegOrder::NumOfAvailRegs,
|
||||
SparcFloatRegOrder::NumOfAllRegs)
|
||||
{ }
|
||||
|
||||
void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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
|
|
@ -1,90 +1,140 @@
|
|||
#include "llvm/CodeGen/IGNode.h"
|
||||
#include "SparcRegInfo.h"
|
||||
#include "SparcInternals.h"
|
||||
|
||||
#include "llvm/Target/Sparc.h"
|
||||
#include "SparcInternals.h"
|
||||
#include "llvm/Method.h"
|
||||
#include "llvm/iTerminators.h"
|
||||
#include "llvm/CodeGen/InstrScheduling.h"
|
||||
#include "llvm/CodeGen/InstrSelection.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Int Register Class
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
|
||||
#include "llvm/CodeGen/PhyRegAlloc.h"
|
||||
|
||||
void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// UltraSparcRegInfo
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Rules for coloring values with sepcial registers:
|
||||
=================================================
|
||||
|
||||
The following are the cases we color values with special regs:
|
||||
|
||||
1) Incoming Method Arguements
|
||||
2) Outgoing Call Arguments
|
||||
3) Return Value of a call
|
||||
4) Return Value of a return statement
|
||||
|
||||
Both 1 and 3 are defs. Therefore, they can be set directly. For case 1,
|
||||
incoming args are colored to %i0-%i5 and %f0 - %fx. For case 3, the return
|
||||
value of the call must be colored to %o0 or %f0.
|
||||
|
||||
For case 2 we can use %o0-%o6 and %f0- %fx and for case 4 we can use %i0 or
|
||||
%f0. However, we cannot pre-color them directly to those regs
|
||||
if there are call interferences or they can be already colred by case 1.
|
||||
(Note that a return value is call is already colored and it is registered
|
||||
as a call interference as well if it is live after the call). Otherwise, they
|
||||
can be precolored. In cases where we cannot precolor, we just have to insert
|
||||
a copy instruction to copy the LR to the required register.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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
|
||||
{
|
||||
|
||||
/* Algorithm:
|
||||
Record the color of all neighbors.
|
||||
// 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;
|
||||
|
||||
If there is no call interf, try to allocate volatile, then non volatile
|
||||
If there is call interf, try to allocate non-volatile. If that fails
|
||||
try to allocate a volatile and insert save across calls
|
||||
If both above fail, spill.
|
||||
// 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;
|
||||
|
||||
unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
|
||||
// for each argument
|
||||
for( ; ArgIt != ArgList.end() ; ++ArgIt) {
|
||||
|
||||
for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh
|
||||
IGNode *NeighIGNode = Node->getAdjIGNode(n);
|
||||
if( NeighIGNode->hasColor() ) { // if neigh has a color
|
||||
IsColorUsedArr[ NeighIGNode->getColor() ] = true; // record that color
|
||||
}
|
||||
}
|
||||
// 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 );
|
||||
|
||||
unsigned SearchStart; // start pos of color in pref-order
|
||||
bool ColorFound= false; // have we found a color yet?
|
||||
|
||||
//if this Node is between calls
|
||||
if( Node->getNumOfCallInterferences() == 0) {
|
||||
|
||||
// start with volatiles (we can allocate volatiles safely)
|
||||
SearchStart = SparcIntRegOrder::StartOfAllRegs;
|
||||
}
|
||||
else {
|
||||
// start with non volatiles (no non-volatiles)
|
||||
SearchStart = SparcIntRegOrder::StartOfNonVolatileRegs;
|
||||
}
|
||||
|
||||
unsigned c=0; // color
|
||||
|
||||
// find first unused color
|
||||
for( c=SearchStart; c < SparcIntRegOrder::NumOfAvailRegs; c++) {
|
||||
if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; }
|
||||
}
|
||||
|
||||
if( ColorFound)
|
||||
Node->setColor(c); // first color found in preffered order
|
||||
|
||||
// if color is not found because of call interference
|
||||
// try even finding a volatile color and insert save across calls
|
||||
else if( Node->getNumOfCallInterferences() )
|
||||
{
|
||||
// start from 0 - try to find even a volatile this time
|
||||
SearchStart = SparcIntRegOrder::StartOfAllRegs;
|
||||
|
||||
// find first unused volatile color
|
||||
for(c=SearchStart; c < SparcIntRegOrder::StartOfNonVolatileRegs; c++) {
|
||||
if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; }
|
||||
if( DEBUG_RA) printReg( LR );
|
||||
}
|
||||
|
||||
else {
|
||||
// TODO: Insert push code here
|
||||
assert( 0 && "Insert push code here!");
|
||||
}
|
||||
++intArgNo;
|
||||
}
|
||||
|
||||
if( ColorFound) {
|
||||
Node->setColor(c);
|
||||
// since LR span across calls, must save across calls
|
||||
Node->markForSaveAcrossCalls();
|
||||
}
|
||||
// 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");
|
||||
}
|
||||
|
||||
// If we couldn't find a color regardless of call interference - i.e., we
|
||||
// don't have either a volatile or non-volatile color left
|
||||
if( !ColorFound )
|
||||
Node->markForSpill(); // no color found - must spill
|
||||
|
||||
|
||||
if( DEBUG_RA)
|
||||
UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,148 +142,334 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const
|
|||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Float Register Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// find the first available color in the range [Start,End] depending on the
|
||||
// type of the Node (i.e., float/double)
|
||||
|
||||
int SparcFloatRegClass::findFloatColor(const IGNode *const Node, unsigned Start,
|
||||
unsigned End,
|
||||
bool IsColorUsedArr[] ) const
|
||||
void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
|
||||
CallInstrList, LiveRangeInfo& LRI,
|
||||
AddedInstrMapType &AddedInstrMap) const
|
||||
{
|
||||
|
||||
bool ColorFound = false;
|
||||
unsigned c;
|
||||
vector<const Instruction *>::const_iterator InstIt;
|
||||
|
||||
if( Node->getTypeID() == Type::DoubleTyID ) {
|
||||
// First color the return value of all call instructions. The return value
|
||||
// will be in %o0 if the value is an integer type, or in %f0 if the
|
||||
// value is a float type.
|
||||
|
||||
for(InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) {
|
||||
|
||||
const Instruction *const CallI = *InstIt;
|
||||
|
||||
// get the live range of return value of this call
|
||||
LiveRange *const LR = LRI.getLiveRangeForValue( CallI );
|
||||
|
||||
if ( LR ) {
|
||||
|
||||
// Since the call is a def, it cannot be colored by some other instr.
|
||||
// Therefore, we can definitely set a color here.
|
||||
// However, this def can be used by some other instr like another call
|
||||
// or return which places that in a special register. In that case
|
||||
// it has to put a copy. Note that, the def will have a call interference
|
||||
// with this call instr itself if it is live after this call.
|
||||
|
||||
assert( ! LR->hasColor() && "Can't have a color since this is a def");
|
||||
|
||||
unsigned RegClassID = (LR->getRegClass())->getID();
|
||||
|
||||
// find first unused color for a double
|
||||
for( c=Start; c < End ;c+= 2){
|
||||
if( ! IsColorUsedArr[ c ] && ! IsColorUsedArr[ c+1 ])
|
||||
{ ColorFound=true; break; }
|
||||
if( RegClassID == IntRegClassID ) {
|
||||
LR->setColor(SparcIntRegOrder::o0);
|
||||
}
|
||||
else if (RegClassID == FloatRegClassID ) {
|
||||
LR->setColor(SparcFloatRegOrder::f0 );
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// find first unused color for a single
|
||||
for( c=Start; c < End; c++) {
|
||||
if( ! IsColorUsedArr[ c ] ) { ColorFound=true; break; }
|
||||
else {
|
||||
cout << "Warning: No Live Range for return value of CALL" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if( ColorFound ) return c;
|
||||
else return -1;
|
||||
|
||||
|
||||
for( InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) {
|
||||
|
||||
// Inst = LLVM call instruction
|
||||
const Instruction *const CallI = *InstIt;
|
||||
|
||||
// find the CALL/JMMPL machine instruction
|
||||
MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec();
|
||||
MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
|
||||
|
||||
/*
|
||||
for( ; MIIt != MInstVec.end() &&
|
||||
! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
|
||||
++MIIt );
|
||||
|
||||
assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
|
||||
*/
|
||||
|
||||
assert(getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode()) &&
|
||||
"First machine instruction is not a Call/JMPL Machine Instr");
|
||||
|
||||
// CallMI = CALL/JMPL machine isntruction
|
||||
const MachineInstr *const CallMI = *MIIt;
|
||||
|
||||
Instruction::op_const_iterator OpIt = CallI->op_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;
|
||||
|
||||
// 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) {
|
||||
setCallOrRetArgCol( LR, SparcIntRegOrder::o0 + intArgNo,
|
||||
CallMI, AddedInstrMap);
|
||||
}
|
||||
|
||||
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] ) {
|
||||
setCallOrRetArgCol(LR, SparcFloatRegOrder::f0 + i,
|
||||
CallMI, AddedInstrMap);
|
||||
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] ) {
|
||||
setCallOrRetArgCol(LR, SparcFloatRegOrder::f0 + i,
|
||||
CallMI, AddedInstrMap);
|
||||
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 SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const
|
||||
void UltraSparcRegInfo::colorRetArg(vector<const Instruction *> &
|
||||
RetInstrList, LiveRangeInfo& LRI,
|
||||
AddedInstrMapType &AddedInstrMap) const
|
||||
{
|
||||
|
||||
/* Algorithm:
|
||||
|
||||
If the LR is a double try to allocate f32 - f63
|
||||
If the above fails or LR is single precision
|
||||
If the LR does not interfere with a call
|
||||
start allocating from f0
|
||||
Else start allocating from f6
|
||||
If a color is still not found because LR interferes with a call
|
||||
Search in f0 - f6. If found mark for spill across calls.
|
||||
If a color is still not fond, mark for spilling
|
||||
*/
|
||||
vector<const Instruction *>::const_iterator InstIt;
|
||||
|
||||
|
||||
unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
|
||||
for(InstIt=RetInstrList.begin(); InstIt != RetInstrList.end(); ++InstIt) {
|
||||
|
||||
const ReturnInst *const RetI = (ReturnInst *) *InstIt;
|
||||
|
||||
// get the return value of this return instruction
|
||||
const Value *RetVal = (RetI)->getReturnValue();
|
||||
|
||||
if( RetVal ) {
|
||||
|
||||
// find the CALL/JMMPL machine instruction
|
||||
MachineCodeForVMInstr & MInstVec = RetI->getMachineInstrVec();
|
||||
MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
|
||||
|
||||
assert(getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode())
|
||||
&& "First machine instruction is not a RET Machine Instr");
|
||||
// RET machine isntruction
|
||||
const MachineInstr *const RetMI = *MIIt;
|
||||
|
||||
LiveRange *const LR = LRI.getLiveRangeForValue( RetVal );
|
||||
unsigned RegClassID = (LR->getRegClass())->getID();
|
||||
|
||||
if ( LR ) {
|
||||
if( RegClassID == IntRegClassID ) {
|
||||
setCallOrRetArgCol( LR, SparcIntRegOrder::i0, RetMI, AddedInstrMap);
|
||||
}
|
||||
else if (RegClassID==FloatRegClassID ) {
|
||||
setCallOrRetArgCol(LR, SparcFloatRegOrder::f0, RetMI, AddedInstrMap);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
cout << "Warning: No LR for return value" << endl;
|
||||
}
|
||||
|
||||
for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh
|
||||
IGNode *NeighIGNode = Node->getAdjIGNode(n);
|
||||
if( NeighIGNode->hasColor() ) { // if neigh has a color
|
||||
IsColorUsedArr[ NeighIGNode->getColor() ] = true; // record that color
|
||||
if( NeighIGNode->getTypeID() == Type::DoubleTyID )
|
||||
IsColorUsedArr[ (NeighIGNode->getColor()) + 1 ] = true;
|
||||
}
|
||||
}
|
||||
|
||||
int ColorFound = -1; // have we found a color yet?
|
||||
unsigned NumOfCallInterf = Node->getNumOfCallInterferences();
|
||||
|
||||
// if value is a double - search the double only reigon (f32 - f63)
|
||||
if( Node->getTypeID() == Type::DoubleTyID )
|
||||
ColorFound = findFloatColor( Node, 32, 64, IsColorUsedArr );
|
||||
|
||||
|
||||
if( ColorFound >= 0 ) {
|
||||
Node->setColor(ColorFound);
|
||||
if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
return;
|
||||
}
|
||||
|
||||
else { // the above fails or LR is single precision
|
||||
|
||||
unsigned SearchStart; // start pos of color in pref-order
|
||||
|
||||
//if this Node is between calls (i.e., no call interferences )
|
||||
if( ! NumOfCallInterf ) {
|
||||
// start with volatiles (we can allocate volatiles safely)
|
||||
SearchStart = SparcFloatRegOrder::StartOfAllRegs;
|
||||
}
|
||||
else {
|
||||
// start with non volatiles (no non-volatiles)
|
||||
SearchStart = SparcFloatRegOrder::StartOfNonVolatileRegs;
|
||||
}
|
||||
|
||||
ColorFound = findFloatColor( Node, SearchStart, 32, IsColorUsedArr );
|
||||
|
||||
}
|
||||
|
||||
if( ColorFound >= 0 ) {
|
||||
Node->setColor(ColorFound);
|
||||
if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
return;
|
||||
}
|
||||
|
||||
else if( NumOfCallInterf ) {
|
||||
|
||||
// We are here because there is a call interference and no non-volatile
|
||||
// color could be found.
|
||||
// Now try to allocate even a volatile color
|
||||
|
||||
ColorFound = findFloatColor( Node, SparcFloatRegOrder::StartOfAllRegs,
|
||||
SparcFloatRegOrder::StartOfNonVolatileRegs,
|
||||
IsColorUsedArr);
|
||||
}
|
||||
|
||||
if( ColorFound >= 0 ) {
|
||||
Node->setColor(ColorFound); // first color found in preffered order
|
||||
Node->markForSaveAcrossCalls();
|
||||
if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
return;
|
||||
}
|
||||
|
||||
else {
|
||||
Node->markForSpill(); // no color found - must spill
|
||||
if( DEBUG_RA) UltraSparcRegInfo::printReg( Node->getParentLR() );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UltraSparcRegInfo::setCallOrRetArgCol(LiveRange *const LR,
|
||||
const unsigned RegNo,
|
||||
const MachineInstr *MI,
|
||||
AddedInstrMapType &AIMap) 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 (e.g., live across a call or produced
|
||||
// by a call instr) or this LR is already colored as an incoming argument
|
||||
|
||||
MachineInstr *MI = getCopy2RegMI((*(LR->begin())), RegNo,
|
||||
(LR->getRegClass())->getID());
|
||||
|
||||
AddedInstrns * AI = AIMap[ MI ]; // get already added instrns for MI
|
||||
if( ! AI ) AI = new AddedInstrns();
|
||||
|
||||
AI->InstrnsBefore.push_back( MI ); // add the new MI yp AMI
|
||||
AIMap[ MI ] = AI;
|
||||
|
||||
|
||||
cout << "Inserted a copy instr for a RET/CALL instr " << endl;
|
||||
|
||||
// We don't color LR here. It's colored as any other normal LR or
|
||||
// as an incoming arg or a return value of a call.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Generates a copy machine instruction to copy a value to a given
|
||||
// register.
|
||||
|
||||
MachineInstr * UltraSparcRegInfo::getCopy2RegMI(const Value *SrcVal,
|
||||
const unsigned Reg,
|
||||
unsigned RegClassID) const {
|
||||
MachineInstr * MI;
|
||||
|
||||
if( RegClassID == IntRegClassID ) { // if integer move
|
||||
|
||||
MI = new MachineInstr(ADD, 3);
|
||||
|
||||
MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
|
||||
MI->SetMachineOperand(1, SparcIntRegOrder::g0, false);
|
||||
MI->SetMachineOperand(2, Reg, true);
|
||||
}
|
||||
else { // if FP move
|
||||
|
||||
if(SrcVal->getType()-> getPrimitiveID() == Type::FloatTyID )
|
||||
MI = new MachineInstr(FMOVS, 2);
|
||||
else if(SrcVal->getType()-> getPrimitiveID() == Type::DoubleTyID)
|
||||
MI = new MachineInstr(FMOVD, 2);
|
||||
else assert( 0 && "Unknown Type");
|
||||
|
||||
MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
|
||||
MI->SetMachineOperand(1, Reg, true);
|
||||
}
|
||||
|
||||
return MI;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Print the register assigned to a LR
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue