--- /dev/null
+/* 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
// 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
//
}
+
+
+
+
+
//---------------------------------------------------------------------------
// class UltraSparcMachine
//
//---------------------------------------------------------------------------
UltraSparc::UltraSparc()
+
: TargetMachine("UltraSparc-Native")
{
machineInstrInfo = new UltraSparcInstrInfo;
machineSchedInfo = new UltraSparcSchedInfo(machineInstrInfo);
+ machineRegInfo = new UltraSparcRegInfo(this);
optSizeForSubWordData = 4;
minMemOpWordSize = 8;
UltraSparc::~UltraSparc()
{
delete (UltraSparcInstrInfo*) machineInstrInfo;
+ delete (UltraSparcRegInfo*) machineRegInfo;
delete (UltraSparcSchedInfo*) machineSchedInfo;
}
--- /dev/null
+#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
--- /dev/null
+/* 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