mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
*** empty log message ***
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@412 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
33b6e9f48b
commit
f2a6477aee
152
lib/CodeGen/RegAlloc/IGNode.h
Normal file
152
lib/CodeGen/RegAlloc/IGNode.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
||||
|
302
lib/CodeGen/TargetMachine/Sparc/SparcRegInfo.cpp
Normal file
302
lib/CodeGen/TargetMachine/Sparc/SparcRegInfo.cpp
Normal 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
|
152
lib/Target/SparcV9/RegAlloc/IGNode.h
Normal file
152
lib/Target/SparcV9/RegAlloc/IGNode.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user