blob: 29f4a4131e426b6be1f3cb301e0e83007bf5b48a [file] [log] [blame]
Misha Brukman8baa01c2003-04-09 21:51:34 +00001//===- ModuloScheduling.cpp - Modulo Software Pipelining ------------------===//
Guochun Shif1c154f2003-03-27 17:57:44 +00002//
Misha Brukman8baa01c2003-04-09 21:51:34 +00003// Implements the llvm/CodeGen/ModuloScheduling.h interface
Guochun Shif1c154f2003-03-27 17:57:44 +00004//
5//===----------------------------------------------------------------------===//
6
Guochun Shi6fbe5fb2003-04-06 23:56:19 +00007//#include "llvm/CodeGen/MachineCodeForBasicBlock.h"
8//#include "llvm/CodeGen/MachineCodeForMethod.h"
Guochun Shi6fbe5fb2003-04-06 23:56:19 +00009//#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h" // FIXME: Remove when modularized better
Guochun Shif1c154f2003-03-27 17:57:44 +000010#include "llvm/BasicBlock.h"
Misha Brukman8baa01c2003-04-09 21:51:34 +000011#include "llvm/Constants.h"
Guochun Shif1c154f2003-03-27 17:57:44 +000012#include "llvm/Instruction.h"
Guochun Shif1c154f2003-03-27 17:57:44 +000013#include "llvm/iTerminators.h"
14#include "llvm/iPHINode.h"
Misha Brukman8baa01c2003-04-09 21:51:34 +000015#include "llvm/CodeGen/MachineInstr.h"
16#include "llvm/CodeGen/MachineCodeForInstruction.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/InstrSelection.h"
19#include "llvm/Target/TargetSchedInfo.h"
20#include "llvm/Target/TargetMachine.h"
21#include "Support/CommandLine.h"
Misha Brukman2c821cc2003-04-10 19:19:23 +000022#include "Support/Statistic.h"
Misha Brukman8baa01c2003-04-09 21:51:34 +000023#include "ModuloSchedGraph.h"
24#include "ModuloScheduling.h"
25#include <algorithm>
26#include <fstream>
Guochun Shif1c154f2003-03-27 17:57:44 +000027#include <iostream>
Guochun Shi33280522003-06-08 20:40:47 +000028
29using std::endl;
Guochun Shi0e936872003-06-10 20:04:30 +000030using std::cerr;
Guochun Shif1c154f2003-03-27 17:57:44 +000031
32//************************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +000033// printing Debug information
34// ModuloSchedDebugLevel stores the value of debug level
35// modsched_os is the ostream to dump debug information, which is written into
36// the file 'moduloSchedDebugInfo.output'
37// see ModuloSchedulingPass::runOnFunction()
Guochun Shif1c154f2003-03-27 17:57:44 +000038//************************************************************
39
Guochun Shi139f0c22003-05-30 00:17:09 +000040ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
41
42cl::opt<ModuloSchedDebugLevel_t,true>
43SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
44 cl::desc("enable modulo scheduling debugging information"),
45 cl::values(clEnumValN(ModuloSchedDebugLevel_NoDebugInfo,
46 "none", "disable debug output"),
47 clEnumValN(ModuloSchedDebugLevel_PrintSchedule,
48 "psched", "print original and new schedule"),
49 clEnumValN(ModuloSchedDebugLevel_PrintScheduleProcess,
50 "pschedproc",
51 "print how the new schdule is produced"),
52 0));
Guochun Shif1c154f2003-03-27 17:57:44 +000053
Misha Brukman8baa01c2003-04-09 21:51:34 +000054// Computes the schedule and inserts epilogue and prologue
55//
Guochun Shi0e936872003-06-10 20:04:30 +000056void
57ModuloScheduling::instrScheduling(){
Guochun Shi33280522003-06-08 20:40:47 +000058
Guochun Shi33280522003-06-08 20:40:47 +000059
Misha Brukman2c821cc2003-04-10 19:19:23 +000060 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +000061 DEBUG_PRINT(std::cerr << "************ computing modulo schedule ***********\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000062
Misha Brukman8baa01c2003-04-09 21:51:34 +000063 const TargetSchedInfo & msi = target.getSchedInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +000064
65 //number of issue slots in the in each cycle
Misha Brukman8baa01c2003-04-09 21:51:34 +000066 int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +000067
68 //compute the schedule
Misha Brukman8baa01c2003-04-09 21:51:34 +000069 bool success = false;
70 while (!success) {
71 //clear memory from the last round and initialize if necessary
72 clearInitMem(msi);
Guochun Shif1c154f2003-03-27 17:57:44 +000073
Misha Brukman8baa01c2003-04-09 21:51:34 +000074 //compute schedule and coreSchedule with the current II
75 success = computeSchedule();
76
77 if (!success) {
78 II++;
Misha Brukman2c821cc2003-04-10 19:19:23 +000079 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +000080 DEBUG_PRINT(std::cerr << "increase II to " << II << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000081 }
Misha Brukman8baa01c2003-04-09 21:51:34 +000082 }
83
Guochun Shi0e936872003-06-10 20:04:30 +000084 //print the final schedule
85 dumpFinalSchedule();
86
Guochun Shif1c154f2003-03-27 17:57:44 +000087 //the schedule has been computed
88 //create epilogue, prologue and kernel BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000089
Guochun Shif1c154f2003-03-27 17:57:44 +000090 //find the successor for this BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000091 BasicBlock *succ_bb = getSuccBB(bb);
92
Guochun Shif1c154f2003-03-27 17:57:44 +000093 //print the original BasicBlock if necessary
Misha Brukman2c821cc2003-04-10 19:19:23 +000094 if (ModuloScheduling::printSchedule()) {
Guochun Shi33280522003-06-08 20:40:47 +000095 DEBUG_PRINT(std::cerr << "dumping the orginal block\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000096 graph.dump(bb);
97 }
Guochun Shif1c154f2003-03-27 17:57:44 +000098 //construction of prologue, kernel and epilogue
Guochun Shi8f1d4ab2003-06-08 23:16:07 +000099
100 /*
Misha Brukman8baa01c2003-04-09 21:51:34 +0000101 BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
102 BasicBlock *prologue = bb;
103 BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000104 */
Misha Brukman8baa01c2003-04-09 21:51:34 +0000105
106 // Construct prologue
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000107 /*constructPrologue(prologue);*/
Guochun Shif1c154f2003-03-27 17:57:44 +0000108
Misha Brukman8baa01c2003-04-09 21:51:34 +0000109 // Construct kernel
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000110
111 /*constructKernel(prologue, kernel, epilogue);*/
Guochun Shif1c154f2003-03-27 17:57:44 +0000112
Misha Brukman8baa01c2003-04-09 21:51:34 +0000113 // Construct epilogue
Guochun Shif1c154f2003-03-27 17:57:44 +0000114
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000115 /*constructEpilogue(epilogue, succ_bb);*/
116
Guochun Shif1c154f2003-03-27 17:57:44 +0000117 //print the BasicBlocks if necessary
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000118// if (0){
119// DEBUG_PRINT(std::cerr << "dumping the prologue block:\n");
120// graph.dump(prologue);
121// DEBUG_PRINT(std::cerr << "dumping the kernel block\n");
122// graph.dump(kernel);
123// DEBUG_PRINT(std::cerr << "dumping the epilogue block\n");
124// graph.dump(epilogue);
125// }
126
Guochun Shif1c154f2003-03-27 17:57:44 +0000127}
128
Guochun Shi0e936872003-06-10 20:04:30 +0000129
Misha Brukman8baa01c2003-04-09 21:51:34 +0000130// Clear memory from the last round and initialize if necessary
131//
Guochun Shi0e936872003-06-10 20:04:30 +0000132
133void
134ModuloScheduling::clearInitMem(const TargetSchedInfo & msi){
135
Misha Brukman8baa01c2003-04-09 21:51:34 +0000136 unsigned numIssueSlots = msi.maxNumIssueTotal;
137 // clear nodeScheduled from the last round
Misha Brukman2c821cc2003-04-10 19:19:23 +0000138 if (ModuloScheduling::printScheduleProcess()) {
Guochun Shi33280522003-06-08 20:40:47 +0000139 DEBUG_PRINT(std::cerr << "***** new round with II= " << II << " ***********\n");
140 DEBUG_PRINT(std::cerr <<
Misha Brukman2c821cc2003-04-10 19:19:23 +0000141 " ************clear the vector nodeScheduled*************\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000142 }
143 nodeScheduled.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000144
Misha Brukman8baa01c2003-04-09 21:51:34 +0000145 // clear resourceTable from the last round and reset it
146 resourceTable.clear();
147 for (unsigned i = 0; i < II; ++i)
148 resourceTable.push_back(msi.resourceNumVector);
Guochun Shif1c154f2003-03-27 17:57:44 +0000149
Misha Brukman8baa01c2003-04-09 21:51:34 +0000150 // clear the schdule and coreSchedule from the last round
151 schedule.clear();
152 coreSchedule.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000153
Misha Brukman8baa01c2003-04-09 21:51:34 +0000154 // create a coreSchedule of size II*numIssueSlots
155 // each entry is NULL
156 while (coreSchedule.size() < II) {
157 std::vector < ModuloSchedGraphNode * >*newCycle =
158 new std::vector < ModuloSchedGraphNode * >();
159 for (unsigned k = 0; k < numIssueSlots; ++k)
160 newCycle->push_back(NULL);
161 coreSchedule.push_back(*newCycle);
162 }
163}
Guochun Shif1c154f2003-03-27 17:57:44 +0000164
Misha Brukman8baa01c2003-04-09 21:51:34 +0000165// Compute schedule and coreSchedule with the current II
166//
Guochun Shi0e936872003-06-10 20:04:30 +0000167bool
168ModuloScheduling::computeSchedule(){
169
Guochun Shif1c154f2003-03-27 17:57:44 +0000170
Misha Brukman2c821cc2003-04-10 19:19:23 +0000171 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000172 DEBUG_PRINT(std::cerr << "start to compute schedule\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000173
Misha Brukman8baa01c2003-04-09 21:51:34 +0000174 // Loop over the ordered nodes
175 for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
176 // Try to schedule for node I
Misha Brukman2c821cc2003-04-10 19:19:23 +0000177 if (ModuloScheduling::printScheduleProcess())
Misha Brukman8baa01c2003-04-09 21:51:34 +0000178 dumpScheduling();
179 ModuloSchedGraphNode *node = *I;
Guochun Shif1c154f2003-03-27 17:57:44 +0000180
Misha Brukman8baa01c2003-04-09 21:51:34 +0000181 // Compute whether this node has successor(s)
182 bool succ = true;
183
184 // Compute whether this node has predessor(s)
185 bool pred = true;
186
187 NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
188 if (schSucc.empty())
189 succ = false;
190 NodeVec schPred = graph.vectorConj(nodeScheduled, graph.predSet(node));
191 if (schPred.empty())
192 pred = false;
193
194 //startTime: the earliest time we will try to schedule this node
195 //endTime: the latest time we will try to schedule this node
196 int startTime, endTime;
197
198 //node's earlyStart: possible earliest time to schedule this node
199 //node's lateStart: possible latest time to schedule this node
200 node->setEarlyStart(-1);
201 node->setLateStart(9999);
202
203 //this node has predessor but no successor
204 if (!succ && pred) {
205 // This node's earlyStart is it's predessor's schedule time + the edge
206 // delay - the iteration difference* II
207 for (unsigned i = 0; i < schPred.size(); i++) {
208 ModuloSchedGraphNode *predNode = schPred[i];
209 SchedGraphEdge *edge =
210 graph.getMaxDelayEdge(predNode->getNodeId(),
211 node->getNodeId());
212 int temp =
213 predNode->getSchTime() + edge->getMinDelay() -
214 edge->getIteDiff() * II;
215 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
Guochun Shif1c154f2003-03-27 17:57:44 +0000216 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000217 startTime = node->getEarlyStart();
218 endTime = node->getEarlyStart() + II - 1;
Guochun Shif1c154f2003-03-27 17:57:44 +0000219 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000220 // This node has a successor but no predecessor
221 if (succ && !pred) {
222 for (unsigned i = 0; i < schSucc.size(); ++i) {
223 ModuloSchedGraphNode *succNode = schSucc[i];
224 SchedGraphEdge *edge =
225 graph.getMaxDelayEdge(succNode->getNodeId(),
226 node->getNodeId());
227 int temp =
228 succNode->getSchTime() - edge->getMinDelay() +
229 edge->getIteDiff() * II;
230 node->setLateStart(std::min(node->getEarlyStart(), temp));
231 }
232 startTime = node->getLateStart() - II + 1;
233 endTime = node->getLateStart();
234 }
235 // This node has both successors and predecessors
236 if (succ && pred) {
237 for (unsigned i = 0; i < schPred.size(); ++i) {
238 ModuloSchedGraphNode *predNode = schPred[i];
239 SchedGraphEdge *edge =
240 graph.getMaxDelayEdge(predNode->getNodeId(),
241 node->getNodeId());
242 int temp =
243 predNode->getSchTime() + edge->getMinDelay() -
244 edge->getIteDiff() * II;
245 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
246 }
247 for (unsigned i = 0; i < schSucc.size(); ++i) {
248 ModuloSchedGraphNode *succNode = schSucc[i];
249 SchedGraphEdge *edge =
250 graph.getMaxDelayEdge(succNode->getNodeId(),
251 node->getNodeId());
252 int temp =
253 succNode->getSchTime() - edge->getMinDelay() +
254 edge->getIteDiff() * II;
255 node->setLateStart(std::min(node->getEarlyStart(), temp));
256 }
257 startTime = node->getEarlyStart();
258 endTime = std::min(node->getLateStart(),
259 node->getEarlyStart() + ((int) II) - 1);
260 }
261 //this node has no successor or predessor
262 if (!succ && !pred) {
263 node->setEarlyStart(node->getASAP());
264 startTime = node->getEarlyStart();
265 endTime = node->getEarlyStart() + II - 1;
266 }
267 //try to schedule this node based on the startTime and endTime
Misha Brukman2c821cc2003-04-10 19:19:23 +0000268 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000269 DEBUG_PRINT(std::cerr << "scheduling the node " << (*I)->getNodeId() << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000270
271 bool success =
272 this->ScheduleNode(node, startTime, endTime, nodeScheduled);
273 if (!success)
274 return false;
275 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000276 return true;
277}
278
279
Misha Brukman8baa01c2003-04-09 21:51:34 +0000280// Get the successor of the BasicBlock
281//
Guochun Shi0e936872003-06-10 20:04:30 +0000282BasicBlock *
283ModuloScheduling::getSuccBB(BasicBlock *bb){
284
Misha Brukman8baa01c2003-04-09 21:51:34 +0000285 BasicBlock *succ_bb;
286 for (unsigned i = 0; i < II; ++i)
287 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
288 if (coreSchedule[i][j]) {
289 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000290
Misha Brukman8baa01c2003-04-09 21:51:34 +0000291 //we can get successor from the BranchInst instruction
292 //assume we only have one successor (besides itself) here
293 if (BranchInst::classof(ist)) {
294 BranchInst *bi = (BranchInst *) ist;
295 assert(bi->isConditional() &&
296 "the branchInst is not a conditional one");
297 assert(bi->getNumSuccessors() == 2
298 && " more than two successors?");
299 BasicBlock *bb1 = bi->getSuccessor(0);
300 BasicBlock *bb2 = bi->getSuccessor(1);
301 assert((bb1 == bb || bb2 == bb) &&
302 " None of its successors is itself?");
303 if (bb1 == bb)
304 succ_bb = bb2;
305 else
306 succ_bb = bb1;
307 return succ_bb;
308 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000309 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000310 assert(0 && "NO Successor?");
Guochun Shif1c154f2003-03-27 17:57:44 +0000311 return NULL;
312}
313
314
Misha Brukman8baa01c2003-04-09 21:51:34 +0000315// Get the predecessor of the BasicBlock
316//
Guochun Shi0e936872003-06-10 20:04:30 +0000317BasicBlock *
318ModuloScheduling::getPredBB(BasicBlock *bb){
319
Misha Brukman8baa01c2003-04-09 21:51:34 +0000320 BasicBlock *pred_bb;
321 for (unsigned i = 0; i < II; ++i)
322 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
323 if (coreSchedule[i][j]) {
324 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000325
Misha Brukman8baa01c2003-04-09 21:51:34 +0000326 //we can get predecessor from the PHINode instruction
327 //assume we only have one predecessor (besides itself) here
328 if (PHINode::classof(ist)) {
329 PHINode *phi = (PHINode *) ist;
330 assert(phi->getNumIncomingValues() == 2 &&
331 " the number of incoming value is not equal to two? ");
332 BasicBlock *bb1 = phi->getIncomingBlock(0);
333 BasicBlock *bb2 = phi->getIncomingBlock(1);
334 assert((bb1 == bb || bb2 == bb) &&
335 " None of its predecessor is itself?");
336 if (bb1 == bb)
337 pred_bb = bb2;
338 else
339 pred_bb = bb1;
340 return pred_bb;
341 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000342 }
343 assert(0 && " no predecessor?");
344 return NULL;
345}
346
347
Misha Brukman8baa01c2003-04-09 21:51:34 +0000348// Construct the prologue
349//
Guochun Shi0e936872003-06-10 20:04:30 +0000350void
351ModuloScheduling::constructPrologue(BasicBlock *prologue){
352
Misha Brukman8baa01c2003-04-09 21:51:34 +0000353 InstListType & prologue_ist = prologue->getInstList();
354 vvNodeType & tempSchedule_prologue =
Misha Brukman2c821cc2003-04-10 19:19:23 +0000355 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000356
Guochun Shif1c154f2003-03-27 17:57:44 +0000357 //compute the schedule for prologue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000358 unsigned round = 0;
359 unsigned scheduleSize = schedule.size();
360 while (round < scheduleSize / II) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000361 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000362 for (unsigned i = 0; i < scheduleSize; ++i) {
363 if (round * II + i >= scheduleSize)
364 break;
365 for (unsigned j = 0; j < schedule[i].size(); ++j) {
366 if (schedule[i][j]) {
367 assert(tempSchedule_prologue[round * II + i][j] == NULL &&
368 "table not consitent with core table");
369 // move the schedule one iteration ahead and overlap with the original
370 tempSchedule_prologue[round * II + i][j] = schedule[i][j];
371 }
372 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000373 }
374 }
375
Misha Brukman8baa01c2003-04-09 21:51:34 +0000376 // Clear the clone memory in the core schedule instructions
Guochun Shif1c154f2003-03-27 17:57:44 +0000377 clearCloneMemory();
Guochun Shif1c154f2003-03-27 17:57:44 +0000378
Misha Brukman8baa01c2003-04-09 21:51:34 +0000379 // Fill in the prologue
380 for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
381 for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
382 if (tempSchedule_prologue[i][j]) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000383
Misha Brukman8baa01c2003-04-09 21:51:34 +0000384 //get the instruction
385 Instruction *orn =
386 (Instruction *) tempSchedule_prologue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000387
Misha Brukman8baa01c2003-04-09 21:51:34 +0000388 //made a clone of it
389 Instruction *cln = cloneInstSetMemory(orn);
Guochun Shif1c154f2003-03-27 17:57:44 +0000390
Misha Brukman8baa01c2003-04-09 21:51:34 +0000391 //insert the instruction
392 prologue_ist.insert(prologue_ist.back(), cln);
393
394 //if there is PHINode in the prologue, the incoming value from itself
395 //should be removed because it is not a loop any longer
396 if (PHINode::classof(cln)) {
397 PHINode *phi = (PHINode *) cln;
398 phi->removeIncomingValue(phi->getParent());
399 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000400 }
401}
402
403
Misha Brukman8baa01c2003-04-09 21:51:34 +0000404// Construct the kernel BasicBlock
405//
Guochun Shi0e936872003-06-10 20:04:30 +0000406void
407ModuloScheduling::constructKernel(BasicBlock *prologue,
Misha Brukman8baa01c2003-04-09 21:51:34 +0000408 BasicBlock *kernel,
Guochun Shi0e936872003-06-10 20:04:30 +0000409 BasicBlock *epilogue){
410
Guochun Shif1c154f2003-03-27 17:57:44 +0000411 //*************fill instructions in the kernel****************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000412 InstListType & kernel_ist = kernel->getInstList();
413 BranchInst *brchInst;
414 PHINode *phiInst, *phiCln;
Guochun Shif1c154f2003-03-27 17:57:44 +0000415
Misha Brukman8baa01c2003-04-09 21:51:34 +0000416 for (unsigned i = 0; i < coreSchedule.size(); ++i)
417 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
418 if (coreSchedule[i][j]) {
419
420 // Take care of branch instruction differently with normal instructions
421 if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
422 brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
423 continue;
424 }
425 // Take care of PHINode instruction differently with normal instructions
426 if (PHINode::classof(coreSchedule[i][j]->getInst())) {
427 phiInst = (PHINode *) coreSchedule[i][j]->getInst();
428 Instruction *cln = cloneInstSetMemory(phiInst);
429 kernel_ist.insert(kernel_ist.back(), cln);
430 phiCln = (PHINode *) cln;
431 continue;
432 }
433 //for normal instructions: made a clone and insert it in the kernel_ist
434 Instruction *cln =
435 cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
436 getInst());
437 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000438 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000439 // The two incoming BasicBlock for PHINode is the prologue and the kernel
440 // (itself)
441 phiCln->setIncomingBlock(0, prologue);
442 phiCln->setIncomingBlock(1, kernel);
Guochun Shif1c154f2003-03-27 17:57:44 +0000443
Misha Brukman8baa01c2003-04-09 21:51:34 +0000444 // The incoming value for the kernel (itself) is the new value which is
445 // computed in the kernel
446 Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000447 phiCln->setIncomingValue(1, originalVal->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000448
Misha Brukman8baa01c2003-04-09 21:51:34 +0000449 // Make a clone of the branch instruction and insert it in the end
450 BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
451 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000452
Misha Brukman8baa01c2003-04-09 21:51:34 +0000453 // delete the unconditional branch instruction, which is generated when
454 // splitting the basicBlock
455 kernel_ist.erase(--kernel_ist.end());
Guochun Shif1c154f2003-03-27 17:57:44 +0000456
Misha Brukman8baa01c2003-04-09 21:51:34 +0000457 // set the first successor to itself
458 ((BranchInst *) cln)->setSuccessor(0, kernel);
459 // set the second successor to eiplogue
460 ((BranchInst *) cln)->setSuccessor(1, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000461
462 //*****change the condition*******
463
464 //get the condition instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000465 Instruction *cond = (Instruction *) cln->getCondition();
Guochun Shif1c154f2003-03-27 17:57:44 +0000466
467 //get the condition's second operand, it should be a constant
Misha Brukman8baa01c2003-04-09 21:51:34 +0000468 Value *operand = cond->getOperand(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000469 assert(ConstantSInt::classof(operand));
470
471 //change the constant in the condtion instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000472 ConstantSInt *iteTimes =
473 ConstantSInt::get(operand->getType(),
474 ((ConstantSInt *) operand)->getValue() - II + 1);
475 cond->setOperand(1, iteTimes);
Guochun Shif1c154f2003-03-27 17:57:44 +0000476
477}
478
479
Misha Brukman8baa01c2003-04-09 21:51:34 +0000480// Construct the epilogue
481//
Guochun Shi0e936872003-06-10 20:04:30 +0000482void
483ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
484 BasicBlock *succ_bb){
Guochun Shif1c154f2003-03-27 17:57:44 +0000485
Guochun Shif1c154f2003-03-27 17:57:44 +0000486 //compute the schedule for epilogue
Misha Brukman2c821cc2003-04-10 19:19:23 +0000487 vvNodeType &tempSchedule_epilogue =
488 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000489 unsigned scheduleSize = schedule.size();
490 int round = 0;
491 while (round < ceil(1.0 * scheduleSize / II) - 1) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000492 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000493 for (unsigned i = 0; i < scheduleSize; i++) {
494 if (i + round * II >= scheduleSize)
495 break;
496 for (unsigned j = 0; j < schedule[i].size(); j++)
497 if (schedule[i + round * II][j]) {
498 assert(tempSchedule_epilogue[i][j] == NULL
499 && "table not consitant with core table");
Guochun Shif1c154f2003-03-27 17:57:44 +0000500
Misha Brukman8baa01c2003-04-09 21:51:34 +0000501 //move the schdule one iteration behind and overlap
502 tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
503 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000504 }
505 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000506
Guochun Shif1c154f2003-03-27 17:57:44 +0000507 //fill in the epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000508 InstListType & epilogue_ist = epilogue->getInstList();
509 for (unsigned i = II; i < scheduleSize; i++)
510 for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
511 if (tempSchedule_epilogue[i][j]) {
512 Instruction *inst =
513 (Instruction *) tempSchedule_epilogue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000514
Misha Brukman8baa01c2003-04-09 21:51:34 +0000515 //BranchInst and PHINode should be treated differently
516 //BranchInst:unecessary, simly omitted
517 //PHINode: omitted
518 if (!BranchInst::classof(inst) && !PHINode::classof(inst)) {
519 //make a clone instruction and insert it into the epilogue
520 Instruction *cln = cloneInstSetMemory(inst);
521 epilogue_ist.push_front(cln);
522 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000523 }
524
Guochun Shif1c154f2003-03-27 17:57:44 +0000525 //*************delete the original instructions****************//
526 //to delete the original instructions, we have to make sure their use is zero
Misha Brukman8baa01c2003-04-09 21:51:34 +0000527
Guochun Shif1c154f2003-03-27 17:57:44 +0000528 //update original core instruction's uses, using its clone instread
Misha Brukman8baa01c2003-04-09 21:51:34 +0000529 for (unsigned i = 0; i < II; i++)
530 for (unsigned j = 0; j < coreSchedule[i].size(); j++) {
531 if (coreSchedule[i][j])
532 updateUseWithClone((Instruction *) coreSchedule[i][j]->getInst());
Guochun Shif1c154f2003-03-27 17:57:44 +0000533 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000534
Guochun Shif1c154f2003-03-27 17:57:44 +0000535 //erase these instructions
Misha Brukman8baa01c2003-04-09 21:51:34 +0000536 for (unsigned i = 0; i < II; i++)
537 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
538 if (coreSchedule[i][j]) {
539 Instruction *ist = (Instruction *) coreSchedule[i][j]->getInst();
540 ist->getParent()->getInstList().erase(ist);
Guochun Shif1c154f2003-03-27 17:57:44 +0000541 }
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000542
Guochun Shif1c154f2003-03-27 17:57:44 +0000543
544
545 //finally, insert an unconditional branch instruction at the end
546 epilogue_ist.push_back(new BranchInst(succ_bb));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000547
Guochun Shif1c154f2003-03-27 17:57:44 +0000548}
549
550
Misha Brukman8baa01c2003-04-09 21:51:34 +0000551//------------------------------------------------------------------------------
552//this function replace the value(instruction) ist in other instructions with
553//its latest clone i.e. after this function is called, the ist is not used
554//anywhere and it can be erased.
555//------------------------------------------------------------------------------
Guochun Shi0e936872003-06-10 20:04:30 +0000556void
557ModuloScheduling::updateUseWithClone(Instruction * ist){
558
Misha Brukman8baa01c2003-04-09 21:51:34 +0000559
560 while (ist->use_size() > 0) {
561 bool destroyed = false;
562
Guochun Shif1c154f2003-03-27 17:57:44 +0000563 //other instruction is using this value ist
564 assert(Instruction::classof(*ist->use_begin()));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000565 Instruction *inst = (Instruction *) (*ist->use_begin());
Guochun Shif1c154f2003-03-27 17:57:44 +0000566
Misha Brukman8baa01c2003-04-09 21:51:34 +0000567 for (unsigned i = 0; i < inst->getNumOperands(); i++)
568 if (inst->getOperand(i) == ist && ist->getClone()) {
569 // if the instruction is TmpInstruction, simly delete it because it has
570 // no parent and it does not belongs to any BasicBlock
571 if (TmpInstruction::classof(inst)) {
572 delete inst;
573 destroyed = true;
574 break;
575 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000576
Misha Brukman8baa01c2003-04-09 21:51:34 +0000577 //otherwise, set the instruction's operand to the value's clone
578 inst->setOperand(i, ist->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000579
Misha Brukman8baa01c2003-04-09 21:51:34 +0000580 //the use from the original value ist is destroyed
581 destroyed = true;
582 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000583 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000584 if (!destroyed) {
585 //if the use can not be destroyed , something is wrong
586 inst->dump();
587 assert(0 && "this use can not be destroyed");
588 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000589 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000590
Guochun Shif1c154f2003-03-27 17:57:44 +0000591}
592
593
594//********************************************************
595//this function clear all clone mememoy
596//i.e. set all instruction's clone memory to NULL
597//*****************************************************
Guochun Shi0e936872003-06-10 20:04:30 +0000598void
599ModuloScheduling::clearCloneMemory(){
600
Misha Brukman8baa01c2003-04-09 21:51:34 +0000601 for (unsigned i = 0; i < coreSchedule.size(); i++)
602 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
603 if (coreSchedule[i][j])
604 ((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
605
Guochun Shif1c154f2003-03-27 17:57:44 +0000606}
607
608
Misha Brukman8baa01c2003-04-09 21:51:34 +0000609//******************************************************************************
610// this function make a clone of the instruction orn the cloned instruction will
611// use the orn's operands' latest clone as its operands it is done this way
612// because LLVM is in SSA form and we should use the correct value
Guochun Shif1c154f2003-03-27 17:57:44 +0000613//this fuction also update the instruction orn's latest clone memory
Misha Brukman8baa01c2003-04-09 21:51:34 +0000614//******************************************************************************
Guochun Shi0e936872003-06-10 20:04:30 +0000615Instruction *
616ModuloScheduling::cloneInstSetMemory(Instruction * orn){
617
Misha Brukman8baa01c2003-04-09 21:51:34 +0000618 // make a clone instruction
619 Instruction *cln = orn->clone();
Guochun Shif1c154f2003-03-27 17:57:44 +0000620
Misha Brukman8baa01c2003-04-09 21:51:34 +0000621 // update the operands
622 for (unsigned k = 0; k < orn->getNumOperands(); k++) {
623 const Value *op = orn->getOperand(k);
624 if (Instruction::classof(op) && ((Instruction *) op)->getClone()) {
625 Instruction *op_inst = (Instruction *) op;
Guochun Shif1c154f2003-03-27 17:57:44 +0000626 cln->setOperand(k, op_inst->getClone());
627 }
628 }
629
Misha Brukman8baa01c2003-04-09 21:51:34 +0000630 // update clone memory
Guochun Shif1c154f2003-03-27 17:57:44 +0000631 orn->setClone(cln);
632 return cln;
633}
634
635
636
Guochun Shi0e936872003-06-10 20:04:30 +0000637bool
638ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
Misha Brukman8baa01c2003-04-09 21:51:34 +0000639 unsigned start, unsigned end,
Guochun Shi0e936872003-06-10 20:04:30 +0000640 NodeVec & nodeScheduled){
641
Misha Brukman8baa01c2003-04-09 21:51:34 +0000642 const TargetSchedInfo & msi = target.getSchedInfo();
643 unsigned int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +0000644
Misha Brukman2c821cc2003-04-10 19:19:23 +0000645 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000646 DEBUG_PRINT(std::cerr << "startTime= " << start << " endTime= " << end << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000647 bool isScheduled = false;
648 for (unsigned i = start; i <= end; i++) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000649 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000650 DEBUG_PRINT(std::cerr << " now try cycle " << i << ":" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000651 for (unsigned j = 0; j < numIssueSlots; j++) {
652 unsigned int core_i = i % II;
653 unsigned int core_j = j;
Misha Brukman2c821cc2003-04-10 19:19:23 +0000654 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000655 DEBUG_PRINT(std::cerr << "\t Trying slot " << j << "...........");
Guochun Shif1c154f2003-03-27 17:57:44 +0000656 //check the resouce table, make sure there is no resource conflicts
Misha Brukman8baa01c2003-04-09 21:51:34 +0000657 const Instruction *instr = node->getInst();
658 MachineCodeForInstruction & tempMvec =
659 MachineCodeForInstruction::get(instr);
660 bool resourceConflict = false;
661 const TargetInstrInfo & mii = msi.getInstrInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000662
Misha Brukman8baa01c2003-04-09 21:51:34 +0000663 if (coreSchedule.size() < core_i + 1
664 || !coreSchedule[core_i][core_j]) {
665 //this->dumpResourceUsageTable();
666 int latency = 0;
667 for (unsigned k = 0; k < tempMvec.size(); k++) {
668 MachineInstr *minstr = tempMvec[k];
669 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
670 std::vector < std::vector < resourceId_t > >resources
671 = rUsage.resourcesByCycle;
672 updateResourceTable(resources, i + latency);
673 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
674 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000675
Misha Brukman8baa01c2003-04-09 21:51:34 +0000676 //this->dumpResourceUsageTable();
Guochun Shif1c154f2003-03-27 17:57:44 +0000677
Misha Brukman8baa01c2003-04-09 21:51:34 +0000678 latency = 0;
679 if (resourceTableNegative()) {
680
681 //undo-update the resource table
682 for (unsigned k = 0; k < tempMvec.size(); k++) {
683 MachineInstr *minstr = tempMvec[k];
684 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
685 std::vector < std::vector < resourceId_t > >resources
686 = rUsage.resourcesByCycle;
687 undoUpdateResourceTable(resources, i + latency);
688 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
689 }
690 resourceConflict = true;
691 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000692 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000693 if (!resourceConflict && !coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000694 if (ModuloScheduling::printScheduleProcess()) {
Guochun Shi33280522003-06-08 20:40:47 +0000695 DEBUG_PRINT(std::cerr << " OK!" << "\n");
696 DEBUG_PRINT(std::cerr << "Node " << node->getNodeId() << " scheduled.\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000697 }
698 //schedule[i][j]=node;
699 while (schedule.size() <= i) {
700 std::vector < ModuloSchedGraphNode * >*newCycle =
701 new std::vector < ModuloSchedGraphNode * >();
702 for (unsigned k = 0; k < numIssueSlots; k++)
703 newCycle->push_back(NULL);
704 schedule.push_back(*newCycle);
705 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000706 std::vector<ModuloSchedGraphNode*>::iterator startIterator;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000707 startIterator = schedule[i].begin();
708 schedule[i].insert(startIterator + j, node);
709 startIterator = schedule[i].begin();
710 schedule[i].erase(startIterator + j + 1);
711
712 //update coreSchedule
713 //coreSchedule[core_i][core_j]=node;
714 while (coreSchedule.size() <= core_i) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000715 std::vector<ModuloSchedGraphNode*> *newCycle =
716 new std::vector<ModuloSchedGraphNode*>();
Misha Brukman8baa01c2003-04-09 21:51:34 +0000717 for (unsigned k = 0; k < numIssueSlots; k++)
718 newCycle->push_back(NULL);
719 coreSchedule.push_back(*newCycle);
720 }
721
722 startIterator = coreSchedule[core_i].begin();
723 coreSchedule[core_i].insert(startIterator + core_j, node);
724 startIterator = coreSchedule[core_i].begin();
725 coreSchedule[core_i].erase(startIterator + core_j + 1);
726
727 node->setSchTime(i);
728 isScheduled = true;
729 nodeScheduled.push_back(node);
730
731 break;
732 } else if (coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000733 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000734 DEBUG_PRINT(std::cerr << " Slot not available\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000735 } else {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000736 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000737 DEBUG_PRINT(std::cerr << " Resource conflicts\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000738 }
739 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000740 if (isScheduled)
741 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000742 }
743 //assert(nodeScheduled &&"this node can not be scheduled?");
744 return isScheduled;
745}
746
Misha Brukman8baa01c2003-04-09 21:51:34 +0000747
Guochun Shi0e936872003-06-10 20:04:30 +0000748void
749ModuloScheduling::updateResourceTable(Resources useResources,
750 int startCycle){
751
Misha Brukman8baa01c2003-04-09 21:51:34 +0000752 for (unsigned i = 0; i < useResources.size(); i++) {
753 int absCycle = startCycle + i;
754 int coreCycle = absCycle % II;
755 std::vector<std::pair<int,int> > &resourceRemained =
756 resourceTable[coreCycle];
757 std::vector < unsigned int >&resourceUsed = useResources[i];
758 for (unsigned j = 0; j < resourceUsed.size(); j++) {
759 for (unsigned k = 0; k < resourceRemained.size(); k++)
760 if ((int) resourceUsed[j] == resourceRemained[k].first) {
761 resourceRemained[k].second--;
762 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000763 }
764 }
765}
766
Guochun Shi0e936872003-06-10 20:04:30 +0000767void
768ModuloScheduling::undoUpdateResourceTable(Resources useResources,
769 int startCycle){
770
Misha Brukman8baa01c2003-04-09 21:51:34 +0000771 for (unsigned i = 0; i < useResources.size(); i++) {
772 int absCycle = startCycle + i;
773 int coreCycle = absCycle % II;
774 std::vector<std::pair<int,int> > &resourceRemained =
775 resourceTable[coreCycle];
776 std::vector < unsigned int >&resourceUsed = useResources[i];
777 for (unsigned j = 0; j < resourceUsed.size(); j++) {
778 for (unsigned k = 0; k < resourceRemained.size(); k++)
779 if ((int) resourceUsed[j] == resourceRemained[k].first) {
780 resourceRemained[k].second++;
781 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000782 }
783 }
784}
785
786
787//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000788// Function: resourceTableNegative
789// return value:
790// return false if any element in the resouceTable is negative
791// otherwise return true
792// Purpose:
Guochun Shif1c154f2003-03-27 17:57:44 +0000793
Misha Brukman8baa01c2003-04-09 21:51:34 +0000794// this function is used to determine if an instruction is eligible for
795// schedule at certain cycle
796//-----------------------------------------------------------------------
797
798
Guochun Shi0e936872003-06-10 20:04:30 +0000799bool
800ModuloScheduling::resourceTableNegative(){
801
Misha Brukman8baa01c2003-04-09 21:51:34 +0000802 assert(resourceTable.size() == (unsigned) II
803 && "resouceTable size must be equal to II");
804 bool isNegative = false;
805 for (unsigned i = 0; i < resourceTable.size(); i++)
806 for (unsigned j = 0; j < resourceTable[i].size(); j++) {
807 if (resourceTable[i][j].second < 0) {
808 isNegative = true;
809 break;
810 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000811 }
812 return isNegative;
813}
814
815
816//----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000817// Function: dumpResouceUsageTable
818// Purpose:
819// print out ResouceTable for debug
Guochun Shif1c154f2003-03-27 17:57:44 +0000820//
821//------------------------------------------------------------------------
822
Guochun Shi0e936872003-06-10 20:04:30 +0000823void
824ModuloScheduling::dumpResourceUsageTable(){
825
Guochun Shi33280522003-06-08 20:40:47 +0000826 DEBUG_PRINT(std::cerr << "dumping resource usage table\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000827 for (unsigned i = 0; i < resourceTable.size(); i++) {
828 for (unsigned j = 0; j < resourceTable[i].size(); j++)
Guochun Shi33280522003-06-08 20:40:47 +0000829 DEBUG_PRINT(std::cerr << resourceTable[i][j].first
Misha Brukman2c821cc2003-04-10 19:19:23 +0000830 << ":" << resourceTable[i][j].second << " ");
Guochun Shi33280522003-06-08 20:40:47 +0000831 DEBUG_PRINT(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000832 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000833
Guochun Shif1c154f2003-03-27 17:57:44 +0000834}
835
836//----------------------------------------------------------------------
837//Function: dumpSchedule
838//Purpose:
839// print out thisSchedule for debug
840//
841//-----------------------------------------------------------------------
Guochun Shi0e936872003-06-10 20:04:30 +0000842void
843ModuloScheduling::dumpSchedule(vvNodeType thisSchedule){
844
Misha Brukman8baa01c2003-04-09 21:51:34 +0000845 const TargetSchedInfo & msi = target.getSchedInfo();
846 unsigned numIssueSlots = msi.maxNumIssueTotal;
847 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000848 DEBUG_PRINT(std::cerr << "\t#");
849 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000850 for (unsigned i = 0; i < thisSchedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000851 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000852 for (unsigned j = 0; j < thisSchedule[i].size(); j++)
853 if (thisSchedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000854 DEBUG_PRINT(std::cerr << thisSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000855 else
Guochun Shi33280522003-06-08 20:40:47 +0000856 DEBUG_PRINT(std::cerr << "\t");
857 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000858 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000859}
860
861
862//----------------------------------------------------
863//Function: dumpScheduling
864//Purpose:
865// print out the schedule and coreSchedule for debug
866//
867//-------------------------------------------------------
868
Guochun Shi0e936872003-06-10 20:04:30 +0000869void
870ModuloScheduling::dumpScheduling(){
871
Guochun Shi33280522003-06-08 20:40:47 +0000872 DEBUG_PRINT(std::cerr << "dump schedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000873 const TargetSchedInfo & msi = target.getSchedInfo();
874 unsigned numIssueSlots = msi.maxNumIssueTotal;
875 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000876 DEBUG_PRINT(std::cerr << "\t#");
877 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000878 for (unsigned i = 0; i < schedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000879 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000880 for (unsigned j = 0; j < schedule[i].size(); j++)
881 if (schedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000882 DEBUG_PRINT(std::cerr << schedule[i][j]->getNodeId() << "\t");
Guochun Shif1c154f2003-03-27 17:57:44 +0000883 else
Guochun Shi33280522003-06-08 20:40:47 +0000884 DEBUG_PRINT(std::cerr << "\t");
885 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000886 }
887
Guochun Shi33280522003-06-08 20:40:47 +0000888 DEBUG_PRINT(std::cerr << "dump coreSchedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000889 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000890 DEBUG_PRINT(std::cerr << "\t#");
891 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000892 for (unsigned i = 0; i < coreSchedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000893 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000894 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
895 if (coreSchedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000896 DEBUG_PRINT(std::cerr << coreSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000897 else
Guochun Shi33280522003-06-08 20:40:47 +0000898 DEBUG_PRINT(std::cerr << "\t");
899 DEBUG_PRINT(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000900 }
901}
902
Guochun Shi0e936872003-06-10 20:04:30 +0000903/*
904 print out final schedule
905*/
Guochun Shif1c154f2003-03-27 17:57:44 +0000906
Guochun Shi0e936872003-06-10 20:04:30 +0000907void
908ModuloScheduling::dumpFinalSchedule(){
909
910 cerr << "dump schedule:" << endl;
911 const TargetSchedInfo & msi = target.getSchedInfo();
912 unsigned numIssueSlots = msi.maxNumIssueTotal;
913
914 for (unsigned i = 0; i < numIssueSlots; i++)
915 cerr << "\t#";
916 cerr << endl;
917
918 for (unsigned i = 0; i < schedule.size(); i++) {
919 cerr << "cycle" << i << ": ";
920
921 for (unsigned j = 0; j < schedule[i].size(); j++)
922 if (schedule[i][j] != NULL)
923 cerr << schedule[i][j]->getNodeId() << "\t";
924 else
925 cerr << "\t";
926 cerr << endl;
927 }
928
929 cerr << "dump coreSchedule:" << endl;
930 for (unsigned i = 0; i < numIssueSlots; i++)
931 cerr << "\t#";
932 cerr << endl;
933
934 for (unsigned i = 0; i < coreSchedule.size(); i++) {
935 cerr << "cycle" << i << ": ";
936 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
937 if (coreSchedule[i][j] != NULL)
938 cerr << coreSchedule[i][j]->getNodeId() << "\t";
939 else
940 cerr << "\t";
941 cerr << endl;
942 }
943}
Guochun Shif1c154f2003-03-27 17:57:44 +0000944
945//---------------------------------------------------------------------------
946// Function: ModuloSchedulingPass
947//
948// Purpose:
949// Entry point for Modulo Scheduling
950// Schedules LLVM instruction
951//
952//---------------------------------------------------------------------------
953
954namespace {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000955 class ModuloSchedulingPass:public FunctionPass {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000956 const TargetMachine &target;
957
Guochun Shif1c154f2003-03-27 17:57:44 +0000958 public:
Misha Brukman2c821cc2003-04-10 19:19:23 +0000959 ModuloSchedulingPass(const TargetMachine &T):target(T) {}
960
961 const char *getPassName() const {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000962 return "Modulo Scheduling";
Guochun Shif1c154f2003-03-27 17:57:44 +0000963 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000964
Misha Brukman8baa01c2003-04-09 21:51:34 +0000965 // getAnalysisUsage - We use LiveVarInfo...
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000966 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000967 //AU.addRequired(FunctionLiveVarInfo::ID);
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000968 }
969
970 bool runOnFunction(Function & F);
Guochun Shif1c154f2003-03-27 17:57:44 +0000971 };
Misha Brukman8baa01c2003-04-09 21:51:34 +0000972} // end anonymous namespace
Guochun Shif1c154f2003-03-27 17:57:44 +0000973
974
Guochun Shi0e936872003-06-10 20:04:30 +0000975bool
976ModuloSchedulingPass::runOnFunction(Function &F){
977
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000978 ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
979
Guochun Shif3252612003-06-10 19:09:00 +0000980 ModuloSchedulingSet ModuloSchedulingSet(*graphSet);
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000981
Guochun Shi0e936872003-06-10 20:04:30 +0000982 DEBUG_PRINT(cerr<<"runOnFunction in ModuloSchedulingPass returns\n"<<endl);
Guochun Shif1c154f2003-03-27 17:57:44 +0000983 return false;
984}
985
986
Guochun Shi0e936872003-06-10 20:04:30 +0000987Pass *
988createModuloSchedulingPass(const TargetMachine & tgt){
989 DEBUG_PRINT(cerr<<"creating modulo scheduling "<<endl);
Guochun Shif1c154f2003-03-27 17:57:44 +0000990 return new ModuloSchedulingPass(tgt);
991}