llvm.org GIT mirror llvm / 4f839cc
Putting my revised version of ModuloScheduling in cvs. This is not complete... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8179 91177308-0d34-0410-b5e6-96231b3b80d8 Tanya Lattner 17 years ago
8 changed file(s) with 392 addition(s) and 5962 deletion(s). Raw diff Collapse all Expand all
None //===- ModuloSchedGraph.cpp - Graph datastructure for Modulo Scheduling ---===//
1 //
2 //
0 //===- ModuloSchedGraph.cpp - Modulo Scheduling Graph and Set -*- C++ -*---===//
1 //
2 // Description here
33 //===----------------------------------------------------------------------===//
44
5 #include "llvm/CodeGen/InstrSelection.h"
6 #include "llvm/Function.h"
7 #include "llvm/Instructions.h"
5 #include "ModuloSchedGraph.h"
86 #include "llvm/Type.h"
9 #include "llvm/CodeGen/MachineCodeForInstruction.h"
10 #include "llvm/CodeGen/MachineInstr.h"
11 #include "llvm/Target/TargetSchedInfo.h"
12 #include "Support/StringExtras.h"
13 #include "Support/STLExtras.h"
14 #include "Support/hash_map"
15 #include "Support/Statistic.h"
16 #include "ModuloScheduling.h"
17 #include "ModuloSchedGraph.h"
18 #include
19 #include
20 #include
21 #include
7
8 ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned id, int index,
9 const Instruction *inst,
10 const TargetMachine &targ)
11 : SchedGraphNodeCommon(id, index), Inst(inst), Target(targ) {
12 }
13
14 void ModuloSchedGraphNode::print(std::ostream &os) const {
15 os << "Modulo Scheduling Node\n";
16 }
17
18 ModuloSchedGraph::ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &targ)
19 : SchedGraphCommon(), BB(bb), Target(targ) {
20
21 assert(BB != NULL && "Basic Block is null");
22
23 //Builds nodes from each instruction in the basic block
24 buildNodesForBB();
25
26 }
27
28 void ModuloSchedGraph::buildNodesForBB() {
29 int count = 0;
30 for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); i != e; ++i) {
31 addNode(i,new ModuloSchedGraphNode(size(), count, i, Target));
32 count++;
33 }
34
35 //Get machine instruction(s) for the llvm instruction
36 //MachineCodeForInstruction &MC = MachineCodeForInstruction::get(Node->first);
37
38
39 }
40
41 void ModuloSchedGraph::addNode(const Instruction *I,
42 ModuloSchedGraphNode *node) {
43 assert(node!= NULL && "New ModuloSchedGraphNode is null");
44 GraphMap[I] = node;
45 }
46
47 void ModuloSchedGraph::addDepEdges() {
48
49 //Get Machine target information for calculating delay
50 const TargetInstrInfo &MTI = Target.getInstrInfo();
51
52 //Loop over instruction in BB and gather dependencies
53 for(BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
54
55 //Ignore instructions of the void type
56 if(I->getType() != Type::VoidTy) {
57
58 //Iterate over def-use chain and add true dependencies
59 for (Value::use_const_iterator U = I->use_begin(), e = I->use_end(); U != e;
60 ++U) {
61 if (Instruction *Inst = dyn_cast(*U)) {
62 //Check if a node already exists for this instruction
63 ModuloSchedGraph::iterator Sink = find(Inst);
64
65 //If the instruction is in our graph, add appropriate edges
66 if(Sink->second != NULL) {
67 //assert if self loop
68 assert(&*I == Sink->first && "Use edge to itself!");
69
70 //Create edge and set delay equal to node latency
71 //FIXME: Is it safe to do this?
72 ModuloSchedGraph::iterator Src = find(I);
73 SchedGraphEdge *trueDep = new SchedGraphEdge(&*Src->second ,&*Sink->second, &*I,
74 SchedGraphEdge::TrueDep,
75 Src->second->getLatency());
76 //Determine the iteration difference
77 //FIXME: Will this ever happen?
78 }
79 }
80 }
81 }
82
83 }
84
85
86 }
87
88 void ModuloSchedGraph::ASAP() {
2289
2390
24 #define UNIDELAY 1
91 }
2592
26 using std::cerr;
27 using std::endl;
28 using std::vector;
93 void ModuloSchedGraph::ALAP() {
2994
3095
31 /***********member functions for ModuloSchedGraphNode*********/
96 }
3297
98 void ModuloSchedGraph::MOB() {
3399
34 ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned int in_nodeId,
35 const BasicBlock * in_bb,
36 const Instruction * in_inst,
37 int indexInBB,
38 const TargetMachine & target)
39 :SchedGraphNodeCommon(in_nodeId, indexInBB), inst(in_inst){
40
41 if (inst) {
42 //FIXME: find the latency
43 //currently set the latency to zero
44 latency = 0;
45 }
100 }
101
102 void ModuloSchedGraph::ComputeDepth() {
103
104 }
105
106 void ModuloSchedGraph::ComputeHeight() {
107
108 }
109
110 void ModuloSchedGraphSet::addGraph(ModuloSchedGraph *graph) {
111 assert(graph!=NULL && "Graph for BasicBlock is null");
112 Graphs.push_back(graph);
46113 }
47114
48115
49 /***********member functions for ModuloSchedGraph*********/
116 ModuloSchedGraphSet::ModuloSchedGraphSet(const Function *F,
117 const TargetMachine &targ)
118 : function(F) {
50119
51 void
52 ModuloSchedGraph::addDefUseEdges(const BasicBlock *bb){
53
54 //collect def instructions, store them in vector
55 const TargetInstrInfo & mii = target.getInstrInfo();
56 vector < ModuloSchedGraphNode * > defVec;
57
58
59 //find those def instructions
60 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; ++I) {
61 if (I->getType() != Type::VoidTy) {
62 defVec.push_back(this->getGraphNodeForInst(I));
63 }
64 }
65
66 for (unsigned int i = 0; i < defVec.size(); i++) {
67 for (Value::use_const_iterator I = defVec[i]->getInst()->use_begin();
68 I != defVec[i]->getInst()->use_end(); I++) {
69 //for each use of a def, add a flow edge from the def instruction to the
70 //ref instruction
71
72 const Instruction *value = defVec[i]->getInst();
73 Instruction *inst = (Instruction *) (*I);
74 ModuloSchedGraphNode *node = NULL;
75
76 for (BasicBlock::const_iterator ins = bb->begin(), E = bb->end();
77 ins != E; ++ins)
78 if ((const Instruction *) ins == inst) {
79 node = (*this)[inst];
80 break;
81 }
82
83
84 if (node == NULL){
85
86 //inst is not an instruction in this block
87 //do nothing
88
89 } else {
90 // Add a flow edge from the def instruction to the ref instruction
91 // This is a true dependence, so the delay is equal to the
92 //delay of the preceding node.
93
94 int delay = 0;
95
96 // self loop will not happen in SSA form
97 assert(defVec[i] != node && "same node?");
98
99 MachineCodeForInstruction & tempMvec =
100 MachineCodeForInstruction::get(value);
101 for (unsigned j = 0; j < tempMvec.size(); j++) {
102 MachineInstr *temp = tempMvec[j];
103 delay = std::max(delay, mii.minLatency(temp->getOpCode()));
104 }
105
106 SchedGraphEdge *trueEdge =
107 new SchedGraphEdge(defVec[i], node, value,
108 SchedGraphEdge::TrueDep, delay);
109
110 // if the ref instruction is before the def instrution
111 // then the def instruction must be a phi instruction
112 // add an anti-dependence edge to from the ref instruction to the def
113 // instruction
114 if (node->getOrigIndexInBB() < defVec[i]->getOrigIndexInBB()) {
115 assert(PHINode::classof(inst)
116 && "the ref instruction befre def is not PHINode?");
117 trueEdge->setIteDiff(1);
118 }
119
120 }
121
122 }
123 }
120 //Create graph for each BB in this function
121 for (Function::const_iterator BI = F->begin(); BI != F->end(); ++BI)
122 addGraph(new ModuloSchedGraph(BI, targ));
124123 }
125
126 void
127 ModuloSchedGraph::addCDEdges(const BasicBlock * bb) {
128
129 // find the last instruction in the basic block
130 // see if it is an branch instruction.
131 // If yes, then add an edge from each node expcept the last node
132 // to the last node
133
134 const Instruction *inst = &(bb->back());
135 ModuloSchedGraphNode *lastNode = (*this)[inst];
136 if (TerminatorInst::classof(inst))
137 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E;
138 I++) {
139 if (inst != I) {
140 ModuloSchedGraphNode *node = (*this)[I];
141 //use latency of 0
142 (void) new SchedGraphEdge(node, lastNode, SchedGraphEdge::CtrlDep,
143 SchedGraphEdge::NonDataDep, 0);
144 }
145
146 }
147 }
148
149 static const int SG_LOAD_REF = 0;
150 static const int SG_STORE_REF = 1;
151 static const int SG_CALL_REF = 2;
152
153 static const unsigned int SG_DepOrderArray[][3] = {
154 {SchedGraphEdge::NonDataDep,
155 SchedGraphEdge::AntiDep,
156 SchedGraphEdge::AntiDep},
157 {SchedGraphEdge::TrueDep,
158 SchedGraphEdge::OutputDep,
159 SchedGraphEdge::TrueDep | SchedGraphEdge::OutputDep},
160 {SchedGraphEdge::TrueDep,
161 SchedGraphEdge::AntiDep | SchedGraphEdge::OutputDep,
162 SchedGraphEdge::TrueDep | SchedGraphEdge::AntiDep
163 | SchedGraphEdge::OutputDep}
164 };
165
166
167 // Add a dependence edge between every pair of machine load/store/call
168 // instructions, where at least one is a store or a call.
169 // Use latency 1 just to ensure that memory operations are ordered;
170 // latency does not otherwise matter (true dependences enforce that).
171 //
172 void
173 ModuloSchedGraph::addMemEdges(const BasicBlock * bb) {
174
175 vector memNodeVec;
176
177 //construct the memNodeVec
178 for (BasicBlock::const_iterator I = bb->begin(),
179 E = bb->end(); I != E; ++I) {
180
181 if (LoadInst::classof(I) || StoreInst::classof(I)
182 || CallInst::classof(I)) {
183
184 ModuloSchedGraphNode *node = (*this)[(const Instruction *) I];
185 memNodeVec.push_back(node);
186
187 }
188 }
189
190 // Instructions in memNodeVec are in execution order within the
191 // basic block, so simply look at all pairs
192 // i]>.
193
194 for (unsigned im = 0, NM = memNodeVec.size(); im < NM; im++) {
195
196 const Instruction *fromInst,*toInst;
197 int toType, fromType;
198
199 //get the first mem instruction and instruction type
200 fromInst = memNodeVec[im]->getInst();
201 fromType = CallInst::classof(fromInst) ? SG_CALL_REF
202 : LoadInst::classof(fromInst) ? SG_LOAD_REF : SG_STORE_REF;
203
204 for (unsigned jm = im + 1; jm < NM; jm++) {
205
206 //get the second mem instruction and instruction type
207 toInst = memNodeVec[jm]->getInst();
208 toType = CallInst::classof(toInst) ? SG_CALL_REF
209 : LoadInst::classof(toInst) ? SG_LOAD_REF : SG_STORE_REF;
210
211 //add two edges if not both of them are LOAD instructions
212 if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF) {
213 (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm],
214 SchedGraphEdge::MemoryDep,
215 SG_DepOrderArray[fromType][toType], 1);
216
217 SchedGraphEdge *edge =
218 new SchedGraphEdge(memNodeVec[jm], memNodeVec[im],
219 SchedGraphEdge::MemoryDep,
220 SG_DepOrderArray[toType][fromType], 1);
221
222 //set the iteration difference for this edge to 1.
223 edge->setIteDiff(1);
224
225 }
226 }
227 }
228 }
229
230 /*
231 this function build graph nodes for each instruction
232 in the basicblock
233 */
234
235 void
236 ModuloSchedGraph::buildNodesforBB(const TargetMachine &target,
237 const BasicBlock *bb){
238
239 int i = 0;
240 ModuloSchedGraphNode *node;
241
242 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end();
243 I != E; ++I) {
244
245 node=new ModuloSchedGraphNode(getNumNodes(), bb, I, i, target);
246
247 i++;
248
249 this->addHash(I, node);
250 }
251
252 }
253
254
255 /*
256 determine if this basicblock includes a loop or not
257 */
258
259 bool
260 ModuloSchedGraph::isLoop(const BasicBlock *bb) {
261
262 //only if the last instruction in the basicblock is branch instruction and
263 //there is at least an option to branch itself
264
265 const Instruction *inst = &(bb->back());
266
267 if (BranchInst::classof(inst)) {
268 for (unsigned i = 0; i < ((BranchInst *) inst)->getNumSuccessors();
269 i++) {
270 BasicBlock *sb = ((BranchInst *) inst)->getSuccessor(i);
271 if (sb == bb)
272 return true;
273 }
274 }
275
276 return false;
277
278 }
279
280 /*
281 compute every node's ASAP
282
283 */
284
285 //FIXME: now assume the only backward edges come from the edges from other
286 //nodes to the phi Node so i will ignore all edges to the phi node; after
287 //this, there shall be no recurrence.
288
289 void
290 ModuloSchedGraph::computeNodeASAP(const BasicBlock *bb) {
291
292
293 unsigned numNodes = bb->size();
294 for (unsigned i = 2; i < numNodes + 2; i++) {
295 ModuloSchedGraphNode *node = getNode(i);
296 node->setPropertyComputed(false);
297 }
298
299 for (unsigned i = 2; i < numNodes + 2; i++) {
300 ModuloSchedGraphNode *node = getNode(i);
301 node->ASAP = 0;
302 if (i == 2 || node->getNumInEdges() == 0) {
303 node->setPropertyComputed(true);
304 continue;
305 }
306 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
307 node->endInEdges(); I != E; I++) {
308 SchedGraphEdge *edge = *I;
309 ModuloSchedGraphNode *pred =
310 (ModuloSchedGraphNode *) (edge->getSrc());
311 assert(pred->getPropertyComputed()
312 && "pred node property is not computed!");
313 int temp =
314 pred->ASAP + edge->getMinDelay() -
315 edge->getIteDiff() * this->MII;
316 node->ASAP = std::max(node->ASAP, temp);
317 }
318 node->setPropertyComputed(true);
319 }
320 }
321
322
323 /*
324 compute every node's ALAP in the basic block
325 */
326
327 void
328 ModuloSchedGraph::computeNodeALAP(const BasicBlock *bb) {
329
330 unsigned numNodes = bb->size();
331 int maxASAP = 0;
332 for (unsigned i = numNodes + 1; i >= 2; i--) {
333
334 ModuloSchedGraphNode *node = getNode(i);
335 node->setPropertyComputed(false);
336 maxASAP = std::max(maxASAP, node->ASAP);
337
338 }
339
340 for (unsigned i = numNodes + 1; i >= 2; i--) {
341 ModuloSchedGraphNode *node = getNode(i);
342
343 node->ALAP = maxASAP;
344
345 for (ModuloSchedGraphNode::const_iterator I =
346 node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) {
347
348 SchedGraphEdge *edge = *I;
349 ModuloSchedGraphNode *succ =
350 (ModuloSchedGraphNode *) (edge->getSink());
351 if (PHINode::classof(succ->getInst()))
352 continue;
353
354 assert(succ->getPropertyComputed()
355 && "succ node property is not computed!");
356
357 int temp =
358 succ->ALAP - edge->getMinDelay() +
359 edge->getIteDiff() * this->MII;
360
361 node->ALAP = std::min(node->ALAP, temp);
362
363 }
364 node->setPropertyComputed(true);
365 }
366 }
367
368 /*
369 compute every node's mov in this basicblock
370 */
371
372 void
373 ModuloSchedGraph::computeNodeMov(const BasicBlock *bb){
374
375 unsigned numNodes = bb->size();
376 for (unsigned i = 2; i < numNodes + 2; i++) {
377
378 ModuloSchedGraphNode *node = getNode(i);
379 node->mov = node->ALAP - node->ASAP;
380 assert(node->mov >= 0
381 && "move freedom for this node is less than zero? ");
382
383 }
384
385 }
386
387
388 /*
389 compute every node's depth in this basicblock
390 */
391 void
392 ModuloSchedGraph::computeNodeDepth(const BasicBlock * bb){
393
394 unsigned numNodes = bb->size();
395
396 for (unsigned i = 2; i < numNodes + 2; i++) {
397
398 ModuloSchedGraphNode *node = getNode(i);
399 node->setPropertyComputed(false);
400
401 }
402
403 for (unsigned i = 2; i < numNodes + 2; i++) {
404
405 ModuloSchedGraphNode *node = getNode(i);
406 node->depth = 0;
407 if (i == 2 || node->getNumInEdges() == 0) {
408 node->setPropertyComputed(true);
409 continue;
410 }
411
412 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
413 node->endInEdges(); I != E; I++) {
414 SchedGraphEdge *edge = *I;
415 ModuloSchedGraphNode *pred =
416 (ModuloSchedGraphNode *) (edge->getSrc());
417 assert(pred->getPropertyComputed()
418 && "pred node property is not computed!");
419 int temp = pred->depth + edge->getMinDelay();
420 node->depth = std::max(node->depth, temp);
421 }
422 node->setPropertyComputed(true);
423
424 }
425
426 }
427
428
429 /*
430 compute every node's height in this basic block
431 */
432
433 void
434 ModuloSchedGraph::computeNodeHeight(const BasicBlock *bb){
435
436 unsigned numNodes = bb->size();
437 for (unsigned i = numNodes + 1; i >= 2; i--) {
438 ModuloSchedGraphNode *node = getNode(i);
439 node->setPropertyComputed(false);
440 }
441
442 for (unsigned i = numNodes + 1; i >= 2; i--) {
443 ModuloSchedGraphNode *node = getNode(i);
444 node->height = 0;
445 for (ModuloSchedGraphNode::const_iterator I =
446 node->beginOutEdges(), E = node->endOutEdges(); I != E; ++I) {
447 SchedGraphEdge *edge = *I;
448 ModuloSchedGraphNode *succ =
449 (ModuloSchedGraphNode *) (edge->getSink());
450 if (PHINode::classof(succ->getInst()))
451 continue;
452 assert(succ->getPropertyComputed()
453 && "succ node property is not computed!");
454 node->height = std::max(node->height, succ->height + edge->getMinDelay());
455
456 }
457 node->setPropertyComputed(true);
458 }
459
460 }
461
462 /*
463 compute every node's property in a basicblock
464 */
465
466 void ModuloSchedGraph::computeNodeProperty(const BasicBlock * bb)
467 {
468 //FIXME: now assume the only backward edges come from the edges from other
469 //nodes to the phi Node so i will ignore all edges to the phi node; after
470 //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 /*
481 compute the preset of this set without considering the edges
482 between backEdgeSrc and backEdgeSink
483 */
484 std::vector
485 ModuloSchedGraph::predSet(std::vector set,
486 unsigned backEdgeSrc,
487 unsigned
488 backEdgeSink){
489
490 std::vector predS;
491
492 for (unsigned i = 0; i < set.size(); i++) {
493
494 ModuloSchedGraphNode *node = set[i];
495 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
496 node->endInEdges(); I != E; I++) {
497 SchedGraphEdge *edge = *I;
498
499 //if edges between backEdgeSrc and backEdgeSink, omitted
500 if (edge->getSrc()->getNodeId() == backEdgeSrc
501 && edge->getSink()->getNodeId() == backEdgeSink)
502 continue;
503 ModuloSchedGraphNode *pred =
504 (ModuloSchedGraphNode *) (edge->getSrc());
505
506 //if pred is not in the predSet ....
507 bool alreadyInset = false;
508 for (unsigned j = 0; j < predS.size(); ++j)
509 if (predS[j]->getNodeId() == pred->getNodeId()) {
510 alreadyInset = true;
511 break;
512 }
513
514 // and pred is not in the set ....
515 for (unsigned j = 0; j < set.size(); ++j)
516 if (set[j]->getNodeId() == pred->getNodeId()) {
517 alreadyInset = true;
518 break;
519 }
520
521 //push it into the predS
522 if (!alreadyInset)
523 predS.push_back(pred);
524 }
525 }
526 return predS;
527 }
528
529
530 /*
531 return pred set to this set
532 */
533
534 ModuloSchedGraph::NodeVec
535 ModuloSchedGraph::predSet(NodeVec set){
536
537 //node number increases from 2,
538 return predSet(set, 0, 0);
539 }
540
541 /*
542 return pred set to _node, ignoring
543 any edge between backEdgeSrc and backEdgeSink
544 */
545 std::vector
546 ModuloSchedGraph::predSet(ModuloSchedGraphNode *_node,
547 unsigned backEdgeSrc, unsigned backEdgeSink){
548
549 std::vector set;
550 set.push_back(_node);
551 return predSet(set, backEdgeSrc, backEdgeSink);
552 }
553
554
555 /*
556 return pred set to _node, ignoring
557 */
558
559 std::vector
560 ModuloSchedGraph::predSet(ModuloSchedGraphNode * _node){
561
562 return predSet(_node, 0, 0);
563
564 }
565
566 /*
567 return successor set to the input set
568 ignoring any edge between src and sink
569 */
570
571 std::vector
572 ModuloSchedGraph::succSet(std::vector set,
573 unsigned src, unsigned sink){
574
575 std::vector succS;
576
577 for (unsigned i = 0; i < set.size(); i++) {
578 ModuloSchedGraphNode *node = set[i];
579 for (ModuloSchedGraphNode::const_iterator I =
580 node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) {
581 SchedGraphEdge *edge = *I;
582
583 //if the edge is between src and sink, skip
584 if (edge->getSrc()->getNodeId() == src
585 && edge->getSink()->getNodeId() == sink)
586 continue;
587 ModuloSchedGraphNode *succ =
588 (ModuloSchedGraphNode *) (edge->getSink());
589
590 //if pred is not in the successor set ....
591 bool alreadyInset = false;
592 for (unsigned j = 0; j < succS.size(); j++)
593 if (succS[j]->getNodeId() == succ->getNodeId()) {
594 alreadyInset = true;
595 break;
596 }
597
598 //and not in this set ....
599 for (unsigned j = 0; j < set.size(); j++)
600 if (set[j]->getNodeId() == succ->getNodeId()) {
601 alreadyInset = true;
602 break;
603 }
604
605 //push it into the successor set
606 if (!alreadyInset)
607 succS.push_back(succ);
608 }
609 }
610 return succS;
611 }
612
613 /*
614 return successor set to the input set
615 */
616
617 ModuloSchedGraph::NodeVec ModuloSchedGraph::succSet(NodeVec set){
618
619 return succSet(set, 0, 0);
620
621 }
622
623 /*
624 return successor set to the input node
625 ignoring any edge between src and sink
626 */
627
628 std::vector
629 ModuloSchedGraph::succSet(ModuloSchedGraphNode *_node,
630 unsigned src, unsigned sink){
631
632 std::vectorset;
633
634 set.push_back(_node);
635
636 return succSet(set, src, sink);
637
638 }
639
640 /*
641 return successor set to the input node
642 */
643
644 std::vector
645 ModuloSchedGraph::succSet(ModuloSchedGraphNode * _node){
646
647 return succSet(_node, 0, 0);
648
649 }
650
651
652 /*
653 find maximum delay between srcId and sinkId
654 */
655
656 SchedGraphEdge*
657 ModuloSchedGraph::getMaxDelayEdge(unsigned srcId,
658 unsigned sinkId){
659
660 ModuloSchedGraphNode *node = getNode(srcId);
661 SchedGraphEdge *maxDelayEdge = NULL;
662 int maxDelay = -1;
663 for (ModuloSchedGraphNode::const_iterator I = node->beginOutEdges(), E =
664 node->endOutEdges(); I != E; I++) {
665 SchedGraphEdge *edge = *I;
666 if (edge->getSink()->getNodeId() == sinkId)
667 if (edge->getMinDelay() > maxDelay) {
668 maxDelayEdge = edge;
669 maxDelay = edge->getMinDelay();
670 }
671 }
672 assert(maxDelayEdge != NULL && "no edge between the srcId and sinkId?");
673 return maxDelayEdge;
674
675 }
676
677 /*
678 dump all circuits found
679 */
680
681 void
682 ModuloSchedGraph::dumpCircuits(){
683
684 DEBUG_PRINT(std::cerr << "dumping circuits for graph:\n");
685 int j = -1;
686 while (circuits[++j][0] != 0) {
687 int k = -1;
688 while (circuits[j][++k] != 0)
689 DEBUG_PRINT(std::cerr << circuits[j][k] << "\t");
690 DEBUG_PRINT(std::cerr << "\n");
691 }
692 }
693
694 /*
695 dump all sets found
696 */
697
698 void
699 ModuloSchedGraph::dumpSet(std::vector < ModuloSchedGraphNode * >set){
700
701 for (unsigned i = 0; i < set.size(); i++)
702 DEBUG_PRINT(std::cerr << set[i]->getNodeId() << "\t");
703 DEBUG_PRINT(std::cerr << "\n");
704
705 }
706
707 /*
708 return union of set1 and set2
709 */
710
711 std::vector
712 ModuloSchedGraph::vectorUnion(std::vector set1,
713 std::vector set2){
714
715 std::vector unionVec;
716 for (unsigned i = 0; i < set1.size(); i++)
717 unionVec.push_back(set1[i]);
718 for (unsigned j = 0; j < set2.size(); j++) {
719 bool inset = false;
720 for (unsigned i = 0; i < unionVec.size(); i++)
721 if (set2[j] == unionVec[i])
722 inset = true;
723 if (!inset)
724 unionVec.push_back(set2[j]);
725 }
726 return unionVec;
727 }
728
729 /*
730 return conjuction of set1 and set2
731 */
732 std::vector
733 ModuloSchedGraph::vectorConj(std::vector set1,
734 std::vector set2){
735
736 std::vector conjVec;
737 for (unsigned i = 0; i < set1.size(); i++)
738 for (unsigned j = 0; j < set2.size(); j++)
739 if (set1[i] == set2[j])
740 conjVec.push_back(set1[i]);
741 return conjVec;
742
743 }
744
745 /*
746 return the result of subtracting set2 from set1
747 (set1 -set2)
748 */
749 ModuloSchedGraph::NodeVec
750 ModuloSchedGraph::vectorSub(NodeVec set1,
751 NodeVec set2){
752
753 NodeVec newVec;
754 for (NodeVec::iterator I = set1.begin(); I != set1.end(); I++) {
755
756 bool inset = false;
757 for (NodeVec::iterator II = set2.begin(); II != set2.end(); II++)
758 if ((*I)->getNodeId() == (*II)->getNodeId()) {
759 inset = true;
760 break;
761 }
762
763 if (!inset)
764 newVec.push_back(*I);
765
766 }
767
768 return newVec;
769
770 }
771
772 /*
773 order all nodes in the basicblock
774 based on the sets information and node property
775
776 output: ordered nodes are stored in oNodes
777 */
778
779 void ModuloSchedGraph::orderNodes() {
780 oNodes.clear();
781
782 std::vector < ModuloSchedGraphNode * >set;
783 unsigned numNodes = bb->size();
784
785 // first order all the sets
786 int j = -1;
787 int totalDelay = -1;
788 int preDelay = -1;
789 while (circuits[++j][0] != 0) {
790 int k = -1;
791 preDelay = totalDelay;
792
793 while (circuits[j][++k] != 0) {
794 ModuloSchedGraphNode *node = getNode(circuits[j][k]);
795 unsigned nextNodeId;
796 nextNodeId =
797 circuits[j][k + 1] != 0 ? circuits[j][k + 1] : circuits[j][0];
798 SchedGraphEdge *edge = getMaxDelayEdge(circuits[j][k], nextNodeId);
799 totalDelay += edge->getMinDelay();
800 }
801 if (preDelay != -1 && totalDelay > preDelay) {
802 // swap circuits[j][] and cuicuits[j-1][]
803 unsigned temp[MAXNODE];
804 for (int k = 0; k < MAXNODE; k++) {
805 temp[k] = circuits[j - 1][k];
806 circuits[j - 1][k] = circuits[j][k];
807 circuits[j][k] = temp[k];
808 }
809 //restart
810 j = -1;
811 }
812 }
813
814
815 // build the first set
816 int backEdgeSrc;
817 int backEdgeSink;
818 if (ModuloScheduling::printScheduleProcess())
819 DEBUG_PRINT(std::cerr << "building the first set" << "\n");
820 int setSeq = -1;
821 int k = -1;
822 setSeq++;
823 while (circuits[setSeq][++k] != 0)
824 set.push_back(getNode(circuits[setSeq][k]));
825 if (circuits[setSeq][0] != 0) {
826 backEdgeSrc = circuits[setSeq][k - 1];
827 backEdgeSink = circuits[setSeq][0];
828 }
829 if (ModuloScheduling::printScheduleProcess()) {
830 DEBUG_PRINT(std::cerr << "the first set is:");
831 dumpSet(set);
832 }
833
834 // implement the ordering algorithm
835 enum OrderSeq { bottom_up, top_down };
836 OrderSeq order;
837 std::vector R;
838 while (!set.empty()) {
839 std::vector pset = predSet(oNodes);
840 std::vector sset = succSet(oNodes);
841
842 if (!pset.empty() && !vectorConj(pset, set).empty()) {
843 R = vectorConj(pset, set);
844 order = bottom_up;
845 } else if (!sset.empty() && !vectorConj(sset, set).empty()) {
846 R = vectorConj(sset, set);
847 order = top_down;
848 } else {
849 int maxASAP = -1;
850 int position = -1;
851 for (unsigned i = 0; i < set.size(); i++) {
852 int temp = set[i]->getASAP();
853 if (temp > maxASAP) {
854 maxASAP = temp;
855 position = i;
856 }
857 }
858 R.push_back(set[position]);
859 order = bottom_up;
860 }
861
862 while (!R.empty()) {
863 if (order == top_down) {
864 if (ModuloScheduling::printScheduleProcess())
865 DEBUG_PRINT(std::cerr << "in top_down round\n");
866 while (!R.empty()) {
867 int maxHeight = -1;
868 NodeVec::iterator chosenI;
869 for (NodeVec::iterator I = R.begin(); I != R.end(); I++) {
870 int temp = (*I)->height;
871 if ((temp > maxHeight)
872 || (temp == maxHeight && (*I)->mov <= (*chosenI)->mov)) {
873
874 if ((temp > maxHeight)
875 || (temp == maxHeight && (*I)->mov < (*chosenI)->mov)) {
876 maxHeight = temp;
877 chosenI = I;
878 continue;
879 }
880
881 //possible case: instruction A and B has the same height and mov,
882 //but A has dependence to B e.g B is the branch instruction in the
883 //end, or A is the phi instruction at the beginning
884 if ((*I)->mov == (*chosenI)->mov)
885 for (ModuloSchedGraphNode::const_iterator oe =
886 (*I)->beginOutEdges(), end = (*I)->endOutEdges();
887 oe != end; oe++) {
888 if ((*oe)->getSink() == (*chosenI)) {
889 maxHeight = temp;
890 chosenI = I;
891 continue;
892 }
893 }
894 }
895 }
896
897 ModuloSchedGraphNode *mu = *chosenI;
898 oNodes.push_back(mu);
899 R.erase(chosenI);
900 std::vector succ_mu =
901 succSet(mu, backEdgeSrc, backEdgeSink);
902 std::vector comm =
903 vectorConj(succ_mu, set);
904 comm = vectorSub(comm, oNodes);
905 R = vectorUnion(comm, R);
906 }
907 order = bottom_up;
908 R = vectorConj(predSet(oNodes), set);
909 } else {
910 if (ModuloScheduling::printScheduleProcess())
911 DEBUG_PRINT(std::cerr << "in bottom up round\n");
912 while (!R.empty()) {
913 int maxDepth = -1;
914 NodeVec::iterator chosenI;
915 for (NodeVec::iterator I = R.begin(); I != R.end(); I++) {
916 int temp = (*I)->depth;
917 if ((temp > maxDepth)
918 || (temp == maxDepth && (*I)->mov < (*chosenI)->mov)) {
919 maxDepth = temp;
920 chosenI = I;
921 }
922 }
923 ModuloSchedGraphNode *mu = *chosenI;
924 oNodes.push_back(mu);
925 R.erase(chosenI);
926 std::vector pred_mu =
927 predSet(mu, backEdgeSrc, backEdgeSink);
928 std::vector comm =
929 vectorConj(pred_mu, set);
930 comm = vectorSub(comm, oNodes);
931 R = vectorUnion(comm, R);
932 }
933 order = top_down;
934 R = vectorConj(succSet(oNodes), set);
935 }
936 }
937 if (ModuloScheduling::printScheduleProcess()) {
938 DEBUG_PRINT(std::cerr << "order finished\n");
939 DEBUG_PRINT(std::cerr << "dumping the ordered nodes:\n");
940 dumpSet(oNodes);
941 dumpCircuits();
942 }
943
944 //create a new set
945 //FIXME: the nodes between onodes and this circuit should also be include in
946 //this set
947 if (ModuloScheduling::printScheduleProcess())
948 DEBUG_PRINT(std::cerr << "building the next set\n");
949 set.clear();
950 int k = -1;
951 setSeq++;
952 while (circuits[setSeq][++k] != 0)
953 set.push_back(getNode(circuits[setSeq][k]));
954 if (circuits[setSeq][0] != 0) {
955 backEdgeSrc = circuits[setSeq][k - 1];
956 backEdgeSink = circuits[setSeq][0];
957 }
958
959 if (set.empty()) {
960 //no circuits any more
961 //collect all other nodes
962 if (ModuloScheduling::printScheduleProcess())
963 DEBUG_PRINT(std::cerr << "no circuits any more, collect the rest nodes\n");
964 for (unsigned i = 2; i < numNodes + 2; i++) {
965 bool inset = false;
966 for (unsigned j = 0; j < oNodes.size(); j++)
967 if (oNodes[j]->getNodeId() == i) {
968 inset = true;
969 break;
970 }
971 if (!inset)
972 set.push_back(getNode(i));
973 }
974 }
975 if (ModuloScheduling::printScheduleProcess()) {
976 DEBUG_PRINT(std::cerr << "next set is:\n");
977 dumpSet(set);
978 }
979 }
980
981 }
982
983
984
985 /*
986
987 build graph for instructions in this basic block
988
989 */
990 void ModuloSchedGraph::buildGraph(const TargetMachine & target)
991 {
992
993 assert(this->bb && "The basicBlock is NULL?");
994
995 // Make a dummy root node. We'll add edges to the real roots later.
996 graphRoot = new ModuloSchedGraphNode(0, NULL, NULL, -1, target);
997 graphLeaf = new ModuloSchedGraphNode(1, NULL, NULL, -1, target);
998
999 if (ModuloScheduling::printScheduleProcess())
1000 this->dump(bb);
1001
1002 if (isLoop(bb)) {
1003
1004 DEBUG_PRINT(cerr << "building nodes for this BasicBlock\n");
1005 buildNodesforBB(target, bb);
1006
1007 DEBUG_PRINT(cerr << "adding def-use edge to this basic block\n");
1008 this->addDefUseEdges(bb);
1009
1010 DEBUG_PRINT(cerr << "adding CD edges to this basic block\n");
1011 this->addCDEdges(bb);
1012
1013 DEBUG_PRINT(cerr << "adding memory edges to this basicblock\n");
1014 this->addMemEdges(bb);
1015
1016 int ResII = this->computeResII(bb);
1017
1018 if (ModuloScheduling::printScheduleProcess())
1019 DEBUG_PRINT(std::cerr << "ResII is " << ResII << "\n");
1020
1021 int RecII = this->computeRecII(bb);
1022 if (ModuloScheduling::printScheduleProcess())
1023 DEBUG_PRINT(std::cerr << "RecII is " << RecII << "\n");
1024
1025 this->MII = std::max(ResII, RecII);
1026
1027 this->computeNodeProperty(bb);
1028 if (ModuloScheduling::printScheduleProcess())
1029 this->dumpNodeProperty();
1030
1031 this->orderNodes();
1032
1033 if (ModuloScheduling::printScheduleProcess())
1034 this->dump();
1035
1036 }
1037 }
1038
1039 /*
1040 get node with nodeId
1041 */
1042
1043 ModuloSchedGraphNode *
1044 ModuloSchedGraph::getNode(const unsigned nodeId) const{
1045
1046 for (const_iterator I = begin(), E = end(); I != E; I++)
1047 if ((*I).second->getNodeId() == nodeId)
1048 return (ModuloSchedGraphNode *) (*I).second;
1049 return NULL;
1050
1051 }
1052
1053 /*
1054 compute RecurrenceII
1055 */
1056
1057 int
1058 ModuloSchedGraph::computeRecII(const BasicBlock *bb){
1059
1060 int RecII = 0;
1061
1062
1063 //FIXME: only deal with circuits starting at the first node: the phi node
1064 //nodeId=2;
1065
1066 //search all elementary circuits in the dependence graph
1067 //assume maximum number of nodes is MAXNODE
1068
1069 unsigned path[MAXNODE];
1070 unsigned stack[MAXNODE][MAXNODE];
1071
1072 for (int j = 0; j < MAXNODE; j++) {
1073 path[j] = 0;
1074 for (int k = 0; k < MAXNODE; k++)
1075 stack[j][k] = 0;
1076 }
1077
1078 //in our graph, the node number starts at 2
1079 const unsigned numNodes = bb->size();
1080
1081 int i = 0;
1082 path[i] = 2;
1083
1084 ModuloSchedGraphNode *initNode = getNode(path[0]);
1085 unsigned initNodeId = initNode->getNodeId();
1086 ModuloSchedGraphNode *currentNode = initNode;
1087
1088 while (currentNode != NULL) {
1089 unsigned currentNodeId = currentNode->getNodeId();
1090 // DEBUG_PRINT(std::cerr<<"current node is "<
1091
1092 ModuloSchedGraphNode *nextNode = NULL;
1093 for (ModuloSchedGraphNode::const_iterator I =
1094 currentNode->beginOutEdges(), E = currentNode->endOutEdges();
1095 I != E; I++) {
1096 //DEBUG_PRINT(std::cerr <<" searching in outgoint edges of node
1097 //"<
1098 unsigned nodeId = ((SchedGraphEdge *) * I)->getSink()->getNodeId();
1099 bool inpath = false, instack = false;
1100 int k;
1101
1102 //DEBUG_PRINT(std::cerr<<"nodeId is "<
1103
1104 k = -1;
1105 while (path[++k] != 0)
1106 if (nodeId == path[k]) {
1107 inpath = true;
1108 break;
1109 }
1110
1111 k = -1;
1112 while (stack[i][++k] != 0)
1113 if (nodeId == stack[i][k]) {
1114 instack = true;
1115 break;
1116 }
1117
1118 if (nodeId > currentNodeId && !inpath && !instack) {
1119 nextNode =
1120 (ModuloSchedGraphNode *) ((SchedGraphEdge *) * I)->getSink();
1121 break;
1122 }
1123 }
1124
1125 if (nextNode != NULL) {
1126 //DEBUG_PRINT(std::cerr<<"find the next Node "<getNodeId()<<"\n");
1127
1128 int j = 0;
1129 while (stack[i][j] != 0)
1130 j++;
1131 stack[i][j] = nextNode->getNodeId();
1132
1133 i++;
1134 path[i] = nextNode->getNodeId();
1135 currentNode = nextNode;
1136 } else {
1137 //DEBUG_PRINT(std::cerr<<"no expansion any more"<<"\n");
1138 //confirmCircuit();
1139 for (ModuloSchedGraphNode::const_iterator I =
1140 currentNode->beginOutEdges(), E = currentNode->endOutEdges();
1141 I != E; I++) {
1142 unsigned nodeId = ((SchedGraphEdge *) * I)->getSink()->getNodeId();
1143 if (nodeId == initNodeId) {
1144
1145 int j = -1;
1146 while (circuits[++j][0] != 0);
1147 for (int k = 0; k < MAXNODE; k++)
1148 circuits[j][k] = path[k];
1149
1150 }
1151 }
1152 //remove this node in the path and clear the corresponding entries in the
1153 //stack
1154 path[i] = 0;
1155 int j = 0;
1156 for (j = 0; j < MAXNODE; j++)
1157 stack[i][j] = 0;
1158 i--;
1159 currentNode = getNode(path[i]);
1160 }
1161 if (i == 0) {
1162
1163 if (ModuloScheduling::printScheduleProcess())
1164 DEBUG_PRINT(std::cerr << "circuits found are:\n");
1165 int j = -1;
1166 while (circuits[++j][0] != 0) {
1167 int k = -1;
1168 while (circuits[j][++k] != 0)
1169 if (ModuloScheduling::printScheduleProcess())
1170 DEBUG_PRINT(std::cerr << circuits[j][k] << "\t");
1171 if (ModuloScheduling::printScheduleProcess())
1172 DEBUG_PRINT(std::cerr << "\n");
1173
1174 //for this circuit, compute the sum of all edge delay
1175 int sumDelay = 0;
1176 k = -1;
1177 while (circuits[j][++k] != 0) {
1178 //ModuloSchedGraphNode* node =getNode(circuits[j][k]);
1179 unsigned nextNodeId;
1180 nextNodeId =
1181 circuits[j][k + 1] !=
1182 0 ? circuits[j][k + 1] : circuits[j][0];
1183
1184 sumDelay +=
1185 getMaxDelayEdge(circuits[j][k], nextNodeId)->getMinDelay();
1186
1187 }
1188 // assume we have distance 1, in this case the sumDelay is RecII
1189 // this is correct for SSA form only
1190 //
1191 if (ModuloScheduling::printScheduleProcess())
1192 DEBUG_PRINT(std::cerr << "The total Delay in the circuit is " << sumDelay
1193 << "\n");
1194
1195 RecII = RecII > sumDelay ? RecII : sumDelay;
1196
1197 }
1198 return RecII;
1199 }
1200
1201 }
1202
1203 return -1;
1204 }
1205
1206 /*
1207 update resource usage vector (ruVec)
1208 */
1209 void
1210 ModuloSchedGraph::addResourceUsage(std::vector > &ruVec,
1211 int rid){
1212
1213 bool alreadyExists = false;
1214 for (unsigned i = 0; i < ruVec.size(); i++) {
1215 if (rid == ruVec[i].first) {
1216 ruVec[i].second++;
1217 alreadyExists = true;
1218 break;
1219 }
1220 }
1221 if (!alreadyExists)
1222 ruVec.push_back(std::make_pair(rid, 1));
1223
1224 }
1225
1226 /*
1227 dump the resource usage vector
1228 */
1229
1230 void
1231 ModuloSchedGraph::dumpResourceUsage(std::vector > &ru){
1232
1233 TargetSchedInfo & msi = (TargetSchedInfo &) target.getSchedInfo();
1234
1235 std::vector > resourceNumVector = msi.resourceNumVector;
1236 DEBUG_PRINT(std::cerr << "resourceID\t" << "resourceNum\n");
1237 for (unsigned i = 0; i < resourceNumVector.size(); i++)
1238 DEBUG_PRINT(std::cerr << resourceNumVector[i].
1239 first << "\t" << resourceNumVector[i].second << "\n");
1240
1241 DEBUG_PRINT(std::cerr << " maxNumIssueTotal(issue slot in one cycle) = " << msi.
1242 maxNumIssueTotal << "\n");
1243 DEBUG_PRINT(std::cerr << "resourceID\t resourceUsage\t ResourceNum\n");
1244 for (unsigned i = 0; i < ru.size(); i++) {
1245 DEBUG_PRINT(std::cerr << ru[i].first << "\t" << ru[i].second);
1246 const unsigned resNum = msi.getCPUResourceNum(ru[i].first);
1247 DEBUG_PRINT(std::cerr << "\t" << resNum << "\n");
1248
1249 }
1250 }
1251
1252 /*
1253 compute thre resource restriction II
1254 */
1255
1256 int
1257 ModuloSchedGraph::computeResII(const BasicBlock * bb){
1258
1259 const TargetInstrInfo & mii = target.getInstrInfo();
1260 const TargetSchedInfo & msi = target.getSchedInfo();
1261
1262 int ResII;
1263 std::vector > resourceUsage;
1264
1265 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E;
1266 I++) {
1267 if (ModuloScheduling::printScheduleProcess()) {
1268 DEBUG_PRINT(std::cerr << "machine instruction for llvm instruction( node " <<
1269 getGraphNodeForInst(I)->getNodeId() << ")\n");
1270 DEBUG_PRINT(std::cerr << "\t" << *I);
1271 }
1272 MachineCodeForInstruction & tempMvec =
1273 MachineCodeForInstruction::get(I);
1274 if (ModuloScheduling::printScheduleProcess())
1275 DEBUG_PRINT(std::cerr << "size =" << tempMvec.size() << "\n");
1276 for (unsigned i = 0; i < tempMvec.size(); i++) {
1277 MachineInstr *minstr = tempMvec[i];
1278
1279 unsigned minDelay = mii.minLatency(minstr->getOpCode());
1280 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
1281 InstrClassRUsage classRUsage =
1282 msi.getClassRUsage(mii.getSchedClass(minstr->getOpCode()));
1283 unsigned totCycles = classRUsage.totCycles;
1284
1285 std::vector > resources=rUsage.resourcesByCycle;
1286 assert(totCycles == resources.size());
1287 if (ModuloScheduling::printScheduleProcess())
1288 DEBUG_PRINT(std::cerr << "resources Usage for this Instr(totCycles="
1289 << totCycles << ",mindLatency="
1290 << mii.minLatency(minstr->getOpCode()) << "): " << *minstr
1291 << "\n");
1292 for (unsigned j = 0; j < resources.size(); j++) {
1293 if (ModuloScheduling::printScheduleProcess())
1294 DEBUG_PRINT(std::cerr << "cycle " << j << ": ");
1295 for (unsigned k = 0; k < resources[j].size(); k++) {
1296 if (ModuloScheduling::printScheduleProcess())
1297 DEBUG_PRINT(std::cerr << "\t" << resources[j][k]);
1298 addResourceUsage(resourceUsage, resources[j][k]);
1299 }
1300 if (ModuloScheduling::printScheduleProcess())
1301 DEBUG_PRINT(std::cerr << "\n");
1302 }
1303 }
1304 }
1305 if (ModuloScheduling::printScheduleProcess())
1306 this->dumpResourceUsage(resourceUsage);
1307
1308 //compute ResII
1309 ResII = 0;
1310 int issueSlots = msi.maxNumIssueTotal;
1311 for (unsigned i = 0; i < resourceUsage.size(); i++) {
1312 int resourceNum = msi.getCPUResourceNum(resourceUsage[i].first);
1313 int useNum = resourceUsage[i].second;
1314 double tempII;
1315 if (resourceNum <= issueSlots)
1316 tempII = ceil(1.0 * useNum / resourceNum);
1317 else
1318 tempII = ceil(1.0 * useNum / issueSlots);
1319 ResII = std::max((int) tempII, ResII);
1320 }
1321 return ResII;
1322 }
1323
1324
1325
1326 /*
1327 dump the basicblock
1328 */
1329
1330 void
1331 ModuloSchedGraph::dump(const BasicBlock * bb){
1332
1333 DEBUG_PRINT(std::cerr << "dumping basic block:");
1334 DEBUG_PRINT(std::cerr << (bb->hasName()? bb->getName() : "block")
1335 << " (" << bb << ")" << "\n");
1336
1337 }
1338
1339 /*
1340 dump the basicblock to ostream os
1341 */
1342
1343 void
1344 ModuloSchedGraph::dump(const BasicBlock * bb, std::ostream & os){
1345
1346 os << "dumping basic block:";
1347 os << (bb->hasName()? bb->getName() : "block")
1348 << " (" << bb << ")" << "\n";
1349 }
1350
1351 /*
1352 dump the graph
1353 */
1354
1355 void ModuloSchedGraph::dump() const
1356 {
1357 DEBUG_PRINT(std::cerr << " ModuloSchedGraph for basic Blocks:");
1358
1359 DEBUG_PRINT(std::cerr << (bb->hasName()? bb->getName() : "block")
1360 << " (" << bb << ")" << "");
1361
1362 DEBUG_PRINT(std::cerr << "\n\n Actual Root nodes : ");
1363 for (unsigned i = 0, N = graphRoot->outEdges.size(); i < N; i++)
1364 DEBUG_PRINT(std::cerr << graphRoot->outEdges[i]->getSink()->getNodeId()
1365 << ((i == N - 1) ? "" : ", "));
1366
1367 DEBUG_PRINT(std::cerr << "\n Graph Nodes:\n");
1368
1369 unsigned numNodes = bb->size();
1370 for (unsigned i = 2; i < numNodes + 2; i++) {
1371 ModuloSchedGraphNode *node = getNode(i);
1372 DEBUG_PRINT(std::cerr << "\n" << *node);
1373 }
1374
1375 DEBUG_PRINT(std::cerr << "\n");
1376 }
1377
1378
1379 /*
1380 dump all node property
1381 */
1382
1383 void ModuloSchedGraph::dumpNodeProperty() const
1384 {
1385
1386 unsigned numNodes = bb->size();
1387 for (unsigned i = 2; i < numNodes + 2; i++) {
1388 ModuloSchedGraphNode *node = getNode(i);
1389 DEBUG_PRINT(std::cerr << "NodeId " << node->getNodeId() << "\t");
1390 DEBUG_PRINT(std::cerr << "ASAP " << node->getASAP() << "\t");
1391 DEBUG_PRINT(std::cerr << "ALAP " << node->getALAP() << "\t");
1392 DEBUG_PRINT(std::cerr << "mov " << node->getMov() << "\t");
1393 DEBUG_PRINT(std::cerr << "depth " << node->getDepth() << "\t");
1394 DEBUG_PRINT(std::cerr << "height " << node->getHeight() << "\t\n");
1395 }
1396 }
1397
1398
1399
1400
1401 /************member functions for ModuloSchedGraphSet**************/
1402
1403 /*
1404 constructor
1405 */
1406
1407 ModuloSchedGraphSet::ModuloSchedGraphSet(const Function *function,
1408 const TargetMachine &target)
1409 : method(function){
1410
1411 buildGraphsForMethod(method, target);
1412
1413 }
1414
1415 /*
1416 destructor
1417 */
1418
1419124
1420125 ModuloSchedGraphSet::~ModuloSchedGraphSet(){
1421126
1422127 //delete all the graphs
1423 for (iterator I = begin(), E = end(); I != E; ++I)
1424 delete *I;
1425128 }
1426129
1427
1428
1429 /*
1430 build graph for each basicblock in this method
1431 */
1432
1433 void
1434 ModuloSchedGraphSet::buildGraphsForMethod(const Function *F,
1435 const TargetMachine &target){
1436
1437 for (Function::const_iterator BI = F->begin(); BI != F->end(); ++BI){
1438 const BasicBlock* local_bb;
1439
1440 local_bb=BI;
1441 addGraph(new ModuloSchedGraph((BasicBlock*)local_bb, target));
1442 }
1443
1444 }
1445
1446 /*
1447 dump the graph set
1448 */
1449
1450 void
1451 ModuloSchedGraphSet::dump() const{
1452
1453 DEBUG_PRINT(std::cerr << " ====== ModuloSched graphs for function `" <<
1454 method->getName() << "' =========\n\n");
1455 for (const_iterator I = begin(); I != end(); ++I)
1456 (*I)->dump();
1457
1458 DEBUG_PRINT(std::cerr << "\n=========End graphs for function `" << method->getName()
1459 << "' ==========\n\n");
1460 }
1461
1462
1463
1464
1465 /********************misc functions***************************/
1466
1467
1468 /*
1469 dump the input basic block
1470 */
1471
1472 static void
1473 dumpBasicBlock(const BasicBlock * bb){
1474
1475 DEBUG_PRINT(std::cerr << "dumping basic block:");
1476 DEBUG_PRINT(std::cerr << (bb->hasName()? bb->getName() : "block")
1477 << " (" << bb << ")" << "\n");
1478 }
1479
1480 /*
1481 dump the input node
1482 */
1483
1484 std::ostream& operator<<(std::ostream &os,
1485 const ModuloSchedGraphNode &node)
1486 {
1487 os << std::string(8, ' ')
1488 << "Node " << node.nodeId << " : "
1489 << "latency = " << node.latency << "\n" << std::string(12, ' ');
1490
1491 if (node.getInst() == NULL)
1492 os << "(Dummy node)\n";
1493 else {
1494 os << *node.getInst() << "\n" << std::string(12, ' ');
1495 os << node.inEdges.size() << " Incoming Edges:\n";
1496 for (unsigned i = 0, N = node.inEdges.size(); i < N; i++)
1497 os << std::string(16, ' ') << *node.inEdges[i];
1498
1499 os << std::string(12, ' ') << node.outEdges.size()
1500 << " Outgoing Edges:\n";
1501 for (unsigned i = 0, N = node.outEdges.size(); i < N; i++)
1502 os << std::string(16, ' ') << *node.outEdges[i];
1503 }
1504
1505 return os;
1506 }
0 //===- ModuloSchedGraph.h - Modulo Scheduling Graph and Set -*- C++ -*-----===//
1 //
2 // This header defines the primative classes that make up a data structure
3 // graph.
1 //
42 //
53 //===----------------------------------------------------------------------===//
64
7 #ifndef LLVM_CODEGEN_MODULO_SCHED_GRAPH_H
8 #define LLVM_CODEGEN_MODULO_SCHED_GRAPH_H
5 #ifndef LLVM_MODULO_SCHED_GRAPH_H
6 #define LLVM_MODULO_SCHED_GRAPH_H
97
108 #include "llvm/Instruction.h"
9 #include "llvm/CodeGen/SchedGraphCommon.h"
1110 #include "llvm/Target/TargetMachine.h"
12 #include "llvm/Target/TargetInstrInfo.h"
13 #include "Support/GraphTraits.h"
11 #include "llvm/BasicBlock.h"
12 #include "llvm/Function.h"
1413 #include "Support/hash_map"
15 #include "../InstrSched/SchedGraphCommon.h"
16 #include <iostream>
14 #include <vector>
1715
18 //===----------------------------------------------------------------------===//
19 // ModuloSchedGraphNode - Implement a data structure based on the
20 // SchedGraphNodeCommon this class stores informtion needed later to order the
21 // nodes in modulo scheduling
22 //
23 class ModuloSchedGraphNode:public SchedGraphNodeCommon {
24 private:
25 // the corresponding instruction
26 const Instruction *inst;
2716
28 // whether this node's property(ASAP,ALAP, ...) has been computed
29 bool propertyComputed;
17 class ModuloSchedGraphNode : public SchedGraphNodeCommon {
3018
31 // ASAP: the earliest time the node could be scheduled
32 // ALAP: the latest time the node couldbe scheduled
33 // depth: the depth of the node
34 // height: the height of the node
35 // mov: the mobility function, computed as ALAP - ASAP
36 // scheTime: the scheduled time if this node has been scheduled
37 // earlyStart: the earliest time to be tried to schedule the node
38 // lateStart: the latest time to be tried to schedule the node
39 int ASAP, ALAP, depth, height, mov;
40 int schTime;
41 int earlyStart, lateStart;
19 const Instruction *Inst; //Node's Instruction
20 unsigned Earliest; //ASAP, or earliest time to be scheduled
21 unsigned Latest; //ALAP, or latested time to be scheduled
22 unsigned Depth; //Max Distance from node to the root
23 unsigned Height; //Max Distance from node to leaf
24 unsigned Mobility; //MOB, number of time slots it can be scheduled
25 const TargetMachine &Target; //Target information.
4226
4327 public:
28 ModuloSchedGraphNode(unsigned ID, int index, const Instruction *inst,
29 const TargetMachine &target);
30
31 void print(std::ostream &os) const;
32 const Instruction* getInst() { return Inst; }
33 unsigned getEarliest() { return Earliest; }
34 unsigned getLatest() { return Latest; }
35 unsigned getDepth() { return Depth; }
36 unsigned getHeight() { return Height; }
37 unsigned getMobility() { return Mobility; }
38
39 void setEarliest(unsigned early) { Earliest = early; }
40 void setLatest(unsigned late) { Latest = late; }
41 void setDepth(unsigned depth) { Depth = depth; }
42 void setHeight(unsigned height) { Height = height; }
43 void setMobility(unsigned mob) { Mobility = mob; }
4444
45 //get the instruction
46 const Instruction *getInst() const {
47 return inst;
48 }
49 //get the instruction op-code name
50 const char *getInstOpcodeName() const {
51 return inst->getOpcodeName();
52 }
53 //get the instruction op-code
54 const unsigned getInstOpcode() const {
55 return inst->getOpcode();
56 }
57
58 //return whether the node is NULL
59 bool isNullNode() const {
60 return (inst == NULL);
61 }
62 //return whether the property of the node has been computed
63 bool getPropertyComputed() {
64 return propertyComputed;
65 }
66 //set the propertyComputed
67 void setPropertyComputed(bool _propertyComputed) {
68 propertyComputed = _propertyComputed;
69 }
70
71 //get the corresponding property
72 int getASAP() {
73 return ASAP;
74 }
75 int getALAP() {
76 return ALAP;
77 }
78 int getMov() {
79 return mov;
80 }
81 int getDepth() {
82 return depth;
83 }
84 int getHeight() {
85 return height;
86 }
87 int getSchTime() {
88 return schTime;
89 }
90 int getEarlyStart() {
91 return earlyStart;
92 }
93 int getLateStart() {
94 return lateStart;
95 }
96 void setEarlyStart(int _earlyStart) {
97 earlyStart = _earlyStart;
98 }
99 void setLateStart(int _lateStart) {
100 lateStart = _lateStart;
101 }
102 void setSchTime(int _time) {
103 schTime = _time;
104 }
105
106 private:
107 friend class ModuloSchedGraph;
108 friend class SchedGraphNode;
109
110 //constructor:
111 //nodeId: the node id, unique within the each BasicBlock
112 //_bb: which BasicBlock the corresponding instruction belongs to
113 //_inst: the corresponding instruction
114 //indexInBB: the corresponding instruction's index in the BasicBlock
115 //target: the targetMachine
116 ModuloSchedGraphNode(unsigned int _nodeId,
117 const BasicBlock * _bb,
118 const Instruction * _inst,
119 int indexInBB, const TargetMachine &target);
120
121
122 friend std::ostream & operator<<(std::ostream & os,
123 const ModuloSchedGraphNode & edge);
12445
12546 };
12647
127 //FIXME: these two value should not be used
128 #define MAXNODE 100
129 #define MAXCC 100
48 class ModuloSchedGraph : public SchedGraphCommon {
49
50 const BasicBlock *BB; //The Basic block this graph represents
51 const TargetMachine &Target;
52 hash_map GraphMap;
13053
131 //===----------------------------------------------------------------------===//
132 /// ModuloSchedGraph- the data structure to store dependence between nodes
133 /// it catches data dependence and constrol dependence
134 ///
135 class ModuloSchedGraph :
136 public SchedGraphCommon,
137 protected hash_map {
138
139 private:
140
141 BasicBlock* bb;
142
143 //iteration Interval
144 int MII;
145
146 //target machine
147 const TargetMachine & target;
148
149 //the circuits in the dependence graph
150 unsigned circuits[MAXCC][MAXNODE];
151
152 //the order nodes
153 std::vector oNodes;
154
155 typedef std::vector NodeVec;
156
157 //the function to compute properties
158 void computeNodeASAP(const BasicBlock * in_bb);
159 void computeNodeALAP(const BasicBlock * in_bb);
160 void computeNodeMov(const BasicBlock * in_bb);
161 void computeNodeDepth(const BasicBlock * in_bb);
162 void computeNodeHeight(const BasicBlock * in_bb);
163
164 //the function to compute node property
165 void computeNodeProperty(const BasicBlock * in_bb);
166
167 //the function to sort nodes
168 void orderNodes();
169
170 //add the resource usage
171 void addResourceUsage(std::vector > &, int);
172
173 //debug functions:
174 //dump circuits
175 void dumpCircuits();
176 //dump the input set of nodes
177 void dumpSet(std::vector set);
178 //dump the input resource usage table
179 void dumpResourceUsage(std::vector > &);
54 void buildNodesForBB();
18055
18156 public:
182 //help functions
57 typedef hash_map
58 ModuloSchedGraphNode*>::iterator iterator;
59 typedef hash_map
60 ModuloSchedGraphNode*>::const_iterator const_iterator;
18361
184 //get the maxium the delay between two nodes
185 SchedGraphEdge *getMaxDelayEdge(unsigned srcId, unsigned sinkId);
18662
187 //FIXME:
188 //get the predessor Set of the set
189 NodeVec predSet(NodeVec set, unsigned, unsigned);
190 NodeVec predSet(NodeVec set);
63 ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &targ);
19164
192 //get the predessor set of the node
193 NodeVec predSet(ModuloSchedGraphNode *node, unsigned, unsigned);
194 NodeVec predSet(ModuloSchedGraphNode *node);
65 const BasicBlock* getBB() { return BB; }
66 void setBB(BasicBlock *bb) { BB = bb; }
67 unsigned size() { return GraphMap.size(); }
68 void addNode(const Instruction *I, ModuloSchedGraphNode *node);
69 void ASAP(); //Calculate earliest schedule time for all nodes in graph.
70 void ALAP(); //Calculate latest schedule time for all nodes in graph.
71 void MOB(); //Calculate mobility for all nodes in the graph.
72 void ComputeDepth(); //Compute depth of each node in graph
73 void ComputeHeight(); //Computer height of each node in graph
74 void addDepEdges(); //Add Dependencies
75 iterator find(const Instruction *I) { return GraphMap.find(I); }
76 };
19577
196 //get the successor set of the set
197 NodeVec succSet(NodeVec set, unsigned, unsigned);
198 NodeVec succSet(NodeVec set);
19978
200 //get the succssor set of the node
201 NodeVec succSet(ModuloSchedGraphNode *node, unsigned, unsigned);
202 NodeVec succSet(ModuloSchedGraphNode *node);
203
204 //return the uniton of the two vectors
205 NodeVec vectorUnion(NodeVec set1, NodeVec set2);
79 class ModuloSchedGraphSet {
20680
207 //return the consjuction of the two vectors
208 NodeVec vectorConj(NodeVec set1, NodeVec set2);
209
210 //return all nodes in set1 but not set2
211 NodeVec vectorSub(NodeVec set1, NodeVec set2);
212
213 typedef hash_map map_base;
81 const Function *function; //Function this set of graphs represent.
82 std::vector Graphs;
21483
21584 public:
216 using map_base::iterator;
217 using map_base::const_iterator;
85 typedef std::vector::iterator iterator;
86 typedef std::vector::const_iterator const_iterator;
87
88 iterator begin() { return Graphs.begin(); }
89 iterator end() { return Graphs.end(); }
90
91 ModuloSchedGraphSet(const Function *func, const TargetMachine &target);
92 ~ModuloSchedGraphSet();
21893
219 public:
220
221 //get target machine
222 const TargetMachine & getTarget() {
223 return target;
224 }
225
226 //get the basic block
227 BasicBlock* getBasicBlock() const {
228 return bb;
229 }
94 void addGraph(ModuloSchedGraph *graph);
95 void dump() const;
23096
23197
232 //get the iteration interval
233 const int getMII() {
234 return MII;
235 }
236
237 //get the ordered nodes
238 const NodeVec & getONodes() {
239 return oNodes;
240 }
241
242 //get the number of nodes (including the root and leaf)
243 //note: actually root and leaf is not used
244 const unsigned int getNumNodes() const {
245 return size() + 2;
246 }
247
248 //return wether the BasicBlock 'bb' contains a loop
249 bool isLoop(const BasicBlock *bb);
250
251 //return the node for the input instruction
252 ModuloSchedGraphNode *getGraphNodeForInst(const Instruction *inst) const {
253 const_iterator onePair = this->find(inst);
254 return (onePair != this->end()) ? (*onePair).second : NULL;
255 }
256
257 // Debugging support
258 //dump the graph
259 void dump() const;
260
261 // dump the basicBlock
262 void dump(const BasicBlock *bb);
263
264 //dump the basicBlock into 'os' stream
265 void dump(const BasicBlock *bb, std::ostream &os);
266
267 //dump the node property
268 void dumpNodeProperty() const;
269
270 private:
271 friend class ModuloSchedGraphSet; //give access to ctor
272
273 public:
274 ModuloSchedGraph(BasicBlock * in_bb,
275 const TargetMachine & in_target)
276 :SchedGraphCommon(), bb(in_bb),target(in_target)
277 {
278 buildGraph(target);
279 }
280
281 ~ModuloSchedGraph() {
282 for (const_iterator I = begin(); I != end(); ++I)
283 delete I->second;
284 }
285
286 // Unorder iterators
287 // return values are pair
288 using map_base::begin;
289 using map_base::end;
290
291 void addHash(const Instruction *inst,
292 ModuloSchedGraphNode *node){
293
294 assert((*this)[inst] == NULL);
295 (*this)[inst] = node;
296
297 }
298
299 // Graph builder
300 ModuloSchedGraphNode *getNode(const unsigned nodeId) const;
301
302 // Build the graph from the basicBlock
303 void buildGraph(const TargetMachine &target);
304
305 // Build nodes for BasicBlock
306 void buildNodesforBB(const TargetMachine &target,
307 const BasicBlock *bb);
308
309 //find definitiona and use information for all nodes
310 void findDefUseInfoAtInstr(const TargetMachine &target,
311 ModuloSchedGraphNode *node,
312 NodeVec &memNode,
313 RegToRefVecMap ®ToRefVecMap,
314 ValueToDefVecMap &valueToDefVecMap);
315
316 //add def-use edge
317 void addDefUseEdges(const BasicBlock *bb);
318
319 //add control dependence edges
320 void addCDEdges(const BasicBlock *bb);
321
322 //add memory dependence dges
323 void addMemEdges(const BasicBlock *bb);
324
325 //computer source restrictoin II
326 int computeResII(const BasicBlock *bb);
327
328 //computer recurrence II
329 int computeRecII(const BasicBlock *bb);
330 };
331
332 //==================================-
333 // Graph set
334
335 class ModuloSchedGraphSet : public std::vector {
336 private:
337 const Function *method;
338
339 public:
340 typedef std::vector baseVector;
341 using baseVector::iterator;
342 using baseVector::const_iterator;
343
344 public:
345 ModuloSchedGraphSet(const Function *function, const TargetMachine &target);
346 ~ModuloSchedGraphSet();
347
348 // Iterators
349 using baseVector::begin;
350 using baseVector::end;
351
352 // Debugging support
353 void dump() const;
354
355 private:
356 void addGraph(ModuloSchedGraph *graph) {
357 assert(graph != NULL);
358 this->push_back(graph);
359 }
360
361 // Graph builder
362 void buildGraphsForMethod(const Function *F,
363 const TargetMachine &target);
36498 };
36599
366100 #endif
None //===- ModuloScheduling.cpp - Modulo Software Pipelining ------------------===//
0 //===-- ModuloScheduling.cpp - Software Pipeling Approach - SMS --*- C++ -*--=//
11 //
2 // Implements the llvm/CodeGen/ModuloScheduling.h interface
2 // The is a software pipelining pass based on the Swing Modulo Scheduling
3 // alogrithm (SMS).
34 //
45 //===----------------------------------------------------------------------===//
56
6 #include "llvm/BasicBlock.h"
7 #include "llvm/Constants.h"
8 #include "llvm/iTerminators.h"
9 #include "llvm/iPHINode.h"
10 #include "llvm/CodeGen/MachineInstr.h"
11 #include "llvm/CodeGen/MachineCodeForInstruction.h"
12 #include "llvm/CodeGen/MachineFunction.h"
13 #include "llvm/CodeGen/InstrSelection.h"
14 #include "llvm/Target/TargetSchedInfo.h"
15 #include "llvm/Target/TargetMachine.h"
16 #include "Support/CommandLine.h"
17 #include "Support/Statistic.h"
187 #include "ModuloSchedGraph.h"
19 #include "ModuloScheduling.h"
20 #include
21 #include
228
23 //************************************************************
24 // printing Debug information
25 // ModuloSchedDebugLevel stores the value of debug level
26 // modsched_os is the ostream to dump debug information, which is written into
27 // the file 'moduloSchedDebugInfo.output'
28 // see ModuloSchedulingPass::runOnFunction()
29 //************************************************************
9 #include "llvm/Pass.h"
10 #include "llvm/Function.h"
3011
31 ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
12 namespace {
13
14 class ModuloScheduling : public FunctionPass {
15
16 public:
17 virtual bool runOnFunction(Function &F);
18 };
3219
33 cl::opt
34 SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
35 cl::desc("enable modulo scheduling debugging information"),
36 cl::values(clEnumValN(ModuloSchedDebugLevel_NoDebugInfo,
37 "none", "disable debug output"),
38 clEnumValN(ModuloSchedDebugLevel_PrintSchedule,
39 "psched", "print original and new schedule"),
40 clEnumValN(ModuloSchedDebugLevel_PrintScheduleProcess,
41 "pschedproc",
42 "print how the new schdule is produced"),
43 0));
44
45 // Computes the schedule and inserts epilogue and prologue
46 //
47 void
48 ModuloScheduling::instrScheduling(){
49
50
51 if (ModuloScheduling::printScheduleProcess())
52 DEBUG_PRINT(std::cerr << "************ computing modulo schedule ***********\n");
53
54 const TargetSchedInfo & msi = target.getSchedInfo();
55
56 //number of issue slots in the in each cycle
57 int numIssueSlots = msi.maxNumIssueTotal;
58
59 //compute the schedule
60 bool success = false;
61 while (!success) {
62 //clear memory from the last round and initialize if necessary
63 clearInitMem(msi);
64
65 //compute schedule and coreSchedule with the current II
66 success = computeSchedule();
67
68 if (!success) {
69 II++;
70 if (ModuloScheduling::printScheduleProcess())
71 DEBUG_PRINT(std::cerr << "increase II to " << II << "\n");
72 }
73 }
74
75 //print the final schedule
76 dumpFinalSchedule();
77
78 //the schedule has been computed
79 //create epilogue, prologue and kernel BasicBlock
80
81 //find the successor for this BasicBlock
82 BasicBlock *succ_bb = getSuccBB(bb);
83
84 //print the original BasicBlock if necessary
85 if (ModuloScheduling::printSchedule()) {
86 DEBUG_PRINT(std::cerr << "dumping the orginal block\n");
87 graph.dump(bb);
88 }
89 //construction of prologue, kernel and epilogue
90
91 /*
92 BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
93 BasicBlock *prologue = bb;
94 BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
95 */
96
97 // Construct prologue
98 /*constructPrologue(prologue);*/
99
100 // Construct kernel
101
102 /*constructKernel(prologue, kernel, epilogue);*/
103
104 // Construct epilogue
105
106 /*constructEpilogue(epilogue, succ_bb);*/
107
108 //print the BasicBlocks if necessary
109 // if (0){
110 // DEBUG_PRINT(std::cerr << "dumping the prologue block:\n");
111 // graph.dump(prologue);
112 // DEBUG_PRINT(std::cerr << "dumping the kernel block\n");
113 // graph.dump(kernel);
114 // DEBUG_PRINT(std::cerr << "dumping the epilogue block\n");
115 // graph.dump(epilogue);
116 // }
117
20 RegisterOpt X("modulo-sched", "Modulo Scheduling/Software Pipelining");
11821 }
11922
120
121 // Clear memory from the last round and initialize if necessary
122 //
123
124 void
125 ModuloScheduling::clearInitMem(const TargetSchedInfo & msi){
126
127 unsigned numIssueSlots = msi.maxNumIssueTotal;
128 // clear nodeScheduled from the last round
129 if (ModuloScheduling::printScheduleProcess()) {
130 DEBUG_PRINT(std::cerr << "***** new round with II= " << II << " ***********\n");
131 DEBUG_PRINT(std::cerr <<
132 " ************clear the vector nodeScheduled*************\n");
133 }
134 nodeScheduled.clear();
135
136 // clear resourceTable from the last round and reset it
137 resourceTable.clear();
138 for (unsigned i = 0; i < II; ++i)
139 resourceTable.push_back(msi.resourceNumVector);
140
141 // clear the schdule and coreSchedule from the last round
142 schedule.clear();
143 coreSchedule.clear();
144
145 // create a coreSchedule of size II*numIssueSlots
146 // each entry is NULL
147 while (coreSchedule.size() < II) {
148 std::vector < ModuloSchedGraphNode * >*newCycle =
149 new std::vector < ModuloSchedGraphNode * >();
150 for (unsigned k = 0; k < numIssueSlots; ++k)
151 newCycle->push_back(NULL);
152 coreSchedule.push_back(*newCycle);
153 }
23 //Create Modulo Scheduling Pass
24 Pass *createModuloSchedPass() {
25 return new ModuloScheduling();
15426 }
15527
156 // Compute schedule and coreSchedule with the current II
157 //
158 bool
159 ModuloScheduling::computeSchedule(){
28 //ModuloScheduling::runOnFunction - Main transformation entry point.
29 bool ModuloScheduling::runOnFunction(Function &F) {
30 bool Changed = false;
16031
161
162 if (ModuloScheduling::printScheduleProcess())
163 DEBUG_PRINT(std::cerr << "start to compute schedule\n");
164
165 // Loop over the ordered nodes
166 for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
167 // Try to schedule for node I
168 if (ModuloScheduling::printScheduleProcess())
169 dumpScheduling();
170 ModuloSchedGraphNode *node = *I;
171
172 // Compute whether this node has successor(s)
173 bool succ = true;
174
175 // Compute whether this node has predessor(s)
176 bool pred = true;
177
178 NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
179 if (schSucc.empty())
180 succ = false;
181 NodeVec schPred = graph.vectorConj(nodeScheduled, graph.predSet(node));
182 if (schPred.empty())
183 pred = false;
184
185 //startTime: the earliest time we will try to schedule this node
186 //endTime: the latest time we will try to schedule this node
187 int startTime, endTime;
188
189 //node's earlyStart: possible earliest time to schedule this node
190 //node's lateStart: possible latest time to schedule this node
191 node->setEarlyStart(-1);
192 node->setLateStart(9999);
193
194 //this node has predessor but no successor
195 if (!succ && pred) {
196 // This node's earlyStart is it's predessor's schedule time + the edge
197 // delay - the iteration difference* II
198 for (unsigned i = 0; i < schPred.size(); i++) {
199 ModuloSchedGraphNode *predNode = schPred[i];
200 SchedGraphEdge *edge =
201 graph.getMaxDelayEdge(predNode->getNodeId(),
202 node->getNodeId());
203 int temp =
204 predNode->getSchTime() + edge->getMinDelay() -
205 edge->getIteDiff() * II;
206 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
207 }
208 startTime = node->getEarlyStart();
209 endTime = node->getEarlyStart() + II - 1;
210 }
211 // This node has a successor but no predecessor
212 if (succ && !pred) {
213 for (unsigned i = 0; i < schSucc.size(); ++i) {
214 ModuloSchedGraphNode *succNode = schSucc[i];
215 SchedGraphEdge *edge =
216 graph.getMaxDelayEdge(succNode->getNodeId(),
217 node->getNodeId());
218 int temp =
219 succNode->getSchTime() - edge->getMinDelay() +
220 edge->getIteDiff() * II;
221 node->setLateStart(std::min(node->getEarlyStart(), temp));
222 }
223 startTime = node->getLateStart() - II + 1;
224 endTime = node->getLateStart();
225 }
226 // This node has both successors and predecessors
227 if (succ && pred) {
228 for (unsigned i = 0; i < schPred.size(); ++i) {
229 ModuloSchedGraphNode *predNode = schPred[i];
230 SchedGraphEdge *edge =
231 graph.getMaxDelayEdge(predNode->getNodeId(),
232 node->getNodeId());
233 int temp =
234 predNode->getSchTime() + edge->getMinDelay() -
235 edge->getIteDiff() * II;
236 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
237 }
238 for (unsigned i = 0; i < schSucc.size(); ++i) {
239 ModuloSchedGraphNode *succNode = schSucc[i];
240 SchedGraphEdge *edge =
241 graph.getMaxDelayEdge(succNode->getNodeId(),
242 node->getNodeId());
243 int temp =
244 succNode->getSchTime() - edge->getMinDelay() +
245 edge->getIteDiff() * II;
246 node->setLateStart(std::min(node->getEarlyStart(), temp));
247 }
248 startTime = node->getEarlyStart();
249 endTime = std::min(node->getLateStart(),
250 node->getEarlyStart() + ((int) II) - 1);
251 }
252 //this node has no successor or predessor
253 if (!succ && !pred) {
254 node->setEarlyStart(node->getASAP());
255 startTime = node->getEarlyStart();
256 endTime = node->getEarlyStart() + II - 1;
257 }
258 //try to schedule this node based on the startTime and endTime
259 if (ModuloScheduling::printScheduleProcess())
260 DEBUG_PRINT(std::cerr << "scheduling the node " << (*I)->getNodeId() << "\n");
261
262 bool success =
263 this->ScheduleNode(node, startTime, endTime, nodeScheduled);
264 if (!success)
265 return false;
266 }
267 return true;
32 return Changed;
26833 }
26934
270
271 // Get the successor of the BasicBlock
272 //
273 BasicBlock *
274 ModuloScheduling::getSuccBB(BasicBlock *bb){
275
276 BasicBlock *succ_bb;
277 for (unsigned i = 0; i < II; ++i)
278 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
279 if (coreSchedule[i][j]) {
280 const Instruction *ist = coreSchedule[i][j]->getInst();
281
282 //we can get successor from the BranchInst instruction
283 //assume we only have one successor (besides itself) here
284 if (BranchInst::classof(ist)) {
285 BranchInst *bi = (BranchInst *) ist;
286 assert(bi->isConditional() &&
287 "the branchInst is not a conditional one");
288 assert(bi->getNumSuccessors() == 2
289 && " more than two successors?");
290 BasicBlock *bb1 = bi->getSuccessor(0);
291 BasicBlock *bb2 = bi->getSuccessor(1);
292 assert((bb1 == bb || bb2 == bb) &&
293 " None of its successors is itself?");
294 if (bb1 == bb)
295 succ_bb = bb2;
296 else
297 succ_bb = bb1;
298 return succ_bb;
299 }
300 }
301 assert(0 && "NO Successor?");
302 return NULL;
303 }
304
305
306 // Get the predecessor of the BasicBlock
307 //
308 BasicBlock *
309 ModuloScheduling::getPredBB(BasicBlock *bb){
310
311 BasicBlock *pred_bb;
312 for (unsigned i = 0; i < II; ++i)
313 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
314 if (coreSchedule[i][j]) {
315 const Instruction *ist = coreSchedule[i][j]->getInst();
316
317 //we can get predecessor from the PHINode instruction
318 //assume we only have one predecessor (besides itself) here
319 if (PHINode::classof(ist)) {
320 PHINode *phi = (PHINode *) ist;
321 assert(phi->getNumIncomingValues() == 2 &&
322 " the number of incoming value is not equal to two? ");
323 BasicBlock *bb1 = phi->getIncomingBlock(0);
324 BasicBlock *bb2 = phi->getIncomingBlock(1);
325 assert((bb1 == bb || bb2 == bb) &&
326 " None of its predecessor is itself?");
327 if (bb1 == bb)
328 pred_bb = bb2;
329 else
330 pred_bb = bb1;
331 return pred_bb;
332 }
333 }
334 assert(0 && " no predecessor?");
335 return NULL;
336 }
337
338
339 // Construct the prologue
340 //
341 void
342 ModuloScheduling::constructPrologue(BasicBlock *prologue){
343
344 InstListType & prologue_ist = prologue->getInstList();
345 vvNodeType & tempSchedule_prologue =
346 *(new std::vector >(schedule));
347
348 //compute the schedule for prologue
349 unsigned round = 0;
350 unsigned scheduleSize = schedule.size();
351 while (round < scheduleSize / II) {
352 round++;
353 for (unsigned i = 0; i < scheduleSize; ++i) {
354 if (round * II + i >= scheduleSize)
355 break;
356 for (unsigned j = 0; j < schedule[i].size(); ++j) {
357 if (schedule[i][j]) {
358 assert(tempSchedule_prologue[round * II + i][j] == NULL &&
359 "table not consitent with core table");
360 // move the schedule one iteration ahead and overlap with the original
361 tempSchedule_prologue[round * II + i][j] = schedule[i][j];
362 }
363 }
364 }
365 }
366
367 // Clear the clone memory in the core schedule instructions
368 clearCloneMemory();
369
370 // Fill in the prologue
371 for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
372 for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
373 if (tempSchedule_prologue[i][j]) {
374
375 //get the instruction
376 Instruction *orn =
377 (Instruction *) tempSchedule_prologue[i][j]->getInst();
378
379 //made a clone of it
380 Instruction *cln = cloneInstSetMemory(orn);
381
382 //insert the instruction
383 prologue_ist.insert(prologue_ist.back(), cln);
384
385 //if there is PHINode in the prologue, the incoming value from itself
386 //should be removed because it is not a loop any longer
387 if (PHINode::classof(cln)) {
388 PHINode *phi = (PHINode *) cln;
389 phi->removeIncomingValue(phi->getParent());
390 }
391 }
392 }
393
394
395 // Construct the kernel BasicBlock
396 //
397 void
398 ModuloScheduling::constructKernel(BasicBlock *prologue,
399 BasicBlock *kernel,
400 BasicBlock *epilogue){
401
402 //*************fill instructions in the kernel****************
403 InstListType & kernel_ist = kernel->getInstList();
404 BranchInst *brchInst;
405 PHINode *phiInst, *phiCln;
406
407 for (unsigned i = 0; i < coreSchedule.size(); ++i)
408 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
409 if (coreSchedule[i][j]) {
410
411 // Take care of branch instruction differently with normal instructions
412 if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
413 brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
414 continue;
415 }
416 // Take care of PHINode instruction differently with normal instructions
417 if (PHINode::classof(coreSchedule[i][j]->getInst())) {
418 phiInst = (PHINode *) coreSchedule[i][j]->getInst();
419 Instruction *cln = cloneInstSetMemory(phiInst);
420 kernel_ist.insert(kernel_ist.back(), cln);
421 phiCln = (PHINode *) cln;
422 continue;
423 }
424 //for normal instructions: made a clone and insert it in the kernel_ist
425 Instruction *cln =
426 cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
427 getInst());
428 kernel_ist.insert(kernel_ist.back(), cln);
429 }
430 // The two incoming BasicBlock for PHINode is the prologue and the kernel
431 // (itself)
432 phiCln->setIncomingBlock(0, prologue);
433 phiCln->setIncomingBlock(1, kernel);
434
435 // The incoming value for the kernel (itself) is the new value which is
436 // computed in the kernel
437 Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
438 phiCln->setIncomingValue(1, originalVal->getClone());
439
440 // Make a clone of the branch instruction and insert it in the end
441 BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
442 kernel_ist.insert(kernel_ist.back(), cln);
443
444 // delete the unconditional branch instruction, which is generated when
445 // splitting the basicBlock
446 kernel_ist.erase(--kernel_ist.end());
447
448 // set the first successor to itself
449 cln->setSuccessor(0, kernel);
450 // set the second successor to eiplogue
451 cln->setSuccessor(1, epilogue);
452
453 //*****change the condition*******
454
455 //get the condition instruction
456 Instruction *cond = (Instruction *) cln->getCondition();
457
458 //get the condition's second operand, it should be a constant
459 Value *operand = cond->getOperand(1);
460 assert(ConstantSInt::classof(operand));
461
462 //change the constant in the condtion instruction
463 ConstantSInt *iteTimes =
464 ConstantSInt::get(operand->getType(),
465 ((ConstantSInt *) operand)->getValue() - II + 1);
466 cond->setOperand(1, iteTimes);
467
468 }
469
470
471 // Construct the epilogue
472 //
473 void
474 ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
475 BasicBlock *succ_bb){
476
477 //compute the schedule for epilogue
478 vvNodeType &tempSchedule_epilogue =
479 *(new std::vector >(schedule));
480 unsigned scheduleSize = schedule.size();
481 int round = 0;
482 while (round < ceil(1.0 * scheduleSize / II) - 1) {
483 round++;
484 for (unsigned i = 0; i < scheduleSize; i++) {
485 if (i + round * II >= scheduleSize)
486 break;
487 for (unsigned j = 0; j < schedule[i].size(); j++)
488 if (schedule[i + round * II][j]) {
489 assert(tempSchedule_epilogue[i][j] == NULL
490 && "table not consitant with core table");
491
492 //move the schdule one iteration behind and overlap
493 tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
494 }
495 }
496 }
497
498 //fill in the epilogue
499 InstListType & epilogue_ist = epilogue->getInstList();
500 for (unsigned i = II; i < scheduleSize; i++)
501 for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
502 if (tempSchedule_epilogue[i][j]) {
503 Instruction *inst =
504 (Instruction *) tempSchedule_epilogue[i][j]->getInst();
505
506 //BranchInst and PHINode should be treated differently
507 //BranchInst:unecessary, simly omitted
508 //PHINode: omitted
509 if (!BranchInst::classof(inst) && !PHINode::classof(inst)) {
510 //make a clone instruction and insert it into the epilogue
511 Instruction *cln = cloneInstSetMemory(inst);
512 epilogue_ist.push_front(cln);
513 }
514 }
515
516 //*************delete the original instructions****************//
517 //to delete the original instructions, we have to make sure their use is zero
518
519 //update original core instruction's uses, using its clone instread
520 for (unsigned i = 0; i < II; i++)
521 for (unsigned j = 0; j < coreSchedule[i].size(); j++) {
522 if (coreSchedule[i][j])
523 updateUseWithClone((Instruction *) coreSchedule[i][j]->getInst());
524 }
525
526 //erase these instructions
527 for (unsigned i = 0; i < II; i++)
528 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
529 if (coreSchedule[i][j]) {
530 Instruction *ist = (Instruction *) coreSchedule[i][j]->getInst();
531 ist->getParent()->getInstList().erase(ist);
532 }
533
534
535
536 //finally, insert an unconditional branch instruction at the end
537 epilogue_ist.push_back(new BranchInst(succ_bb));
538
539 }
540
541
542 //------------------------------------------------------------------------------
543 //this function replace the value(instruction) ist in other instructions with
544 //its latest clone i.e. after this function is called, the ist is not used
545 //anywhere and it can be erased.
546 //------------------------------------------------------------------------------
547 void
548 ModuloScheduling::updateUseWithClone(Instruction * ist){
549
550
551 while (ist->use_size() > 0) {
552 bool destroyed = false;
553
554 //other instruction is using this value ist
555 assert(Instruction::classof(*ist->use_begin()));
556 Instruction *inst = (Instruction *) (*ist->use_begin());
557
558 for (unsigned i = 0; i < inst->getNumOperands(); i++)
559 if (inst->getOperand(i) == ist && ist->getClone()) {
560 // if the instruction is TmpInstruction, simly delete it because it has
561 // no parent and it does not belongs to any BasicBlock
562 if (TmpInstruction::classof(inst)) {
563 delete inst;
564 destroyed = true;
565 break;
566 }
567
568 //otherwise, set the instruction's operand to the value's clone
569 inst->setOperand(i, ist->getClone());
570
571 //the use from the original value ist is destroyed
572 destroyed = true;
573 break;
574 }
575 if (!destroyed) {
576 //if the use can not be destroyed , something is wrong
577 inst->dump();
578 assert(0 && "this use can not be destroyed");
579 }
580 }
581
582 }
583
584
585 //********************************************************
586 //this function clear all clone mememoy
587 //i.e. set all instruction's clone memory to NULL
588 //*****************************************************
589 void
590 ModuloScheduling::clearCloneMemory(){
591
592 for (unsigned i = 0; i < coreSchedule.size(); i++)
593 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
594 if (coreSchedule[i][j])
595 ((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
596
597 }
598
599
600 //******************************************************************************
601 // this function make a clone of the instruction orn the cloned instruction will
602 // use the orn's operands' latest clone as its operands it is done this way
603 // because LLVM is in SSA form and we should use the correct value
604 //this fuction also update the instruction orn's latest clone memory
605 //******************************************************************************
606 Instruction *
607 ModuloScheduling::cloneInstSetMemory(Instruction * orn){
608
609 // make a clone instruction
610 Instruction *cln = orn->clone();
611
612 // update the operands
613 for (unsigned k = 0; k < orn->getNumOperands(); k++) {
614 const Value *op = orn->getOperand(k);
615 if (Instruction::classof(op) && ((Instruction *) op)->getClone()) {
616 Instruction *op_inst = (Instruction *) op;
617 cln->setOperand(k, op_inst->getClone());
618 }
619 }
620
621 // update clone memory
622 orn->setClone(cln);
623 return cln;
624 }
625
626
627
628 bool
629 ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
630 unsigned start, unsigned end,
631 NodeVec & nodeScheduled){
632
633 const TargetSchedInfo & msi = target.getSchedInfo();
634 unsigned int numIssueSlots = msi.maxNumIssueTotal;
635
636 if (ModuloScheduling::printScheduleProcess())
637 DEBUG_PRINT(std::cerr << "startTime= " << start << " endTime= " << end << "\n");
638 bool isScheduled = false;
639 for (unsigned i = start; i <= end; i++) {
640 if (ModuloScheduling::printScheduleProcess())
641 DEBUG_PRINT(std::cerr << " now try cycle " << i << ":" << "\n");
642 for (unsigned j = 0; j < numIssueSlots; j++) {
643 unsigned int core_i = i % II;
644 unsigned int core_j = j;
645 if (ModuloScheduling::printScheduleProcess())
646 DEBUG_PRINT(std::cerr << "\t Trying slot " << j << "...........");
647 //check the resouce table, make sure there is no resource conflicts
648 const Instruction *instr = node->getInst();
649 MachineCodeForInstruction & tempMvec =
650 MachineCodeForInstruction::get(instr);
651 bool resourceConflict = false;
652 const TargetInstrInfo & mii = msi.getInstrInfo();
653
654 if (coreSchedule.size() < core_i + 1
655 || !coreSchedule[core_i][core_j]) {
656 //this->dumpResourceUsageTable();
657 int latency = 0;
658 for (unsigned k = 0; k < tempMvec.size(); k++) {
659 MachineInstr *minstr = tempMvec[k];
660 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
661 std::vector < std::vector < resourceId_t > >resources
662 = rUsage.resourcesByCycle;
663 updateResourceTable(resources, i + latency);
664 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
665 }
666
667 //this->dumpResourceUsageTable();
668
669 latency = 0;
670 if (resourceTableNegative()) {
671
672 //undo-update the resource table
673 for (unsigned k = 0; k < tempMvec.size(); k++) {
674 MachineInstr *minstr = tempMvec[k];
675 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
676 std::vector < std::vector < resourceId_t > >resources
677 = rUsage.resourcesByCycle;
678 undoUpdateResourceTable(resources, i + latency);
679 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
680 }
681 resourceConflict = true;
682 }
683 }
684 if (!resourceConflict && !coreSchedule[core_i][core_j]) {
685 if (ModuloScheduling::printScheduleProcess()) {
686 DEBUG_PRINT(std::cerr << " OK!" << "\n");
687 DEBUG_PRINT(std::cerr << "Node " << node->getNodeId() << " scheduled.\n");
688 }
689 //schedule[i][j]=node;
690 while (schedule.size() <= i) {
691 std::vector < ModuloSchedGraphNode * >*newCycle =
692 new std::vector < ModuloSchedGraphNode * >();
693 for (unsigned k = 0; k < numIssueSlots; k++)
694 newCycle->push_back(NULL);
695 schedule.push_back(*newCycle);
696 }
697 std::vector::iterator startIterator;
698 startIterator = schedule[i].begin();
699 schedule[i].insert(startIterator + j, node);
700 startIterator = schedule[i].begin();
701 schedule[i].erase(startIterator + j + 1);
702
703 //update coreSchedule
704 //coreSchedule[core_i][core_j]=node;
705 while (coreSchedule.size() <= core_i) {
706 std::vector *newCycle =
707 new std::vector();
708 for (unsigned k = 0; k < numIssueSlots; k++)
709 newCycle->push_back(NULL);
710 coreSchedule.push_back(*newCycle);
711 }
712
713 startIterator = coreSchedule[core_i].begin();
714 coreSchedule[core_i].insert(startIterator + core_j, node);
715 startIterator = coreSchedule[core_i].begin();
716 coreSchedule[core_i].erase(startIterator + core_j + 1);
717
718 node->setSchTime(i);
719 isScheduled = true;
720 nodeScheduled.push_back(node);
721
722 break;
723 } else if (coreSchedule[core_i][core_j]) {
724 if (ModuloScheduling::printScheduleProcess())
725 DEBUG_PRINT(std::cerr << " Slot not available\n");
726 } else {
727 if (ModuloScheduling::printScheduleProcess())
728 DEBUG_PRINT(std::cerr << " Resource conflicts\n");
729 }
730 }
731 if (isScheduled)
732 break;
733 }
734 //assert(nodeScheduled &&"this node can not be scheduled?");
735 return isScheduled;
736 }
737
738
739 void
740 ModuloScheduling::updateResourceTable(Resources useResources,
741 int startCycle){
742
743 for (unsigned i = 0; i < useResources.size(); i++) {
744 int absCycle = startCycle + i;
745 int coreCycle = absCycle % II;
746 std::vector > &resourceRemained =
747 resourceTable[coreCycle];
748 std::vector < unsigned int >&resourceUsed = useResources[i];
749 for (unsigned j = 0; j < resourceUsed.size(); j++) {
750 for (unsigned k = 0; k < resourceRemained.size(); k++)
751 if ((int) resourceUsed[j] == resourceRemained[k].first) {
752 resourceRemained[k].second--;
753 }
754 }
755 }
756 }
757
758 void
759 ModuloScheduling::undoUpdateResourceTable(Resources useResources,
760 int startCycle){
761
762 for (unsigned i = 0; i < useResources.size(); i++) {
763 int absCycle = startCycle + i;
764 int coreCycle = absCycle % II;
765 std::vector > &resourceRemained =
766 resourceTable[coreCycle];
767 std::vector < unsigned int >&resourceUsed = useResources[i];
768 for (unsigned j = 0; j < resourceUsed.size(); j++) {
769 for (unsigned k = 0; k < resourceRemained.size(); k++)
770 if ((int) resourceUsed[j] == resourceRemained[k].first) {
771 resourceRemained[k].second++;
772 }
773 }
774 }
775 }
776
777
778 //-----------------------------------------------------------------------
779 // Function: resourceTableNegative
780 // return value:
781 // return false if any element in the resouceTable is negative
782 // otherwise return true
783 // Purpose:
784
785 // this function is used to determine if an instruction is eligible for
786 // schedule at certain cycle
787 //-----------------------------------------------------------------------
788
789
790 bool
791 ModuloScheduling::resourceTableNegative(){
792
793 assert(resourceTable.size() == (unsigned) II
794 && "resouceTable size must be equal to II");
795 bool isNegative = false;
796 for (unsigned i = 0; i < resourceTable.size(); i++)
797 for (unsigned j = 0; j < resourceTable[i].size(); j++) {
798 if (resourceTable[i][j].second < 0) {
799 isNegative = true;
800 break;
801 }
802 }
803 return isNegative;
804 }
805
806
807 //----------------------------------------------------------------------
808 // Function: dumpResouceUsageTable
809 // Purpose:
810 // print out ResouceTable for debug
811 //
812 //------------------------------------------------------------------------
813
814 void
815 ModuloScheduling::dumpResourceUsageTable(){
816
817 DEBUG_PRINT(std::cerr << "dumping resource usage table\n");
818 for (unsigned i = 0; i < resourceTable.size(); i++) {
819 for (unsigned j = 0; j < resourceTable[i].size(); j++)
820 DEBUG_PRINT(std::cerr << resourceTable[i][j].first
821 << ":" << resourceTable[i][j].second << " ");
822 DEBUG_PRINT(std::cerr << "\n");
823 }
824
825 }
826
827 //----------------------------------------------------------------------
828 //Function: dumpSchedule
829 //Purpose:
830 // print out thisSchedule for debug
831 //
832 //-----------------------------------------------------------------------
833 void
834 ModuloScheduling::dumpSchedule(vvNodeType thisSchedule){
835
836 const TargetSchedInfo & msi = target.getSchedInfo();
837 unsigned numIssueSlots = msi.maxNumIssueTotal;
838 for (unsigned i = 0; i < numIssueSlots; i++)
839 DEBUG_PRINT(std::cerr << "\t#");
840 DEBUG_PRINT(std::cerr << "\n");
841 for (unsigned i = 0; i < thisSchedule.size(); i++) {
842 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
843 for (unsigned j = 0; j < thisSchedule[i].size(); j++)
844 if (thisSchedule[i][j] != NULL)
845 DEBUG_PRINT(std::cerr << thisSchedule[i][j]->getNodeId() << "\t");
846 else
847 DEBUG_PRINT(std::cerr << "\t");
848 DEBUG_PRINT(std::cerr << "\n");
849 }
850 }
851
852
853 //----------------------------------------------------
854 //Function: dumpScheduling
855 //Purpose:
856 // print out the schedule and coreSchedule for debug
857 //
858 //-------------------------------------------------------
859
860 void
861 ModuloScheduling::dumpScheduling(){
862
863 DEBUG_PRINT(std::cerr << "dump schedule:" << "\n");
864 const TargetSchedInfo & msi = target.getSchedInfo();
865 unsigned numIssueSlots = msi.maxNumIssueTotal;
866 for (unsigned i = 0; i < numIssueSlots; i++)
867 DEBUG_PRINT(std::cerr << "\t#");
868 DEBUG_PRINT(std::cerr << "\n");
869 for (unsigned i = 0; i < schedule.size(); i++) {
870 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
871 for (unsigned j = 0; j < schedule[i].size(); j++)
872 if (schedule[i][j] != NULL)
873 DEBUG_PRINT(std::cerr << schedule[i][j]->getNodeId() << "\t");
874 else
875 DEBUG_PRINT(std::cerr << "\t");
876 DEBUG_PRINT(std::cerr << "\n");
877 }
878
879 DEBUG_PRINT(std::cerr << "dump coreSchedule:" << "\n");
880 for (unsigned i = 0; i < numIssueSlots; i++)
881 DEBUG_PRINT(std::cerr << "\t#");
882 DEBUG_PRINT(std::cerr << "\n");
883 for (unsigned i = 0; i < coreSchedule.size(); i++) {
884 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
885 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
886 if (coreSchedule[i][j] != NULL)
887 DEBUG_PRINT(std::cerr << coreSchedule[i][j]->getNodeId() << "\t");
888 else
889 DEBUG_PRINT(std::cerr << "\t");
890 DEBUG_PRINT(std::cerr << "\n");
891 }
892 }
893
894 /*
895 print out final schedule
896 */
897
898 void
899 ModuloScheduling::dumpFinalSchedule(){
900
901 std::cerr << "dump schedule:" << "\n";
902 const TargetSchedInfo & msi = target.getSchedInfo();
903 unsigned numIssueSlots = msi.maxNumIssueTotal;
904
905 for (unsigned i = 0; i < numIssueSlots; i++)
906 std::cerr << "\t#";
907 std::cerr << "\n";
908
909 for (unsigned i = 0; i < schedule.size(); i++) {
910 std::cerr << "cycle" << i << ": ";
911
912 for (unsigned j = 0; j < schedule[i].size(); j++)
913 if (schedule[i][j] != NULL)
914 std::cerr << schedule[i][j]->getNodeId() << "\t";
915 else
916 std::cerr << "\t";
917 std::cerr << "\n";
918 }
919
920 std::cerr << "dump coreSchedule:" << "\n";
921 for (unsigned i = 0; i < numIssueSlots; i++)
922 std::cerr << "\t#";
923 std::cerr << "\n";
924
925 for (unsigned i = 0; i < coreSchedule.size(); i++) {
926 std::cerr << "cycle" << i << ": ";
927 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
928 if (coreSchedule[i][j] != NULL)
929 std::cerr << coreSchedule[i][j]->getNodeId() << "\t";
930 else
931 std::cerr << "\t";
932 std::cerr << "\n";
933 }
934 }
935
936 //---------------------------------------------------------------------------
937 // Function: ModuloSchedulingPass
938 //
939 // Purpose:
940 // Entry point for Modulo Scheduling
941 // Schedules LLVM instruction
942 //
943 //---------------------------------------------------------------------------
944
945 namespace {
946 class ModuloSchedulingPass:public FunctionPass {
947 const TargetMachine ⌖
948
949 public:
950 ModuloSchedulingPass(const TargetMachine &T):target(T) {}
951
952 const char *getPassName() const {
953 return "Modulo Scheduling";
954 }
955
956 // getAnalysisUsage - We use LiveVarInfo...
957 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
958 //AU.addRequired(FunctionLiveVarInfo::ID);
959 }
960
961 bool runOnFunction(Function & F);
962 };
963 } // end anonymous namespace
964
965
966 bool
967 ModuloSchedulingPass::runOnFunction(Function &F){
968
969 ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
970
971 ModuloSchedulingSet ModuloSchedulingSet(*graphSet);
972
973 DEBUG_PRINT(std::cerr<<"runOnFunction in ModuloSchedulingPass returns\n"<<"\n");
974 return false;
975 }
976
977
978 Pass *
979 createModuloSchedulingPass(const TargetMachine & tgt){
980 DEBUG_PRINT(std::cerr<<"creating modulo scheduling\n");
981 return new ModuloSchedulingPass(tgt);
982 }
+0
-194
lib/CodeGen/ModuloScheduling/ModuloScheduling.h less more
None // ModuloScheduling.h -------------------------------------------*- C++ -*-===//
1 //
2 // This header defines the the classes ModuloScheduling and
3 // ModuloSchedulingSet's structure
4 //
5 //===----------------------------------------------------------------------===//
6
7
8 #ifndef LLVM_CODEGEN_MODULOSCHEDULING_H
9 #define LLVM_CODEGEN_MODULOSCHEDULING_H
10
11 #include "ModuloSchedGraph.h"
12 #include
13 #include
14
15 //#define DEBUG_PRINT(x) x
16
17 #define DEBUG_PRINT(x)
18
19 // for debug information selecton
20 enum ModuloSchedDebugLevel_t {
21 ModuloSchedDebugLevel_NoDebugInfo,
22 ModuloSchedDebugLevel_PrintSchedule,
23 ModuloSchedDebugLevel_PrintScheduleProcess,
24 };
25
26 class ModuloScheduling: NonCopyable {
27 private:
28
29 typedef std::vector NodeVec;
30 typedef std::vector > Resources;
31
32 // The graph to feed in
33 ModuloSchedGraph &graph;
34 const TargetMachine ⌖
35
36 // The BasicBlock to be scheduled
37 BasicBlock *bb;
38
39 // Iteration Interval
40 // FIXME: II may be a better name for its meaning
41 unsigned II;
42
43 // The vector containing the nodes which have been scheduled
44 NodeVec nodeScheduled;
45
46 // The remaining unscheduled nodes
47 const NodeVec &oNodes;
48
49 // The machine resource table
50 std::vector > > resourceTable;
51
52 ///the schedule( with many schedule stage)
53 std::vector > schedule;
54
55 ///the kernel(core) schedule(length = II)
56 std::vector > coreSchedule;
57
58 typedef BasicBlock::InstListType InstListType;
59 typedef std::vector > vvNodeType;
60
61
62
63
64
65 public:
66
67 ModuloScheduling(ModuloSchedGraph & _graph):
68 graph(_graph), target(graph.getTarget()), oNodes(graph.getONodes())
69 {
70 II = graph.getMII();
71 bb = graph.getBasicBlock();
72 instrScheduling();
73 };
74
75 ~ModuloScheduling() {};
76
77
78
79 static bool
80 printSchedule() {
81
82 //return ModuloScheduling::DebugLevel >= DebugLevel_PrintSchedule;
83 return true;
84
85
86 }
87 static bool
88 printScheduleProcess() {
89
90 //return DebugLevel >= DebugLevel_PrintScheduleProcess;
91 return true;
92
93
94 }
95
96 // The method to compute schedule and instert epilogue and prologue
97 void instrScheduling();
98
99 // Debug functions:
100 // Dump the schedule and core schedule
101 void dumpScheduling();
102 void dumpFinalSchedule();
103
104 // Dump the input vector of nodes
105 // sch: the input vector of nodes
106 void dumpSchedule(std::vector > sch);
107
108 // Dump the resource usage table
109 void dumpResourceUsageTable();
110
111 //*******************internal functions*******************************
112 private:
113 //clear memory from the last round and initialize if necessary
114 void clearInitMem(const TargetSchedInfo&);
115
116 //compute schedule and coreSchedule with the current II
117 bool computeSchedule();
118
119 BasicBlock *getSuccBB(BasicBlock *);
120 BasicBlock *getPredBB(BasicBlock *);
121 void constructPrologue(BasicBlock *prologue);
122 void constructKernel(BasicBlock *prologue,
123 BasicBlock *kernel,
124 BasicBlock *epilogue);
125 void constructEpilogue(BasicBlock *epilogue, BasicBlock *succ_bb);
126
127 // update the resource table at the startCycle
128 // vec: the resouce usage
129 // startCycle: the start cycle the resouce usage is
130 void updateResourceTable(std::vector > vec,
131 int startCycle);
132
133 // un-do the update in the resource table in the startCycle
134 // vec: the resouce usage
135 // startCycle: the start cycle the resouce usage is
136 void undoUpdateResourceTable(std::vector > vec,
137 int startCycle);
138
139 // return whether the resourcetable has negative element
140 // this function is called after updateResouceTable() to determine whether a
141 // node can be scheduled at certain cycle
142 bool resourceTableNegative();
143
144 // try to Schedule the node starting from start to end cycle(inclusive)
145 // if it can be scheduled, put it in the schedule and update nodeScheduled
146 // node: the node to be scheduled
147 // start: start cycle
148 // end : end cycle
149 // nodeScheduled: a vector storing nodes which has been scheduled
150 bool ScheduleNode(ModuloSchedGraphNode * node, unsigned start,
151 unsigned end, NodeVec &nodeScheduled);
152
153 //each instruction has a memory of the latest clone instruction
154 //the clone instruction can be get using getClone()
155 //this function clears the memory, i.e. getClone() after calling this function
156 //returns null
157 void clearCloneMemory();
158
159 //this fuction make a clone of this input Instruction and update the clone
160 //memory
161 //inst: the instrution to be cloned
162 Instruction *cloneInstSetMemory(Instruction *inst);
163
164 //this function update each instrutions which uses ist as its operand
165 //after update, each instruction will use ist's clone as its operand
166 void updateUseWithClone(Instruction * ist);
167
168 };
169
170
171 class ModuloSchedulingSet:
172 NonCopyable {
173 private:
174
175 //the graphSet to feed in
176 ModuloSchedGraphSet & graphSet;
177
178 public:
179
180 //constructor
181 //Scheduling graph one by one
182 ModuloSchedulingSet(ModuloSchedGraphSet _graphSet): graphSet(_graphSet) {
183 for (unsigned i = 0; i < graphSet.size(); i++) {
184 ModuloSchedGraph & graph = *(graphSet[i]);
185 if (graph.isLoop(graph.getBasicBlock()))
186 ModuloScheduling ModuloScheduling(graph);
187 }
188 };
189
190 ~ModuloSchedulingSet() {};
191 };
192
193 #endif
None //===- ModuloSchedGraph.cpp - Graph datastructure for Modulo Scheduling ---===//
1 //
2 //
0 //===- ModuloSchedGraph.cpp - Modulo Scheduling Graph and Set -*- C++ -*---===//
1 //
2 // Description here
33 //===----------------------------------------------------------------------===//
44
5 #include "llvm/CodeGen/InstrSelection.h"
6 #include "llvm/Function.h"
7 #include "llvm/Instructions.h"
5 #include "ModuloSchedGraph.h"
86 #include "llvm/Type.h"
9 #include "llvm/CodeGen/MachineCodeForInstruction.h"
10 #include "llvm/CodeGen/MachineInstr.h"
11 #include "llvm/Target/TargetSchedInfo.h"
12 #include "Support/StringExtras.h"
13 #include "Support/STLExtras.h"
14 #include "Support/hash_map"
15 #include "Support/Statistic.h"
16 #include "ModuloScheduling.h"
17 #include "ModuloSchedGraph.h"
18 #include
19 #include
20 #include
21 #include
7
8 ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned id, int index,
9 const Instruction *inst,
10 const TargetMachine &targ)
11 : SchedGraphNodeCommon(id, index), Inst(inst), Target(targ) {
12 }
13
14 void ModuloSchedGraphNode::print(std::ostream &os) const {
15 os << "Modulo Scheduling Node\n";
16 }
17
18 ModuloSchedGraph::ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &targ)
19 : SchedGraphCommon(), BB(bb), Target(targ) {
20
21 assert(BB != NULL && "Basic Block is null");
22
23 //Builds nodes from each instruction in the basic block
24 buildNodesForBB();
25
26 }
27
28 void ModuloSchedGraph::buildNodesForBB() {
29 int count = 0;
30 for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); i != e; ++i) {
31 addNode(i,new ModuloSchedGraphNode(size(), count, i, Target));
32 count++;
33 }
34
35 //Get machine instruction(s) for the llvm instruction
36 //MachineCodeForInstruction &MC = MachineCodeForInstruction::get(Node->first);
37
38
39 }
40
41 void ModuloSchedGraph::addNode(const Instruction *I,
42 ModuloSchedGraphNode *node) {
43 assert(node!= NULL && "New ModuloSchedGraphNode is null");
44 GraphMap[I] = node;
45 }
46
47 void ModuloSchedGraph::addDepEdges() {
48
49 //Get Machine target information for calculating delay
50 const TargetInstrInfo &MTI = Target.getInstrInfo();
51
52 //Loop over instruction in BB and gather dependencies
53 for(BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
54
55 //Ignore instructions of the void type
56 if(I->getType() != Type::VoidTy) {
57
58 //Iterate over def-use chain and add true dependencies
59 for (Value::use_const_iterator U = I->use_begin(), e = I->use_end(); U != e;
60 ++U) {
61 if (Instruction *Inst = dyn_cast(*U)) {
62 //Check if a node already exists for this instruction
63 ModuloSchedGraph::iterator Sink = find(Inst);
64
65 //If the instruction is in our graph, add appropriate edges
66 if(Sink->second != NULL) {
67 //assert if self loop
68 assert(&*I == Sink->first && "Use edge to itself!");
69
70 //Create edge and set delay equal to node latency
71 //FIXME: Is it safe to do this?
72 ModuloSchedGraph::iterator Src = find(I);
73 SchedGraphEdge *trueDep = new SchedGraphEdge(&*Src->second ,&*Sink->second, &*I,
74 SchedGraphEdge::TrueDep,
75 Src->second->getLatency());
76 //Determine the iteration difference
77 //FIXME: Will this ever happen?
78 }
79 }
80 }
81 }
82
83 }
84
85
86 }
87
88 void ModuloSchedGraph::ASAP() {
2289
2390
24 #define UNIDELAY 1
91 }
2592
26 using std::cerr;
27 using std::endl;
28 using std::vector;
93 void ModuloSchedGraph::ALAP() {
2994
3095
31 /***********member functions for ModuloSchedGraphNode*********/
96 }
3297
98 void ModuloSchedGraph::MOB() {
3399
34 ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned int in_nodeId,
35 const BasicBlock * in_bb,
36 const Instruction * in_inst,
37 int indexInBB,
38 const TargetMachine & target)
39 :SchedGraphNodeCommon(in_nodeId, indexInBB), inst(in_inst){
40
41 if (inst) {
42 //FIXME: find the latency
43 //currently set the latency to zero
44 latency = 0;
45 }
100 }
101
102 void ModuloSchedGraph::ComputeDepth() {
103
104 }
105
106 void ModuloSchedGraph::ComputeHeight() {
107
108 }
109
110 void ModuloSchedGraphSet::addGraph(ModuloSchedGraph *graph) {
111 assert(graph!=NULL && "Graph for BasicBlock is null");
112 Graphs.push_back(graph);
46113 }
47114
48115
49 /***********member functions for ModuloSchedGraph*********/
116 ModuloSchedGraphSet::ModuloSchedGraphSet(const Function *F,
117 const TargetMachine &targ)
118 : function(F) {
50119
51 void
52 ModuloSchedGraph::addDefUseEdges(const BasicBlock *bb){
53
54 //collect def instructions, store them in vector
55 const TargetInstrInfo & mii = target.getInstrInfo();
56 vector < ModuloSchedGraphNode * > defVec;
57
58
59 //find those def instructions
60 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; ++I) {
61 if (I->getType() != Type::VoidTy) {
62 defVec.push_back(this->getGraphNodeForInst(I));
63 }
64 }
65
66 for (unsigned int i = 0; i < defVec.size(); i++) {
67 for (Value::use_const_iterator I = defVec[i]->getInst()->use_begin();
68 I != defVec[i]->getInst()->use_end(); I++) {
69 //for each use of a def, add a flow edge from the def instruction to the
70 //ref instruction
71
72 const Instruction *value = defVec[i]->getInst();
73 Instruction *inst = (Instruction *) (*I);
74 ModuloSchedGraphNode *node = NULL;
75
76 for (BasicBlock::const_iterator ins = bb->begin(), E = bb->end();
77 ins != E; ++ins)
78 if ((const Instruction *) ins == inst) {
79 node = (*this)[inst];
80 break;
81 }
82
83
84 if (node == NULL){
85
86 //inst is not an instruction in this block
87 //do nothing
88
89 } else {
90 // Add a flow edge from the def instruction to the ref instruction
91 // This is a true dependence, so the delay is equal to the
92 //delay of the preceding node.
93
94 int delay = 0;
95
96 // self loop will not happen in SSA form
97 assert(defVec[i] != node && "same node?");
98
99 MachineCodeForInstruction & tempMvec =
100 MachineCodeForInstruction::get(value);
101 for (unsigned j = 0; j < tempMvec.size(); j++) {
102 MachineInstr *temp = tempMvec[j];
103 delay = std::max(delay, mii.minLatency(temp->getOpCode()));
104 }
105
106 SchedGraphEdge *trueEdge =
107 new SchedGraphEdge(defVec[i], node, value,
108 SchedGraphEdge::TrueDep, delay);
109
110 // if the ref instruction is before the def instrution
111 // then the def instruction must be a phi instruction
112 // add an anti-dependence edge to from the ref instruction to the def
113 // instruction
114 if (node->getOrigIndexInBB() < defVec[i]->getOrigIndexInBB()) {
115 assert(PHINode::classof(inst)
116 && "the ref instruction befre def is not PHINode?");
117 trueEdge->setIteDiff(1);
118 }
119
120 }
121
122 }
123 }
120 //Create graph for each BB in this function
121 for (Function::const_iterator BI = F->begin(); BI != F->end(); ++BI)
122 addGraph(new ModuloSchedGraph(BI, targ));
124123 }
125
126 void
127 ModuloSchedGraph::addCDEdges(const BasicBlock * bb) {
128
129 // find the last instruction in the basic block
130 // see if it is an branch instruction.
131 // If yes, then add an edge from each node expcept the last node
132 // to the last node
133
134 const Instruction *inst = &(bb->back());
135 ModuloSchedGraphNode *lastNode = (*this)[inst];
136 if (TerminatorInst::classof(inst))
137 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E;
138 I++) {
139 if (inst != I) {
140 ModuloSchedGraphNode *node = (*this)[I];
141 //use latency of 0
142 (void) new SchedGraphEdge(node, lastNode, SchedGraphEdge::CtrlDep,
143 SchedGraphEdge::NonDataDep, 0);
144 }
145
146 }
147 }
148
149 static const int SG_LOAD_REF = 0;
150 static const int SG_STORE_REF = 1;
151 static const int SG_CALL_REF = 2;
152
153 static const unsigned int SG_DepOrderArray[][3] = {
154 {SchedGraphEdge::NonDataDep,
155 SchedGraphEdge::AntiDep,
156 SchedGraphEdge::AntiDep},
157 {SchedGraphEdge::TrueDep,
158 SchedGraphEdge::OutputDep,
159 SchedGraphEdge::TrueDep | SchedGraphEdge::OutputDep},
160 {SchedGraphEdge::TrueDep,
161 SchedGraphEdge::AntiDep | SchedGraphEdge::OutputDep,
162 SchedGraphEdge::TrueDep | SchedGraphEdge::AntiDep
163 | SchedGraphEdge::OutputDep}
164 };
165
166
167 // Add a dependence edge between every pair of machine load/store/call
168 // instructions, where at least one is a store or a call.
169 // Use latency 1 just to ensure that memory operations are ordered;
170 // latency does not otherwise matter (true dependences enforce that).
171 //
172 void
173 ModuloSchedGraph::addMemEdges(const BasicBlock * bb) {
174
175 vector memNodeVec;
176
177 //construct the memNodeVec
178 for (BasicBlock::const_iterator I = bb->begin(),
179 E = bb->end(); I != E; ++I) {
180
181 if (LoadInst::classof(I) || StoreInst::classof(I)
182 || CallInst::classof(I)) {
183
184 ModuloSchedGraphNode *node = (*this)[(const Instruction *) I];
185 memNodeVec.push_back(node);
186
187 }
188 }
189
190 // Instructions in memNodeVec are in execution order within the
191 // basic block, so simply look at all pairs
192 // i]>.
193
194 for (unsigned im = 0, NM = memNodeVec.size(); im < NM; im++) {
195
196 const Instruction *fromInst,*toInst;
197 int toType, fromType;
198
199 //get the first mem instruction and instruction type
200 fromInst = memNodeVec[im]->getInst();
201 fromType = CallInst::classof(fromInst) ? SG_CALL_REF
202 : LoadInst::classof(fromInst) ? SG_LOAD_REF : SG_STORE_REF;
203
204 for (unsigned jm = im + 1; jm < NM; jm++) {
205
206 //get the second mem instruction and instruction type
207 toInst = memNodeVec[jm]->getInst();
208 toType = CallInst::classof(toInst) ? SG_CALL_REF
209 : LoadInst::classof(toInst) ? SG_LOAD_REF : SG_STORE_REF;
210
211 //add two edges if not both of them are LOAD instructions
212 if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF) {
213 (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm],
214 SchedGraphEdge::MemoryDep,
215 SG_DepOrderArray[fromType][toType], 1);
216
217 SchedGraphEdge *edge =
218 new SchedGraphEdge(memNodeVec[jm], memNodeVec[im],
219 SchedGraphEdge::MemoryDep,
220 SG_DepOrderArray[toType][fromType], 1);
221
222 //set the iteration difference for this edge to 1.
223 edge->setIteDiff(1);
224
225 }
226 }
227 }
228 }
229
230 /*
231 this function build graph nodes for each instruction
232 in the basicblock
233 */
234
235 void
236 ModuloSchedGraph::buildNodesforBB(const TargetMachine &target,
237 const BasicBlock *bb){
238
239 int i = 0;
240 ModuloSchedGraphNode *node;
241
242 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end();
243 I != E; ++I) {
244
245 node=new ModuloSchedGraphNode(getNumNodes(), bb, I, i, target);
246
247 i++;
248
249 this->addHash(I, node);
250 }
251
252 }
253
254
255 /*
256 determine if this basicblock includes a loop or not
257 */
258
259 bool
260 ModuloSchedGraph::isLoop(const BasicBlock *bb) {
261
262 //only if the last instruction in the basicblock is branch instruction and
263 //there is at least an option to branch itself
264
265 const Instruction *inst = &(bb->back());
266
267 if (BranchInst::classof(inst)) {
268 for (unsigned i = 0; i < ((BranchInst *) inst)->getNumSuccessors();
269 i++) {
270 BasicBlock *sb = ((BranchInst *) inst)->getSuccessor(i);
271 if (sb == bb)
272 return true;
273 }
274 }
275
276 return false;
277
278 }
279
280 /*
281 compute every node's ASAP
282
283 */
284
285 //FIXME: now assume the only backward edges come from the edges from other
286 //nodes to the phi Node so i will ignore all edges to the phi node; after
287 //this, there shall be no recurrence.
288
289 void
290 ModuloSchedGraph::computeNodeASAP(const BasicBlock *bb) {
291
292
293 unsigned numNodes = bb->size();
294 for (unsigned i = 2; i < numNodes + 2; i++) {
295 ModuloSchedGraphNode *node = getNode(i);
296 node->setPropertyComputed(false);
297 }
298
299 for (unsigned i = 2; i < numNodes + 2; i++) {
300 ModuloSchedGraphNode *node = getNode(i);
301 node->ASAP = 0;
302 if (i == 2 || node->getNumInEdges() == 0) {
303 node->setPropertyComputed(true);
304 continue;
305 }
306 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
307 node->endInEdges(); I != E; I++) {
308 SchedGraphEdge *edge = *I;
309 ModuloSchedGraphNode *pred =
310 (ModuloSchedGraphNode *) (edge->getSrc());
311 assert(pred->getPropertyComputed()
312 && "pred node property is not computed!");
313 int temp =
314 pred->ASAP + edge->getMinDelay() -
315 edge->getIteDiff() * this->MII;
316 node->ASAP = std::max(node->ASAP, temp);
317 }
318 node->setPropertyComputed(true);
319 }
320 }
321
322
323 /*
324 compute every node's ALAP in the basic block
325 */
326
327 void
328 ModuloSchedGraph::computeNodeALAP(const BasicBlock *bb) {
329
330 unsigned numNodes = bb->size();
331 int maxASAP = 0;
332 for (unsigned i = numNodes + 1; i >= 2; i--) {
333
334 ModuloSchedGraphNode *node = getNode(i);
335 node->setPropertyComputed(false);
336 maxASAP = std::max(maxASAP, node->ASAP);
337
338 }
339
340 for (unsigned i = numNodes + 1; i >= 2; i--) {
341 ModuloSchedGraphNode *node = getNode(i);
342
343 node->ALAP = maxASAP;
344
345 for (ModuloSchedGraphNode::const_iterator I =
346 node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) {
347
348 SchedGraphEdge *edge = *I;
349 ModuloSchedGraphNode *succ =
350 (ModuloSchedGraphNode *) (edge->getSink());
351 if (PHINode::classof(succ->getInst()))
352 continue;
353
354 assert(succ->getPropertyComputed()
355 && "succ node property is not computed!");
356
357 int temp =
358 succ->ALAP - edge->getMinDelay() +
359 edge->getIteDiff() * this->MII;
360
361 node->ALAP = std::min(node->ALAP, temp);
362
363 }
364 node->setPropertyComputed(true);
365 }
366 }
367
368 /*
369 compute every node's mov in this basicblock
370 */
371
372 void
373 ModuloSchedGraph::computeNodeMov(const BasicBlock *bb){
374
375 unsigned numNodes = bb->size();
376 for (unsigned i = 2; i < numNodes + 2; i++) {
377
378 ModuloSchedGraphNode *node = getNode(i);
379 node->mov = node->ALAP - node->ASAP;
380 assert(node->mov >= 0
381 && "move freedom for this node is less than zero? ");
382
383 }
384
385 }
386
387
388 /*
389 compute every node's depth in this basicblock </