1 //===- ModuloSchedGraph.cpp - Graph datastructure for Modulo Scheduling ---===//
4 //===----------------------------------------------------------------------===//
6 #include "llvm/CodeGen/InstrSelection.h"
7 #include "llvm/Function.h"
8 #include "llvm/Instructions.h"
10 #include "llvm/CodeGen/MachineCodeForInstruction.h"
11 #include "llvm/CodeGen/MachineInstr.h"
12 #include "llvm/Target/TargetSchedInfo.h"
13 #include "Support/StringExtras.h"
14 #include "Support/STLExtras.h"
15 #include "Support/hash_map"
16 #include "Support/Statistic.h"
17 #include "ModuloScheduling.h"
18 #include "ModuloSchedGraph.h"
32 /***********member functions for ModuloSchedGraphNode*********/
35 ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned int in_nodeId,
36 const BasicBlock * in_bb,
37 const Instruction * in_inst,
39 const TargetMachine & target)
40 :SchedGraphNodeCommon(in_nodeId, indexInBB), inst(in_inst){
43 //FIXME: find the latency
44 //currently set the latency to zero
50 /***********member functions for ModuloSchedGraph*********/
53 ModuloSchedGraph::addDefUseEdges(const BasicBlock *bb){
55 //collect def instructions, store them in vector
56 const TargetInstrInfo & mii = target.getInstrInfo();
57 vector < ModuloSchedGraphNode * > defVec;
60 //find those def instructions
61 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; ++I) {
62 if (I->getType() != Type::VoidTy) {
63 defVec.push_back(this->getGraphNodeForInst(I));
67 for (unsigned int i = 0; i < defVec.size(); i++) {
68 for (Value::use_const_iterator I = defVec[i]->getInst()->use_begin();
69 I != defVec[i]->getInst()->use_end(); I++) {
70 //for each use of a def, add a flow edge from the def instruction to the
73 const Instruction *value = defVec[i]->getInst();
74 Instruction *inst = (Instruction *) (*I);
75 ModuloSchedGraphNode *node = NULL;
77 for (BasicBlock::const_iterator ins = bb->begin(), E = bb->end();
79 if ((const Instruction *) ins == inst) {
87 //inst is not an instruction in this block
91 // Add a flow edge from the def instruction to the ref instruction
92 // This is a true dependence, so the delay is equal to the
93 //delay of the preceding node.
97 // self loop will not happen in SSA form
98 assert(defVec[i] != node && "same node?");
100 MachineCodeForInstruction & tempMvec =
101 MachineCodeForInstruction::get(value);
102 for (unsigned j = 0; j < tempMvec.size(); j++) {
103 MachineInstr *temp = tempMvec[j];
104 delay = std::max(delay, mii.minLatency(temp->getOpCode()));
107 SchedGraphEdge *trueEdge =
108 new SchedGraphEdge(defVec[i], node, value,
109 SchedGraphEdge::TrueDep, delay);
111 // if the ref instruction is before the def instrution
112 // then the def instruction must be a phi instruction
113 // add an anti-dependence edge to from the ref instruction to the def
115 if (node->getOrigIndexInBB() < defVec[i]->getOrigIndexInBB()) {
116 assert(PHINode::classof(inst)
117 && "the ref instruction befre def is not PHINode?");
118 trueEdge->setIteDiff(1);
128 ModuloSchedGraph::addCDEdges(const BasicBlock * bb) {
130 // find the last instruction in the basic block
131 // see if it is an branch instruction.
132 // If yes, then add an edge from each node expcept the last node
135 const Instruction *inst = &(bb->back());
136 ModuloSchedGraphNode *lastNode = (*this)[inst];
137 if (TerminatorInst::classof(inst))
138 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E;
141 ModuloSchedGraphNode *node = (*this)[I];
143 (void) new SchedGraphEdge(node, lastNode, SchedGraphEdge::CtrlDep,
144 SchedGraphEdge::NonDataDep, 0);
150 static const int SG_LOAD_REF = 0;
151 static const int SG_STORE_REF = 1;
152 static const int SG_CALL_REF = 2;
154 static const unsigned int SG_DepOrderArray[][3] = {
155 {SchedGraphEdge::NonDataDep,
156 SchedGraphEdge::AntiDep,
157 SchedGraphEdge::AntiDep},
158 {SchedGraphEdge::TrueDep,
159 SchedGraphEdge::OutputDep,
160 SchedGraphEdge::TrueDep | SchedGraphEdge::OutputDep},
161 {SchedGraphEdge::TrueDep,
162 SchedGraphEdge::AntiDep | SchedGraphEdge::OutputDep,
163 SchedGraphEdge::TrueDep | SchedGraphEdge::AntiDep
164 | SchedGraphEdge::OutputDep}
168 // Add a dependence edge between every pair of machine load/store/call
169 // instructions, where at least one is a store or a call.
170 // Use latency 1 just to ensure that memory operations are ordered;
171 // latency does not otherwise matter (true dependences enforce that).
174 ModuloSchedGraph::addMemEdges(const BasicBlock * bb) {
176 vector<ModuloSchedGraphNode*> memNodeVec;
178 //construct the memNodeVec
179 for (BasicBlock::const_iterator I = bb->begin(),
180 E = bb->end(); I != E; ++I) {
182 if (LoadInst::classof(I) || StoreInst::classof(I)
183 || CallInst::classof(I)) {
185 ModuloSchedGraphNode *node = (*this)[(const Instruction *) I];
186 memNodeVec.push_back(node);
191 // Instructions in memNodeVec are in execution order within the
192 // basic block, so simply look at all pairs
193 // <memNodeVec[i], memNodeVec[j: j > i]>.
195 for (unsigned im = 0, NM = memNodeVec.size(); im < NM; im++) {
197 const Instruction *fromInst,*toInst;
198 int toType, fromType;
200 //get the first mem instruction and instruction type
201 fromInst = memNodeVec[im]->getInst();
202 fromType = CallInst::classof(fromInst) ? SG_CALL_REF
203 : LoadInst::classof(fromInst) ? SG_LOAD_REF : SG_STORE_REF;
205 for (unsigned jm = im + 1; jm < NM; jm++) {
207 //get the second mem instruction and instruction type
208 toInst = memNodeVec[jm]->getInst();
209 toType = CallInst::classof(toInst) ? SG_CALL_REF
210 : LoadInst::classof(toInst) ? SG_LOAD_REF : SG_STORE_REF;
212 //add two edges if not both of them are LOAD instructions
213 if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF) {
214 (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm],
215 SchedGraphEdge::MemoryDep,
216 SG_DepOrderArray[fromType][toType], 1);
218 SchedGraphEdge *edge =
219 new SchedGraphEdge(memNodeVec[jm], memNodeVec[im],
220 SchedGraphEdge::MemoryDep,
221 SG_DepOrderArray[toType][fromType], 1);
223 //set the iteration difference for this edge to 1.
232 this function build graph nodes for each instruction
237 ModuloSchedGraph::buildNodesforBB(const TargetMachine &target,
238 const BasicBlock *bb){
241 ModuloSchedGraphNode *node;
243 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end();
246 node=new ModuloSchedGraphNode(getNumNodes(), bb, I, i, target);
250 this->addHash(I, node);
257 determine if this basicblock includes a loop or not
261 ModuloSchedGraph::isLoop(const BasicBlock *bb) {
263 //only if the last instruction in the basicblock is branch instruction and
264 //there is at least an option to branch itself
266 const Instruction *inst = &(bb->back());
268 if (BranchInst::classof(inst)) {
269 for (unsigned i = 0; i < ((BranchInst *) inst)->getNumSuccessors();
271 BasicBlock *sb = ((BranchInst *) inst)->getSuccessor(i);
282 compute every node's ASAP
286 //FIXME: now assume the only backward edges come from the edges from other
287 //nodes to the phi Node so i will ignore all edges to the phi node; after
288 //this, there shall be no recurrence.
291 ModuloSchedGraph::computeNodeASAP(const BasicBlock *bb) {
294 unsigned numNodes = bb->size();
295 for (unsigned i = 2; i < numNodes + 2; i++) {
296 ModuloSchedGraphNode *node = getNode(i);
297 node->setPropertyComputed(false);
300 for (unsigned i = 2; i < numNodes + 2; i++) {
301 ModuloSchedGraphNode *node = getNode(i);
303 if (i == 2 || node->getNumInEdges() == 0) {
304 node->setPropertyComputed(true);
307 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
308 node->endInEdges(); I != E; I++) {
309 SchedGraphEdge *edge = *I;
310 ModuloSchedGraphNode *pred =
311 (ModuloSchedGraphNode *) (edge->getSrc());
312 assert(pred->getPropertyComputed()
313 && "pred node property is not computed!");
315 pred->ASAP + edge->getMinDelay() -
316 edge->getIteDiff() * this->MII;
317 node->ASAP = std::max(node->ASAP, temp);
319 node->setPropertyComputed(true);
325 compute every node's ALAP in the basic block
329 ModuloSchedGraph::computeNodeALAP(const BasicBlock *bb) {
331 unsigned numNodes = bb->size();
333 for (unsigned i = numNodes + 1; i >= 2; i--) {
335 ModuloSchedGraphNode *node = getNode(i);
336 node->setPropertyComputed(false);
337 maxASAP = std::max(maxASAP, node->ASAP);
341 for (unsigned i = numNodes + 1; i >= 2; i--) {
342 ModuloSchedGraphNode *node = getNode(i);
344 node->ALAP = maxASAP;
346 for (ModuloSchedGraphNode::const_iterator I =
347 node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) {
349 SchedGraphEdge *edge = *I;
350 ModuloSchedGraphNode *succ =
351 (ModuloSchedGraphNode *) (edge->getSink());
352 if (PHINode::classof(succ->getInst()))
355 assert(succ->getPropertyComputed()
356 && "succ node property is not computed!");
359 succ->ALAP - edge->getMinDelay() +
360 edge->getIteDiff() * this->MII;
362 node->ALAP = std::min(node->ALAP, temp);
365 node->setPropertyComputed(true);
370 compute every node's mov in this basicblock
374 ModuloSchedGraph::computeNodeMov(const BasicBlock *bb){
376 unsigned numNodes = bb->size();
377 for (unsigned i = 2; i < numNodes + 2; i++) {
379 ModuloSchedGraphNode *node = getNode(i);
380 node->mov = node->ALAP - node->ASAP;
381 assert(node->mov >= 0
382 && "move freedom for this node is less than zero? ");
390 compute every node's depth in this basicblock
393 ModuloSchedGraph::computeNodeDepth(const BasicBlock * bb){
395 unsigned numNodes = bb->size();
397 for (unsigned i = 2; i < numNodes + 2; i++) {
399 ModuloSchedGraphNode *node = getNode(i);
400 node->setPropertyComputed(false);
404 for (unsigned i = 2; i < numNodes + 2; i++) {
406 ModuloSchedGraphNode *node = getNode(i);
408 if (i == 2 || node->getNumInEdges() == 0) {
409 node->setPropertyComputed(true);
413 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
414 node->endInEdges(); I != E; I++) {
415 SchedGraphEdge *edge = *I;
416 ModuloSchedGraphNode *pred =
417 (ModuloSchedGraphNode *) (edge->getSrc());
418 assert(pred->getPropertyComputed()
419 && "pred node property is not computed!");
420 int temp = pred->depth + edge->getMinDelay();
421 node->depth = std::max(node->depth, temp);
423 node->setPropertyComputed(true);
431 compute every node's height in this basic block
435 ModuloSchedGraph::computeNodeHeight(const BasicBlock *bb){
437 unsigned numNodes = bb->size();
438 for (unsigned i = numNodes + 1; i >= 2; i--) {
439 ModuloSchedGraphNode *node = getNode(i);
440 node->setPropertyComputed(false);
443 for (unsigned i = numNodes + 1; i >= 2; i--) {
444 ModuloSchedGraphNode *node = getNode(i);
446 for (ModuloSchedGraphNode::const_iterator I =
447 node->beginOutEdges(), E = node->endOutEdges(); I != E; ++I) {
448 SchedGraphEdge *edge = *I;
449 ModuloSchedGraphNode *succ =
450 (ModuloSchedGraphNode *) (edge->getSink());
451 if (PHINode::classof(succ->getInst()))
453 assert(succ->getPropertyComputed()
454 && "succ node property is not computed!");
455 node->height = std::max(node->height, succ->height + edge->getMinDelay());
458 node->setPropertyComputed(true);
464 compute every node's property in a basicblock
467 void ModuloSchedGraph::computeNodeProperty(const BasicBlock * bb)
469 //FIXME: now assume the only backward edges come from the edges from other
470 //nodes to the phi Node so i will ignore all edges to the phi node; after
471 //this, there shall be no recurrence.
473 this->computeNodeASAP(bb);
474 this->computeNodeALAP(bb);
475 this->computeNodeMov(bb);
476 this->computeNodeDepth(bb);
477 this->computeNodeHeight(bb);
482 compute the preset of this set without considering the edges
483 between backEdgeSrc and backEdgeSink
485 std::vector<ModuloSchedGraphNode*>
486 ModuloSchedGraph::predSet(std::vector<ModuloSchedGraphNode*> set,
487 unsigned backEdgeSrc,
491 std::vector<ModuloSchedGraphNode*> predS;
493 for (unsigned i = 0; i < set.size(); i++) {
495 ModuloSchedGraphNode *node = set[i];
496 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
497 node->endInEdges(); I != E; I++) {
498 SchedGraphEdge *edge = *I;
500 //if edges between backEdgeSrc and backEdgeSink, omitted
501 if (edge->getSrc()->getNodeId() == backEdgeSrc
502 && edge->getSink()->getNodeId() == backEdgeSink)
504 ModuloSchedGraphNode *pred =
505 (ModuloSchedGraphNode *) (edge->getSrc());
507 //if pred is not in the predSet ....
508 bool alreadyInset = false;
509 for (unsigned j = 0; j < predS.size(); ++j)
510 if (predS[j]->getNodeId() == pred->getNodeId()) {
515 // and pred is not in the set ....
516 for (unsigned j = 0; j < set.size(); ++j)
517 if (set[j]->getNodeId() == pred->getNodeId()) {
522 //push it into the predS
524 predS.push_back(pred);
532 return pred set to this set
535 ModuloSchedGraph::NodeVec
536 ModuloSchedGraph::predSet(NodeVec set){
538 //node number increases from 2,
539 return predSet(set, 0, 0);
543 return pred set to _node, ignoring
544 any edge between backEdgeSrc and backEdgeSink
546 std::vector <ModuloSchedGraphNode*>
547 ModuloSchedGraph::predSet(ModuloSchedGraphNode *_node,
548 unsigned backEdgeSrc, unsigned backEdgeSink){
550 std::vector<ModuloSchedGraphNode*> set;
551 set.push_back(_node);
552 return predSet(set, backEdgeSrc, backEdgeSink);
557 return pred set to _node, ignoring
560 std::vector <ModuloSchedGraphNode*>
561 ModuloSchedGraph::predSet(ModuloSchedGraphNode * _node){
563 return predSet(_node, 0, 0);
568 return successor set to the input set
569 ignoring any edge between src and sink
572 std::vector<ModuloSchedGraphNode*>
573 ModuloSchedGraph::succSet(std::vector<ModuloSchedGraphNode*> set,
574 unsigned src, unsigned sink){
576 std::vector<ModuloSchedGraphNode*> succS;
578 for (unsigned i = 0; i < set.size(); i++) {
579 ModuloSchedGraphNode *node = set[i];
580 for (ModuloSchedGraphNode::const_iterator I =
581 node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) {
582 SchedGraphEdge *edge = *I;
584 //if the edge is between src and sink, skip
585 if (edge->getSrc()->getNodeId() == src
586 && edge->getSink()->getNodeId() == sink)
588 ModuloSchedGraphNode *succ =
589 (ModuloSchedGraphNode *) (edge->getSink());
591 //if pred is not in the successor set ....
592 bool alreadyInset = false;
593 for (unsigned j = 0; j < succS.size(); j++)
594 if (succS[j]->getNodeId() == succ->getNodeId()) {
599 //and not in this set ....
600 for (unsigned j = 0; j < set.size(); j++)
601 if (set[j]->getNodeId() == succ->getNodeId()) {
606 //push it into the successor set
608 succS.push_back(succ);
615 return successor set to the input set
618 ModuloSchedGraph::NodeVec ModuloSchedGraph::succSet(NodeVec set){
620 return succSet(set, 0, 0);
625 return successor set to the input node
626 ignoring any edge between src and sink
629 std::vector<ModuloSchedGraphNode*>
630 ModuloSchedGraph::succSet(ModuloSchedGraphNode *_node,
631 unsigned src, unsigned sink){
633 std::vector<ModuloSchedGraphNode*>set;
635 set.push_back(_node);
637 return succSet(set, src, sink);
642 return successor set to the input node
645 std::vector<ModuloSchedGraphNode*>
646 ModuloSchedGraph::succSet(ModuloSchedGraphNode * _node){
648 return succSet(_node, 0, 0);
654 find maximum delay between srcId and sinkId
658 ModuloSchedGraph::getMaxDelayEdge(unsigned srcId,
661 ModuloSchedGraphNode *node = getNode(srcId);
662 SchedGraphEdge *maxDelayEdge = NULL;
664 for (ModuloSchedGraphNode::const_iterator I = node->beginOutEdges(), E =
665 node->endOutEdges(); I != E; I++) {
666 SchedGraphEdge *edge = *I;
667 if (edge->getSink()->getNodeId() == sinkId)
668 if (edge->getMinDelay() > maxDelay) {
670 maxDelay = edge->getMinDelay();
673 assert(maxDelayEdge != NULL && "no edge between the srcId and sinkId?");
679 dump all circuits found
683 ModuloSchedGraph::dumpCircuits(){
685 DEBUG_PRINT(std::cerr << "dumping circuits for graph:\n");
687 while (circuits[++j][0] != 0) {
689 while (circuits[j][++k] != 0)
690 DEBUG_PRINT(std::cerr << circuits[j][k] << "\t");
691 DEBUG_PRINT(std::cerr << "\n");
700 ModuloSchedGraph::dumpSet(std::vector < ModuloSchedGraphNode * >set){
702 for (unsigned i = 0; i < set.size(); i++)
703 DEBUG_PRINT(std::cerr << set[i]->getNodeId() << "\t");
704 DEBUG_PRINT(std::cerr << "\n");
709 return union of set1 and set2
712 std::vector<ModuloSchedGraphNode*>
713 ModuloSchedGraph::vectorUnion(std::vector<ModuloSchedGraphNode*> set1,
714 std::vector<ModuloSchedGraphNode*> set2){
716 std::vector<ModuloSchedGraphNode*> unionVec;
717 for (unsigned i = 0; i < set1.size(); i++)
718 unionVec.push_back(set1[i]);
719 for (unsigned j = 0; j < set2.size(); j++) {
721 for (unsigned i = 0; i < unionVec.size(); i++)
722 if (set2[j] == unionVec[i])
725 unionVec.push_back(set2[j]);
731 return conjuction of set1 and set2
733 std::vector<ModuloSchedGraphNode*>
734 ModuloSchedGraph::vectorConj(std::vector<ModuloSchedGraphNode*> set1,
735 std::vector<ModuloSchedGraphNode*> set2){
737 std::vector<ModuloSchedGraphNode*> conjVec;
738 for (unsigned i = 0; i < set1.size(); i++)
739 for (unsigned j = 0; j < set2.size(); j++)
740 if (set1[i] == set2[j])
741 conjVec.push_back(set1[i]);
747 return the result of subtracting set2 from set1
750 ModuloSchedGraph::NodeVec
751 ModuloSchedGraph::vectorSub(NodeVec set1,
755 for (NodeVec::iterator I = set1.begin(); I != set1.end(); I++) {
758 for (NodeVec::iterator II = set2.begin(); II != set2.end(); II++)
759 if ((*I)->getNodeId() == (*II)->getNodeId()) {
765 newVec.push_back(*I);
774 order all nodes in the basicblock
775 based on the sets information and node property
777 output: ordered nodes are stored in oNodes
780 void ModuloSchedGraph::orderNodes() {
783 std::vector < ModuloSchedGraphNode * >set;
784 unsigned numNodes = bb->size();
786 // first order all the sets
790 while (circuits[++j][0] != 0) {
792 preDelay = totalDelay;
794 while (circuits[j][++k] != 0) {
795 ModuloSchedGraphNode *node = getNode(circuits[j][k]);
798 circuits[j][k + 1] != 0 ? circuits[j][k + 1] : circuits[j][0];
799 SchedGraphEdge *edge = getMaxDelayEdge(circuits[j][k], nextNodeId);
800 totalDelay += edge->getMinDelay();
802 if (preDelay != -1 && totalDelay > preDelay) {
803 // swap circuits[j][] and cuicuits[j-1][]
804 unsigned temp[MAXNODE];
805 for (int k = 0; k < MAXNODE; k++) {
806 temp[k] = circuits[j - 1][k];
807 circuits[j - 1][k] = circuits[j][k];
808 circuits[j][k] = temp[k];
816 // build the first set
819 if (ModuloScheduling::printScheduleProcess())
820 DEBUG_PRINT(std::cerr << "building the first set" << "\n");
824 while (circuits[setSeq][++k] != 0)
825 set.push_back(getNode(circuits[setSeq][k]));
826 if (circuits[setSeq][0] != 0) {
827 backEdgeSrc = circuits[setSeq][k - 1];
828 backEdgeSink = circuits[setSeq][0];
830 if (ModuloScheduling::printScheduleProcess()) {
831 DEBUG_PRINT(std::cerr << "the first set is:");
835 // implement the ordering algorithm
836 enum OrderSeq { bottom_up, top_down };
838 std::vector<ModuloSchedGraphNode*> R;
839 while (!set.empty()) {
840 std::vector<ModuloSchedGraphNode*> pset = predSet(oNodes);
841 std::vector<ModuloSchedGraphNode*> sset = succSet(oNodes);
843 if (!pset.empty() && !vectorConj(pset, set).empty()) {
844 R = vectorConj(pset, set);
846 } else if (!sset.empty() && !vectorConj(sset, set).empty()) {
847 R = vectorConj(sset, set);
852 for (unsigned i = 0; i < set.size(); i++) {
853 int temp = set[i]->getASAP();
854 if (temp > maxASAP) {
859 R.push_back(set[position]);
864 if (order == top_down) {
865 if (ModuloScheduling::printScheduleProcess())
866 DEBUG_PRINT(std::cerr << "in top_down round\n");
869 NodeVec::iterator chosenI;
870 for (NodeVec::iterator I = R.begin(); I != R.end(); I++) {
871 int temp = (*I)->height;
872 if ((temp > maxHeight)
873 || (temp == maxHeight && (*I)->mov <= (*chosenI)->mov)) {
875 if ((temp > maxHeight)
876 || (temp == maxHeight && (*I)->mov < (*chosenI)->mov)) {
882 //possible case: instruction A and B has the same height and mov,
883 //but A has dependence to B e.g B is the branch instruction in the
884 //end, or A is the phi instruction at the beginning
885 if ((*I)->mov == (*chosenI)->mov)
886 for (ModuloSchedGraphNode::const_iterator oe =
887 (*I)->beginOutEdges(), end = (*I)->endOutEdges();
889 if ((*oe)->getSink() == (*chosenI)) {
898 ModuloSchedGraphNode *mu = *chosenI;
899 oNodes.push_back(mu);
901 std::vector<ModuloSchedGraphNode*> succ_mu =
902 succSet(mu, backEdgeSrc, backEdgeSink);
903 std::vector<ModuloSchedGraphNode*> comm =
904 vectorConj(succ_mu, set);
905 comm = vectorSub(comm, oNodes);
906 R = vectorUnion(comm, R);
909 R = vectorConj(predSet(oNodes), set);
911 if (ModuloScheduling::printScheduleProcess())
912 DEBUG_PRINT(std::cerr << "in bottom up round\n");
915 NodeVec::iterator chosenI;
916 for (NodeVec::iterator I = R.begin(); I != R.end(); I++) {
917 int temp = (*I)->depth;
918 if ((temp > maxDepth)
919 || (temp == maxDepth && (*I)->mov < (*chosenI)->mov)) {
924 ModuloSchedGraphNode *mu = *chosenI;
925 oNodes.push_back(mu);
927 std::vector<ModuloSchedGraphNode*> pred_mu =
928 predSet(mu, backEdgeSrc, backEdgeSink);
929 std::vector<ModuloSchedGraphNode*> comm =
930 vectorConj(pred_mu, set);
931 comm = vectorSub(comm, oNodes);
932 R = vectorUnion(comm, R);
935 R = vectorConj(succSet(oNodes), set);
938 if (ModuloScheduling::printScheduleProcess()) {
939 DEBUG_PRINT(std::cerr << "order finished\n");
940 DEBUG_PRINT(std::cerr << "dumping the ordered nodes:\n");
946 //FIXME: the nodes between onodes and this circuit should also be include in
948 if (ModuloScheduling::printScheduleProcess())
949 DEBUG_PRINT(std::cerr << "building the next set\n");
953 while (circuits[setSeq][++k] != 0)
954 set.push_back(getNode(circuits[setSeq][k]));
955 if (circuits[setSeq][0] != 0) {
956 backEdgeSrc = circuits[setSeq][k - 1];
957 backEdgeSink = circuits[setSeq][0];
961 //no circuits any more
962 //collect all other nodes
963 if (ModuloScheduling::printScheduleProcess())
964 DEBUG_PRINT(std::cerr << "no circuits any more, collect the rest nodes\n");
965 for (unsigned i = 2; i < numNodes + 2; i++) {
967 for (unsigned j = 0; j < oNodes.size(); j++)
968 if (oNodes[j]->getNodeId() == i) {
973 set.push_back(getNode(i));
976 if (ModuloScheduling::printScheduleProcess()) {
977 DEBUG_PRINT(std::cerr << "next set is:\n");
988 build graph for instructions in this basic block
991 void ModuloSchedGraph::buildGraph(const TargetMachine & target)
994 assert(this->bb && "The basicBlock is NULL?");
996 // Make a dummy root node. We'll add edges to the real roots later.
997 graphRoot = new ModuloSchedGraphNode(0, NULL, NULL, -1, target);
998 graphLeaf = new ModuloSchedGraphNode(1, NULL, NULL, -1, target);
1000 if (ModuloScheduling::printScheduleProcess())
1005 DEBUG_PRINT(cerr << "building nodes for this BasicBlock\n");
1006 buildNodesforBB(target, bb);
1008 DEBUG_PRINT(cerr << "adding def-use edge to this basic block\n");
1009 this->addDefUseEdges(bb);
1011 DEBUG_PRINT(cerr << "adding CD edges to this basic block\n");
1012 this->addCDEdges(bb);
1014 DEBUG_PRINT(cerr << "adding memory edges to this basicblock\n");
1015 this->addMemEdges(bb);
1017 int ResII = this->computeResII(bb);
1019 if (ModuloScheduling::printScheduleProcess())
1020 DEBUG_PRINT(std::cerr << "ResII is " << ResII << "\n");
1022 int RecII = this->computeRecII(bb);
1023 if (ModuloScheduling::printScheduleProcess())
1024 DEBUG_PRINT(std::cerr << "RecII is " << RecII << "\n");
1026 this->MII = std::max(ResII, RecII);
1028 this->computeNodeProperty(bb);
1029 if (ModuloScheduling::printScheduleProcess())
1030 this->dumpNodeProperty();
1034 if (ModuloScheduling::printScheduleProcess())
1041 get node with nodeId
1044 ModuloSchedGraphNode *
1045 ModuloSchedGraph::getNode(const unsigned nodeId) const{
1047 for (const_iterator I = begin(), E = end(); I != E; I++)
1048 if ((*I).second->getNodeId() == nodeId)
1049 return (ModuloSchedGraphNode *) (*I).second;
1055 compute RecurrenceII
1059 ModuloSchedGraph::computeRecII(const BasicBlock *bb){
1064 //FIXME: only deal with circuits starting at the first node: the phi node
1067 //search all elementary circuits in the dependence graph
1068 //assume maximum number of nodes is MAXNODE
1070 unsigned path[MAXNODE];
1071 unsigned stack[MAXNODE][MAXNODE];
1073 for (int j = 0; j < MAXNODE; j++) {
1075 for (int k = 0; k < MAXNODE; k++)
1079 //in our graph, the node number starts at 2
1080 const unsigned numNodes = bb->size();
1085 ModuloSchedGraphNode *initNode = getNode(path[0]);
1086 unsigned initNodeId = initNode->getNodeId();
1087 ModuloSchedGraphNode *currentNode = initNode;
1089 while (currentNode != NULL) {
1090 unsigned currentNodeId = currentNode->getNodeId();
1091 // DEBUG_PRINT(std::cerr<<"current node is "<<currentNodeId<<"\n");
1093 ModuloSchedGraphNode *nextNode = NULL;
1094 for (ModuloSchedGraphNode::const_iterator I =
1095 currentNode->beginOutEdges(), E = currentNode->endOutEdges();
1097 //DEBUG_PRINT(std::cerr <<" searching in outgoint edges of node
1098 //"<<currentNodeId<<"\n";
1099 unsigned nodeId = ((SchedGraphEdge *) * I)->getSink()->getNodeId();
1100 bool inpath = false, instack = false;
1103 //DEBUG_PRINT(std::cerr<<"nodeId is "<<nodeId<<"\n");
1106 while (path[++k] != 0)
1107 if (nodeId == path[k]) {
1113 while (stack[i][++k] != 0)
1114 if (nodeId == stack[i][k]) {
1119 if (nodeId > currentNodeId && !inpath && !instack) {
1121 (ModuloSchedGraphNode *) ((SchedGraphEdge *) * I)->getSink();
1126 if (nextNode != NULL) {
1127 //DEBUG_PRINT(std::cerr<<"find the next Node "<<nextNode->getNodeId()<<"\n");
1130 while (stack[i][j] != 0)
1132 stack[i][j] = nextNode->getNodeId();
1135 path[i] = nextNode->getNodeId();
1136 currentNode = nextNode;
1138 //DEBUG_PRINT(std::cerr<<"no expansion any more"<<"\n");
1140 for (ModuloSchedGraphNode::const_iterator I =
1141 currentNode->beginOutEdges(), E = currentNode->endOutEdges();
1143 unsigned nodeId = ((SchedGraphEdge *) * I)->getSink()->getNodeId();
1144 if (nodeId == initNodeId) {
1147 while (circuits[++j][0] != 0);
1148 for (int k = 0; k < MAXNODE; k++)
1149 circuits[j][k] = path[k];
1153 //remove this node in the path and clear the corresponding entries in the
1157 for (j = 0; j < MAXNODE; j++)
1160 currentNode = getNode(path[i]);
1164 if (ModuloScheduling::printScheduleProcess())
1165 DEBUG_PRINT(std::cerr << "circuits found are:\n");
1167 while (circuits[++j][0] != 0) {
1169 while (circuits[j][++k] != 0)
1170 if (ModuloScheduling::printScheduleProcess())
1171 DEBUG_PRINT(std::cerr << circuits[j][k] << "\t");
1172 if (ModuloScheduling::printScheduleProcess())
1173 DEBUG_PRINT(std::cerr << "\n");
1175 //for this circuit, compute the sum of all edge delay
1178 while (circuits[j][++k] != 0) {
1179 //ModuloSchedGraphNode* node =getNode(circuits[j][k]);
1180 unsigned nextNodeId;
1182 circuits[j][k + 1] !=
1183 0 ? circuits[j][k + 1] : circuits[j][0];
1186 getMaxDelayEdge(circuits[j][k], nextNodeId)->getMinDelay();
1189 // assume we have distance 1, in this case the sumDelay is RecII
1190 // this is correct for SSA form only
1192 if (ModuloScheduling::printScheduleProcess())
1193 DEBUG_PRINT(std::cerr << "The total Delay in the circuit is " << sumDelay
1196 RecII = RecII > sumDelay ? RecII : sumDelay;
1208 update resource usage vector (ruVec)
1211 ModuloSchedGraph::addResourceUsage(std::vector<std::pair<int,int> > &ruVec,
1214 bool alreadyExists = false;
1215 for (unsigned i = 0; i < ruVec.size(); i++) {
1216 if (rid == ruVec[i].first) {
1218 alreadyExists = true;
1223 ruVec.push_back(std::make_pair(rid, 1));
1228 dump the resource usage vector
1232 ModuloSchedGraph::dumpResourceUsage(std::vector<std::pair<int,int> > &ru){
1234 TargetSchedInfo & msi = (TargetSchedInfo &) target.getSchedInfo();
1236 std::vector<std::pair<int,int> > resourceNumVector = msi.resourceNumVector;
1237 DEBUG_PRINT(std::cerr << "resourceID\t" << "resourceNum\n");
1238 for (unsigned i = 0; i < resourceNumVector.size(); i++)
1239 DEBUG_PRINT(std::cerr << resourceNumVector[i].
1240 first << "\t" << resourceNumVector[i].second << "\n");
1242 DEBUG_PRINT(std::cerr << " maxNumIssueTotal(issue slot in one cycle) = " << msi.
1243 maxNumIssueTotal << "\n");
1244 DEBUG_PRINT(std::cerr << "resourceID\t resourceUsage\t ResourceNum\n");
1245 for (unsigned i = 0; i < ru.size(); i++) {
1246 DEBUG_PRINT(std::cerr << ru[i].first << "\t" << ru[i].second);
1247 const unsigned resNum = msi.getCPUResourceNum(ru[i].first);
1248 DEBUG_PRINT(std::cerr << "\t" << resNum << "\n");
1254 compute thre resource restriction II
1258 ModuloSchedGraph::computeResII(const BasicBlock * bb){
1260 const TargetInstrInfo & mii = target.getInstrInfo();
1261 const TargetSchedInfo & msi = target.getSchedInfo();
1264 std::vector<std::pair<int,int> > resourceUsage;
1266 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E;
1268 if (ModuloScheduling::printScheduleProcess()) {
1269 DEBUG_PRINT(std::cerr << "machine instruction for llvm instruction( node " <<
1270 getGraphNodeForInst(I)->getNodeId() << ")\n");
1271 DEBUG_PRINT(std::cerr << "\t" << *I);
1273 MachineCodeForInstruction & tempMvec =
1274 MachineCodeForInstruction::get(I);
1275 if (ModuloScheduling::printScheduleProcess())
1276 DEBUG_PRINT(std::cerr << "size =" << tempMvec.size() << "\n");
1277 for (unsigned i = 0; i < tempMvec.size(); i++) {
1278 MachineInstr *minstr = tempMvec[i];
1280 unsigned minDelay = mii.minLatency(minstr->getOpCode());
1281 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
1282 InstrClassRUsage classRUsage =
1283 msi.getClassRUsage(mii.getSchedClass(minstr->getOpCode()));
1284 unsigned totCycles = classRUsage.totCycles;
1286 std::vector<std::vector<resourceId_t> > resources=rUsage.resourcesByCycle;
1287 assert(totCycles == resources.size());
1288 if (ModuloScheduling::printScheduleProcess())
1289 DEBUG_PRINT(std::cerr << "resources Usage for this Instr(totCycles="
1290 << totCycles << ",mindLatency="
1291 << mii.minLatency(minstr->getOpCode()) << "): " << *minstr
1293 for (unsigned j = 0; j < resources.size(); j++) {
1294 if (ModuloScheduling::printScheduleProcess())
1295 DEBUG_PRINT(std::cerr << "cycle " << j << ": ");
1296 for (unsigned k = 0; k < resources[j].size(); k++) {
1297 if (ModuloScheduling::printScheduleProcess())
1298 DEBUG_PRINT(std::cerr << "\t" << resources[j][k]);
1299 addResourceUsage(resourceUsage, resources[j][k]);
1301 if (ModuloScheduling::printScheduleProcess())
1302 DEBUG_PRINT(std::cerr << "\n");
1306 if (ModuloScheduling::printScheduleProcess())
1307 this->dumpResourceUsage(resourceUsage);
1311 int issueSlots = msi.maxNumIssueTotal;
1312 for (unsigned i = 0; i < resourceUsage.size(); i++) {
1313 int resourceNum = msi.getCPUResourceNum(resourceUsage[i].first);
1314 int useNum = resourceUsage[i].second;
1316 if (resourceNum <= issueSlots)
1317 tempII = ceil(1.0 * useNum / resourceNum);
1319 tempII = ceil(1.0 * useNum / issueSlots);
1320 ResII = std::max((int) tempII, ResII);
1332 ModuloSchedGraph::dump(const BasicBlock * bb){
1334 DEBUG_PRINT(std::cerr << "dumping basic block:");
1335 DEBUG_PRINT(std::cerr << (bb->hasName()? bb->getName() : "block")
1336 << " (" << bb << ")" << "\n");
1341 dump the basicblock to ostream os
1345 ModuloSchedGraph::dump(const BasicBlock * bb, std::ostream & os){
1347 os << "dumping basic block:";
1348 os << (bb->hasName()? bb->getName() : "block")
1349 << " (" << bb << ")" << "\n";
1356 void ModuloSchedGraph::dump() const
1358 DEBUG_PRINT(std::cerr << " ModuloSchedGraph for basic Blocks:");
1360 DEBUG_PRINT(std::cerr << (bb->hasName()? bb->getName() : "block")
1361 << " (" << bb << ")" << "");
1363 DEBUG_PRINT(std::cerr << "\n\n Actual Root nodes : ");
1364 for (unsigned i = 0, N = graphRoot->outEdges.size(); i < N; i++)
1365 DEBUG_PRINT(std::cerr << graphRoot->outEdges[i]->getSink()->getNodeId()
1366 << ((i == N - 1) ? "" : ", "));
1368 DEBUG_PRINT(std::cerr << "\n Graph Nodes:\n");
1370 unsigned numNodes = bb->size();
1371 for (unsigned i = 2; i < numNodes + 2; i++) {
1372 ModuloSchedGraphNode *node = getNode(i);
1373 DEBUG_PRINT(std::cerr << "\n" << *node);
1376 DEBUG_PRINT(std::cerr << "\n");
1381 dump all node property
1384 void ModuloSchedGraph::dumpNodeProperty() const
1387 unsigned numNodes = bb->size();
1388 for (unsigned i = 2; i < numNodes + 2; i++) {
1389 ModuloSchedGraphNode *node = getNode(i);
1390 DEBUG_PRINT(std::cerr << "NodeId " << node->getNodeId() << "\t");
1391 DEBUG_PRINT(std::cerr << "ASAP " << node->getASAP() << "\t");
1392 DEBUG_PRINT(std::cerr << "ALAP " << node->getALAP() << "\t");
1393 DEBUG_PRINT(std::cerr << "mov " << node->getMov() << "\t");
1394 DEBUG_PRINT(std::cerr << "depth " << node->getDepth() << "\t");
1395 DEBUG_PRINT(std::cerr << "height " << node->getHeight() << "\t\n");
1402 /************member functions for ModuloSchedGraphSet**************/
1408 ModuloSchedGraphSet::ModuloSchedGraphSet(const Function *function,
1409 const TargetMachine &target)
1412 buildGraphsForMethod(method, target);
1421 ModuloSchedGraphSet::~ModuloSchedGraphSet(){
1423 //delete all the graphs
1424 for (iterator I = begin(), E = end(); I != E; ++I)
1431 build graph for each basicblock in this method
1435 ModuloSchedGraphSet::buildGraphsForMethod(const Function *F,
1436 const TargetMachine &target){
1438 for (Function::const_iterator BI = F->begin(); BI != F->end(); ++BI){
1439 const BasicBlock* local_bb;
1442 addGraph(new ModuloSchedGraph((BasicBlock*)local_bb, target));
1452 ModuloSchedGraphSet::dump() const{
1454 DEBUG_PRINT(std::cerr << " ====== ModuloSched graphs for function `" <<
1455 method->getName() << "' =========\n\n");
1456 for (const_iterator I = begin(); I != end(); ++I)
1459 DEBUG_PRINT(std::cerr << "\n=========End graphs for function `" << method->getName()
1460 << "' ==========\n\n");
1466 /********************misc functions***************************/
1470 dump the input basic block
1474 dumpBasicBlock(const BasicBlock * bb){
1476 DEBUG_PRINT(std::cerr << "dumping basic block:");
1477 DEBUG_PRINT(std::cerr << (bb->hasName()? bb->getName() : "block")
1478 << " (" << bb << ")" << "\n");
1485 std::ostream& operator<<(std::ostream &os,
1486 const ModuloSchedGraphNode &node)
1488 os << std::string(8, ' ')
1489 << "Node " << node.nodeId << " : "
1490 << "latency = " << node.latency << "\n" << std::string(12, ' ');
1492 if (node.getInst() == NULL)
1493 os << "(Dummy node)\n";
1495 os << *node.getInst() << "\n" << std::string(12, ' ');
1496 os << node.inEdges.size() << " Incoming Edges:\n";
1497 for (unsigned i = 0, N = node.inEdges.size(); i < N; i++)
1498 os << std::string(16, ' ') << *node.inEdges[i];
1500 os << std::string(12, ' ') << node.outEdges.size()
1501 << " Outgoing Edges:\n";
1502 for (unsigned i = 0, N = node.outEdges.size(); i < N; i++)
1503 os << std::string(16, ' ') << *node.outEdges[i];