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