*** empty log message ***

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@580 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ruchira Sasanka 2001-09-14 21:18:34 +00:00
parent 94d86e9677
commit 8e6047920d
10 changed files with 2170 additions and 0 deletions

View File

@ -0,0 +1,31 @@
#include "llvm/CodeGen/IGNode.h"
IGNode::IGNode(LiveRange *const PLR, unsigned int Ind): Index(Ind),
ParentLR(PLR)
{
OnStack = false;
CurDegree = -1 ;
ParentLR->setUserIGNode( this );
}
void IGNode::pushOnStack() // sets on to stack and
{ // reduce the degree of neighbors
OnStack = true;
unsigned int neighs = AdjList.size();
for(unsigned int i=0; i < neighs; i++) (AdjList[i])->decCurDegree();
}
void IGNode::delAdjIGNode(const IGNode *const Node) {
vector <IGNode *>::iterator It = AdjList.begin();
// find Node
for( ; It != AdjList.end() && (*It != Node); It++ ) ;
assert( It != AdjList.end() ); // the node must be there
AdjList.erase( It );
}

View File

@ -0,0 +1,226 @@
#include "llvm/CodeGen/InterferenceGraph.h"
InterferenceGraph::InterferenceGraph(RegClass *const RC) : RegCl(RC),
IGNodeList()
{
IG = NULL;
Size = 0;
if( DEBUG_RA) {
cout << "Interference graph created!" << endl;
}
}
InterferenceGraph:: ~InterferenceGraph() { // destructor
if( IG )
delete []IG;
}
void InterferenceGraph::createGraph()
{
Size = IGNodeList.size();
IG = (char **) new char *[Size];
for( unsigned int r=0; r < Size; ++r)
IG[r] = new char[Size];
// init IG matrix
for(unsigned int i=0; i < Size; i++)
for( unsigned int j=0; j < Size ; j++)
IG[i][j] = 0;
}
void InterferenceGraph::addLRToIG(LiveRange *const LR)
{
IGNode *Node = new IGNode(LR, IGNodeList.size() );
IGNodeList.push_back( Node );
//Node->setRegClass( RegCl );
}
// update both the matrix and AdjLists of nodes.
// If there is already an interference between LR1 and LR2, adj lists
// are not updated. LR1 and LR2 must be distinct since if not, it suggests
// that there is some wrong logic in some other method.
void InterferenceGraph::setInterference(const LiveRange *const LR1,
const LiveRange *const LR2 ) {
assert(LR1 != LR2);
IGNode *const IGNode1 = LR1->getUserIGNode();
IGNode *const IGNode2 = LR2->getUserIGNode();
if( DEBUG_RA) {
assertIGNode( IGNode1 );
assertIGNode( IGNode2 );
}
const unsigned int row = IGNode1->getIndex();
const unsigned int col = IGNode2->getIndex();
char *val;
if( DEBUG_RA > 1)
cout << "setting intf for: [" << row << "][" << col << "]" << endl;
( row > col) ? val = &IG[row][col]: val = &IG[col][row];
if( ! (*val) ) { // if this interf is not previously set
*val = 1; // add edges between nodes
IGNode1->addAdjIGNode( IGNode2 );
IGNode2->addAdjIGNode( IGNode1 );
}
}
unsigned InterferenceGraph::getInterference(const LiveRange *const LR1,
const LiveRange *const LR2 ) const {
assert(LR1 != LR2);
if( DEBUG_RA) {
assertIGNode( LR1->getUserIGNode() );
assertIGNode( LR2->getUserIGNode() );
}
const unsigned int row = LR1->getUserIGNode()->getIndex();
const unsigned int col = LR2->getUserIGNode()->getIndex();
char ret;
( row > col) ? (ret = IG[row][col]) : (ret = IG[col][row]) ;
return ret;
}
// Merge 2 IGNodes. The neighbors of the SrcNode will be added to the DestNode.
// Then the IGNode2L will be deleted. Necessary for coalescing.
// IMPORTANT: The live ranges are NOT merged by this method. Use
// LiveRangeInfo::unionAndUpdateLRs for that purpose.
void InterferenceGraph::mergeIGNodesOfLRs(const LiveRange *const LR1,
LiveRange *const LR2 ) {
assert( LR1 != LR2); // cannot merge the same live range
IGNode *const DestNode = LR1->getUserIGNode();
IGNode *SrcNode = LR2->getUserIGNode();
assertIGNode( DestNode );
assertIGNode( SrcNode );
if( DEBUG_RA > 1) {
cout << "Merging LRs: \""; LR1->printSet();
cout << "\" and \""; LR2->printSet();
cout << "\"" << endl;
}
unsigned SrcDegree = SrcNode->getNumOfNeighbors();
const unsigned SrcInd = SrcNode->getIndex();
// for all neighs of SrcNode
for(unsigned i=0; i < SrcDegree; i++) {
IGNode *NeighNode = SrcNode->getAdjIGNode(i);
LiveRange *const LROfNeigh = NeighNode->getParentLR();
// delete edge between src and neigh - even neigh == dest
NeighNode->delAdjIGNode(SrcNode);
// set the matrix posn to 0 betn src and neigh - even neigh == dest
const unsigned NInd = NeighNode->getIndex();
( SrcInd > NInd) ? (IG[SrcInd][NInd]=0) : (IG[NInd][SrcInd]=0) ;
if( LR1 != LROfNeigh) { // if the neigh != dest
// add edge betwn Dest and Neigh - if there is no current edge
setInterference(LR1, LROfNeigh );
}
//cout<< " #Neighs - Neigh: ["<< NeighNode->getIndex()<< "] ";
//cout << NeighNode->getNumOfNeighbors();
//cout << " Dest: [" << DestNode->getIndex() << "] ";
//cout << DestNode->getNumOfNeighbors() << endl;
}
IGNodeList[ SrcInd ] = NULL;
// SrcNode is no longer necessary - LR2 must be deleted by the caller
delete( SrcNode );
}
// must be called after modifications to the graph are over but before
// pushing IGNodes on to the stack for coloring.
void InterferenceGraph::setCurDegreeOfIGNodes()
{
unsigned Size = IGNodeList.size();
for( unsigned i=0; i < Size; i++) {
IGNode *Node = IGNodeList[i];
if( Node )
Node->setCurDegree();
}
}
//--------------------- debugging (Printing) methods -----------------------
void InterferenceGraph::printIG() const
{
for(unsigned int i=0; i < Size; i++) {
const IGNode *const Node = IGNodeList[i];
if( ! Node )
continue; // skip empty rows
cout << " [" << i << "] ";
for( unsigned int j=0; j < Size; j++) {
if( j >= i) break;
if( IG[i][j] ) cout << "(" << i << "," << j << ") ";
}
cout << endl;
}
}
void InterferenceGraph::printIGNodeList() const
{
vector<IGNode *>::const_iterator IGIt = IGNodeList.begin(); // hash map iter
for(unsigned i=0; i < IGNodeList.size() ; ++i) {
const IGNode *const Node = IGNodeList[i];
if( ! Node )
continue;
cout << " [" << Node->getIndex() << "] ";
(Node->getParentLR())->printSet();
//int Deg = Node->getCurDegree();
cout << "\t <# of Neighs: " << Node->getNumOfNeighbors() << ">" << endl;
}
}

View File

@ -0,0 +1,283 @@
#include "llvm/CodeGen/LiveRangeInfo.h"
LiveRangeInfo::LiveRangeInfo(const Method *const M,
const TargetMachine& tm,
vector<RegClass *> &RCL)
: Meth(M), LiveRangeMap(),
TM(tm), RegClassList(RCL)
{ }
// union two live ranges into one. The 2nd LR is deleted. Used for coalescing.
// Note: the caller must make sure that L1 and L2 are distinct
void LiveRangeInfo::unionAndUpdateLRs(LiveRange *const L1, LiveRange *L2)
{
assert( L1 != L2);
L1->setUnion( L2 ); // add elements of L2 to L1
ValueSet::iterator L2It;
for( L2It = L2->begin() ; L2It != L2->end(); ++L2It) {
//assert(( L1->getTypeID() == L2->getTypeID()) && "Merge:Different types");
L1->add( *L2It ); // add the var in L2 to L1
LiveRangeMap[ *L2It ] = L1; // now the elements in L2 should map to L1
}
delete ( L2 ); // delete L2 as it is no longer needed
}
void LiveRangeInfo::constructLiveRanges()
{
if( DEBUG_RA)
cout << "Consturcting Live Ranges ..." << endl;
// first find the live ranges for all incoming args of the method since
// those LRs start from the start of the method
// get the argument list
const Method::ArgumentListType& ArgList = Meth->getArgumentList();
// get an iterator to arg list
Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
for( ; ArgIt != ArgList.end() ; ++ArgIt) { // for each argument
LiveRange * ArgRange = new LiveRange(); // creates a new LR and
const Value *const Val = (const Value *) *ArgIt;
assert( Val);
ArgRange->add( Val ); // add the arg (def) to it
LiveRangeMap[ Val ] = ArgRange;
// create a temp machine op to find the register class of value
//const MachineOperand Op(MachineOperand::MO_VirtualRegister);
unsigned rcid = (TM.getRegInfo()).getRegClassIDOfValue( Val );
ArgRange->setRegClass(RegClassList[ rcid ] );
if( DEBUG_RA > 1) {
cout << " adding LiveRange for argument ";
printValue( (const Value *) *ArgIt); cout << endl;
}
}
// Now find all LRs for machine the instructions. A new LR will be created
// only for defs in the machine instr since, we assume that all Values are
// defined before they are used. However, there can be multiple defs for
// the same Value in machine instructions.
Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
for( ; BBI != Meth->end(); ++BBI) { // go thru BBs in random order
// get the iterator for machine instructions
const MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
MachineCodeForBasicBlock::const_iterator
MInstIterator = MIVec.begin();
// iterate over all the machine instructions in BB
for( ; MInstIterator != MIVec.end(); MInstIterator++) {
const MachineInstr * MInst = *MInstIterator;
// iterate over MI operands to find defs
for( MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done(); OpI++) {
// create a new LR iff this operand is a def
if( OpI.isDef() ) {
const Value *const Def = *OpI;
LiveRange *DefRange = LiveRangeMap[Def];
// see LR already there (because of multiple defs)
if( !DefRange) { // if it is not in LiveRangeMap
DefRange = new LiveRange(); // creates a new live range and
DefRange->add( Def ); // add the instruction (def) to it
LiveRangeMap[ Def ] = DefRange; // update the map
if( DEBUG_RA > 1) {
cout << " creating a LR for def: ";
printValue(Def); cout << endl;
}
// set the register class of the new live range
//assert( RegClassList.size() );
MachineOperand::MachineOperandType OpTy =
OpI.getMachineOperand().getOperandType();
bool isCC = ( OpTy == MachineOperand::MO_CCRegister);
unsigned rcid = (TM.getRegInfo()).getRegClassIDOfValue(
OpI.getMachineOperand().getVRegValue(), isCC );
if(isCC )
cout << "\a" << "**created a LR for a CC reg**" << cout;
DefRange->setRegClass( RegClassList[ rcid ] );
}
else {
DefRange->add( Def ); // add the opearand to def range
// update the map - Operand points
// to the merged set
LiveRangeMap[ Def ] = DefRange;
if( DEBUG_RA > 1) {
cout << " added to an existing LR for def: ";
printValue( Def ); cout << endl;
}
}
} // if isDef()
} // for all opereands in machine instructions
} // for all machine instructions in the BB
} // for all BBs in method
if( DEBUG_RA)
cout << "Initial Live Ranges constructed!" << endl;
}
void LiveRangeInfo::coalesceLRs()
{
/* Algorithm:
for each BB in method
for each machine instruction (inst)
for each definition (def) in inst
for each operand (op) of inst that is a use
if the def and op are of the same type
if the def and op do not interfere //i.e., not simultaneously live
if (degree(LR of def) + degree(LR of op)) <= # avail regs
merge2IGNodes(def, op) // i.e., merge 2 LRs
*/
if( DEBUG_RA)
cout << endl << "Coalscing LRs ..." << endl;
Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
for( ; BBI != Meth->end(); ++BBI) { // traverse BBs in random order
// get the iterator for machine instructions
const MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
MachineCodeForBasicBlock::const_iterator
MInstIterator = MIVec.begin();
// iterate over all the machine instructions in BB
for( ; MInstIterator != MIVec.end(); ++MInstIterator) {
const MachineInstr * MInst = *MInstIterator;
if( DEBUG_RA > 1) {
cout << " *Iterating over machine instr ";
MInst->dump();
cout << endl;
}
// iterate over MI operands to find defs
for(MachineInstr::val_op_const_iterator DefI(MInst);!DefI.done();++DefI){
if( DefI.isDef() ) { // iff this operand is a def
LiveRange *const LROfDef = getLiveRangeForValue( *DefI );
assert( LROfDef );
RegClass *const RCOfDef = LROfDef->getRegClass();
MachineInstr::val_op_const_iterator UseI(MInst);
for( ; !UseI.done(); ++UseI){ // for all uses
LiveRange *const LROfUse = getLiveRangeForValue( *UseI );
if( ! LROfUse ) { // if LR of use is not found
//don't warn about labels
if (!((*UseI)->getType())->isLabelType() && DEBUG_RA) {
cout<<" !! Warning: No LR for use "; printValue(*UseI);
cout << endl;
}
continue; // ignore and continue
}
if( LROfUse == LROfDef) // nothing to merge if they are same
continue;
// RegClass *const RCOfUse = LROfUse->getRegClass();
//if( RCOfDef == RCOfUse ) { // if the reg classes are the same
if( LROfUse->getTypeID() == LROfDef->getTypeID() ) {
if( ! RCOfDef->getInterference(LROfDef, LROfUse) ) {
unsigned CombinedDegree =
LROfDef->getUserIGNode()->getNumOfNeighbors() +
LROfUse->getUserIGNode()->getNumOfNeighbors();
if( CombinedDegree <= RCOfDef->getNumOfAvailRegs() ) {
RCOfDef->mergeIGNodesOfLRs(LROfDef, LROfUse);
unionAndUpdateLRs(LROfDef, LROfUse);
} // if combined degree is less than # of regs
} // if def and use do not interfere
} // if reg classes are the same
} // for all uses
} // if def
} // for all defs
} // for all machine instructions
} // for all BBs
if( DEBUG_RA)
cout << endl << "Coalscing Done!" << endl;
}
/*--------------------------- Debug code for printing ---------------*/
void LiveRangeInfo::printLiveRanges()
{
LiveRangeMapType::iterator HMI = LiveRangeMap.begin(); // hash map iterator
cout << endl << "Printing Live Ranges from Hash Map:" << endl;
for( ; HMI != LiveRangeMap.end() ; HMI ++ ) {
if( (*HMI).first ) {
cout <<" "; printValue((*HMI).first); cout << "\t: ";
((*HMI).second)->printSet(); cout << endl;
}
}
}

View File

@ -0,0 +1,343 @@
#include "llvm/CodeGen/PhyRegAlloc.h"
PhyRegAlloc::PhyRegAlloc(const Method *const M,
const TargetMachine& tm,
MethodLiveVarInfo *const Lvi)
: RegClassList(),
Meth(M), TM(tm), LVI(Lvi), LRI(M, tm, RegClassList),
MRI( tm.getRegInfo() ),
NumOfRegClasses(MRI.getNumOfRegClasses()),
CallInstrList(),
AddedInstrMap()
{
// **TODO: use an actual reserved color list
ReservedColorListType *RCL = new ReservedColorListType();
// create each RegisterClass and put in RegClassList
for( unsigned int rc=0; rc < NumOfRegClasses; rc++)
RegClassList.push_back( new RegClass(M, MRI.getMachineRegClass(rc), RCL) );
}
void PhyRegAlloc::createIGNodeListsAndIGs()
{
cout << "Creating LR lists ..." << endl;
// hash map iterator
LiveRangeMapType::const_iterator HMI = (LRI.getLiveRangeMap())->begin();
// hash map end
LiveRangeMapType::const_iterator HMIEnd = (LRI.getLiveRangeMap())->end();
for( ; HMI != HMIEnd ; ++HMI ) {
LiveRange *L = (*HMI).second; // get the LiveRange
if( (*HMI).first ) {
// if the Value * is not null, and LR
// is not yet written to the IGNodeList
if( !(L->getUserIGNode()) ) {
RegClass *const RC = // RegClass of first value in the LR
//RegClassList [MRI.getRegClassIDOfValue(*(L->begin()))];
RegClassList[ L->getRegClass()->getID() ];
RC-> addLRToIG( L ); // add this LR to an IG
}
}
}
// init RegClassList
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->createInterferenceGraph();
if( DEBUG_RA)
cout << "LRLists Created!" << endl;
}
// Interence occurs only if the LR of Def (Inst or Arg) is of the same reg
// class as that of live var. The live var passed to this function is the
// LVset AFTER the instruction
void PhyRegAlloc::addInterference(const Value *const Def,
const LiveVarSet *const LVSet,
const bool isCallInst) {
LiveVarSet::const_iterator LIt = LVSet->begin();
// get the live range of instruction
const LiveRange *const LROfDef = LRI.getLiveRangeForValue( Def );
IGNode *const IGNodeOfDef = LROfDef->getUserIGNode();
assert( IGNodeOfDef );
RegClass *const RCOfDef = LROfDef->getRegClass();
// for each live var in live variable set
for( ; LIt != LVSet->end(); ++LIt) {
if( DEBUG_RA > 1) {
cout << "< Def="; printValue(Def);
cout << ", Lvar="; printValue( *LIt); cout << "> ";
}
// get the live range corresponding to live var
LiveRange *const LROfVar = LRI.getLiveRangeForValue(*LIt );
// LROfVar can be null if it is a const since a const
// doesn't have a dominating def - see Assumptions above
if( LROfVar) {
if(LROfDef == LROfVar) // do not set interf for same LR
continue;
// if 2 reg classes are the same set interference
if( RCOfDef == LROfVar->getRegClass() ){
RCOfDef->setInterference( LROfDef, LROfVar);
}
//the live range of this var interferes with this call
if( isCallInst )
LROfVar->addCallInterference( (const Instruction *const) Def );
}
else if(DEBUG_RA) {
// we will not have LRs for values not explicitly allocated in the
// instruction stream (e.g., constants)
cout << " warning: no live range for " ;
printValue( *LIt); cout << endl; }
}
}
void PhyRegAlloc::buildInterferenceGraphs()
{
if(DEBUG_RA) cout << "Creating interference graphs ..." << endl;
Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
for( ; BBI != Meth->end(); ++BBI) { // traverse BBs in random order
// get the iterator for machine instructions
const MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
MachineCodeForBasicBlock::const_iterator
MInstIterator = MIVec.begin();
// iterate over all the machine instructions in BB
for( ; MInstIterator != MIVec.end(); ++MInstIterator) {
const MachineInstr *const MInst = *MInstIterator;
// get the LV set after the instruction
const LiveVarSet *const LVSetAI =
LVI->getLiveVarSetAfterMInst(MInst, *BBI);
const bool isCallInst = TM.getInstrInfo().isCall(MInst->getOpCode());
// iterate over MI operands to find defs
for( MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done(); ++OpI) {
if( OpI.isDef() ) {
// create a new LR iff this operand is a def
addInterference(*OpI, LVSetAI, isCallInst );
} //if this is a def
} // for all operands
} // for all machine instructions in BB
// go thru LLVM instructions in the basic block and record all CALL
// instructions in the CallInstrList
BasicBlock::const_iterator InstIt = (*BBI)->begin();
for( ; InstIt != (*BBI)->end() ; ++ InstIt) {
if( (*InstIt)->getOpcode() == Instruction::Call )
CallInstrList.push_back( *InstIt );
}
} // for all BBs in method
// add interferences for method arguments. Since there are no explict
// defs in method for args, we have to add them manually
addInterferencesForArgs(); // add interference for method args
if( DEBUG_RA)
cout << "Interference graphs calculted!" << endl;
}
void PhyRegAlloc::addInterferencesForArgs()
{
// get the InSet of root BB
const LiveVarSet *const InSet = LVI->getInSetOfBB( Meth->front() );
// get the argument list
const Method::ArgumentListType& ArgList = Meth->getArgumentList();
// get an iterator to arg list
Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
for( ; ArgIt != ArgList.end() ; ++ArgIt) { // for each argument
addInterference( *ArgIt, InSet, false ); // add interferences between
// args and LVars at start
if( DEBUG_RA > 1) {
cout << " - %% adding interference for argument ";
printValue( (const Value *) *ArgIt); cout << endl;
}
}
}
void PhyRegAlloc::updateMachineCode()
{
Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
for( ; BBI != Meth->end(); ++BBI) { // traverse BBs in random order
cout << endl << "BB "; printValue( *BBI); cout << ": ";
// get the iterator for machine instructions
MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
MachineCodeForBasicBlock::iterator MInstIterator = MIVec.begin();
// iterate over all the machine instructions in BB
for( ; MInstIterator != MIVec.end(); ++MInstIterator) {
MachineInstr *const MInst = *MInstIterator;
cout << endl << "\t";
cout << TargetInstrDescriptors[MInst->getOpCode()].opCodeString;
//for(MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done();++OpI) {
for(unsigned OpNum=0; OpNum < MInst->getNumOperands(); ++OpNum) {
MachineOperand& Op = MInst->getOperand(OpNum);
if( Op.getOperandType() == MachineOperand::MO_VirtualRegister ||
Op.getOperandType() == MachineOperand::MO_CCRegister) {
const Value *const Val = Op.getVRegValue();
if( !Val ) {
cout << "\t<** Value is NULL!!!**>";
continue;
}
assert( Val && "Value is NULL");
const LiveRange *const LR = LRI.getLiveRangeForValue(Val);
if ( !LR ) {
if( ! ( (Val->getType())->isLabelType() ||
(Val->getValueType() == Value::ConstantVal) ) ) {
cout << "\t" << "<*No LiveRange for: ";
printValue( Val); cout << "*>";
}
//assert( LR && "No LR found for Value");
continue;
}
unsigned RCID = (LR->getRegClass())->getID();
//cout << "Setting reg for value: "; printValue( Val );
//cout << endl;
//Op.setRegForValue( MRI.getUnifiedRegNum(RCID, LR->getColor()) );
int RegNum = MRI.getUnifiedRegNum(RCID, LR->getColor());
cout << "\t" << "%" << MRI.getUnifiedRegName( RegNum );
}
else
cout << "\t" << Op; // use dump field
}
}
}
}
void PhyRegAlloc::allocateRegisters()
{
constructLiveRanges(); // create LR info
if( DEBUG_RA)
LRI.printLiveRanges();
createIGNodeListsAndIGs(); // create IGNode list and IGs
buildInterferenceGraphs(); // build IGs in all reg classes
if( DEBUG_RA) {
// print all LRs in all reg classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->printIGNodeList();
// print IGs in all register classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->printIG();
}
LRI.coalesceLRs(); // coalesce all live ranges
if( DEBUG_RA) {
// print all LRs in all reg classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->printIGNodeList();
// print IGs in all register classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->printIG();
}
MRI.colorArgs(Meth, LRI); // color method args
MRI.colorCallArgs(CallInstrList, LRI, AddedInstrMap); // color call args of call instrns
// color all register classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->colorAllRegs();
updateMachineCode();
//PrintMachineInstructions(Meth);
}

View File

@ -0,0 +1,202 @@
#include "llvm/CodeGen/RegClass.h"
RegClass::RegClass(const Method *const M,
const MachineRegClassInfo *const Mrc,
const ReservedColorListType *const RCL)
: Meth(M), MRC(Mrc), RegClassID( Mrc->getRegClassID() ),
IG(this), IGNodeStack(), ReservedColorList(RCL)
{
if( DEBUG_RA)
cout << "Created Reg Class: " << RegClassID << endl;
// This constructor inits IG. The actual matrix is created by a call to
// createInterferenceGraph() above.
IsColorUsedArr = new bool[ Mrc->getNumOfAllRegs() ];
}
void RegClass::colorAllRegs()
{
if(DEBUG_RA) cout << "Coloring IGs ..." << endl;
//preColorIGNodes(); // pre-color IGNodes
pushAllIGNodes(); // push all IG Nodes
unsigned int StackSize = IGNodeStack.size();
IGNode *CurIGNode;
// for all LRs on stack
for( unsigned int IGN=0; IGN < StackSize; IGN++) {
CurIGNode = IGNodeStack.top(); // pop the IGNode on top of stack
IGNodeStack.pop();
colorIGNode (CurIGNode); // color it
}
// InsertSpillCode; ********* TODO ********
}
void RegClass::pushAllIGNodes()
{
bool NeedMoreSpills;
IGNode *IGNodeSpill, *IGNode;
IG.setCurDegreeOfIGNodes(); // calculate degree of IGNodes
// push non-constrained IGNodes
bool PushedAll = pushUnconstrainedIGNodes();
if( DEBUG_RA) {
cout << " Puhsed all-unconstrained IGNodes. ";
if( PushedAll ) cout << " No constrained nodes left.";
cout << endl;
}
if( PushedAll ) // if NO constrained nodes left
return;
// now, we have constrained nodes. So, push one of them (the one with min
// spill cost) and try to push the others as unConstrained nodes.
// Repeat this.
do{
//get IGNode with min spill cost
IGNodeSpill = getIGNodeWithMinSpillCost();
// push IGNode on to stack
IGNodeStack.push( IGNodeSpill );
// set OnStack flag and decrement degree of neighs
IGNode->pushOnStack();
// now push NON-constrined ones, if any
NeedMoreSpills = ! pushUnconstrainedIGNodes();
} while( NeedMoreSpills ); // repeat until we have pushed all
}
bool RegClass::pushUnconstrainedIGNodes()
{
// # of LRs for this reg class
unsigned int IGNodeListSize = IG.getIGNodeList().size();
bool pushedall = true;
// a pass over IGNodeList
for( unsigned i =0; i < IGNodeListSize; i++) {
// get IGNode i from IGNodeList
IGNode *IGNode = IG.getIGNodeList()[i];
if( ! IGNode ) // can be null due to merging
continue;
// if the degree of IGNode is lower
if( (unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs() ) {
IGNodeStack.push( IGNode ); // push IGNode on to the stack
IGNode->pushOnStack(); // set OnStack and dec deg of neighs
if (DEBUG_RA > 1) {
cout << " pushed un-constrained IGNode " << IGNode->getIndex() ;
cout << " on to stack" << endl;
}
}
else pushedall = false; // we didn't push all live ranges
} // for
// returns true if we pushed all live ranges - else false
return pushedall;
}
IGNode * RegClass::getIGNodeWithMinSpillCost()
{
IGNode *IGNode=NULL;
unsigned int IGNodeListSize = IG.getIGNodeList().size();
// pass over IGNodeList
for( unsigned int i =0; i < IGNodeListSize; i++) {
IGNode = IG.getIGNodeList()[i];
if( ! IGNode ) // can be null due to merging
continue;
// return the first IGNode ########## Change this #######
if( ! IGNode->isOnStack() ) return IGNode;
}
assert(0);
return NULL;
}
void RegClass::colorIGNode(IGNode *const Node)
{
if( ! Node->hasColor() ) { // not colored as an arg etc.
// init all elements to false;
for( unsigned i=0; i < MRC->getNumOfAllRegs(); i++) {
IsColorUsedArr[ i ] = false;
}
// init all reserved_regs to true - we can't use them
for( unsigned i=0; i < ReservedColorList->size() ; i++) {
IsColorUsedArr[ (*ReservedColorList)[i] ] = true;
}
MRC->colorIGNode(Node, IsColorUsedArr);
}
else {
cout << " Node " << Node->getIndex();
cout << " already colored with color " << Node->getColor() << endl;
}
if( !Node->hasColor() ) {
cout << " Node " << Node->getIndex();
cout << " - could not find a color (needs spilling)" << endl;
}
}
#if 0
if( DEBUG_RA) { // printing code
/* cout << " Node " << Node->getIndex();
if( Node->hasColor() ) {
cout << " colored with color " << Node->getColor() << " [" ;
cout << SparcFloatRegOrder::getRegName(Node->getColor());
if( Node->getTypeID() == Type::DoubleTyID )
cout << "+" << SparcFloatRegOrder::getRegName(Node->getColor()+1);
cout << "]" << endl;
}
*/
// MRC->printReg( Node->getParentLR());
cout << " Node " << Node->getIndex();
if( Node->hasColor() )
cout << " colored with color " << Node->getColor() << endl;
#endif

View File

@ -0,0 +1,31 @@
#include "llvm/CodeGen/IGNode.h"
IGNode::IGNode(LiveRange *const PLR, unsigned int Ind): Index(Ind),
ParentLR(PLR)
{
OnStack = false;
CurDegree = -1 ;
ParentLR->setUserIGNode( this );
}
void IGNode::pushOnStack() // sets on to stack and
{ // reduce the degree of neighbors
OnStack = true;
unsigned int neighs = AdjList.size();
for(unsigned int i=0; i < neighs; i++) (AdjList[i])->decCurDegree();
}
void IGNode::delAdjIGNode(const IGNode *const Node) {
vector <IGNode *>::iterator It = AdjList.begin();
// find Node
for( ; It != AdjList.end() && (*It != Node); It++ ) ;
assert( It != AdjList.end() ); // the node must be there
AdjList.erase( It );
}

View File

@ -0,0 +1,226 @@
#include "llvm/CodeGen/InterferenceGraph.h"
InterferenceGraph::InterferenceGraph(RegClass *const RC) : RegCl(RC),
IGNodeList()
{
IG = NULL;
Size = 0;
if( DEBUG_RA) {
cout << "Interference graph created!" << endl;
}
}
InterferenceGraph:: ~InterferenceGraph() { // destructor
if( IG )
delete []IG;
}
void InterferenceGraph::createGraph()
{
Size = IGNodeList.size();
IG = (char **) new char *[Size];
for( unsigned int r=0; r < Size; ++r)
IG[r] = new char[Size];
// init IG matrix
for(unsigned int i=0; i < Size; i++)
for( unsigned int j=0; j < Size ; j++)
IG[i][j] = 0;
}
void InterferenceGraph::addLRToIG(LiveRange *const LR)
{
IGNode *Node = new IGNode(LR, IGNodeList.size() );
IGNodeList.push_back( Node );
//Node->setRegClass( RegCl );
}
// update both the matrix and AdjLists of nodes.
// If there is already an interference between LR1 and LR2, adj lists
// are not updated. LR1 and LR2 must be distinct since if not, it suggests
// that there is some wrong logic in some other method.
void InterferenceGraph::setInterference(const LiveRange *const LR1,
const LiveRange *const LR2 ) {
assert(LR1 != LR2);
IGNode *const IGNode1 = LR1->getUserIGNode();
IGNode *const IGNode2 = LR2->getUserIGNode();
if( DEBUG_RA) {
assertIGNode( IGNode1 );
assertIGNode( IGNode2 );
}
const unsigned int row = IGNode1->getIndex();
const unsigned int col = IGNode2->getIndex();
char *val;
if( DEBUG_RA > 1)
cout << "setting intf for: [" << row << "][" << col << "]" << endl;
( row > col) ? val = &IG[row][col]: val = &IG[col][row];
if( ! (*val) ) { // if this interf is not previously set
*val = 1; // add edges between nodes
IGNode1->addAdjIGNode( IGNode2 );
IGNode2->addAdjIGNode( IGNode1 );
}
}
unsigned InterferenceGraph::getInterference(const LiveRange *const LR1,
const LiveRange *const LR2 ) const {
assert(LR1 != LR2);
if( DEBUG_RA) {
assertIGNode( LR1->getUserIGNode() );
assertIGNode( LR2->getUserIGNode() );
}
const unsigned int row = LR1->getUserIGNode()->getIndex();
const unsigned int col = LR2->getUserIGNode()->getIndex();
char ret;
( row > col) ? (ret = IG[row][col]) : (ret = IG[col][row]) ;
return ret;
}
// Merge 2 IGNodes. The neighbors of the SrcNode will be added to the DestNode.
// Then the IGNode2L will be deleted. Necessary for coalescing.
// IMPORTANT: The live ranges are NOT merged by this method. Use
// LiveRangeInfo::unionAndUpdateLRs for that purpose.
void InterferenceGraph::mergeIGNodesOfLRs(const LiveRange *const LR1,
LiveRange *const LR2 ) {
assert( LR1 != LR2); // cannot merge the same live range
IGNode *const DestNode = LR1->getUserIGNode();
IGNode *SrcNode = LR2->getUserIGNode();
assertIGNode( DestNode );
assertIGNode( SrcNode );
if( DEBUG_RA > 1) {
cout << "Merging LRs: \""; LR1->printSet();
cout << "\" and \""; LR2->printSet();
cout << "\"" << endl;
}
unsigned SrcDegree = SrcNode->getNumOfNeighbors();
const unsigned SrcInd = SrcNode->getIndex();
// for all neighs of SrcNode
for(unsigned i=0; i < SrcDegree; i++) {
IGNode *NeighNode = SrcNode->getAdjIGNode(i);
LiveRange *const LROfNeigh = NeighNode->getParentLR();
// delete edge between src and neigh - even neigh == dest
NeighNode->delAdjIGNode(SrcNode);
// set the matrix posn to 0 betn src and neigh - even neigh == dest
const unsigned NInd = NeighNode->getIndex();
( SrcInd > NInd) ? (IG[SrcInd][NInd]=0) : (IG[NInd][SrcInd]=0) ;
if( LR1 != LROfNeigh) { // if the neigh != dest
// add edge betwn Dest and Neigh - if there is no current edge
setInterference(LR1, LROfNeigh );
}
//cout<< " #Neighs - Neigh: ["<< NeighNode->getIndex()<< "] ";
//cout << NeighNode->getNumOfNeighbors();
//cout << " Dest: [" << DestNode->getIndex() << "] ";
//cout << DestNode->getNumOfNeighbors() << endl;
}
IGNodeList[ SrcInd ] = NULL;
// SrcNode is no longer necessary - LR2 must be deleted by the caller
delete( SrcNode );
}
// must be called after modifications to the graph are over but before
// pushing IGNodes on to the stack for coloring.
void InterferenceGraph::setCurDegreeOfIGNodes()
{
unsigned Size = IGNodeList.size();
for( unsigned i=0; i < Size; i++) {
IGNode *Node = IGNodeList[i];
if( Node )
Node->setCurDegree();
}
}
//--------------------- debugging (Printing) methods -----------------------
void InterferenceGraph::printIG() const
{
for(unsigned int i=0; i < Size; i++) {
const IGNode *const Node = IGNodeList[i];
if( ! Node )
continue; // skip empty rows
cout << " [" << i << "] ";
for( unsigned int j=0; j < Size; j++) {
if( j >= i) break;
if( IG[i][j] ) cout << "(" << i << "," << j << ") ";
}
cout << endl;
}
}
void InterferenceGraph::printIGNodeList() const
{
vector<IGNode *>::const_iterator IGIt = IGNodeList.begin(); // hash map iter
for(unsigned i=0; i < IGNodeList.size() ; ++i) {
const IGNode *const Node = IGNodeList[i];
if( ! Node )
continue;
cout << " [" << Node->getIndex() << "] ";
(Node->getParentLR())->printSet();
//int Deg = Node->getCurDegree();
cout << "\t <# of Neighs: " << Node->getNumOfNeighbors() << ">" << endl;
}
}

View File

@ -0,0 +1,283 @@
#include "llvm/CodeGen/LiveRangeInfo.h"
LiveRangeInfo::LiveRangeInfo(const Method *const M,
const TargetMachine& tm,
vector<RegClass *> &RCL)
: Meth(M), LiveRangeMap(),
TM(tm), RegClassList(RCL)
{ }
// union two live ranges into one. The 2nd LR is deleted. Used for coalescing.
// Note: the caller must make sure that L1 and L2 are distinct
void LiveRangeInfo::unionAndUpdateLRs(LiveRange *const L1, LiveRange *L2)
{
assert( L1 != L2);
L1->setUnion( L2 ); // add elements of L2 to L1
ValueSet::iterator L2It;
for( L2It = L2->begin() ; L2It != L2->end(); ++L2It) {
//assert(( L1->getTypeID() == L2->getTypeID()) && "Merge:Different types");
L1->add( *L2It ); // add the var in L2 to L1
LiveRangeMap[ *L2It ] = L1; // now the elements in L2 should map to L1
}
delete ( L2 ); // delete L2 as it is no longer needed
}
void LiveRangeInfo::constructLiveRanges()
{
if( DEBUG_RA)
cout << "Consturcting Live Ranges ..." << endl;
// first find the live ranges for all incoming args of the method since
// those LRs start from the start of the method
// get the argument list
const Method::ArgumentListType& ArgList = Meth->getArgumentList();
// get an iterator to arg list
Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
for( ; ArgIt != ArgList.end() ; ++ArgIt) { // for each argument
LiveRange * ArgRange = new LiveRange(); // creates a new LR and
const Value *const Val = (const Value *) *ArgIt;
assert( Val);
ArgRange->add( Val ); // add the arg (def) to it
LiveRangeMap[ Val ] = ArgRange;
// create a temp machine op to find the register class of value
//const MachineOperand Op(MachineOperand::MO_VirtualRegister);
unsigned rcid = (TM.getRegInfo()).getRegClassIDOfValue( Val );
ArgRange->setRegClass(RegClassList[ rcid ] );
if( DEBUG_RA > 1) {
cout << " adding LiveRange for argument ";
printValue( (const Value *) *ArgIt); cout << endl;
}
}
// Now find all LRs for machine the instructions. A new LR will be created
// only for defs in the machine instr since, we assume that all Values are
// defined before they are used. However, there can be multiple defs for
// the same Value in machine instructions.
Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
for( ; BBI != Meth->end(); ++BBI) { // go thru BBs in random order
// get the iterator for machine instructions
const MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
MachineCodeForBasicBlock::const_iterator
MInstIterator = MIVec.begin();
// iterate over all the machine instructions in BB
for( ; MInstIterator != MIVec.end(); MInstIterator++) {
const MachineInstr * MInst = *MInstIterator;
// iterate over MI operands to find defs
for( MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done(); OpI++) {
// create a new LR iff this operand is a def
if( OpI.isDef() ) {
const Value *const Def = *OpI;
LiveRange *DefRange = LiveRangeMap[Def];
// see LR already there (because of multiple defs)
if( !DefRange) { // if it is not in LiveRangeMap
DefRange = new LiveRange(); // creates a new live range and
DefRange->add( Def ); // add the instruction (def) to it
LiveRangeMap[ Def ] = DefRange; // update the map
if( DEBUG_RA > 1) {
cout << " creating a LR for def: ";
printValue(Def); cout << endl;
}
// set the register class of the new live range
//assert( RegClassList.size() );
MachineOperand::MachineOperandType OpTy =
OpI.getMachineOperand().getOperandType();
bool isCC = ( OpTy == MachineOperand::MO_CCRegister);
unsigned rcid = (TM.getRegInfo()).getRegClassIDOfValue(
OpI.getMachineOperand().getVRegValue(), isCC );
if(isCC )
cout << "\a" << "**created a LR for a CC reg**" << cout;
DefRange->setRegClass( RegClassList[ rcid ] );
}
else {
DefRange->add( Def ); // add the opearand to def range
// update the map - Operand points
// to the merged set
LiveRangeMap[ Def ] = DefRange;
if( DEBUG_RA > 1) {
cout << " added to an existing LR for def: ";
printValue( Def ); cout << endl;
}
}
} // if isDef()
} // for all opereands in machine instructions
} // for all machine instructions in the BB
} // for all BBs in method
if( DEBUG_RA)
cout << "Initial Live Ranges constructed!" << endl;
}
void LiveRangeInfo::coalesceLRs()
{
/* Algorithm:
for each BB in method
for each machine instruction (inst)
for each definition (def) in inst
for each operand (op) of inst that is a use
if the def and op are of the same type
if the def and op do not interfere //i.e., not simultaneously live
if (degree(LR of def) + degree(LR of op)) <= # avail regs
merge2IGNodes(def, op) // i.e., merge 2 LRs
*/
if( DEBUG_RA)
cout << endl << "Coalscing LRs ..." << endl;
Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
for( ; BBI != Meth->end(); ++BBI) { // traverse BBs in random order
// get the iterator for machine instructions
const MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
MachineCodeForBasicBlock::const_iterator
MInstIterator = MIVec.begin();
// iterate over all the machine instructions in BB
for( ; MInstIterator != MIVec.end(); ++MInstIterator) {
const MachineInstr * MInst = *MInstIterator;
if( DEBUG_RA > 1) {
cout << " *Iterating over machine instr ";
MInst->dump();
cout << endl;
}
// iterate over MI operands to find defs
for(MachineInstr::val_op_const_iterator DefI(MInst);!DefI.done();++DefI){
if( DefI.isDef() ) { // iff this operand is a def
LiveRange *const LROfDef = getLiveRangeForValue( *DefI );
assert( LROfDef );
RegClass *const RCOfDef = LROfDef->getRegClass();
MachineInstr::val_op_const_iterator UseI(MInst);
for( ; !UseI.done(); ++UseI){ // for all uses
LiveRange *const LROfUse = getLiveRangeForValue( *UseI );
if( ! LROfUse ) { // if LR of use is not found
//don't warn about labels
if (!((*UseI)->getType())->isLabelType() && DEBUG_RA) {
cout<<" !! Warning: No LR for use "; printValue(*UseI);
cout << endl;
}
continue; // ignore and continue
}
if( LROfUse == LROfDef) // nothing to merge if they are same
continue;
// RegClass *const RCOfUse = LROfUse->getRegClass();
//if( RCOfDef == RCOfUse ) { // if the reg classes are the same
if( LROfUse->getTypeID() == LROfDef->getTypeID() ) {
if( ! RCOfDef->getInterference(LROfDef, LROfUse) ) {
unsigned CombinedDegree =
LROfDef->getUserIGNode()->getNumOfNeighbors() +
LROfUse->getUserIGNode()->getNumOfNeighbors();
if( CombinedDegree <= RCOfDef->getNumOfAvailRegs() ) {
RCOfDef->mergeIGNodesOfLRs(LROfDef, LROfUse);
unionAndUpdateLRs(LROfDef, LROfUse);
} // if combined degree is less than # of regs
} // if def and use do not interfere
} // if reg classes are the same
} // for all uses
} // if def
} // for all defs
} // for all machine instructions
} // for all BBs
if( DEBUG_RA)
cout << endl << "Coalscing Done!" << endl;
}
/*--------------------------- Debug code for printing ---------------*/
void LiveRangeInfo::printLiveRanges()
{
LiveRangeMapType::iterator HMI = LiveRangeMap.begin(); // hash map iterator
cout << endl << "Printing Live Ranges from Hash Map:" << endl;
for( ; HMI != LiveRangeMap.end() ; HMI ++ ) {
if( (*HMI).first ) {
cout <<" "; printValue((*HMI).first); cout << "\t: ";
((*HMI).second)->printSet(); cout << endl;
}
}
}

View File

@ -0,0 +1,343 @@
#include "llvm/CodeGen/PhyRegAlloc.h"
PhyRegAlloc::PhyRegAlloc(const Method *const M,
const TargetMachine& tm,
MethodLiveVarInfo *const Lvi)
: RegClassList(),
Meth(M), TM(tm), LVI(Lvi), LRI(M, tm, RegClassList),
MRI( tm.getRegInfo() ),
NumOfRegClasses(MRI.getNumOfRegClasses()),
CallInstrList(),
AddedInstrMap()
{
// **TODO: use an actual reserved color list
ReservedColorListType *RCL = new ReservedColorListType();
// create each RegisterClass and put in RegClassList
for( unsigned int rc=0; rc < NumOfRegClasses; rc++)
RegClassList.push_back( new RegClass(M, MRI.getMachineRegClass(rc), RCL) );
}
void PhyRegAlloc::createIGNodeListsAndIGs()
{
cout << "Creating LR lists ..." << endl;
// hash map iterator
LiveRangeMapType::const_iterator HMI = (LRI.getLiveRangeMap())->begin();
// hash map end
LiveRangeMapType::const_iterator HMIEnd = (LRI.getLiveRangeMap())->end();
for( ; HMI != HMIEnd ; ++HMI ) {
LiveRange *L = (*HMI).second; // get the LiveRange
if( (*HMI).first ) {
// if the Value * is not null, and LR
// is not yet written to the IGNodeList
if( !(L->getUserIGNode()) ) {
RegClass *const RC = // RegClass of first value in the LR
//RegClassList [MRI.getRegClassIDOfValue(*(L->begin()))];
RegClassList[ L->getRegClass()->getID() ];
RC-> addLRToIG( L ); // add this LR to an IG
}
}
}
// init RegClassList
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->createInterferenceGraph();
if( DEBUG_RA)
cout << "LRLists Created!" << endl;
}
// Interence occurs only if the LR of Def (Inst or Arg) is of the same reg
// class as that of live var. The live var passed to this function is the
// LVset AFTER the instruction
void PhyRegAlloc::addInterference(const Value *const Def,
const LiveVarSet *const LVSet,
const bool isCallInst) {
LiveVarSet::const_iterator LIt = LVSet->begin();
// get the live range of instruction
const LiveRange *const LROfDef = LRI.getLiveRangeForValue( Def );
IGNode *const IGNodeOfDef = LROfDef->getUserIGNode();
assert( IGNodeOfDef );
RegClass *const RCOfDef = LROfDef->getRegClass();
// for each live var in live variable set
for( ; LIt != LVSet->end(); ++LIt) {
if( DEBUG_RA > 1) {
cout << "< Def="; printValue(Def);
cout << ", Lvar="; printValue( *LIt); cout << "> ";
}
// get the live range corresponding to live var
LiveRange *const LROfVar = LRI.getLiveRangeForValue(*LIt );
// LROfVar can be null if it is a const since a const
// doesn't have a dominating def - see Assumptions above
if( LROfVar) {
if(LROfDef == LROfVar) // do not set interf for same LR
continue;
// if 2 reg classes are the same set interference
if( RCOfDef == LROfVar->getRegClass() ){
RCOfDef->setInterference( LROfDef, LROfVar);
}
//the live range of this var interferes with this call
if( isCallInst )
LROfVar->addCallInterference( (const Instruction *const) Def );
}
else if(DEBUG_RA) {
// we will not have LRs for values not explicitly allocated in the
// instruction stream (e.g., constants)
cout << " warning: no live range for " ;
printValue( *LIt); cout << endl; }
}
}
void PhyRegAlloc::buildInterferenceGraphs()
{
if(DEBUG_RA) cout << "Creating interference graphs ..." << endl;
Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
for( ; BBI != Meth->end(); ++BBI) { // traverse BBs in random order
// get the iterator for machine instructions
const MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
MachineCodeForBasicBlock::const_iterator
MInstIterator = MIVec.begin();
// iterate over all the machine instructions in BB
for( ; MInstIterator != MIVec.end(); ++MInstIterator) {
const MachineInstr *const MInst = *MInstIterator;
// get the LV set after the instruction
const LiveVarSet *const LVSetAI =
LVI->getLiveVarSetAfterMInst(MInst, *BBI);
const bool isCallInst = TM.getInstrInfo().isCall(MInst->getOpCode());
// iterate over MI operands to find defs
for( MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done(); ++OpI) {
if( OpI.isDef() ) {
// create a new LR iff this operand is a def
addInterference(*OpI, LVSetAI, isCallInst );
} //if this is a def
} // for all operands
} // for all machine instructions in BB
// go thru LLVM instructions in the basic block and record all CALL
// instructions in the CallInstrList
BasicBlock::const_iterator InstIt = (*BBI)->begin();
for( ; InstIt != (*BBI)->end() ; ++ InstIt) {
if( (*InstIt)->getOpcode() == Instruction::Call )
CallInstrList.push_back( *InstIt );
}
} // for all BBs in method
// add interferences for method arguments. Since there are no explict
// defs in method for args, we have to add them manually
addInterferencesForArgs(); // add interference for method args
if( DEBUG_RA)
cout << "Interference graphs calculted!" << endl;
}
void PhyRegAlloc::addInterferencesForArgs()
{
// get the InSet of root BB
const LiveVarSet *const InSet = LVI->getInSetOfBB( Meth->front() );
// get the argument list
const Method::ArgumentListType& ArgList = Meth->getArgumentList();
// get an iterator to arg list
Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
for( ; ArgIt != ArgList.end() ; ++ArgIt) { // for each argument
addInterference( *ArgIt, InSet, false ); // add interferences between
// args and LVars at start
if( DEBUG_RA > 1) {
cout << " - %% adding interference for argument ";
printValue( (const Value *) *ArgIt); cout << endl;
}
}
}
void PhyRegAlloc::updateMachineCode()
{
Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
for( ; BBI != Meth->end(); ++BBI) { // traverse BBs in random order
cout << endl << "BB "; printValue( *BBI); cout << ": ";
// get the iterator for machine instructions
MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
MachineCodeForBasicBlock::iterator MInstIterator = MIVec.begin();
// iterate over all the machine instructions in BB
for( ; MInstIterator != MIVec.end(); ++MInstIterator) {
MachineInstr *const MInst = *MInstIterator;
cout << endl << "\t";
cout << TargetInstrDescriptors[MInst->getOpCode()].opCodeString;
//for(MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done();++OpI) {
for(unsigned OpNum=0; OpNum < MInst->getNumOperands(); ++OpNum) {
MachineOperand& Op = MInst->getOperand(OpNum);
if( Op.getOperandType() == MachineOperand::MO_VirtualRegister ||
Op.getOperandType() == MachineOperand::MO_CCRegister) {
const Value *const Val = Op.getVRegValue();
if( !Val ) {
cout << "\t<** Value is NULL!!!**>";
continue;
}
assert( Val && "Value is NULL");
const LiveRange *const LR = LRI.getLiveRangeForValue(Val);
if ( !LR ) {
if( ! ( (Val->getType())->isLabelType() ||
(Val->getValueType() == Value::ConstantVal) ) ) {
cout << "\t" << "<*No LiveRange for: ";
printValue( Val); cout << "*>";
}
//assert( LR && "No LR found for Value");
continue;
}
unsigned RCID = (LR->getRegClass())->getID();
//cout << "Setting reg for value: "; printValue( Val );
//cout << endl;
//Op.setRegForValue( MRI.getUnifiedRegNum(RCID, LR->getColor()) );
int RegNum = MRI.getUnifiedRegNum(RCID, LR->getColor());
cout << "\t" << "%" << MRI.getUnifiedRegName( RegNum );
}
else
cout << "\t" << Op; // use dump field
}
}
}
}
void PhyRegAlloc::allocateRegisters()
{
constructLiveRanges(); // create LR info
if( DEBUG_RA)
LRI.printLiveRanges();
createIGNodeListsAndIGs(); // create IGNode list and IGs
buildInterferenceGraphs(); // build IGs in all reg classes
if( DEBUG_RA) {
// print all LRs in all reg classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->printIGNodeList();
// print IGs in all register classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->printIG();
}
LRI.coalesceLRs(); // coalesce all live ranges
if( DEBUG_RA) {
// print all LRs in all reg classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->printIGNodeList();
// print IGs in all register classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->printIG();
}
MRI.colorArgs(Meth, LRI); // color method args
MRI.colorCallArgs(CallInstrList, LRI, AddedInstrMap); // color call args of call instrns
// color all register classes
for( unsigned int rc=0; rc < NumOfRegClasses ; rc++)
RegClassList[ rc ]->colorAllRegs();
updateMachineCode();
//PrintMachineInstructions(Meth);
}

View File

@ -0,0 +1,202 @@
#include "llvm/CodeGen/RegClass.h"
RegClass::RegClass(const Method *const M,
const MachineRegClassInfo *const Mrc,
const ReservedColorListType *const RCL)
: Meth(M), MRC(Mrc), RegClassID( Mrc->getRegClassID() ),
IG(this), IGNodeStack(), ReservedColorList(RCL)
{
if( DEBUG_RA)
cout << "Created Reg Class: " << RegClassID << endl;
// This constructor inits IG. The actual matrix is created by a call to
// createInterferenceGraph() above.
IsColorUsedArr = new bool[ Mrc->getNumOfAllRegs() ];
}
void RegClass::colorAllRegs()
{
if(DEBUG_RA) cout << "Coloring IGs ..." << endl;
//preColorIGNodes(); // pre-color IGNodes
pushAllIGNodes(); // push all IG Nodes
unsigned int StackSize = IGNodeStack.size();
IGNode *CurIGNode;
// for all LRs on stack
for( unsigned int IGN=0; IGN < StackSize; IGN++) {
CurIGNode = IGNodeStack.top(); // pop the IGNode on top of stack
IGNodeStack.pop();
colorIGNode (CurIGNode); // color it
}
// InsertSpillCode; ********* TODO ********
}
void RegClass::pushAllIGNodes()
{
bool NeedMoreSpills;
IGNode *IGNodeSpill, *IGNode;
IG.setCurDegreeOfIGNodes(); // calculate degree of IGNodes
// push non-constrained IGNodes
bool PushedAll = pushUnconstrainedIGNodes();
if( DEBUG_RA) {
cout << " Puhsed all-unconstrained IGNodes. ";
if( PushedAll ) cout << " No constrained nodes left.";
cout << endl;
}
if( PushedAll ) // if NO constrained nodes left
return;
// now, we have constrained nodes. So, push one of them (the one with min
// spill cost) and try to push the others as unConstrained nodes.
// Repeat this.
do{
//get IGNode with min spill cost
IGNodeSpill = getIGNodeWithMinSpillCost();
// push IGNode on to stack
IGNodeStack.push( IGNodeSpill );
// set OnStack flag and decrement degree of neighs
IGNode->pushOnStack();
// now push NON-constrined ones, if any
NeedMoreSpills = ! pushUnconstrainedIGNodes();
} while( NeedMoreSpills ); // repeat until we have pushed all
}
bool RegClass::pushUnconstrainedIGNodes()
{
// # of LRs for this reg class
unsigned int IGNodeListSize = IG.getIGNodeList().size();
bool pushedall = true;
// a pass over IGNodeList
for( unsigned i =0; i < IGNodeListSize; i++) {
// get IGNode i from IGNodeList
IGNode *IGNode = IG.getIGNodeList()[i];
if( ! IGNode ) // can be null due to merging
continue;
// if the degree of IGNode is lower
if( (unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs() ) {
IGNodeStack.push( IGNode ); // push IGNode on to the stack
IGNode->pushOnStack(); // set OnStack and dec deg of neighs
if (DEBUG_RA > 1) {
cout << " pushed un-constrained IGNode " << IGNode->getIndex() ;
cout << " on to stack" << endl;
}
}
else pushedall = false; // we didn't push all live ranges
} // for
// returns true if we pushed all live ranges - else false
return pushedall;
}
IGNode * RegClass::getIGNodeWithMinSpillCost()
{
IGNode *IGNode=NULL;
unsigned int IGNodeListSize = IG.getIGNodeList().size();
// pass over IGNodeList
for( unsigned int i =0; i < IGNodeListSize; i++) {
IGNode = IG.getIGNodeList()[i];
if( ! IGNode ) // can be null due to merging
continue;
// return the first IGNode ########## Change this #######
if( ! IGNode->isOnStack() ) return IGNode;
}
assert(0);
return NULL;
}
void RegClass::colorIGNode(IGNode *const Node)
{
if( ! Node->hasColor() ) { // not colored as an arg etc.
// init all elements to false;
for( unsigned i=0; i < MRC->getNumOfAllRegs(); i++) {
IsColorUsedArr[ i ] = false;
}
// init all reserved_regs to true - we can't use them
for( unsigned i=0; i < ReservedColorList->size() ; i++) {
IsColorUsedArr[ (*ReservedColorList)[i] ] = true;
}
MRC->colorIGNode(Node, IsColorUsedArr);
}
else {
cout << " Node " << Node->getIndex();
cout << " already colored with color " << Node->getColor() << endl;
}
if( !Node->hasColor() ) {
cout << " Node " << Node->getIndex();
cout << " - could not find a color (needs spilling)" << endl;
}
}
#if 0
if( DEBUG_RA) { // printing code
/* cout << " Node " << Node->getIndex();
if( Node->hasColor() ) {
cout << " colored with color " << Node->getColor() << " [" ;
cout << SparcFloatRegOrder::getRegName(Node->getColor());
if( Node->getTypeID() == Type::DoubleTyID )
cout << "+" << SparcFloatRegOrder::getRegName(Node->getColor()+1);
cout << "]" << endl;
}
*/
// MRC->printReg( Node->getParentLR());
cout << " Node " << Node->getIndex();
if( Node->hasColor() )
cout << " colored with color " << Node->getColor() << endl;
#endif