From f1c154f5e69fdd11426b4e2a5cdea98fcab1606b Mon Sep 17 00:00:00 2001 From: Guochun Shi Date: Thu, 27 Mar 2003 17:57:44 +0000 Subject: *** empty log message *** git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5755 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp | 1313 +++++++++++++++++++++ 1 file changed, 1313 insertions(+) create mode 100644 lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp (limited to 'lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp') diff --git a/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp b/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp new file mode 100644 index 0000000000..4e36b070b4 --- /dev/null +++ b/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp @@ -0,0 +1,1313 @@ +#include +#include "ModuloSchedGraph.h" +#include "llvm/CodeGen/InstrSelection.h" +#include "llvm/BasicBlock.h" +#include "llvm/Function.h" +#include "llvm/iOther.h" +#include "Support/StringExtras.h" +#include "Support/STLExtras.h" +#include +#include +#include "llvm/iOperators.h" +#include "llvm/iOther.h" +#include "llvm/iPHINode.h" +#include "llvm/iTerminators.h" +#include "llvm/iMemory.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/MachineCodeForInstruction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/MachineSchedInfo.h" + +#define UNIDELAY 1 +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) < (b) ? (b) : (a)) + +using std::vector; +using std::pair; +//using std::hash_map; +using std::cerr; +extern std::ostream modSched_os; +extern ModuloSchedDebugLevel_t ModuloSchedDebugLevel; +//*********************** Internal Data Structures *************************/ + +// The following two types need to be classes, not typedefs, so we can use +// opaque declarations in SchedGraph.h +// +struct RefVec: public vector< pair > { + typedef vector< pair >:: iterator iterator; + typedef vector< pair >::const_iterator const_iterator; +}; + +struct RegToRefVecMap: public hash_map { + typedef hash_map:: iterator iterator; + typedef hash_map::const_iterator const_iterator; +}; + +struct ValueToDefVecMap: public hash_map { + typedef hash_map:: iterator iterator; + typedef hash_map::const_iterator const_iterator; +}; + + + +// class Modulo SchedGraphNode + +/*ctor*/ +ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned int _nodeId, + const BasicBlock* _bb, + const Instruction* _inst, + int indexInBB, + const TargetMachine& target) + : + SchedGraphNodeCommon(_nodeId, _bb, indexInBB), + inst(_inst) +{ + if(inst) + { + //FIXME: find the latency + //currently setthe latency to zero + latency =0; + } + +} + +//class ModuloScheGraph + + +void +ModuloSchedGraph::addDummyEdges() +{ + assert(graphRoot->outEdges.size() == 0); + + for (const_iterator I=begin(); I != end(); ++I) + { + ModuloSchedGraphNode* node = (ModuloSchedGraphNode*)( (*I).second); + assert(node != graphRoot && node != graphLeaf); + if (node->beginInEdges() == node->endInEdges()) + (void) new SchedGraphEdge(graphRoot, node, SchedGraphEdge::CtrlDep, + SchedGraphEdge::NonDataDep, 0); + if (node->beginOutEdges() == node->endOutEdges()) + (void) new SchedGraphEdge(node, graphLeaf, SchedGraphEdge::CtrlDep, + SchedGraphEdge::NonDataDep, 0); + } +} + +bool isDefinition(const Instruction* I) +{ + //if(TerminatorInst::classof(I)||FreeInst::classof(I) || StoreInst::classof(I) || CallInst::classof(I)) + if(!I->hasName()) + return false; + else + return true; +} + +void ModuloSchedGraph::addDefUseEdges(const BasicBlock* bb) +{ + //collect def instructions, store them in vector + const MachineInstrInfo& mii = target.getInstrInfo(); + + typedef std::vector DefVec; + DefVec defVec; + + //find those def instructions + for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I !=E; I++) + if(I->getType() != Type::VoidTy) + { + defVec.push_back(this->getGraphNodeForInst(I)) ; + } + + for(unsigned int i=0; i < defVec.size();i++) + for(Value::use_const_iterator I=defVec[i]->getInst()->use_begin();I !=defVec[i]->getInst()->use_end() ;I++) + { + //for each use of a def, add a flow edge from the def instruction to the ref instruction + + + const Instruction* value=defVec[i]->getInst(); + Instruction *inst=(Instruction*)(*I); + ModuloSchedGraphNode* node=NULL; + + for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I !=E; I++) + if((const Instruction*)I == inst) + { + node=(*this)[inst]; + break; + } + + assert(inst != NULL &&" Use not an Instruction ?" ); + + if(node == NULL) //inst is not an instruction in this block + {} + else + { + //add a flow edge from the def instruction to the ref instruction + + //self loop will not happen in SSA form + assert(defVec[i] != node && "same node?"); + + + //this is a true dependence, so the delay is equal to the delay of the pred node. + int delay=0; + MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(value); + for(unsigned j=0;j< tempMvec.size();j++) + { + MachineInstr* temp=tempMvec[j]; + //delay +=mii.minLatency(temp->getOpCode()); + delay = max(delay, mii.minLatency(temp->getOpCode())); + } + + SchedGraphEdge* trueEdge=new SchedGraphEdge(defVec[i],node,value, SchedGraphEdge::TrueDep,delay); + + //if the ref instruction is before the def instrution + //then the def instruction must be a phi instruction + //add an anti-dependence edge to from the ref instruction to the def instruction + if( node->getOrigIndexInBB() < defVec[i]->getOrigIndexInBB()) + { + assert(PHINode::classof(inst) && "the ref instruction befre def is not PHINode?"); + trueEdge->setIteDiff(1); + } + + } + + } +} + +void ModuloSchedGraph::addCDEdges(const BasicBlock* bb) +{ + //find the last instruction in the basic block + //see if it is an branch instruction. + //If yes, then add an edge from each node expcept the last node to the last node + + const Instruction* inst=&(bb->back()); + ModuloSchedGraphNode* lastNode=(*this)[inst]; + if( TerminatorInst::classof(inst)) + for(BasicBlock::const_iterator I=bb->begin(),E=bb->end(); I != E; I++) + { + if(inst != I) + { + ModuloSchedGraphNode* node = (*this)[I]; + //use latency of 0 + (void) new SchedGraphEdge(node,lastNode,SchedGraphEdge::CtrlDep, + SchedGraphEdge::NonDataDep,0); + } + + } + + +} + + + + +static const int SG_LOAD_REF = 0; +static const int SG_STORE_REF = 1; +static const int SG_CALL_REF = 2; + +static const unsigned int SG_DepOrderArray[][3] = { + { SchedGraphEdge::NonDataDep, + SchedGraphEdge::AntiDep, + SchedGraphEdge::AntiDep }, + { SchedGraphEdge::TrueDep, + SchedGraphEdge::OutputDep, + SchedGraphEdge::TrueDep | SchedGraphEdge::OutputDep }, + { SchedGraphEdge::TrueDep, + SchedGraphEdge::AntiDep | SchedGraphEdge::OutputDep, + SchedGraphEdge::TrueDep | SchedGraphEdge::AntiDep + | SchedGraphEdge::OutputDep } +}; + + +// Add a dependence edge between every pair of machine load/store/call +// instructions, where at least one is a store or a call. +// Use latency 1 just to ensure that memory operations are ordered; +// latency does not otherwise matter (true dependences enforce that). +// +void +ModuloSchedGraph::addMemEdges(const BasicBlock* bb) +{ + + vector memNodeVec; + + //construct the memNodeVec + + for( BasicBlock::const_iterator I=bb->begin(), E=bb->end();I != E; I++) + if(LoadInst::classof(I) ||StoreInst::classof(I) || CallInst::classof(I)) + { + ModuloSchedGraphNode* node =(*this)[(const Instruction*)I]; + memNodeVec.push_back(node); + } + // Instructions in memNodeVec are in execution order within the basic block, + // so simply look at all pairs i]>. + // + for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++) + { + const Instruction* fromInst = memNodeVec[im]->getInst(); + int fromType = CallInst::classof(fromInst)? SG_CALL_REF + : LoadInst::classof(fromInst)? SG_LOAD_REF + : SG_STORE_REF; + for (unsigned jm=im+1; jm < NM; jm++) + { + const Instruction* toInst=memNodeVec[jm]->getInst(); + int toType = CallInst::classof(toInst)? SG_CALL_REF + : LoadInst::classof(toInst)? SG_LOAD_REF + : SG_STORE_REF; + if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF) + { + (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm], + SchedGraphEdge::MemoryDep, + SG_DepOrderArray[fromType][toType], 1); + + SchedGraphEdge* edge=new SchedGraphEdge(memNodeVec[jm],memNodeVec[im], + SchedGraphEdge::MemoryDep, + SG_DepOrderArray[toType][fromType],1); + edge->setIteDiff(1); + + } + } + } +} + + + +void ModuloSchedGraph::buildNodesforBB (const TargetMachine& target, + const BasicBlock* bb, + std::vector& memNode, + RegToRefVecMap& regToRefVecMap, + ValueToDefVecMap& valueToDefVecMap) +{ + //const MachineInstrInfo& mii=target.getInstrInfo(); + + //Build graph nodes for each LLVM instruction and gather def/use info. + //Do both together in a single pass over all machine instructions. + + int i=0; + for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I!=E; I++) + { + ModuloSchedGraphNode* node=new ModuloSchedGraphNode(getNumNodes(), bb,I,i, target); + i++; + this->noteModuloSchedGraphNodeForInst(I,node); + } + + //this function finds some info about instruction in basic block for later use + //findDefUseInfoAtInstr(target, node, memNode,regToRefVecMap,valueToDefVecMap); + + +} + + +bool ModuloSchedGraph::isLoop(const BasicBlock* bb) +{ + //only if the last instruction in the basicblock is branch instruction and + //there is at least an option to branch itself + + + const Instruction* inst=&(bb->back()); + if( BranchInst::classof(inst)) + for(unsigned i=0;i < ((BranchInst*)inst)->getNumSuccessors();i++) + { + BasicBlock* sb=((BranchInst*)inst)->getSuccessor(i); + if(sb ==bb) return true; + } + + return false; + +} +bool ModuloSchedGraph::isLoop() +{ + //only if the last instruction in the basicblock is branch instruction and + //there is at least an option to branch itself + + assert(bbVec.size() ==1 &&"only 1 basicblock in a graph"); + const BasicBlock* bb=bbVec[0]; + const Instruction* inst=&(bb->back()); + if( BranchInst::classof(inst)) + for(unsigned i=0;i < ((BranchInst*)inst)->getNumSuccessors();i++) + { + BasicBlock* sb=((BranchInst*)inst)->getSuccessor(i); + if(sb ==bb) return true; + } + + return false; + +} + +void ModuloSchedGraph::computeNodeASAP(const BasicBlock* bb) +{ + + //FIXME: now assume the only backward edges come from the edges from other nodes to the phi Node + //so i will ignore all edges to the phi node; after this, there shall be no recurrence. + + unsigned numNodes=bb->size(); + for(unsigned i=2;i < numNodes+2;i++) + { + ModuloSchedGraphNode* node=getNode(i); + node->setPropertyComputed(false); + } + + for(unsigned i=2;i < numNodes+2; i++) + { + ModuloSchedGraphNode* node=getNode(i); + node->ASAP=0; + if(i==2 ||node->getNumInEdges() ==0) + { node->setPropertyComputed(true);continue;} + for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges();I !=E; I++) + { + SchedGraphEdge* edge=*I; + ModuloSchedGraphNode* pred=(ModuloSchedGraphNode*)(edge->getSrc()); + assert(pred->getPropertyComputed()&&"pred node property is not computed!"); + int temp=pred->ASAP + edge->getMinDelay() - edge->getIteDiff()*this->MII; + node->ASAP= max(node->ASAP,temp); + } + node->setPropertyComputed(true); + } +} + +void ModuloSchedGraph::computeNodeALAP(const BasicBlock* bb) +{ + + unsigned numNodes=bb->size(); + int maxASAP=0; + for(unsigned i=numNodes+1;i >= 2;i--) + { + ModuloSchedGraphNode* node=getNode(i); + node->setPropertyComputed(false); + //cerr<< " maxASAP= " <ASAP= "<< node->ASAP<<"\n"; + maxASAP=max(maxASAP,node->ASAP); + } + + //cerr<<"maxASAP is "<= 2; i--) + { + ModuloSchedGraphNode* node=getNode(i); + node->ALAP=maxASAP; + for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I!=E; I++) + { + SchedGraphEdge* edge= *I; + ModuloSchedGraphNode* succ=(ModuloSchedGraphNode*) (edge->getSink()); + if(PHINode::classof(succ->getInst()))continue; + assert(succ->getPropertyComputed()&&"succ node property is not computed!"); + int temp=succ->ALAP - edge->getMinDelay()+edge->getIteDiff()*this->MII; + node->ALAP =min(node->ALAP,temp); + } + node->setPropertyComputed(true); + + } +} + +void ModuloSchedGraph::computeNodeMov(const BasicBlock* bb) +{ + unsigned numNodes=bb->size(); + for(unsigned i =2;i < numNodes +2 ;i++) + { + ModuloSchedGraphNode* node=getNode(i); + node->mov=node->ALAP-node->ASAP; + assert(node->mov >=0 &&"move freedom for this node is less than zero? "); + } +} + + +void ModuloSchedGraph::computeNodeDepth(const BasicBlock* bb) +{ + + unsigned numNodes=bb->size(); + for(unsigned i=2;i < numNodes+2;i++) + { + ModuloSchedGraphNode* node=getNode(i); + node->setPropertyComputed(false); + } + + for(unsigned i=2;i < numNodes+2; i++) + { + ModuloSchedGraphNode* node=getNode(i); + node->depth=0; + if(i==2 ||node->getNumInEdges() ==0) + { node->setPropertyComputed(true);continue;} + for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges();I !=E; I++) + { + SchedGraphEdge* edge=*I; + ModuloSchedGraphNode* pred=(ModuloSchedGraphNode*)(edge->getSrc()); + assert(pred->getPropertyComputed()&&"pred node property is not computed!"); + int temp=pred->depth + edge->getMinDelay(); + node->depth= max(node->depth,temp); + } + node->setPropertyComputed(true); + } + +} + + +void ModuloSchedGraph::computeNodeHeight(const BasicBlock* bb) +{ + unsigned numNodes=bb->size(); + for(unsigned i=numNodes+1;i >= 2;i--) + { + ModuloSchedGraphNode* node=getNode(i); + node->setPropertyComputed(false); + } + + for(unsigned i=numNodes+1;i >= 2; i--) + { + ModuloSchedGraphNode* node=getNode(i); + node->height=0; + for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I!=E; I++) + { + SchedGraphEdge* edge= *I; + ModuloSchedGraphNode* succ=(ModuloSchedGraphNode*)(edge->getSink()); + if(PHINode::classof(succ->getInst())) continue; + assert(succ->getPropertyComputed()&&"succ node property is not computed!"); + node->height=max(node->height, succ->height+edge->getMinDelay()); + + } + node->setPropertyComputed(true); + + } + +} + +void ModuloSchedGraph::computeNodeProperty(const BasicBlock* bb) +{ + //FIXME: now assume the only backward edges come from the edges from other nodes to the phi Node + //so i will ignore all edges to the phi node; after this, there shall be no recurrence. + + this->computeNodeASAP(bb); + this->computeNodeALAP(bb); + this->computeNodeMov(bb); + this->computeNodeDepth(bb); + this->computeNodeHeight(bb); +} + + +//do not consider the backedge in these two functions: +// i.e. don't consider the edge with destination in phi node +std::vector ModuloSchedGraph::predSet(std::vector set, unsigned backEdgeSrc, unsigned backEdgeSink) +{ + std::vector predS; + for(unsigned i=0; i < set.size(); i++) + { + ModuloSchedGraphNode* node = set[i]; + for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges(); I !=E; I++) + { + SchedGraphEdge* edge= *I; + if(edge->getSrc()->getNodeId() ==backEdgeSrc && edge->getSink()->getNodeId() == backEdgeSink) continue; + ModuloSchedGraphNode* pred= (ModuloSchedGraphNode*)(edge->getSrc()); + //if pred is not in the predSet, push it in vector + bool alreadyInset=false; + for(unsigned j=0; j < predS.size(); j++) + if(predS[j]->getNodeId() == pred->getNodeId() ) + {alreadyInset=true;break;} + + for(unsigned j=0; j < set.size(); j++) + if(set[j]->getNodeId() == pred->getNodeId() ) + {alreadyInset=true; break;} + + if(! alreadyInset) + predS.push_back(pred); + } + } + return predS; +} + +ModuloSchedGraph::NodeVec ModuloSchedGraph::predSet(NodeVec set) +{ + //node number increases from 2 + return predSet(set,0, 0); +} + + +std::vector ModuloSchedGraph::predSet(ModuloSchedGraphNode* _node, unsigned backEdgeSrc, unsigned backEdgeSink) +{ + + std::vector set; + set.push_back(_node); + return predSet(set, backEdgeSrc, backEdgeSink); + +} + +std::vector ModuloSchedGraph::predSet(ModuloSchedGraphNode* _node) +{ + return predSet(_node,0,0); +} + +std::vector ModuloSchedGraph::succSet(std::vector set,unsigned src, unsigned sink) +{ + vector succS; + for(unsigned i=0; i < set.size(); i++) + { + ModuloSchedGraphNode* node = set[i]; + for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I !=E; I++) + { + SchedGraphEdge* edge= *I; + if(edge->getSrc()->getNodeId() == src && edge->getSink()->getNodeId() == sink) continue; + ModuloSchedGraphNode* succ= (ModuloSchedGraphNode*)(edge->getSink()); + //if pred is not in the predSet, push it in vector + bool alreadyInset=false; + for(unsigned j=0; j < succS.size(); j++) + if(succS[j]->getNodeId() == succ->getNodeId() ) + {alreadyInset=true;break;} + + for(unsigned j=0; j < set.size(); j++) + if(set[j]->getNodeId() == succ->getNodeId() ) + {alreadyInset=true;break;} + if(! alreadyInset) + succS.push_back(succ); + } + } + return succS; +} + +ModuloSchedGraph::NodeVec ModuloSchedGraph::succSet(NodeVec set) +{ + return succSet(set,0,0); +} + + +std::vector ModuloSchedGraph::succSet(ModuloSchedGraphNode* _node,unsigned src, unsigned sink) +{ + std::vector set; + set.push_back(_node); + return succSet(set, src, sink); + + +} + +std::vector ModuloSchedGraph::succSet(ModuloSchedGraphNode* _node) +{ + return succSet(_node, 0, 0); +} + +SchedGraphEdge* ModuloSchedGraph::getMaxDelayEdge(unsigned srcId, unsigned sinkId) +{ + + ModuloSchedGraphNode* node =getNode(srcId); + SchedGraphEdge* maxDelayEdge=NULL; + int maxDelay=-1; + for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges();I !=E; I++) + { + SchedGraphEdge* edge= *I; + if(edge->getSink()->getNodeId() == sinkId) + if(edge->getMinDelay() > maxDelay){ + maxDelayEdge=edge; + maxDelay=edge->getMinDelay(); + } + } + assert(maxDelayEdge != NULL&&"no edge between the srcId and sinkId?"); + return maxDelayEdge; +} + +void ModuloSchedGraph::dumpCircuits() +{ + modSched_os<<"dumping circuits for graph: "<<"\n"; + int j=-1; + while(circuits[++j][0] !=0){ + int k=-1; + while(circuits[j][++k] !=0) + modSched_os<< circuits[j][k]<<"\t"; + modSched_os<<"\n"; + } +} + +void ModuloSchedGraph::dumpSet(std::vector set) +{ + for(unsigned i=0;i < set.size() ; i++) + modSched_os<< set[i]->getNodeId()<<"\t"; + modSched_os<<"\n"; +} + +std::vector ModuloSchedGraph::vectorUnion(std::vector set1,std::vector set2 ) +{ + std::vector unionVec; + for(unsigned i=0;i ModuloSchedGraph::vectorConj(std::vector set1,std::vector set2 ) +{ + std::vector conjVec; + for(unsigned i=0;igetNodeId() ==(*II)->getNodeId()) + {inset=true;break;} + if(!inset) newVec.push_back(*I); + } + return newVec; +} + +void ModuloSchedGraph::orderNodes(){ + oNodes.clear(); + + std::vector set; + const BasicBlock* bb=bbVec[0]; + unsigned numNodes = bb->size(); + + //first order all the sets + int j=-1; + int totalDelay=-1; + int preDelay=-1; + while(circuits[++j][0] !=0){ + int k=-1; + preDelay=totalDelay; + + while(circuits[j][++k] !=0){ + ModuloSchedGraphNode* node =getNode(circuits[j][k]); + unsigned nextNodeId; + nextNodeId =circuits[j][k+1] !=0? circuits[j][k+1]:circuits[j][0]; + SchedGraphEdge* edge = getMaxDelayEdge(circuits[j][k], nextNodeId); + totalDelay += edge->getMinDelay(); + } + if(preDelay != -1 && totalDelay > preDelay){ + //swap circuits[j][] and cuicuits[j-1][] + unsigned temp[MAXNODE]; + for(int k=0;k= ModuloSched_PrintScheduleProcess) + modSched_os<<"building the first set"<<"\n"; + int setSeq=-1; + int k=-1; + setSeq++; + while(circuits[setSeq][++k]!=0) + set.push_back(getNode(circuits[setSeq][k])); + if(circuits[setSeq][0]!=0){ + backEdgeSrc=circuits[setSeq][k-1]; + backEdgeSink=circuits[setSeq][0]; + } + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ + modSched_os<<"the first set is:"; + dumpSet(set); + } + + //implement the ordering algorithm + enum OrderSeq{ bottom_up, top_down}; + OrderSeq order; + std::vector R; + while(!set.empty()) + { + std::vector pset=predSet(oNodes); + std::vector sset=succSet(oNodes); + + if(!pset.empty() && !vectorConj(pset,set).empty()) + {R=vectorConj(pset,set);order=bottom_up;} + else if( !sset.empty() && !vectorConj(sset,set).empty()) + {R=vectorConj(sset,set);order=top_down;} + else + { + int maxASAP=-1; + int position=-1; + for(unsigned i=0;igetASAP(); + if(temp>maxASAP ) { + maxASAP=temp; + position=i; + } + } + R.push_back(set[position]); + order=bottom_up; + } + + while(!R.empty()){ + if(order== top_down){ + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os<<"in top_down round"<<"\n"; + while(!R.empty()){ + int maxHeight=-1; + NodeVec::iterator chosenI; + for(NodeVec::iterator I=R.begin();I != R.end();I++){ + int temp=(*I)->height; + if( (temp > maxHeight) || ( temp == maxHeight && (*I)->mov <= (*chosenI)->mov ) ){ + + if((temp > maxHeight) || ( temp == maxHeight && (*I)->mov < (*chosenI)->mov )){ + maxHeight=temp; + chosenI=I; + continue; + } + //possible case: instruction A and B has the same height and mov, but A has dependence to B + //e.g B is the branch instruction in the end, or A is the phi instruction at the beginning + if((*I)->mov == (*chosenI)->mov) + for(ModuloSchedGraphNode::const_iterator oe=(*I)->beginOutEdges(), end=(*I)->endOutEdges();oe !=end; oe++){ + if((*oe)->getSink() == (*chosenI)){ + maxHeight=temp; + chosenI=I; + continue; + } + } + } + } + ModuloSchedGraphNode* mu= *chosenI; + oNodes.push_back(mu); + R.erase(chosenI); + std::vector succ_mu= succSet(mu,backEdgeSrc,backEdgeSink); + std::vector comm=vectorConj(succ_mu,set); + comm=vectorSub(comm,oNodes); + R = vectorUnion(comm, R); + } + order=bottom_up; + R= vectorConj(predSet(oNodes), set); + } else{ + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os<<"in bottom up round"<<"\n"; + while(!R.empty()){ + int maxDepth=-1; + NodeVec::iterator chosenI; + for(NodeVec::iterator I=R.begin();I != R.end();I++){ + int temp=(*I)->depth; + if( (temp > maxDepth) || ( temp == maxDepth && (*I)->mov < (*chosenI)->mov )){ + maxDepth=temp; + chosenI=I; + } + } + ModuloSchedGraphNode* mu=*chosenI; + oNodes.push_back(mu); + R.erase(chosenI); + std::vector pred_mu= predSet(mu,backEdgeSrc,backEdgeSink); + std::vector comm=vectorConj(pred_mu,set); + comm=vectorSub(comm,oNodes); + R = vectorUnion(comm, R); + } + order=top_down; + R= vectorConj(succSet(oNodes), set); + } + } + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ + modSched_os<<"order finished"<<"\n"; + modSched_os<<"dumping the ordered nodes: "<<"\n"; + dumpSet(oNodes); + dumpCircuits(); + } + //create a new set + //FIXME: the nodes between onodes and this circuit should also be include in this set + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os<<"building the next set"<<"\n"; + set.clear(); + int k=-1; + setSeq++; + while(circuits[setSeq][++k]!=0) + set.push_back(getNode(circuits[setSeq][k])); + if(circuits[setSeq][0]!=0){ + backEdgeSrc=circuits[setSeq][k-1]; + backEdgeSink=circuits[setSeq][0]; + } + if(set.empty()){ + //no circuits any more + //collect all other nodes + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os<<"no circuits any more, collect the rest nodes"<<"\n"; + for(unsigned i=2;igetNodeId() == i) + {inset=true;break;} + if(!inset)set.push_back(getNode(i)); + } + } + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ + modSched_os<<"next set is: "<<"\n"; + dumpSet(set); + } + }//while(!set.empty()) + +} + + + + + + +void ModuloSchedGraph::buildGraph (const TargetMachine& target) +{ + const BasicBlock* bb=bbVec[0]; + + assert(bbVec.size() ==1 &&"only handling a single basic block here"); + + // Use this data structure to note all machine operands that compute + // ordinary LLVM values. These must be computed defs (i.e., instructions). + // Note that there may be multiple machine instructions that define + // each Value. + ValueToDefVecMap valueToDefVecMap; + + // Use this data structure to note all memory instructions. + // We use this to add memory dependence edges without a second full walk. + // + // vector memVec; + vector memNodeVec; + + // Use this data structure to note any uses or definitions of + // machine registers so we can add edges for those later without + // extra passes over the nodes. + // The vector holds an ordered list of references to the machine reg, + // ordered according to control-flow order. This only works for a + // single basic block, hence the assertion. Each reference is identified + // by the pair: . + // + RegToRefVecMap regToRefVecMap; + + + + // Make a dummy root node. We'll add edges to the real roots later. + graphRoot = new ModuloSchedGraphNode(0, NULL, NULL, -1,target); + graphLeaf = new ModuloSchedGraphNode(1, NULL, NULL, -1,target); + + //---------------------------------------------------------------- + // First add nodes for all the LLVM instructions in the basic block + // because this greatly simplifies identifying which edges to add. + // Do this one VM instruction at a time since the ModuloSchedGraphNode needs that. + // Also, remember the load/store instructions to add memory deps later. + //---------------------------------------------------------------- + + //FIXME:if there is call instruction, then we shall quit somewhere + // currently we leave call instruction and continue construct graph + + //dump only the blocks which are from loops + + + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + this->dump(bb); + + if(!isLoop(bb)){ + modSched_os <<" dumping non-loop BB:"<addDefUseEdges(bb); + + this->addCDEdges(bb); + + this->addMemEdges(bb); + + //this->dump(); + + int ResII=this->computeResII(bb); + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "ResII is " << ResII<<"\n";; + int RecII=this->computeRecII(bb); + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "RecII is " <MII=max(ResII, RecII); + + this->computeNodeProperty(bb); + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + this->dumpNodeProperty(); + + this->orderNodes(); + + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + this->dump(); + //this->instrScheduling(); + + //this->dumpScheduling(); + + + } +} + +ModuloSchedGraphNode* ModuloSchedGraph::getNode (const unsigned nodeId) const +{ + for(const_iterator I=begin(), E=end();I !=E;I++) + if((*I).second->getNodeId() ==nodeId) + return (ModuloSchedGraphNode*)(*I).second; + return NULL; +} + +int ModuloSchedGraph::computeRecII(const BasicBlock* bb) +{ + + int RecII=0; + + //os<<"begining computerRecII()"<<"\n"; + + + //FIXME: only deal with circuits starting at the first node: the phi node nodeId=2; + + //search all elementary circuits in the dependance graph + //assume maximum number of nodes is MAXNODE + + unsigned path[MAXNODE]; + unsigned stack[MAXNODE][MAXNODE]; + + + for(int j=0;jsize(); + + int i=0; + path[i]=2; + + ModuloSchedGraphNode* initNode=getNode(path[0]); + unsigned initNodeId=initNode->getNodeId(); + ModuloSchedGraphNode* currentNode=initNode; + + while(currentNode != NULL) + { + unsigned currentNodeId=currentNode->getNodeId(); + // modSched_os<<"current node is "<beginOutEdges(), E=currentNode->endOutEdges(); I !=E; I++) + { + //modSched_os <<" searching in outgoint edges of node "<getSink()->getNodeId(); + bool inpath=false,instack=false; + int k; + + //modSched_os<<"nodeId is "< currentNodeId && !inpath && !instack) + {nextNode=(ModuloSchedGraphNode*) ((SchedGraphEdge*)*I)->getSink();break;} + + } + if(nextNode != NULL) + { + //modSched_os<<"find the next Node "<getNodeId()<<"\n"; + + + int j=0; + while( stack[i][j] !=0) j++; + stack[i][j]=nextNode->getNodeId(); + + + i++; + path[i]=nextNode->getNodeId(); + currentNode=nextNode; + } + else + { + //modSched_os<<"no expansion any more"<<"\n"; + //confirmCircuit(); + for(ModuloSchedGraphNode::const_iterator I=currentNode->beginOutEdges(), E=currentNode->endOutEdges() ; I != E; I++) + { + unsigned nodeId=((SchedGraphEdge*)*I)->getSink()->getNodeId(); + if(nodeId == initNodeId) + { + + int j=-1; + while(circuits[++j][0] !=0); + for(int k=0;k= ModuloSched_PrintScheduleProcess) + modSched_os<<"circuits found are: "<<"\n"; + int j=-1; + while(circuits[++j][0] !=0){ + int k=-1; + while(circuits[j][++k] !=0) + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os<< circuits[j][k]<<"\t"; + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os<<"\n"; + + + //for this circuit, compute the sum of all edge delay + int sumDelay=0; + k=-1; + while(circuits[j][++k] !=0) + { + //ModuloSchedGraphNode* node =getNode(circuits[j][k]); + unsigned nextNodeId; + nextNodeId =circuits[j][k+1] !=0? circuits[j][k+1]:circuits[j][0]; + + /* + for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges();I !=E; I++) + { + SchedGraphEdge* edge= *I; + if(edge->getSink()->getNodeId() == nextNodeId) + {sumDelay += edge->getMinDelay();break;} + } + */ + + sumDelay += getMaxDelayEdge(circuits[j][k],nextNodeId)->getMinDelay(); + + } + // assume we have distance 1, in this case the sumDelay is RecII + // this is correct for SSA form only + // + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os<<"The total Delay in the circuit is " < sumDelay? RecII: sumDelay; + + } + return RecII; + } + + } + + return -1; +} + +void ModuloSchedGraph::addResourceUsage(std::vector >& ruVec, int rid){ + //modSched_os<<"\nadding a resouce , current resouceUsage vector size is "< > &ru) +{ + MachineSchedInfo& msi = (MachineSchedInfo&)target.getSchedInfo(); + + std::vector > resourceNumVector = msi.resourceNumVector; + modSched_os <<"resourceID\t"<<"resourceNum"<<"\n"; + for(unsigned i=0;i > resourceUsage; //pair + + //FIXME: number of functional units the target machine can provide should be get from Target + // here I temporary hardcode it + + for(BasicBlock::const_iterator I=bb->begin(),E=bb->end(); I !=E; I++) + { + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ + modSched_os<<"machine instruction for llvm instruction( node "<getNodeId()<<")" <<"\n"; + modSched_os<<"\t"<<*I; + } + MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(I); + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os <<"size =" <getOpCode()); + InstrRUsage rUsage=msi.getInstrRUsage(minstr->getOpCode()); + InstrClassRUsage classRUsage=msi.getClassRUsage(mii.getSchedClass(minstr->getOpCode())); + unsigned totCycles= classRUsage.totCycles; + + std::vector > resources + =rUsage.resourcesByCycle; + assert(totCycles == resources.size()); + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os <<"resources Usage for this Instr(totCycles=" << totCycles << ",mindLatency="<getOpCode())<<"): "<< *minstr <<"\n"; + for(unsigned j=0;j< resources.size();j++){ + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os<<"cycle "<= ModuloSched_PrintScheduleProcess) + modSched_os<<"\t"<= ModuloSched_PrintScheduleProcess) + modSched_os<<"\n"; + } + } + } + if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + this->dumpResourceUsage(resourceUsage); + + //compute ResII + ResII=0; + int issueSlots=msi.maxNumIssueTotal; + for(unsigned i=0;igetName() + << "' =========\n\n"; + for(const_iterator I=begin(); I != end(); ++I) + (*I)->dump(); + + modSched_os << "\n=========End graphs for funtion` "<getName() + << "' ==========\n\n"; +} + +void ModuloSchedGraph::dump(const BasicBlock* bb) +{ + modSched_os<<"dumping basic block:"; + modSched_os<<(bb->hasName()?bb->getName(): "block") + <<" (" << bb << ")"<<"\n"; + +} + +void ModuloSchedGraph::dump(const BasicBlock* bb, std::ostream& os) +{ + os<<"dumping basic block:"; + os<<(bb->hasName()?bb->getName(): "block") + <<" (" << bb << ")"<<"\n"; +} + +void +ModuloSchedGraph::dump() const +{ + modSched_os << " ModuloSchedGraph for basic Blocks:"; + for(unsigned i=0, N =bbVec.size(); i< N; i++) + { + modSched_os<<(bbVec[i]->hasName()?bbVec[i]->getName(): "block") + <<" (" << bbVec[i] << ")" + << ((i==N-1)?"":", "); + } + + modSched_os <<"\n\n Actual Root nodes : "; + for (unsigned i=0, N=graphRoot->outEdges.size(); i < N; i++) + modSched_os << graphRoot->outEdges[i]->getSink()->getNodeId() + << ((i == N-1)? "" : ", "); + + modSched_os << "\n Graph Nodes:\n"; + //for (const_iterator I=begin(); I != end(); ++I) + //modSched_os << "\n" << *I->second; + unsigned numNodes=bbVec[0]->size(); + for(unsigned i=2;i< numNodes+2;i++) + { + ModuloSchedGraphNode* node= getNode(i); + modSched_os << "\n" << *node; + } + + modSched_os << "\n"; +} +void +ModuloSchedGraph::dumpNodeProperty() const +{ + const BasicBlock* bb=bbVec[0]; + unsigned numNodes=bb->size(); + for(unsigned i=2;i < numNodes+2;i++) + { + ModuloSchedGraphNode* node=getNode(i); + modSched_os<<"NodeId "<getNodeId()<<"\t"; + modSched_os<<"ASAP "<getASAP()<<"\t"; + modSched_os<<"ALAP "<getALAP()<<"\t"; + modSched_os<<"mov " <getMov() <<"\t"; + modSched_os<<"depth "<getDepth()<<"\t"; + modSched_os<<"height "<getHeight()<<"\t"; + modSched_os<<"\n"; + } +} + +void ModuloSchedGraphSet::buildGraphsForMethod (const Function *F, const TargetMachine& target) +{ + for(Function::const_iterator BI = F->begin(); BI != F->end(); ++BI) + addGraph(new ModuloSchedGraph(BI,target)); +} + +std::ostream &operator<<(std::ostream &os, const ModuloSchedGraphNode& node) +{ + os << std::string(8, ' ') + << "Node " << node.nodeId << " : " + << "latency = " << node.latency << "\n" << std::string(12, ' '); + + + + if (node.getInst() == NULL) + os << "(Dummy node)\n"; + else + { + os << *node.getInst() << "\n" << std::string(12, ' '); + os << node.inEdges.size() << " Incoming Edges:\n"; + for (unsigned i=0, N=node.inEdges.size(); i < N; i++) + os << std::string(16, ' ') << *node.inEdges[i]; + + os << std::string(12, ' ') << node.outEdges.size() + << " Outgoing Edges:\n"; + for (unsigned i=0, N=node.outEdges.size(); i < N; i++) + os << std::string(16, ' ') << *node.outEdges[i]; + } + + + return os; +} -- cgit v1.2.3-18-g5258