blob: 4e36b070b411fe291b5d65eea447efc71b1262f5 [file] [log] [blame]
Guochun Shif1c154f2003-03-27 17:57:44 +00001#include <math.h>
2#include "ModuloSchedGraph.h"
3#include "llvm/CodeGen/InstrSelection.h"
4#include "llvm/BasicBlock.h"
5#include "llvm/Function.h"
6#include "llvm/iOther.h"
7#include "Support/StringExtras.h"
8#include "Support/STLExtras.h"
9#include <iostream>
10#include <swig.h>
11#include "llvm/iOperators.h"
12#include "llvm/iOther.h"
13#include "llvm/iPHINode.h"
14#include "llvm/iTerminators.h"
15#include "llvm/iMemory.h"
16#include "llvm/Type.h"
17#include "llvm/CodeGen/MachineCodeForInstruction.h"
18#include "llvm/CodeGen/MachineInstr.h"
19#include "llvm/Target/MachineSchedInfo.h"
20
21#define UNIDELAY 1
22#define min(a, b) ((a) < (b) ? (a) : (b))
23#define max(a, b) ((a) < (b) ? (b) : (a))
24
25using std::vector;
26using std::pair;
27//using std::hash_map;
28using std::cerr;
29extern std::ostream modSched_os;
30extern ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
31//*********************** Internal Data Structures *************************/
32
33// The following two types need to be classes, not typedefs, so we can use
34// opaque declarations in SchedGraph.h
35//
36struct RefVec: public vector< pair<ModuloSchedGraphNode*, int> > {
37 typedef vector< pair<ModuloSchedGraphNode*, int> >:: iterator iterator;
38 typedef vector< pair<ModuloSchedGraphNode*, int> >::const_iterator const_iterator;
39};
40
41struct RegToRefVecMap: public hash_map<int, RefVec> {
42 typedef hash_map<int, RefVec>:: iterator iterator;
43 typedef hash_map<int, RefVec>::const_iterator const_iterator;
44};
45
46struct ValueToDefVecMap: public hash_map<const Instruction*, RefVec> {
47 typedef hash_map<const Instruction*, RefVec>:: iterator iterator;
48 typedef hash_map<const Instruction*, RefVec>::const_iterator const_iterator;
49};
50
51
52
53// class Modulo SchedGraphNode
54
55/*ctor*/
56ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned int _nodeId,
57 const BasicBlock* _bb,
58 const Instruction* _inst,
59 int indexInBB,
60 const TargetMachine& target)
61 :
62 SchedGraphNodeCommon(_nodeId, _bb, indexInBB),
63 inst(_inst)
64{
65 if(inst)
66 {
67 //FIXME: find the latency
68 //currently setthe latency to zero
69 latency =0;
70 }
71
72}
73
74//class ModuloScheGraph
75
76
77void
78ModuloSchedGraph::addDummyEdges()
79{
80 assert(graphRoot->outEdges.size() == 0);
81
82 for (const_iterator I=begin(); I != end(); ++I)
83 {
84 ModuloSchedGraphNode* node = (ModuloSchedGraphNode*)( (*I).second);
85 assert(node != graphRoot && node != graphLeaf);
86 if (node->beginInEdges() == node->endInEdges())
87 (void) new SchedGraphEdge(graphRoot, node, SchedGraphEdge::CtrlDep,
88 SchedGraphEdge::NonDataDep, 0);
89 if (node->beginOutEdges() == node->endOutEdges())
90 (void) new SchedGraphEdge(node, graphLeaf, SchedGraphEdge::CtrlDep,
91 SchedGraphEdge::NonDataDep, 0);
92 }
93}
94
95bool isDefinition(const Instruction* I)
96{
97 //if(TerminatorInst::classof(I)||FreeInst::classof(I) || StoreInst::classof(I) || CallInst::classof(I))
98 if(!I->hasName())
99 return false;
100 else
101 return true;
102}
103
104void ModuloSchedGraph::addDefUseEdges(const BasicBlock* bb)
105{
106 //collect def instructions, store them in vector
107 const MachineInstrInfo& mii = target.getInstrInfo();
108
109 typedef std::vector<ModuloSchedGraphNode*> DefVec;
110 DefVec defVec;
111
112 //find those def instructions
113 for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I !=E; I++)
114 if(I->getType() != Type::VoidTy)
115 {
116 defVec.push_back(this->getGraphNodeForInst(I)) ;
117 }
118
119 for(unsigned int i=0; i < defVec.size();i++)
120 for(Value::use_const_iterator I=defVec[i]->getInst()->use_begin();I !=defVec[i]->getInst()->use_end() ;I++)
121 {
122 //for each use of a def, add a flow edge from the def instruction to the ref instruction
123
124
125 const Instruction* value=defVec[i]->getInst();
126 Instruction *inst=(Instruction*)(*I);
127 ModuloSchedGraphNode* node=NULL;
128
129 for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I !=E; I++)
130 if((const Instruction*)I == inst)
131 {
132 node=(*this)[inst];
133 break;
134 }
135
136 assert(inst != NULL &&" Use not an Instruction ?" );
137
138 if(node == NULL) //inst is not an instruction in this block
139 {}
140 else
141 {
142 //add a flow edge from the def instruction to the ref instruction
143
144 //self loop will not happen in SSA form
145 assert(defVec[i] != node && "same node?");
146
147
148 //this is a true dependence, so the delay is equal to the delay of the pred node.
149 int delay=0;
150 MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(value);
151 for(unsigned j=0;j< tempMvec.size();j++)
152 {
153 MachineInstr* temp=tempMvec[j];
154 //delay +=mii.minLatency(temp->getOpCode());
155 delay = max(delay, mii.minLatency(temp->getOpCode()));
156 }
157
158 SchedGraphEdge* trueEdge=new SchedGraphEdge(defVec[i],node,value, SchedGraphEdge::TrueDep,delay);
159
160 //if the ref instruction is before the def instrution
161 //then the def instruction must be a phi instruction
162 //add an anti-dependence edge to from the ref instruction to the def instruction
163 if( node->getOrigIndexInBB() < defVec[i]->getOrigIndexInBB())
164 {
165 assert(PHINode::classof(inst) && "the ref instruction befre def is not PHINode?");
166 trueEdge->setIteDiff(1);
167 }
168
169 }
170
171 }
172}
173
174void ModuloSchedGraph::addCDEdges(const BasicBlock* bb)
175{
176 //find the last instruction in the basic block
177 //see if it is an branch instruction.
178 //If yes, then add an edge from each node expcept the last node to the last node
179
180 const Instruction* inst=&(bb->back());
181 ModuloSchedGraphNode* lastNode=(*this)[inst];
182 if( TerminatorInst::classof(inst))
183 for(BasicBlock::const_iterator I=bb->begin(),E=bb->end(); I != E; I++)
184 {
185 if(inst != I)
186 {
187 ModuloSchedGraphNode* node = (*this)[I];
188 //use latency of 0
189 (void) new SchedGraphEdge(node,lastNode,SchedGraphEdge::CtrlDep,
190 SchedGraphEdge::NonDataDep,0);
191 }
192
193 }
194
195
196}
197
198
199
200
201static const int SG_LOAD_REF = 0;
202static const int SG_STORE_REF = 1;
203static const int SG_CALL_REF = 2;
204
205static const unsigned int SG_DepOrderArray[][3] = {
206 { SchedGraphEdge::NonDataDep,
207 SchedGraphEdge::AntiDep,
208 SchedGraphEdge::AntiDep },
209 { SchedGraphEdge::TrueDep,
210 SchedGraphEdge::OutputDep,
211 SchedGraphEdge::TrueDep | SchedGraphEdge::OutputDep },
212 { SchedGraphEdge::TrueDep,
213 SchedGraphEdge::AntiDep | SchedGraphEdge::OutputDep,
214 SchedGraphEdge::TrueDep | SchedGraphEdge::AntiDep
215 | SchedGraphEdge::OutputDep }
216};
217
218
219// Add a dependence edge between every pair of machine load/store/call
220// instructions, where at least one is a store or a call.
221// Use latency 1 just to ensure that memory operations are ordered;
222// latency does not otherwise matter (true dependences enforce that).
223//
224void
225ModuloSchedGraph::addMemEdges(const BasicBlock* bb)
226{
227
228 vector<ModuloSchedGraphNode*> memNodeVec;
229
230 //construct the memNodeVec
231
232 for( BasicBlock::const_iterator I=bb->begin(), E=bb->end();I != E; I++)
233 if(LoadInst::classof(I) ||StoreInst::classof(I) || CallInst::classof(I))
234 {
235 ModuloSchedGraphNode* node =(*this)[(const Instruction*)I];
236 memNodeVec.push_back(node);
237 }
238 // Instructions in memNodeVec are in execution order within the basic block,
239 // so simply look at all pairs <memNodeVec[i], memNodeVec[j: j > i]>.
240 //
241 for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++)
242 {
243 const Instruction* fromInst = memNodeVec[im]->getInst();
244 int fromType = CallInst::classof(fromInst)? SG_CALL_REF
245 : LoadInst::classof(fromInst)? SG_LOAD_REF
246 : SG_STORE_REF;
247 for (unsigned jm=im+1; jm < NM; jm++)
248 {
249 const Instruction* toInst=memNodeVec[jm]->getInst();
250 int toType = CallInst::classof(toInst)? SG_CALL_REF
251 : LoadInst::classof(toInst)? SG_LOAD_REF
252 : SG_STORE_REF;
253 if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF)
254 {
255 (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm],
256 SchedGraphEdge::MemoryDep,
257 SG_DepOrderArray[fromType][toType], 1);
258
259 SchedGraphEdge* edge=new SchedGraphEdge(memNodeVec[jm],memNodeVec[im],
260 SchedGraphEdge::MemoryDep,
261 SG_DepOrderArray[toType][fromType],1);
262 edge->setIteDiff(1);
263
264 }
265 }
266 }
267}
268
269
270
271void ModuloSchedGraph::buildNodesforBB (const TargetMachine& target,
272 const BasicBlock* bb,
273 std::vector<ModuloSchedGraphNode*>& memNode,
274 RegToRefVecMap& regToRefVecMap,
275 ValueToDefVecMap& valueToDefVecMap)
276{
277 //const MachineInstrInfo& mii=target.getInstrInfo();
278
279 //Build graph nodes for each LLVM instruction and gather def/use info.
280 //Do both together in a single pass over all machine instructions.
281
282 int i=0;
283 for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I!=E; I++)
284 {
285 ModuloSchedGraphNode* node=new ModuloSchedGraphNode(getNumNodes(), bb,I,i, target);
286 i++;
287 this->noteModuloSchedGraphNodeForInst(I,node);
288 }
289
290 //this function finds some info about instruction in basic block for later use
291 //findDefUseInfoAtInstr(target, node, memNode,regToRefVecMap,valueToDefVecMap);
292
293
294}
295
296
297bool ModuloSchedGraph::isLoop(const BasicBlock* bb)
298{
299 //only if the last instruction in the basicblock is branch instruction and
300 //there is at least an option to branch itself
301
302
303 const Instruction* inst=&(bb->back());
304 if( BranchInst::classof(inst))
305 for(unsigned i=0;i < ((BranchInst*)inst)->getNumSuccessors();i++)
306 {
307 BasicBlock* sb=((BranchInst*)inst)->getSuccessor(i);
308 if(sb ==bb) return true;
309 }
310
311 return false;
312
313}
314bool ModuloSchedGraph::isLoop()
315{
316 //only if the last instruction in the basicblock is branch instruction and
317 //there is at least an option to branch itself
318
319 assert(bbVec.size() ==1 &&"only 1 basicblock in a graph");
320 const BasicBlock* bb=bbVec[0];
321 const Instruction* inst=&(bb->back());
322 if( BranchInst::classof(inst))
323 for(unsigned i=0;i < ((BranchInst*)inst)->getNumSuccessors();i++)
324 {
325 BasicBlock* sb=((BranchInst*)inst)->getSuccessor(i);
326 if(sb ==bb) return true;
327 }
328
329 return false;
330
331}
332
333void ModuloSchedGraph::computeNodeASAP(const BasicBlock* bb)
334{
335
336 //FIXME: now assume the only backward edges come from the edges from other nodes to the phi Node
337 //so i will ignore all edges to the phi node; after this, there shall be no recurrence.
338
339 unsigned numNodes=bb->size();
340 for(unsigned i=2;i < numNodes+2;i++)
341 {
342 ModuloSchedGraphNode* node=getNode(i);
343 node->setPropertyComputed(false);
344 }
345
346 for(unsigned i=2;i < numNodes+2; i++)
347 {
348 ModuloSchedGraphNode* node=getNode(i);
349 node->ASAP=0;
350 if(i==2 ||node->getNumInEdges() ==0)
351 { node->setPropertyComputed(true);continue;}
352 for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges();I !=E; I++)
353 {
354 SchedGraphEdge* edge=*I;
355 ModuloSchedGraphNode* pred=(ModuloSchedGraphNode*)(edge->getSrc());
356 assert(pred->getPropertyComputed()&&"pred node property is not computed!");
357 int temp=pred->ASAP + edge->getMinDelay() - edge->getIteDiff()*this->MII;
358 node->ASAP= max(node->ASAP,temp);
359 }
360 node->setPropertyComputed(true);
361 }
362}
363
364void ModuloSchedGraph::computeNodeALAP(const BasicBlock* bb)
365{
366
367 unsigned numNodes=bb->size();
368 int maxASAP=0;
369 for(unsigned i=numNodes+1;i >= 2;i--)
370 {
371 ModuloSchedGraphNode* node=getNode(i);
372 node->setPropertyComputed(false);
373 //cerr<< " maxASAP= " <<maxASAP<<" node->ASAP= "<< node->ASAP<<"\n";
374 maxASAP=max(maxASAP,node->ASAP);
375 }
376
377 //cerr<<"maxASAP is "<<maxASAP<<"\n";
378
379 for(unsigned i=numNodes+1;i >= 2; i--)
380 {
381 ModuloSchedGraphNode* node=getNode(i);
382 node->ALAP=maxASAP;
383 for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I!=E; I++)
384 {
385 SchedGraphEdge* edge= *I;
386 ModuloSchedGraphNode* succ=(ModuloSchedGraphNode*) (edge->getSink());
387 if(PHINode::classof(succ->getInst()))continue;
388 assert(succ->getPropertyComputed()&&"succ node property is not computed!");
389 int temp=succ->ALAP - edge->getMinDelay()+edge->getIteDiff()*this->MII;
390 node->ALAP =min(node->ALAP,temp);
391 }
392 node->setPropertyComputed(true);
393
394 }
395}
396
397void ModuloSchedGraph::computeNodeMov(const BasicBlock* bb)
398{
399 unsigned numNodes=bb->size();
400 for(unsigned i =2;i < numNodes +2 ;i++)
401 {
402 ModuloSchedGraphNode* node=getNode(i);
403 node->mov=node->ALAP-node->ASAP;
404 assert(node->mov >=0 &&"move freedom for this node is less than zero? ");
405 }
406}
407
408
409void ModuloSchedGraph::computeNodeDepth(const BasicBlock* bb)
410{
411
412 unsigned numNodes=bb->size();
413 for(unsigned i=2;i < numNodes+2;i++)
414 {
415 ModuloSchedGraphNode* node=getNode(i);
416 node->setPropertyComputed(false);
417 }
418
419 for(unsigned i=2;i < numNodes+2; i++)
420 {
421 ModuloSchedGraphNode* node=getNode(i);
422 node->depth=0;
423 if(i==2 ||node->getNumInEdges() ==0)
424 { node->setPropertyComputed(true);continue;}
425 for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges();I !=E; I++)
426 {
427 SchedGraphEdge* edge=*I;
428 ModuloSchedGraphNode* pred=(ModuloSchedGraphNode*)(edge->getSrc());
429 assert(pred->getPropertyComputed()&&"pred node property is not computed!");
430 int temp=pred->depth + edge->getMinDelay();
431 node->depth= max(node->depth,temp);
432 }
433 node->setPropertyComputed(true);
434 }
435
436}
437
438
439void ModuloSchedGraph::computeNodeHeight(const BasicBlock* bb)
440{
441 unsigned numNodes=bb->size();
442 for(unsigned i=numNodes+1;i >= 2;i--)
443 {
444 ModuloSchedGraphNode* node=getNode(i);
445 node->setPropertyComputed(false);
446 }
447
448 for(unsigned i=numNodes+1;i >= 2; i--)
449 {
450 ModuloSchedGraphNode* node=getNode(i);
451 node->height=0;
452 for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I!=E; I++)
453 {
454 SchedGraphEdge* edge= *I;
455 ModuloSchedGraphNode* succ=(ModuloSchedGraphNode*)(edge->getSink());
456 if(PHINode::classof(succ->getInst())) continue;
457 assert(succ->getPropertyComputed()&&"succ node property is not computed!");
458 node->height=max(node->height, succ->height+edge->getMinDelay());
459
460 }
461 node->setPropertyComputed(true);
462
463 }
464
465}
466
467void ModuloSchedGraph::computeNodeProperty(const BasicBlock* bb)
468{
469 //FIXME: now assume the only backward edges come from the edges from other nodes to the phi Node
470 //so i will ignore all edges to the phi node; after this, there shall be no recurrence.
471
472 this->computeNodeASAP(bb);
473 this->computeNodeALAP(bb);
474 this->computeNodeMov(bb);
475 this->computeNodeDepth(bb);
476 this->computeNodeHeight(bb);
477}
478
479
480//do not consider the backedge in these two functions:
481// i.e. don't consider the edge with destination in phi node
482std::vector<ModuloSchedGraphNode*> ModuloSchedGraph::predSet(std::vector<ModuloSchedGraphNode*> set, unsigned backEdgeSrc, unsigned backEdgeSink)
483{
484 std::vector<ModuloSchedGraphNode*> predS;
485 for(unsigned i=0; i < set.size(); i++)
486 {
487 ModuloSchedGraphNode* node = set[i];
488 for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges(); I !=E; I++)
489 {
490 SchedGraphEdge* edge= *I;
491 if(edge->getSrc()->getNodeId() ==backEdgeSrc && edge->getSink()->getNodeId() == backEdgeSink) continue;
492 ModuloSchedGraphNode* pred= (ModuloSchedGraphNode*)(edge->getSrc());
493 //if pred is not in the predSet, push it in vector
494 bool alreadyInset=false;
495 for(unsigned j=0; j < predS.size(); j++)
496 if(predS[j]->getNodeId() == pred->getNodeId() )
497 {alreadyInset=true;break;}
498
499 for(unsigned j=0; j < set.size(); j++)
500 if(set[j]->getNodeId() == pred->getNodeId() )
501 {alreadyInset=true; break;}
502
503 if(! alreadyInset)
504 predS.push_back(pred);
505 }
506 }
507 return predS;
508}
509
510ModuloSchedGraph::NodeVec ModuloSchedGraph::predSet(NodeVec set)
511{
512 //node number increases from 2
513 return predSet(set,0, 0);
514}
515
516
517std::vector<ModuloSchedGraphNode*> ModuloSchedGraph::predSet(ModuloSchedGraphNode* _node, unsigned backEdgeSrc, unsigned backEdgeSink)
518{
519
520 std::vector<ModuloSchedGraphNode*> set;
521 set.push_back(_node);
522 return predSet(set, backEdgeSrc, backEdgeSink);
523
524}
525
526std::vector<ModuloSchedGraphNode*> ModuloSchedGraph::predSet(ModuloSchedGraphNode* _node)
527{
528 return predSet(_node,0,0);
529}
530
531std::vector<ModuloSchedGraphNode*> ModuloSchedGraph::succSet(std::vector<ModuloSchedGraphNode*> set,unsigned src, unsigned sink)
532{
533 vector<ModuloSchedGraphNode*> succS;
534 for(unsigned i=0; i < set.size(); i++)
535 {
536 ModuloSchedGraphNode* node = set[i];
537 for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I !=E; I++)
538 {
539 SchedGraphEdge* edge= *I;
540 if(edge->getSrc()->getNodeId() == src && edge->getSink()->getNodeId() == sink) continue;
541 ModuloSchedGraphNode* succ= (ModuloSchedGraphNode*)(edge->getSink());
542 //if pred is not in the predSet, push it in vector
543 bool alreadyInset=false;
544 for(unsigned j=0; j < succS.size(); j++)
545 if(succS[j]->getNodeId() == succ->getNodeId() )
546 {alreadyInset=true;break;}
547
548 for(unsigned j=0; j < set.size(); j++)
549 if(set[j]->getNodeId() == succ->getNodeId() )
550 {alreadyInset=true;break;}
551 if(! alreadyInset)
552 succS.push_back(succ);
553 }
554 }
555 return succS;
556}
557
558ModuloSchedGraph::NodeVec ModuloSchedGraph::succSet(NodeVec set)
559{
560 return succSet(set,0,0);
561}
562
563
564std::vector<ModuloSchedGraphNode*> ModuloSchedGraph::succSet(ModuloSchedGraphNode* _node,unsigned src, unsigned sink)
565{
566 std::vector<ModuloSchedGraphNode*> set;
567 set.push_back(_node);
568 return succSet(set, src, sink);
569
570
571}
572
573std::vector<ModuloSchedGraphNode*> ModuloSchedGraph::succSet(ModuloSchedGraphNode* _node)
574{
575 return succSet(_node, 0, 0);
576}
577
578SchedGraphEdge* ModuloSchedGraph::getMaxDelayEdge(unsigned srcId, unsigned sinkId)
579{
580
581 ModuloSchedGraphNode* node =getNode(srcId);
582 SchedGraphEdge* maxDelayEdge=NULL;
583 int maxDelay=-1;
584 for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges();I !=E; I++)
585 {
586 SchedGraphEdge* edge= *I;
587 if(edge->getSink()->getNodeId() == sinkId)
588 if(edge->getMinDelay() > maxDelay){
589 maxDelayEdge=edge;
590 maxDelay=edge->getMinDelay();
591 }
592 }
593 assert(maxDelayEdge != NULL&&"no edge between the srcId and sinkId?");
594 return maxDelayEdge;
595}
596
597void ModuloSchedGraph::dumpCircuits()
598{
599 modSched_os<<"dumping circuits for graph: "<<"\n";
600 int j=-1;
601 while(circuits[++j][0] !=0){
602 int k=-1;
603 while(circuits[j][++k] !=0)
604 modSched_os<< circuits[j][k]<<"\t";
605 modSched_os<<"\n";
606 }
607}
608
609void ModuloSchedGraph::dumpSet(std::vector<ModuloSchedGraphNode*> set)
610{
611 for(unsigned i=0;i < set.size() ; i++)
612 modSched_os<< set[i]->getNodeId()<<"\t";
613 modSched_os<<"\n";
614}
615
616std::vector<ModuloSchedGraphNode*> ModuloSchedGraph::vectorUnion(std::vector<ModuloSchedGraphNode*> set1,std::vector<ModuloSchedGraphNode*> set2 )
617{
618 std::vector<ModuloSchedGraphNode*> unionVec;
619 for(unsigned i=0;i<set1.size();i++)
620 unionVec.push_back(set1[i]);
621 for(unsigned j=0;j < set2.size();j++){
622 bool inset=false;
623 for(unsigned i=0;i < unionVec.size();i++)
624 if(set2[j]==unionVec[i]) inset=true;
625 if(!inset)unionVec.push_back(set2[j]);
626 }
627 return unionVec;
628}
629std::vector<ModuloSchedGraphNode*> ModuloSchedGraph::vectorConj(std::vector<ModuloSchedGraphNode*> set1,std::vector<ModuloSchedGraphNode*> set2 )
630{
631 std::vector<ModuloSchedGraphNode*> conjVec;
632 for(unsigned i=0;i<set1.size();i++)
633 for(unsigned j=0;j < set2.size();j++)
634 if(set1[i]==set2[j]) conjVec.push_back(set1[i]);
635 return conjVec;
636}
637
638ModuloSchedGraph::NodeVec ModuloSchedGraph::vectorSub(NodeVec set1, NodeVec set2)
639{
640 NodeVec newVec;
641 for(NodeVec::iterator I=set1.begin(); I != set1.end(); I++){
642 bool inset=false;
643 for(NodeVec::iterator II=set2.begin(); II!=set2.end(); II++)
644 if( (*I)->getNodeId() ==(*II)->getNodeId())
645 {inset=true;break;}
646 if(!inset) newVec.push_back(*I);
647 }
648 return newVec;
649}
650
651void ModuloSchedGraph::orderNodes(){
652 oNodes.clear();
653
654 std::vector<ModuloSchedGraphNode*> set;
655 const BasicBlock* bb=bbVec[0];
656 unsigned numNodes = bb->size();
657
658 //first order all the sets
659 int j=-1;
660 int totalDelay=-1;
661 int preDelay=-1;
662 while(circuits[++j][0] !=0){
663 int k=-1;
664 preDelay=totalDelay;
665
666 while(circuits[j][++k] !=0){
667 ModuloSchedGraphNode* node =getNode(circuits[j][k]);
668 unsigned nextNodeId;
669 nextNodeId =circuits[j][k+1] !=0? circuits[j][k+1]:circuits[j][0];
670 SchedGraphEdge* edge = getMaxDelayEdge(circuits[j][k], nextNodeId);
671 totalDelay += edge->getMinDelay();
672 }
673 if(preDelay != -1 && totalDelay > preDelay){
674 //swap circuits[j][] and cuicuits[j-1][]
675 unsigned temp[MAXNODE];
676 for(int k=0;k<MAXNODE;k++){
677 temp[k]=circuits[j-1][k];
678 circuits[j-1][k]=circuits[j][k];
679 circuits[j][k]=temp[k];
680 }
681 //restart
682 j=-1;
683 }
684 }
685
686 //build the first set
687 int backEdgeSrc;
688 int backEdgeSink;
689 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
690 modSched_os<<"building the first set"<<"\n";
691 int setSeq=-1;
692 int k=-1;
693 setSeq++;
694 while(circuits[setSeq][++k]!=0)
695 set.push_back(getNode(circuits[setSeq][k]));
696 if(circuits[setSeq][0]!=0){
697 backEdgeSrc=circuits[setSeq][k-1];
698 backEdgeSink=circuits[setSeq][0];
699 }
700 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){
701 modSched_os<<"the first set is:";
702 dumpSet(set);
703 }
704
705 //implement the ordering algorithm
706 enum OrderSeq{ bottom_up, top_down};
707 OrderSeq order;
708 std::vector<ModuloSchedGraphNode*> R;
709 while(!set.empty())
710 {
711 std::vector<ModuloSchedGraphNode*> pset=predSet(oNodes);
712 std::vector<ModuloSchedGraphNode*> sset=succSet(oNodes);
713
714 if(!pset.empty() && !vectorConj(pset,set).empty())
715 {R=vectorConj(pset,set);order=bottom_up;}
716 else if( !sset.empty() && !vectorConj(sset,set).empty())
717 {R=vectorConj(sset,set);order=top_down;}
718 else
719 {
720 int maxASAP=-1;
721 int position=-1;
722 for(unsigned i=0;i<set.size();i++){
723 int temp= set[i]->getASAP();
724 if(temp>maxASAP ) {
725 maxASAP=temp;
726 position=i;
727 }
728 }
729 R.push_back(set[position]);
730 order=bottom_up;
731 }
732
733 while(!R.empty()){
734 if(order== top_down){
735 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
736 modSched_os<<"in top_down round"<<"\n";
737 while(!R.empty()){
738 int maxHeight=-1;
739 NodeVec::iterator chosenI;
740 for(NodeVec::iterator I=R.begin();I != R.end();I++){
741 int temp=(*I)->height;
742 if( (temp > maxHeight) || ( temp == maxHeight && (*I)->mov <= (*chosenI)->mov ) ){
743
744 if((temp > maxHeight) || ( temp == maxHeight && (*I)->mov < (*chosenI)->mov )){
745 maxHeight=temp;
746 chosenI=I;
747 continue;
748 }
749 //possible case: instruction A and B has the same height and mov, but A has dependence to B
750 //e.g B is the branch instruction in the end, or A is the phi instruction at the beginning
751 if((*I)->mov == (*chosenI)->mov)
752 for(ModuloSchedGraphNode::const_iterator oe=(*I)->beginOutEdges(), end=(*I)->endOutEdges();oe !=end; oe++){
753 if((*oe)->getSink() == (*chosenI)){
754 maxHeight=temp;
755 chosenI=I;
756 continue;
757 }
758 }
759 }
760 }
761 ModuloSchedGraphNode* mu= *chosenI;
762 oNodes.push_back(mu);
763 R.erase(chosenI);
764 std::vector<ModuloSchedGraphNode*> succ_mu= succSet(mu,backEdgeSrc,backEdgeSink);
765 std::vector<ModuloSchedGraphNode*> comm=vectorConj(succ_mu,set);
766 comm=vectorSub(comm,oNodes);
767 R = vectorUnion(comm, R);
768 }
769 order=bottom_up;
770 R= vectorConj(predSet(oNodes), set);
771 } else{
772 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
773 modSched_os<<"in bottom up round"<<"\n";
774 while(!R.empty()){
775 int maxDepth=-1;
776 NodeVec::iterator chosenI;
777 for(NodeVec::iterator I=R.begin();I != R.end();I++){
778 int temp=(*I)->depth;
779 if( (temp > maxDepth) || ( temp == maxDepth && (*I)->mov < (*chosenI)->mov )){
780 maxDepth=temp;
781 chosenI=I;
782 }
783 }
784 ModuloSchedGraphNode* mu=*chosenI;
785 oNodes.push_back(mu);
786 R.erase(chosenI);
787 std::vector<ModuloSchedGraphNode*> pred_mu= predSet(mu,backEdgeSrc,backEdgeSink);
788 std::vector<ModuloSchedGraphNode*> comm=vectorConj(pred_mu,set);
789 comm=vectorSub(comm,oNodes);
790 R = vectorUnion(comm, R);
791 }
792 order=top_down;
793 R= vectorConj(succSet(oNodes), set);
794 }
795 }
796 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){
797 modSched_os<<"order finished"<<"\n";
798 modSched_os<<"dumping the ordered nodes: "<<"\n";
799 dumpSet(oNodes);
800 dumpCircuits();
801 }
802 //create a new set
803 //FIXME: the nodes between onodes and this circuit should also be include in this set
804 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
805 modSched_os<<"building the next set"<<"\n";
806 set.clear();
807 int k=-1;
808 setSeq++;
809 while(circuits[setSeq][++k]!=0)
810 set.push_back(getNode(circuits[setSeq][k]));
811 if(circuits[setSeq][0]!=0){
812 backEdgeSrc=circuits[setSeq][k-1];
813 backEdgeSink=circuits[setSeq][0];
814 }
815 if(set.empty()){
816 //no circuits any more
817 //collect all other nodes
818 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
819 modSched_os<<"no circuits any more, collect the rest nodes"<<"\n";
820 for(unsigned i=2;i<numNodes+2;i++){
821 bool inset=false;
822 for(unsigned j=0;j< oNodes.size();j++)
823 if(oNodes[j]->getNodeId() == i)
824 {inset=true;break;}
825 if(!inset)set.push_back(getNode(i));
826 }
827 }
828 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){
829 modSched_os<<"next set is: "<<"\n";
830 dumpSet(set);
831 }
832 }//while(!set.empty())
833
834}
835
836
837
838
839
840
841void ModuloSchedGraph::buildGraph (const TargetMachine& target)
842{
843 const BasicBlock* bb=bbVec[0];
844
845 assert(bbVec.size() ==1 &&"only handling a single basic block here");
846
847 // Use this data structure to note all machine operands that compute
848 // ordinary LLVM values. These must be computed defs (i.e., instructions).
849 // Note that there may be multiple machine instructions that define
850 // each Value.
851 ValueToDefVecMap valueToDefVecMap;
852
853 // Use this data structure to note all memory instructions.
854 // We use this to add memory dependence edges without a second full walk.
855 //
856 // vector<const Instruction*> memVec;
857 vector<ModuloSchedGraphNode*> memNodeVec;
858
859 // Use this data structure to note any uses or definitions of
860 // machine registers so we can add edges for those later without
861 // extra passes over the nodes.
862 // The vector holds an ordered list of references to the machine reg,
863 // ordered according to control-flow order. This only works for a
864 // single basic block, hence the assertion. Each reference is identified
865 // by the pair: <node, operand-number>.
866 //
867 RegToRefVecMap regToRefVecMap;
868
869
870
871 // Make a dummy root node. We'll add edges to the real roots later.
872 graphRoot = new ModuloSchedGraphNode(0, NULL, NULL, -1,target);
873 graphLeaf = new ModuloSchedGraphNode(1, NULL, NULL, -1,target);
874
875 //----------------------------------------------------------------
876 // First add nodes for all the LLVM instructions in the basic block
877 // because this greatly simplifies identifying which edges to add.
878 // Do this one VM instruction at a time since the ModuloSchedGraphNode needs that.
879 // Also, remember the load/store instructions to add memory deps later.
880 //----------------------------------------------------------------
881
882 //FIXME:if there is call instruction, then we shall quit somewhere
883 // currently we leave call instruction and continue construct graph
884
885 //dump only the blocks which are from loops
886
887
888 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
889 this->dump(bb);
890
891 if(!isLoop(bb)){
892 modSched_os <<" dumping non-loop BB:"<<endl;
893 dump(bb);
894 }
895 if( isLoop(bb))
896 {
897 buildNodesforBB(target, bb, memNodeVec, regToRefVecMap, valueToDefVecMap);
898
899 this->addDefUseEdges(bb);
900
901 this->addCDEdges(bb);
902
903 this->addMemEdges(bb);
904
905 //this->dump();
906
907 int ResII=this->computeResII(bb);
908 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
909 modSched_os << "ResII is " << ResII<<"\n";;
910 int RecII=this->computeRecII(bb);
911 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
912 modSched_os << "RecII is " <<RecII<<"\n";
913
914 this->MII=max(ResII, RecII);
915
916 this->computeNodeProperty(bb);
917 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
918 this->dumpNodeProperty();
919
920 this->orderNodes();
921
922 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
923 this->dump();
924 //this->instrScheduling();
925
926 //this->dumpScheduling();
927
928
929 }
930}
931
932ModuloSchedGraphNode* ModuloSchedGraph::getNode (const unsigned nodeId) const
933{
934 for(const_iterator I=begin(), E=end();I !=E;I++)
935 if((*I).second->getNodeId() ==nodeId)
936 return (ModuloSchedGraphNode*)(*I).second;
937 return NULL;
938}
939
940int ModuloSchedGraph::computeRecII(const BasicBlock* bb)
941{
942
943 int RecII=0;
944
945 //os<<"begining computerRecII()"<<"\n";
946
947
948 //FIXME: only deal with circuits starting at the first node: the phi node nodeId=2;
949
950 //search all elementary circuits in the dependance graph
951 //assume maximum number of nodes is MAXNODE
952
953 unsigned path[MAXNODE];
954 unsigned stack[MAXNODE][MAXNODE];
955
956
957 for(int j=0;j<MAXNODE;j++)
958 {path[j]=0;
959 for(int k=0;k<MAXNODE;k++)
960 stack[j][k]=0;
961 }
962 //in our graph, the node number starts at 2
963
964 //number of nodes, because each instruction will result in one node
965 const unsigned numNodes= bb->size();
966
967 int i=0;
968 path[i]=2;
969
970 ModuloSchedGraphNode* initNode=getNode(path[0]);
971 unsigned initNodeId=initNode->getNodeId();
972 ModuloSchedGraphNode* currentNode=initNode;
973
974 while(currentNode != NULL)
975 {
976 unsigned currentNodeId=currentNode->getNodeId();
977 // modSched_os<<"current node is "<<currentNodeId<<"\n";
978
979 ModuloSchedGraphNode* nextNode=NULL;
980 for(ModuloSchedGraphNode::const_iterator I=currentNode->beginOutEdges(), E=currentNode->endOutEdges(); I !=E; I++)
981 {
982 //modSched_os <<" searching in outgoint edges of node "<<currentNodeId<<"\n";
983 unsigned nodeId=((SchedGraphEdge*) *I)->getSink()->getNodeId();
984 bool inpath=false,instack=false;
985 int k;
986
987 //modSched_os<<"nodeId is "<<nodeId<<"\n";
988
989 k=-1;
990 while(path[++k] !=0)
991 if(nodeId == path[k])
992 {inpath=true;break;}
993
994
995
996 k=-1;
997 while(stack[i][++k] !=0 )
998 if(nodeId == stack[i][k])
999 {instack =true; break;}
1000
1001
1002 if( nodeId > currentNodeId && !inpath && !instack)
1003 {nextNode=(ModuloSchedGraphNode*) ((SchedGraphEdge*)*I)->getSink();break;}
1004
1005 }
1006 if(nextNode != NULL)
1007 {
1008 //modSched_os<<"find the next Node "<<nextNode->getNodeId()<<"\n";
1009
1010
1011 int j=0;
1012 while( stack[i][j] !=0) j++;
1013 stack[i][j]=nextNode->getNodeId();
1014
1015
1016 i++;
1017 path[i]=nextNode->getNodeId();
1018 currentNode=nextNode;
1019 }
1020 else
1021 {
1022 //modSched_os<<"no expansion any more"<<"\n";
1023 //confirmCircuit();
1024 for(ModuloSchedGraphNode::const_iterator I=currentNode->beginOutEdges(), E=currentNode->endOutEdges() ; I != E; I++)
1025 {
1026 unsigned nodeId=((SchedGraphEdge*)*I)->getSink()->getNodeId();
1027 if(nodeId == initNodeId)
1028 {
1029
1030 int j=-1;
1031 while(circuits[++j][0] !=0);
1032 for(int k=0;k<MAXNODE;k++)circuits[j][k]=path[k];
1033
1034 }
1035 }
1036 //remove this node in the path and clear the corresponding entries in the stack
1037 path[i]=0;
1038 int j=0;
1039 for(j=0;j<MAXNODE;j++)stack[i][j]=0;
1040 i--;
1041 currentNode=getNode(path[i]);
1042 }
1043 if(i==0)
1044 {
1045
1046 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1047 modSched_os<<"circuits found are: "<<"\n";
1048 int j=-1;
1049 while(circuits[++j][0] !=0){
1050 int k=-1;
1051 while(circuits[j][++k] !=0)
1052 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1053 modSched_os<< circuits[j][k]<<"\t";
1054 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1055 modSched_os<<"\n";
1056
1057
1058 //for this circuit, compute the sum of all edge delay
1059 int sumDelay=0;
1060 k=-1;
1061 while(circuits[j][++k] !=0)
1062 {
1063 //ModuloSchedGraphNode* node =getNode(circuits[j][k]);
1064 unsigned nextNodeId;
1065 nextNodeId =circuits[j][k+1] !=0? circuits[j][k+1]:circuits[j][0];
1066
1067 /*
1068 for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges();I !=E; I++)
1069 {
1070 SchedGraphEdge* edge= *I;
1071 if(edge->getSink()->getNodeId() == nextNodeId)
1072 {sumDelay += edge->getMinDelay();break;}
1073 }
1074 */
1075
1076 sumDelay += getMaxDelayEdge(circuits[j][k],nextNodeId)->getMinDelay();
1077
1078 }
1079 // assume we have distance 1, in this case the sumDelay is RecII
1080 // this is correct for SSA form only
1081 //
1082 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1083 modSched_os<<"The total Delay in the circuit is " <<sumDelay<<"\n";
1084
1085 RecII= RecII > sumDelay? RecII: sumDelay;
1086
1087 }
1088 return RecII;
1089 }
1090
1091 }
1092
1093 return -1;
1094}
1095
1096void ModuloSchedGraph::addResourceUsage(std::vector<pair<int,int> >& ruVec, int rid){
1097 //modSched_os<<"\nadding a resouce , current resouceUsage vector size is "<<ruVec.size()<<"\n";
1098 bool alreadyExists=false;
1099 for(unsigned i=0;i <ruVec.size() ; i++){
1100 if(rid == ruVec[i].first) {
1101 ruVec[i].second++;
1102 alreadyExists=true;
1103 break;
1104 }
1105 }
1106 if( !alreadyExists) ruVec.push_back(std::make_pair(rid, 1));
1107 //modSched_os<<"current resouceUsage vector size is "<<ruVec.size()<<"\n";
1108
1109}
1110void ModuloSchedGraph::dumpResourceUsage(std::vector< pair<int,int> > &ru)
1111{
1112 MachineSchedInfo& msi = (MachineSchedInfo&)target.getSchedInfo();
1113
1114 std::vector<pair<int,int> > resourceNumVector = msi.resourceNumVector;
1115 modSched_os <<"resourceID\t"<<"resourceNum"<<"\n";
1116 for(unsigned i=0;i<resourceNumVector.size();i++)
1117 modSched_os <<resourceNumVector[i].first<<"\t"<<resourceNumVector[i].second<<"\n";
1118
1119 modSched_os <<" maxNumIssueTotal(issue slot in one cycle) = "<<msi.maxNumIssueTotal<<"\n";
1120 modSched_os<<"resourceID\t resourceUsage\t ResourceNum"<<"\n";
1121 for(unsigned i=0;i<ru.size();i++){
1122 modSched_os<<ru[i].first<<"\t"<<ru[i].second;
1123 const unsigned resNum=msi.getCPUResourceNum(ru[i].first);
1124 modSched_os<<"\t"<<resNum<<"\n";
1125 }
1126}
1127
1128int ModuloSchedGraph::computeResII(const BasicBlock* bb)
1129{
1130
1131 const MachineInstrInfo& mii = target.getInstrInfo();
1132 const MachineSchedInfo& msi = target.getSchedInfo();
1133
1134 int ResII;
1135 std::vector<pair<int,int> > resourceUsage; //pair<int resourceid, int resourceUsageTimes_in_the_whole_block>
1136
1137 //FIXME: number of functional units the target machine can provide should be get from Target
1138 // here I temporary hardcode it
1139
1140 for(BasicBlock::const_iterator I=bb->begin(),E=bb->end(); I !=E; I++)
1141 {
1142 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){
1143 modSched_os<<"machine instruction for llvm instruction( node "<<getGraphNodeForInst(I)->getNodeId()<<")" <<"\n";
1144 modSched_os<<"\t"<<*I;
1145 }
1146 MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(I);
1147 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1148 modSched_os <<"size =" <<tempMvec.size()<<"\n";
1149 for(unsigned i=0;i< tempMvec.size();i++)
1150 {
1151 MachineInstr* minstr=tempMvec[i];
1152
1153 unsigned minDelay=mii.minLatency(minstr->getOpCode());
1154 InstrRUsage rUsage=msi.getInstrRUsage(minstr->getOpCode());
1155 InstrClassRUsage classRUsage=msi.getClassRUsage(mii.getSchedClass(minstr->getOpCode()));
1156 unsigned totCycles= classRUsage.totCycles;
1157
1158 std::vector<std::vector<resourceId_t> > resources
1159 =rUsage.resourcesByCycle;
1160 assert(totCycles == resources.size());
1161 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1162 modSched_os <<"resources Usage for this Instr(totCycles=" << totCycles << ",mindLatency="<<mii.minLatency(minstr->getOpCode())<<"): "<< *minstr <<"\n";
1163 for(unsigned j=0;j< resources.size();j++){
1164 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1165 modSched_os<<"cycle "<<j<<": ";
1166 for(unsigned k=0;k< resources[j].size(); k++){
1167 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1168 modSched_os<<"\t"<<resources[j][k];
1169 addResourceUsage(resourceUsage,resources[j][k]);
1170 }
1171 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1172 modSched_os<<"\n";
1173 }
1174 }
1175 }
1176 if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1177 this->dumpResourceUsage(resourceUsage);
1178
1179 //compute ResII
1180 ResII=0;
1181 int issueSlots=msi.maxNumIssueTotal;
1182 for(unsigned i=0;i<resourceUsage.size();i++){
1183 int resourceNum=msi.getCPUResourceNum(resourceUsage[i].first);
1184 int useNum=resourceUsage[i].second;
1185 double tempII;
1186 if(resourceNum <= issueSlots)
1187 tempII=ceil(1.0*useNum/resourceNum);
1188 else
1189 tempII=ceil(1.0*useNum/issueSlots);
1190 ResII=max((int)tempII,ResII);
1191 }
1192 return ResII;
1193}
1194
1195ModuloSchedGraphSet::ModuloSchedGraphSet(const Function* function, const TargetMachine& target)
1196 :method(function)
1197{
1198 buildGraphsForMethod(method,target);
1199
1200}
1201
1202
1203ModuloSchedGraphSet::~ModuloSchedGraphSet()
1204{
1205 //delete all the graphs
1206 for(iterator I=begin(), E=end();I !=E; ++I)
1207 delete *I;
1208}
1209
1210void ModuloSchedGraphSet::dump() const
1211{
1212 modSched_os << " ====== ModuloSched graphs for function `" <<method->getName()
1213 << "' =========\n\n";
1214 for(const_iterator I=begin(); I != end(); ++I)
1215 (*I)->dump();
1216
1217 modSched_os << "\n=========End graphs for funtion` "<<method->getName()
1218 << "' ==========\n\n";
1219}
1220
1221void ModuloSchedGraph::dump(const BasicBlock* bb)
1222{
1223 modSched_os<<"dumping basic block:";
1224 modSched_os<<(bb->hasName()?bb->getName(): "block")
1225 <<" (" << bb << ")"<<"\n";
1226
1227}
1228
1229void ModuloSchedGraph::dump(const BasicBlock* bb, std::ostream& os)
1230{
1231 os<<"dumping basic block:";
1232 os<<(bb->hasName()?bb->getName(): "block")
1233 <<" (" << bb << ")"<<"\n";
1234}
1235
1236void
1237ModuloSchedGraph::dump() const
1238{
1239 modSched_os << " ModuloSchedGraph for basic Blocks:";
1240 for(unsigned i=0, N =bbVec.size(); i< N; i++)
1241 {
1242 modSched_os<<(bbVec[i]->hasName()?bbVec[i]->getName(): "block")
1243 <<" (" << bbVec[i] << ")"
1244 << ((i==N-1)?"":", ");
1245 }
1246
1247 modSched_os <<"\n\n Actual Root nodes : ";
1248 for (unsigned i=0, N=graphRoot->outEdges.size(); i < N; i++)
1249 modSched_os << graphRoot->outEdges[i]->getSink()->getNodeId()
1250 << ((i == N-1)? "" : ", ");
1251
1252 modSched_os << "\n Graph Nodes:\n";
1253 //for (const_iterator I=begin(); I != end(); ++I)
1254 //modSched_os << "\n" << *I->second;
1255 unsigned numNodes=bbVec[0]->size();
1256 for(unsigned i=2;i< numNodes+2;i++)
1257 {
1258 ModuloSchedGraphNode* node= getNode(i);
1259 modSched_os << "\n" << *node;
1260 }
1261
1262 modSched_os << "\n";
1263}
1264void
1265ModuloSchedGraph::dumpNodeProperty() const
1266{
1267 const BasicBlock* bb=bbVec[0];
1268 unsigned numNodes=bb->size();
1269 for(unsigned i=2;i < numNodes+2;i++)
1270 {
1271 ModuloSchedGraphNode* node=getNode(i);
1272 modSched_os<<"NodeId "<<node->getNodeId()<<"\t";
1273 modSched_os<<"ASAP "<<node->getASAP()<<"\t";
1274 modSched_os<<"ALAP "<<node->getALAP()<<"\t";
1275 modSched_os<<"mov " <<node->getMov() <<"\t";
1276 modSched_os<<"depth "<<node->getDepth()<<"\t";
1277 modSched_os<<"height "<<node->getHeight()<<"\t";
1278 modSched_os<<"\n";
1279 }
1280}
1281
1282void ModuloSchedGraphSet::buildGraphsForMethod (const Function *F, const TargetMachine& target)
1283{
1284 for(Function::const_iterator BI = F->begin(); BI != F->end(); ++BI)
1285 addGraph(new ModuloSchedGraph(BI,target));
1286}
1287
1288std::ostream &operator<<(std::ostream &os, const ModuloSchedGraphNode& node)
1289{
1290 os << std::string(8, ' ')
1291 << "Node " << node.nodeId << " : "
1292 << "latency = " << node.latency << "\n" << std::string(12, ' ');
1293
1294
1295
1296 if (node.getInst() == NULL)
1297 os << "(Dummy node)\n";
1298 else
1299 {
1300 os << *node.getInst() << "\n" << std::string(12, ' ');
1301 os << node.inEdges.size() << " Incoming Edges:\n";
1302 for (unsigned i=0, N=node.inEdges.size(); i < N; i++)
1303 os << std::string(16, ' ') << *node.inEdges[i];
1304
1305 os << std::string(12, ' ') << node.outEdges.size()
1306 << " Outgoing Edges:\n";
1307 for (unsigned i=0, N=node.outEdges.size(); i < N; i++)
1308 os << std::string(16, ' ') << *node.outEdges[i];
1309 }
1310
1311
1312 return os;
1313}