blob: 08cea9dce9fada39565fc09f0cb735ecff88860a [file] [log] [blame]
Guochun Shif1c154f2003-03-27 17:57:44 +00001
2//===- SPLInstrScheduling.cpp - Modulo Software Pipelining Instruction Scheduling support -------===//
3//
4// this file implements the llvm/CodeGen/ModuloScheduling.h interface
5//
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/CodeGen/MachineInstr.h"
10#include "llvm/CodeGen/MachineCodeForInstruction.h"
Guochun Shi6fbe5fb2003-04-06 23:56:19 +000011//#include "llvm/CodeGen/MachineCodeForBasicBlock.h"
12//#include "llvm/CodeGen/MachineCodeForMethod.h"
13#include "llvm/CodeGen/MachineFunction.h"
14//#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h" // FIXME: Remove when modularized better
Guochun Shif1c154f2003-03-27 17:57:44 +000015#include "llvm/Target/TargetMachine.h"
16#include "llvm/BasicBlock.h"
17#include "llvm/Instruction.h"
18#include "Support/CommandLine.h"
19#include <algorithm>
20#include "ModuloSchedGraph.h"
21#include "ModuloScheduling.h"
Guochun Shi6fbe5fb2003-04-06 23:56:19 +000022#include "llvm/Target/TargetSchedInfo.h"
Guochun Shif1c154f2003-03-27 17:57:44 +000023#include "llvm/BasicBlock.h"
24#include "llvm/iTerminators.h"
25#include "llvm/iPHINode.h"
26#include "llvm/Constants.h"
27#include <iostream>
Guochun Shi6fbe5fb2003-04-06 23:56:19 +000028//#include <swig.h>
Guochun Shif1c154f2003-03-27 17:57:44 +000029#include <fstream>
30#include "llvm/CodeGen/InstrSelection.h"
31
32#define max(x,y) (x>y?x:y)
33#define min(x,y) (x<y?x:y)
34using std::cerr;
35using std::cout;
36using std::ostream;
37using std::ios;
38using std::filebuf;
39
40//************************************************************
41//printing Debug information
42//ModuloSchedDebugLevel stores the value of debug level
43// modsched_os is the ostream to dump debug information, which is written into the file 'moduloSchedDebugInfo.output'
44//see ModuloSchedulingPass::runOnFunction()
45//************************************************************
46
47ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
48static cl::opt<ModuloSchedDebugLevel_t, true>
49SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
50 cl::desc("enable modulo scheduling debugging information"),
51 cl::values(
52 clEnumValN(ModuloSched_NoDebugInfo, "n", "disable debug output"),
53 clEnumValN(ModuloSched_Disable, "off", "disable modulo scheduling"),
54 clEnumValN(ModuloSched_PrintSchedule, "psched", "print original and new schedule"),
55 clEnumValN(ModuloSched_PrintScheduleProcess,"pschedproc", "print how the new schdule is produced"),
56 0));
57
58filebuf modSched_fb;
59ostream modSched_os(&modSched_fb);
60
61//************************************************************
62
63
64///the method to compute schedule and instert epilogue and prologue
65void ModuloScheduling::instrScheduling(){
66
67 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
68 modSched_os<<"*************************computing modulo schedule ************************\n";
69
70
Guochun Shi6fbe5fb2003-04-06 23:56:19 +000071 const TargetSchedInfo& msi=target.getSchedInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +000072
73 //number of issue slots in the in each cycle
74 int numIssueSlots=msi.maxNumIssueTotal;
75
76
77
78 //compute the schedule
79 bool success=false;
80 while(!success)
81 {
82 //clear memory from the last round and initialize if necessary
83 clearInitMem(msi);
84
85 //compute schedule and coreSchedule with the current II
86 success=computeSchedule();
87
88 if(!success){
89 II++;
90 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
91 modSched_os<<"increase II to "<<II<<"\n";
92 }
93 }
94
95 //print the final schedule if necessary
96 if( ModuloSchedDebugLevel >= ModuloSched_PrintSchedule)
97 dumpScheduling();
98
99
100 //the schedule has been computed
101 //create epilogue, prologue and kernel BasicBlock
102
103 //find the successor for this BasicBlock
104 BasicBlock* succ_bb= getSuccBB(bb);
105
106 //print the original BasicBlock if necessary
107 if( ModuloSchedDebugLevel >= ModuloSched_PrintSchedule){
108 modSched_os<<"dumping the orginal block\n";
109 graph.dump(bb);
110 }
111
112 //construction of prologue, kernel and epilogue
113 BasicBlock* kernel=bb->splitBasicBlock(bb->begin());
114 BasicBlock* prologue= bb;
115 BasicBlock* epilogue=kernel->splitBasicBlock(kernel->begin());
116
117
118 //construct prologue
119 constructPrologue(prologue);
120
121 //construct kernel
122 constructKernel(prologue,kernel,epilogue);
123
124 //construct epilogue
125 constructEpilogue(epilogue,succ_bb);
126
127
128 //print the BasicBlocks if necessary
129 if( ModuloSchedDebugLevel >= ModuloSched_PrintSchedule){
130 modSched_os<<"dumping the prologue block:\n";
131 graph.dump(prologue);
132 modSched_os<<"dumping the kernel block\n";
133 graph.dump(kernel);
134 modSched_os<<"dumping the epilogue block\n";
135 graph.dump(epilogue);
136 }
137
138}
139
140//clear memory from the last round and initialize if necessary
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000141void ModuloScheduling::clearInitMem(const TargetSchedInfo& msi){
Guochun Shif1c154f2003-03-27 17:57:44 +0000142
143
144 unsigned numIssueSlots = msi.maxNumIssueTotal;
145 //clear nodeScheduled from the last round
146 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000147 modSched_os<< "***** new round with II= "<<II<<" *******************"<<"\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000148 modSched_os<< " **************clear the vector nodeScheduled**************** \n";
149 }
150 nodeScheduled.clear();
151
152
153 //clear resourceTable from the last round and reset it
154 resourceTable.clear();
155 for(unsigned i=0;i< II;i++)
156 resourceTable.push_back(msi.resourceNumVector);
157
158
159 //clear the schdule and coreSchedule from the last round
160 schedule.clear();
161 coreSchedule.clear();
162
163 //create a coreSchedule of size II*numIssueSlots
164 //each entry is NULL
165 while( coreSchedule.size() < II){
166 std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
167 for(unsigned k=0;k<numIssueSlots;k++)
168 newCycle->push_back(NULL);
169 coreSchedule.push_back(*newCycle);
170 }
171}
172
173
174//compute schedule and coreSchedule with the current II
175bool ModuloScheduling::computeSchedule(){
176
177 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
178 modSched_os <<"start to compute schedule \n";
179
180 //loop over the ordered nodes
181 for(NodeVec::const_iterator I=oNodes.begin();I!=oNodes.end();I++)
182 {
183 //try to schedule for node I
184 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
185 dumpScheduling();
186 ModuloSchedGraphNode* node=*I;
187
188 //compute whether this node has successor(s)
189 bool succ=true;
190
191 //compute whether this node has predessor(s)
192 bool pred=true;
193
194 NodeVec schSucc=graph.vectorConj(nodeScheduled,graph.succSet(node));
195 if(schSucc.empty())
196 succ=false;
197 NodeVec schPred=graph.vectorConj(nodeScheduled,graph.predSet(node));
198 if(schPred.empty())
199 pred=false;
200
201 //startTime: the earliest time we will try to schedule this node
202 //endTime: the latest time we will try to schedule this node
203 int startTime, endTime;
204
205 //node's earlyStart: possible earliest time to schedule this node
206 //node's lateStart: possible latest time to schedule this node
207 node->setEarlyStart(-1);
208 node->setLateStart(9999);
209
210
211 //this node has predessor but no successor
212 if(!succ && pred){
213
214 //this node's earlyStart is it's predessor's schedule time + the edge delay
215 // - the iteration difference* II
216 for(unsigned i=0;i<schPred.size();i++){
217 ModuloSchedGraphNode* predNode=schPred[i];
218 SchedGraphEdge* edge=graph.getMaxDelayEdge(predNode->getNodeId(),node->getNodeId());
219 int temp=predNode->getSchTime()+edge->getMinDelay() - edge->getIteDiff()*II;
220 node->setEarlyStart( max(node->getEarlyStart(),temp));
221 }
222 startTime=node->getEarlyStart();
223 endTime=node->getEarlyStart()+II-1;
224 }
225
226
227 //this node has successor but no predessor
228 if(succ && !pred){
229 for(unsigned i=0;i<schSucc.size();i++){
230 ModuloSchedGraphNode* succNode=schSucc[i];
231 SchedGraphEdge* edge=graph.getMaxDelayEdge(succNode->getNodeId(),node->getNodeId());
232 int temp=succNode->getSchTime() - edge->getMinDelay() + edge->getIteDiff()*II;
233 node->setLateStart(min(node->getEarlyStart(),temp));
234 }
235 startTime=node->getLateStart()- II+1;
236 endTime=node->getLateStart();
237 }
238
239 //this node has both successors and predessors
240 if(succ && pred)
241 {
242 for(unsigned i=0;i<schPred.size();i++){
243 ModuloSchedGraphNode* predNode=schPred[i];
244 SchedGraphEdge* edge=graph.getMaxDelayEdge(predNode->getNodeId(),node->getNodeId());
245 int temp=predNode->getSchTime()+edge->getMinDelay() - edge->getIteDiff()*II;
246 node->setEarlyStart(max(node->getEarlyStart(),temp));
247 }
248 for(unsigned i=0;i<schSucc.size();i++){
249 ModuloSchedGraphNode* succNode=schSucc[i];
250 SchedGraphEdge* edge=graph.getMaxDelayEdge(succNode->getNodeId(),node->getNodeId());
251 int temp=succNode->getSchTime() - edge->getMinDelay() + edge->getIteDiff()*II;
252 node->setLateStart(min(node->getEarlyStart(),temp));
253 }
254 startTime=node->getEarlyStart();
255 endTime=min(node->getLateStart(),node->getEarlyStart()+((int)II)-1);
256 }
257
258 //this node has no successor or predessor
259 if(!succ && !pred){
260 node->setEarlyStart(node->getASAP());
261 startTime=node->getEarlyStart();
262 endTime=node->getEarlyStart()+II -1;
263 }
264
265 //try to schedule this node based on the startTime and endTime
266 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
267 modSched_os<<"scheduling the node "<<(*I)->getNodeId()<<"\n";
268
269 bool success= this->ScheduleNode(node,startTime, endTime,nodeScheduled);
270 if(!success)return false;
271 }
272 return true;
273}
274
275
276//get the successor of the BasicBlock
277BasicBlock* ModuloScheduling::getSuccBB(BasicBlock* bb){
278
279 BasicBlock* succ_bb;
280 for(unsigned i=0;i < II; i++)
281 for(unsigned j=0;j< coreSchedule[i].size();j++)
282 if(coreSchedule[i][j]){
283 const Instruction* ist=coreSchedule[i][j]->getInst();
284
285 //we can get successor from the BranchInst instruction
286 //assume we only have one successor (besides itself) here
287 if(BranchInst::classof(ist)){
288 BranchInst* bi=(BranchInst*)ist;
289 assert(bi->isConditional()&&"the branchInst is not a conditional one");
290 assert(bi->getNumSuccessors() ==2&&" more than two successors?");
291 BasicBlock* bb1=bi->getSuccessor(0);
292 BasicBlock* bb2=bi->getSuccessor(1);
293 assert( (bb1 == bb|| bb2 == bb) && " None of its successor is itself?");
294 if(bb1 == bb) succ_bb=bb2;
295 else succ_bb=bb1;
296 return succ_bb;
297 }
298 }
299 assert( 0 && "NO Successor?");
300 return NULL;
301}
302
303
304//get the predecessor of the BasicBlock
305BasicBlock* ModuloScheduling::getPredBB(BasicBlock* bb){
306
307 BasicBlock* pred_bb;
308
309 for(unsigned i=0;i < II; i++)
310 for(unsigned j=0;j< coreSchedule[i].size();j++)
311 if(coreSchedule[i][j]){
312 const Instruction* ist=coreSchedule[i][j]->getInst();
313
314 //we can get predecessor from the PHINode instruction
315 //assume we only have one predecessor (besides itself) here
316 if(PHINode::classof(ist)){
317 PHINode* phi=(PHINode*) ist;
318 assert(phi->getNumIncomingValues() == 2 &&" the number of incoming value is not equal to two? ");
319 BasicBlock* bb1= phi->getIncomingBlock(0);
320 BasicBlock* bb2= phi->getIncomingBlock(1);
321 assert( (bb1 == bb || bb2 == bb) && " None of its predecessor is itself?");
322 if(bb1 == bb) pred_bb=bb2;
323 else pred_bb=bb1;
324 return pred_bb;
325 }
326 }
327 assert(0 && " no predecessor?");
328 return NULL;
329}
330
331
332//construct the prologue
333void ModuloScheduling::constructPrologue(BasicBlock* prologue){
334
335 InstListType& prologue_ist = prologue->getInstList();
336 vvNodeType& tempSchedule_prologue= *(new vector< std::vector<ModuloSchedGraphNode*> >(schedule));
337
338 //compute the schedule for prologue
339 unsigned round=0;
340 unsigned scheduleSize=schedule.size();
341 while(round < scheduleSize/II){
342 round++;
343 for(unsigned i=0;i < scheduleSize ;i++){
344 if(round*II + i >= scheduleSize) break;
345 for(unsigned j=0;j < schedule[i].size(); j++)
346 if(schedule[i][j]){
347 assert( tempSchedule_prologue[round*II +i ][j] == NULL && "table not consitant with core table");
348
349 //move the schedule one iteration ahead and overlap with the original one
350 tempSchedule_prologue[round*II + i][j]=schedule[i][j];
351 }
352 }
353 }
354
355 //clear the clone memory in the core schedule instructions
356 clearCloneMemory();
357
358 //fill in the prologue
359 for(unsigned i=0;i < ceil(1.0*scheduleSize/II -1)*II ;i++)
360 for(unsigned j=0;j < tempSchedule_prologue[i].size();j++)
361 if(tempSchedule_prologue[i][j]){
362
363 //get the instruction
364 Instruction* orn=(Instruction*)tempSchedule_prologue[i][j]->getInst();
365
366 //made a clone of it
367 Instruction* cln=cloneInstSetMemory(orn);
368
369 //insert the instruction
370 prologue_ist.insert(prologue_ist.back(),cln );
371
372 //if there is PHINode in the prologue, the incoming value from itself should be removed
373 //because it is not a loop any longer
374 if( PHINode::classof(cln)){
375 PHINode* phi=(PHINode*)cln;
376 phi->removeIncomingValue(phi->getParent());
377 }
378 }
379}
380
381
382//construct the kernel BasicBlock
383void ModuloScheduling::constructKernel(BasicBlock* prologue,BasicBlock* kernel,BasicBlock* epilogue){
384
385 //*************fill instructions in the kernel****************
386 InstListType& kernel_ist = kernel->getInstList();
387 BranchInst* brchInst;
388 PHINode* phiInst, *phiCln;
389
390 for(unsigned i=0;i<coreSchedule.size();i++)
391 for(unsigned j=0;j<coreSchedule[i].size();j++)
392 if(coreSchedule[i][j]){
393
394 //we should take care of branch instruction differently with normal instructions
395 if(BranchInst::classof(coreSchedule[i][j]->getInst())){
396 brchInst=(BranchInst*)coreSchedule[i][j]->getInst();
397 continue;
398 }
399
400 //we should take care of PHINode instruction differently with normal instructions
401 if( PHINode::classof(coreSchedule[i][j]->getInst())){
402 phiInst= (PHINode*)coreSchedule[i][j]->getInst();
403 Instruction* cln=cloneInstSetMemory(phiInst);
404 kernel_ist.insert(kernel_ist.back(),cln);
405 phiCln=(PHINode*)cln;
406 continue;
407 }
408
409 //for normal instructions: made a clone and insert it in the kernel_ist
410 Instruction* cln=cloneInstSetMemory( (Instruction*)coreSchedule[i][j]->getInst());
411 kernel_ist.insert(kernel_ist.back(),cln);
412 }
413
414 //the two incoming BasicBlock for PHINode is the prologue and the kernel (itself)
415 phiCln->setIncomingBlock(0,prologue);
416 phiCln->setIncomingBlock(1,kernel);
417
418 //the incoming value for the kernel (itself) is the new value which is computed in the kernel
419 Instruction* originalVal=(Instruction*)phiInst->getIncomingValue(1);
420 phiCln->setIncomingValue(1, originalVal->getClone());
421
422
423 //make a clone of the branch instruction and insert it in the end
424 BranchInst* cln=(BranchInst*)cloneInstSetMemory( brchInst);
425 kernel_ist.insert(kernel_ist.back(),cln);
426
427 //delete the unconditional branch instruction, which is generated when splitting the basicBlock
428 kernel_ist.erase( --kernel_ist.end());
429
430 //set the first successor to itself
431 ((BranchInst*)cln)->setSuccessor(0, kernel);
432 //set the second successor to eiplogue
433 ((BranchInst*)cln)->setSuccessor(1,epilogue);
434
435 //*****change the condition*******
436
437 //get the condition instruction
438 Instruction* cond=(Instruction*)cln->getCondition();
439
440 //get the condition's second operand, it should be a constant
441 Value* operand=cond->getOperand(1);
442 assert(ConstantSInt::classof(operand));
443
444 //change the constant in the condtion instruction
445 ConstantSInt* iteTimes=ConstantSInt::get(operand->getType(),((ConstantSInt*)operand)->getValue()-II+1);
446 cond->setOperand(1,iteTimes);
447
448}
449
450
451
452
453
454//construct the epilogue
455void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_bb){
456
457 //compute the schedule for epilogue
458 vvNodeType& tempSchedule_epilogue= *(new vector< std::vector<ModuloSchedGraphNode*> >(schedule));
459 unsigned scheduleSize=schedule.size();
460 int round =0;
461 while(round < ceil(1.0*scheduleSize/II )-1 ){
462 round++;
463 for( unsigned i=0;i < scheduleSize ; i++){
464 if(i + round *II >= scheduleSize) break;
465 for(unsigned j=0;j < schedule[i].size();j++)
466 if(schedule[i + round*II ][j]){
467 assert( tempSchedule_epilogue[i][j] == NULL && "table not consitant with core table");
468
469 //move the schdule one iteration behind and overlap
470 tempSchedule_epilogue[i][j]=schedule[i + round*II][j];
471 }
472 }
473 }
474
475 //fill in the epilogue
476 InstListType& epilogue_ist = epilogue->getInstList();
477 for(unsigned i=II;i <scheduleSize ;i++)
478 for(unsigned j=0;j < tempSchedule_epilogue[i].size();j++)
479 if(tempSchedule_epilogue[i][j]){
480 Instruction* inst=(Instruction*)tempSchedule_epilogue[i][j]->getInst();
481
482 //BranchInst and PHINode should be treated differently
483 //BranchInst:unecessary, simly omitted
484 //PHINode: omitted
485 if( !BranchInst::classof(inst) && ! PHINode::classof(inst) ){
486 //make a clone instruction and insert it into the epilogue
487 Instruction* cln=cloneInstSetMemory(inst);
488 epilogue_ist.push_front(cln);
489 }
490 }
491
492
493 //*************delete the original instructions****************//
494 //to delete the original instructions, we have to make sure their use is zero
495
496 //update original core instruction's uses, using its clone instread
497 for(unsigned i=0;i < II; i++)
498 for(unsigned j=0;j < coreSchedule[i].size() ;j++){
499 if(coreSchedule[i][j])
500 updateUseWithClone((Instruction*)coreSchedule[i][j]->getInst() );
501 }
502
503 //erase these instructions
504 for(unsigned i=0;i < II; i++)
505 for(unsigned j=0;j < coreSchedule[i].size();j++)
506 if(coreSchedule[i][j]){
507 Instruction* ist=(Instruction*)coreSchedule[i][j]->getInst();
508 ist->getParent()->getInstList().erase(ist);
509 }
510 //**************************************************************//
511
512
513 //finally, insert an unconditional branch instruction at the end
514 epilogue_ist.push_back(new BranchInst(succ_bb));
515
516}
517
518
519//----------------------------------------------------------------------------------------------
520//this function replace the value(instruction) ist in other instructions with its latest clone
521//i.e. after this function is called, the ist is not used anywhere and it can be erased.
522//----------------------------------------------------------------------------------------------
523void ModuloScheduling::updateUseWithClone(Instruction* ist){
524
525 while(ist->use_size() >0){
526 bool destroyed=false;
527
528 //other instruction is using this value ist
529 assert(Instruction::classof(*ist->use_begin()));
530 Instruction *inst=(Instruction*)(* ist->use_begin());
531
532 for(unsigned i=0;i<inst->getNumOperands();i++)
533 if(inst->getOperand(i) == ist && ist->getClone()){
534
535 //if the instruction is TmpInstruction, simly delete it because it has no parent
536 // and it does not belongs to any BasicBlock
537 if(TmpInstruction::classof(inst)) {
538 delete inst;
539 destroyed=true;
540 break;
541 }
542
543
544 //otherwise, set the instruction's operand to the value's clone
545 inst->setOperand(i, ist->getClone());
546
547 //the use from the original value ist is destroyed
548 destroyed=true;
549 break;
550 }
551 if( !destroyed)
552 {
553 //if the use can not be destroyed , something is wrong
554 inst->dump();
555 assert( 0 &&"this use can not be destroyed");
556 }
557 }
558
559}
560
561
562//********************************************************
563//this function clear all clone mememoy
564//i.e. set all instruction's clone memory to NULL
565//*****************************************************
566void ModuloScheduling::clearCloneMemory(){
567for(unsigned i=0; i < coreSchedule.size();i++)
568 for(unsigned j=0;j<coreSchedule[i].size();j++)
569 if(coreSchedule[i][j]) ((Instruction*)coreSchedule[i][j]->getInst())->clearClone();
570
571}
572
573
574//********************************************************************************
575//this function make a clone of the instruction orn
576//the cloned instruction will use the orn's operands' latest clone as its operands
577//it is done this way because LLVM is in SSA form and we should use the correct value
578//
579//this fuction also update the instruction orn's latest clone memory
580//**********************************************************************************
581Instruction* ModuloScheduling::cloneInstSetMemory(Instruction* orn) {
582
583//make a clone instruction
584 Instruction* cln=orn->clone();
585
586
587 //update the operands
588 for(unsigned k=0;k<orn->getNumOperands();k++){
589 const Value* op=orn->getOperand(k);
590 if(Instruction::classof(op) && ((Instruction*)op)->getClone()){
591 Instruction* op_inst=(Instruction*)op;
592 cln->setOperand(k, op_inst->getClone());
593 }
594 }
595
596 //update clone memory
597 orn->setClone(cln);
598 return cln;
599}
600
601
602
603bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, unsigned end, NodeVec& nodeScheduled)
604{
605
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000606 const TargetSchedInfo& msi=target.getSchedInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000607 unsigned int numIssueSlots=msi.maxNumIssueTotal;
608
609 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
610 modSched_os<<"startTime= "<<start<<" endTime= "<<end<<"\n";
611 bool isScheduled=false;
612 for(unsigned i=start;i<= end;i++){
613 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
614 modSched_os<< " now try cycle " <<i<<":"<<"\n";
615 for(unsigned j=0;j<numIssueSlots;j++){
616 unsigned int core_i = i%II;
617 unsigned int core_j=j;
618 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
619 modSched_os <<"\t Trying slot "<<j<<"...........";
620 //check the resouce table, make sure there is no resource conflicts
621 const Instruction* instr=node->getInst();
622 MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(instr);
623 bool resourceConflict=false;
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000624 const TargetInstrInfo &mii=msi.getInstrInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000625
626 if(coreSchedule.size() < core_i+1 || !coreSchedule[core_i][core_j]){
627 //this->dumpResourceUsageTable();
628 int latency=0;
629 for(unsigned k=0;k< tempMvec.size();k++)
630 {
631 MachineInstr* minstr=tempMvec[k];
632 InstrRUsage rUsage=msi.getInstrRUsage(minstr->getOpCode());
633 std::vector<std::vector<resourceId_t> > resources
634 =rUsage.resourcesByCycle;
635 updateResourceTable(resources,i + latency);
636 latency +=max(mii.minLatency(minstr->getOpCode()),1) ;
637 }
638
639 //this->dumpResourceUsageTable();
640
641 latency=0;
642 if( resourceTableNegative()){
643
644 //undo-update the resource table
645 for(unsigned k=0;k< tempMvec.size();k++){
646 MachineInstr* minstr=tempMvec[k];
647 InstrRUsage rUsage=msi.getInstrRUsage(minstr->getOpCode());
648 std::vector<std::vector<resourceId_t> > resources
649 =rUsage.resourcesByCycle;
650 undoUpdateResourceTable(resources,i + latency);
651 latency +=max(mii.minLatency(minstr->getOpCode()),1) ;
652 }
653 resourceConflict=true;
654 }
655 }
656 if( !resourceConflict && !coreSchedule[core_i][core_j]){
657 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){
658 modSched_os <<" OK!"<<"\n";
659 modSched_os<<"Node "<<node->getNodeId()<< " is scheduleed."<<"\n";
660 }
661 //schedule[i][j]=node;
662 while(schedule.size() <= i){
663 std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
664 for(unsigned k=0;k<numIssueSlots;k++)
665 newCycle->push_back(NULL);
666 schedule.push_back(*newCycle);
667 }
668 vector<ModuloSchedGraphNode*>::iterator startIterator;
669 startIterator = schedule[i].begin();
670 schedule[i].insert(startIterator+j,node);
671 startIterator = schedule[i].begin();
672 schedule[i].erase(startIterator+j+1);
673
674 //update coreSchedule
675 //coreSchedule[core_i][core_j]=node;
676 while(coreSchedule.size() <= core_i){
677 std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
678 for(unsigned k=0;k<numIssueSlots;k++)
679 newCycle->push_back(NULL);
680 coreSchedule.push_back(*newCycle);
681 }
682
683 startIterator = coreSchedule[core_i].begin();
684 coreSchedule[core_i].insert(startIterator+core_j,node);
685 startIterator = coreSchedule[core_i].begin();
686 coreSchedule[core_i].erase(startIterator+core_j+1);
687
688 node->setSchTime(i);
689 isScheduled=true;
690 nodeScheduled.push_back(node);
691
692 break;
693 }
694 else if( coreSchedule[core_i][core_j]) {
695 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
696 modSched_os <<" Slot not available "<<"\n";
697 }
698 else{
699 if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
700 modSched_os <<" Resource conflicts"<<"\n";
701 }
702 }
703 if(isScheduled) break;
704 }
705 //assert(nodeScheduled &&"this node can not be scheduled?");
706 return isScheduled;
707}
708
709void ModuloScheduling::updateResourceTable(std::vector<std::vector<unsigned int> > useResources, int startCycle){
710 for(unsigned i=0;i< useResources.size();i++){
711 int absCycle=startCycle+i;
712 int coreCycle=absCycle % II;
713 std::vector<pair<int,int> >& resourceRemained=resourceTable[coreCycle];
714 std::vector<unsigned int>& resourceUsed= useResources[i];
715 for(unsigned j=0;j< resourceUsed.size();j++){
716 for(unsigned k=0;k< resourceRemained.size();k++)
717 if((int)resourceUsed[j] == resourceRemained[k].first){
718 resourceRemained[k].second--;
719 }
720 }
721 }
722}
723
724void ModuloScheduling::undoUpdateResourceTable(std::vector<std::vector<unsigned int> > useResources, int startCycle){
725 for(unsigned i=0;i< useResources.size();i++){
726 int absCycle=startCycle+i;
727 int coreCycle=absCycle % II;
728 std::vector<pair<int,int> >& resourceRemained=resourceTable[coreCycle];
729 std::vector<unsigned int>& resourceUsed= useResources[i];
730 for(unsigned j=0;j< resourceUsed.size();j++){
731 for(unsigned k=0;k< resourceRemained.size();k++)
732 if((int)resourceUsed[j] == resourceRemained[k].first){
733 resourceRemained[k].second++;
734 }
735 }
736 }
737}
738
739
740//-----------------------------------------------------------------------
741//Function: resouceTableNegative
742//return value:
743// return false if any element in the resouceTable is negative
744// otherwise return true
745//Purpose:
746// this function is used to determine if an instruction is eligible for schedule at certain cycle
747//---------------------------------------------------------------------------------------
748
749bool ModuloScheduling::resourceTableNegative(){
750 assert(resourceTable.size() == (unsigned)II&& "resouceTable size must be equal to II");
751 bool isNegative=false;
752 for(unsigned i=0; i < resourceTable.size();i++)
753 for(unsigned j=0;j < resourceTable[i].size();j++){
754 if(resourceTable[i][j].second <0) {
755 isNegative=true;
756 break;
757 }
758 }
759 return isNegative;
760}
761
762
763//----------------------------------------------------------------------
764//Function: dumpResouceUsageTable
765//Purpose:
766// print out ResouceTable for debug
767//
768//------------------------------------------------------------------------
769
770void ModuloScheduling::dumpResourceUsageTable(){
771 modSched_os<<"dumping resource usage table"<<"\n";
772 for(unsigned i=0;i< resourceTable.size();i++){
773 for(unsigned j=0;j < resourceTable[i].size();j++)
774 modSched_os <<resourceTable[i][j].first<<":"<< resourceTable[i][j].second<<" ";
775 modSched_os <<"\n";
776 }
777
778}
779
780//----------------------------------------------------------------------
781//Function: dumpSchedule
782//Purpose:
783// print out thisSchedule for debug
784//
785//-----------------------------------------------------------------------
786void ModuloScheduling::dumpSchedule(std::vector< std::vector<ModuloSchedGraphNode*> > thisSchedule){
787
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000788 const TargetSchedInfo& msi=target.getSchedInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000789 unsigned numIssueSlots=msi.maxNumIssueTotal;
790 for(unsigned i=0;i< numIssueSlots;i++)
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000791 modSched_os <<"\t#";
Guochun Shif1c154f2003-03-27 17:57:44 +0000792 modSched_os<<"\n";
793 for(unsigned i=0;i < thisSchedule.size();i++)
794 {
795 modSched_os<<"cycle"<<i<<": ";
796 for(unsigned j=0;j<thisSchedule[i].size();j++)
797 if(thisSchedule[i][j]!= NULL)
798 modSched_os<<thisSchedule[i][j]->getNodeId()<<"\t";
799 else
800 modSched_os<<"\t";
801 modSched_os<<"\n";
802 }
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000803
Guochun Shif1c154f2003-03-27 17:57:44 +0000804}
805
806
807//----------------------------------------------------
808//Function: dumpScheduling
809//Purpose:
810// print out the schedule and coreSchedule for debug
811//
812//-------------------------------------------------------
813
814void ModuloScheduling::dumpScheduling(){
815 modSched_os<<"dump schedule:"<<"\n";
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000816 const TargetSchedInfo& msi=target.getSchedInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000817 unsigned numIssueSlots=msi.maxNumIssueTotal;
818 for(unsigned i=0;i< numIssueSlots;i++)
819 modSched_os <<"\t#";
820 modSched_os<<"\n";
821 for(unsigned i=0;i < schedule.size();i++)
822 {
823 modSched_os<<"cycle"<<i<<": ";
824 for(unsigned j=0;j<schedule[i].size();j++)
825 if(schedule[i][j]!= NULL)
826 modSched_os<<schedule[i][j]->getNodeId()<<"\t";
827 else
828 modSched_os<<"\t";
829 modSched_os<<"\n";
830 }
831
832 modSched_os<<"dump coreSchedule:"<<"\n";
833 for(unsigned i=0;i< numIssueSlots;i++)
834 modSched_os <<"\t#";
835 modSched_os<<"\n";
836 for(unsigned i=0;i < coreSchedule.size();i++){
837 modSched_os<<"cycle"<<i<<": ";
838 for(unsigned j=0;j< coreSchedule[i].size();j++)
839 if(coreSchedule[i][j] !=NULL)
840 modSched_os<<coreSchedule[i][j]->getNodeId()<<"\t";
841 else
842 modSched_os<<"\t";
843 modSched_os<<"\n";
844 }
845}
846
847
848
849//---------------------------------------------------------------------------
850// Function: ModuloSchedulingPass
851//
852// Purpose:
853// Entry point for Modulo Scheduling
854// Schedules LLVM instruction
855//
856//---------------------------------------------------------------------------
857
858namespace {
859 class ModuloSchedulingPass : public FunctionPass {
860 const TargetMachine &target;
861 public:
862 ModuloSchedulingPass(const TargetMachine &T) : target(T) {}
863 const char *getPassName() const { return "Modulo Scheduling"; }
864
865 // getAnalysisUsage - We use LiveVarInfo...
866 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
867 //AU.addRequired(FunctionLiveVarInfo::ID);
868 }
869 bool runOnFunction(Function &F);
870 };
871} // end anonymous namespace
872
873
874
875bool ModuloSchedulingPass::runOnFunction(Function &F)
876{
877
878 //if necessary , open the output for debug purpose
879 if(ModuloSchedDebugLevel== ModuloSched_Disable)
880 return false;
881
882 if(ModuloSchedDebugLevel>= ModuloSched_PrintSchedule){
883 modSched_fb.open("moduloSchedDebugInfo.output", ios::out);
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000884 modSched_os<<"******************Modula Scheduling debug information*************************"<<"\n ";
Guochun Shif1c154f2003-03-27 17:57:44 +0000885 }
886
887 ModuloSchedGraphSet* graphSet = new ModuloSchedGraphSet(&F,target);
888 ModuloSchedulingSet ModuloSchedulingSet(*graphSet);
889
890 if(ModuloSchedDebugLevel>= ModuloSched_PrintSchedule)
891 modSched_fb.close();
892
893 return false;
894}
895
896
897Pass *createModuloSchedulingPass(const TargetMachine &tgt) {
898 return new ModuloSchedulingPass(tgt);
899}
900