From 8e6047920dbf22a1edcbd98e65a8bc57a56c0e17 Mon Sep 17 00:00:00 2001 From: Ruchira Sasanka Date: Fri, 14 Sep 2001 21:18:34 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@580 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/RegAlloc/IGNode.cpp | 31 ++ lib/CodeGen/RegAlloc/InterferenceGraph.cpp | 226 ++++++++++++ lib/CodeGen/RegAlloc/LiveRangeInfo.cpp | 283 +++++++++++++++ lib/CodeGen/RegAlloc/PhyRegAloc.cpp | 343 ++++++++++++++++++ lib/CodeGen/RegAlloc/RegClass.cpp | 202 +++++++++++ lib/Target/SparcV9/RegAlloc/IGNode.cpp | 31 ++ .../SparcV9/RegAlloc/InterferenceGraph.cpp | 226 ++++++++++++ lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp | 283 +++++++++++++++ lib/Target/SparcV9/RegAlloc/PhyRegAloc.cpp | 343 ++++++++++++++++++ lib/Target/SparcV9/RegAlloc/RegClass.cpp | 202 +++++++++++ 10 files changed, 2170 insertions(+) create mode 100644 lib/CodeGen/RegAlloc/IGNode.cpp create mode 100644 lib/CodeGen/RegAlloc/InterferenceGraph.cpp create mode 100644 lib/CodeGen/RegAlloc/LiveRangeInfo.cpp create mode 100644 lib/CodeGen/RegAlloc/PhyRegAloc.cpp create mode 100644 lib/CodeGen/RegAlloc/RegClass.cpp create mode 100644 lib/Target/SparcV9/RegAlloc/IGNode.cpp create mode 100644 lib/Target/SparcV9/RegAlloc/InterferenceGraph.cpp create mode 100644 lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp create mode 100644 lib/Target/SparcV9/RegAlloc/PhyRegAloc.cpp create mode 100644 lib/Target/SparcV9/RegAlloc/RegClass.cpp diff --git a/lib/CodeGen/RegAlloc/IGNode.cpp b/lib/CodeGen/RegAlloc/IGNode.cpp new file mode 100644 index 00000000000..0e8a124cd3d --- /dev/null +++ b/lib/CodeGen/RegAlloc/IGNode.cpp @@ -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 ::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 ); +} diff --git a/lib/CodeGen/RegAlloc/InterferenceGraph.cpp b/lib/CodeGen/RegAlloc/InterferenceGraph.cpp new file mode 100644 index 00000000000..d8ec2470aaa --- /dev/null +++ b/lib/CodeGen/RegAlloc/InterferenceGraph.cpp @@ -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::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; + + } +} + + diff --git a/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp b/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp new file mode 100644 index 00000000000..5ef350207b8 --- /dev/null +++ b/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp @@ -0,0 +1,283 @@ +#include "llvm/CodeGen/LiveRangeInfo.h" + +LiveRangeInfo::LiveRangeInfo(const Method *const M, + const TargetMachine& tm, + vector &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; + } + } +} + + diff --git a/lib/CodeGen/RegAlloc/PhyRegAloc.cpp b/lib/CodeGen/RegAlloc/PhyRegAloc.cpp new file mode 100644 index 00000000000..c2c7c64ec90 --- /dev/null +++ b/lib/CodeGen/RegAlloc/PhyRegAloc.cpp @@ -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); +} + + + + diff --git a/lib/CodeGen/RegAlloc/RegClass.cpp b/lib/CodeGen/RegAlloc/RegClass.cpp new file mode 100644 index 00000000000..90ad960ba59 --- /dev/null +++ b/lib/CodeGen/RegAlloc/RegClass.cpp @@ -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 diff --git a/lib/Target/SparcV9/RegAlloc/IGNode.cpp b/lib/Target/SparcV9/RegAlloc/IGNode.cpp new file mode 100644 index 00000000000..0e8a124cd3d --- /dev/null +++ b/lib/Target/SparcV9/RegAlloc/IGNode.cpp @@ -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 ::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 ); +} diff --git a/lib/Target/SparcV9/RegAlloc/InterferenceGraph.cpp b/lib/Target/SparcV9/RegAlloc/InterferenceGraph.cpp new file mode 100644 index 00000000000..d8ec2470aaa --- /dev/null +++ b/lib/Target/SparcV9/RegAlloc/InterferenceGraph.cpp @@ -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::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; + + } +} + + diff --git a/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp b/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp new file mode 100644 index 00000000000..5ef350207b8 --- /dev/null +++ b/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp @@ -0,0 +1,283 @@ +#include "llvm/CodeGen/LiveRangeInfo.h" + +LiveRangeInfo::LiveRangeInfo(const Method *const M, + const TargetMachine& tm, + vector &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; + } + } +} + + diff --git a/lib/Target/SparcV9/RegAlloc/PhyRegAloc.cpp b/lib/Target/SparcV9/RegAlloc/PhyRegAloc.cpp new file mode 100644 index 00000000000..c2c7c64ec90 --- /dev/null +++ b/lib/Target/SparcV9/RegAlloc/PhyRegAloc.cpp @@ -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); +} + + + + diff --git a/lib/Target/SparcV9/RegAlloc/RegClass.cpp b/lib/Target/SparcV9/RegAlloc/RegClass.cpp new file mode 100644 index 00000000000..90ad960ba59 --- /dev/null +++ b/lib/Target/SparcV9/RegAlloc/RegClass.cpp @@ -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