*** empty log message ***

llvm-svn: 412
This commit is contained in:
Ruchira Sasanka 2001-08-31 20:59:58 +00:00
parent b7237c88ae
commit 4d30f4bb6c
3 changed files with 758 additions and 0 deletions

View File

@ -0,0 +1,152 @@
/* Title: IGNode.h
Author: Ruchira Sasanka
Date: July 25, 01
Purpose: Represents a node in an interference graph.
Notes:
For efficiency, the AdjList is updated only once - ie. we can add but not
remove nodes from AdjList.
The removal of nodes from IG is simulated by decrementing the CurDegree.
If this node is put on stack (that is removed from IG), the CurDegree of all
the neighbors are decremented and this node is marked OnSack. Hence
the effective neighbors in the AdjList are the ones that do not have the
OnStack flag set (therefore, they are in the IG).
The methods that modify/use the CurDegree Must be called only
fter all modifications to the IG are over (i.e., all neighbors are fixed).
The vector representation the most efficient one for adj list.
Though nodes are removed when coalsing is done, we access it in sequence
for far many times when coloring (colorNode()).
*/
#ifndef IG_NODE_H
#define IG_NODE_H
#include "llvm/CodeGen/RegAllocCommon.h"
#include "llvm/CodeGen/LiveRange.h"
class IGNode
{
private:
const int Index; // index within IGNodeList
bool OnStack; // this has been pushed on to stack for coloring
vector<IGNode *> AdjList; // adjacency list for this live range
// set by InterferenceGraph::setCurDegreeOfIGNodes() after calculating
// all adjacency lists.
// Decremented when a neighbor is pushed on to the stack.
// After that, never incremented/set again nor used.
int CurDegree;
LiveRange *const ParentLR; // parent LR (cannot be a const)
public:
inline unsigned int getIndex() const
{ return Index; }
// adjLists must be updated only once. However, the CurDegree can be changed
inline void addAdjIGNode( IGNode *const AdjNode)
{ AdjList.push_back(AdjNode); }
inline IGNode * getAdjIGNode(unsigned int ind) const
{ assert ( ind < AdjList.size()); return AdjList[ ind ]; }
// delete a node in AdjList - node must be in the list
// should not be called often
void delAdjIGNode(const IGNode *const Node);
inline unsigned int getNumOfNeighbors() const
{ return AdjList.size() ; }
inline bool isOnStack() const
{ return OnStack; }
// remove form IG and pushes on to stack (reduce the degree of neighbors)
void pushOnStack();
// CurDegree is the effective number of neighbors when neighbors are
// pushed on to the stack during the coloring phase. Must be called
// after all modifications to the IG are over (i.e., all neighbors are
// fixed).
inline void setCurDegree()
{ assert( CurDegree == -1); CurDegree = AdjList.size(); }
inline int getCurDegree() const
{ return CurDegree; }
// called when a neigh is pushed on to stack
inline void decCurDegree()
{ assert( CurDegree > 0 ); --CurDegree; }
// The following methods call the methods in ParentLR
// They are added to this class for convenience
// If many of these are called within a single scope,
// consider calling the methods directly on LR
inline void setRegClass(RegClass *const RC)
{ ParentLR->setRegClass(RC); }
inline RegClass *const getRegClass() const
{ return ParentLR->getRegClass(); }
inline bool hasColor() const
{ return ParentLR->hasColor(); }
inline unsigned int getColor() const
{ return ParentLR->getColor(); }
inline void setColor(unsigned int Col)
{ ParentLR->setColor(Col); }
inline void markForSpill()
{ ParentLR->markForSpill(); }
inline void markForSaveAcrossCalls()
{ ParentLR->markForSaveAcrossCalls(); }
// inline void markForLoadFromStack()
// { ParentLR->markForLoadFromStack(); }
inline unsigned int getNumOfCallInterferences() const
{ return ParentLR->getNumOfCallInterferences(); }
inline LiveRange *getParentLR() const
{ return ParentLR; }
inline Type::PrimitiveID getTypeID() const
{ return ParentLR->getTypeID(); }
//---- constructor and destructor ----
IGNode(LiveRange *const LR, unsigned int index);
~IGNode() { } // an empty destructor
};
#endif

View File

@ -9,11 +9,307 @@
// 7/15/01 - Vikram Adve - Created
//**************************************************************************/
#include "llvm/Method.h"
#include "llvm/Instruction.h"
#include "llvm/CodeGen/LiveRange.h"
#include "llvm/CodeGen/LiveRangeInfo.h"
#include "llvm/CodeGen/Sparc.h"
#include "llvm/CodeGen/SparcRegInfo.h"
//************************ Class Implementations **************************/
//---------------------------------------------------------------------------
// 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 ) 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!");
}
++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 UltraSparcInstrInfo
//
@ -79,6 +375,11 @@ UltraSparcSchedInfo::initializeResources()
}
//---------------------------------------------------------------------------
// class UltraSparcMachine
//
@ -91,10 +392,12 @@ UltraSparcSchedInfo::initializeResources()
//---------------------------------------------------------------------------
UltraSparc::UltraSparc()
: TargetMachine("UltraSparc-Native")
{
machineInstrInfo = new UltraSparcInstrInfo;
machineSchedInfo = new UltraSparcSchedInfo(machineInstrInfo);
machineRegInfo = new UltraSparcRegInfo(this);
optSizeForSubWordData = 4;
minMemOpWordSize = 8;
@ -105,6 +408,7 @@ UltraSparc::UltraSparc()
UltraSparc::~UltraSparc()
{
delete (UltraSparcInstrInfo*) machineInstrInfo;
delete (UltraSparcRegInfo*) machineRegInfo;
delete (UltraSparcSchedInfo*) machineSchedInfo;
}

View File

@ -0,0 +1,302 @@
#include "llvm/CodeGen/IGNode.h"
#include "llvm/CodeGen/SparcRegInfo.h"
#include "llvm/CodeGen/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() );
}
}
#if 0
//-----------------------------------------------------------------------------
// Float Register Class
//-----------------------------------------------------------------------------
void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const
{
/* Algorithm:
Record the color of all neighbors.
Single precision can use f0 - f31
Double precision can use f0 - f63
if LR is a double, try to allocate f32 - f63.
if the above attempt fails, or Value is single presion, try to allcoate
f0 - f31.
*/
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;
}
}
unsigned SearchStart; // start pos of color in pref-order
bool ColorFound= false; // have we found a color yet?
unsigned c;
if( Node->getTypeID() == Type::DoubleTyID ) { // if value is a double
// search the double only reigon (f32 - f63)
for( c=32; c < 64; c+= 2) {
if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; }
}
// search f0 - f31 region
if( ! ColorFound ) { // if color not found
for( c=0; c < 32; c+= 2) {
if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; }
}
}
}
else { // value is Single
for( c=0; c < 32; c++) {
if( ! IsColorUsedArr[ c ] ) { ColorFound = true; break; }
}
}
if( ColorFound)
Node->setColor(c); // first color found in preferred order
else
Node->markForSpill(); // no color found - must spill
if( DEBUG_RA)
UltraSparcRegInfo::printReg( Node->getParentLR() );
}
#endif