blob: 10a888f55e175fcc145dc594be6e1f7710cb4dc1 [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 Shi6fbe5fb2003-04-06 23:56:19 +000028//#include <swig.h>
Guochun Shif1c154f2003-03-27 17:57:44 +000029
30//************************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +000031// printing Debug information
32// ModuloSchedDebugLevel stores the value of debug level
33// modsched_os is the ostream to dump debug information, which is written into
34// the file 'moduloSchedDebugInfo.output'
35// see ModuloSchedulingPass::runOnFunction()
Guochun Shif1c154f2003-03-27 17:57:44 +000036//************************************************************
37
Guochun Shi139f0c22003-05-30 00:17:09 +000038ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
39
40cl::opt<ModuloSchedDebugLevel_t,true>
41SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
42 cl::desc("enable modulo scheduling debugging information"),
43 cl::values(clEnumValN(ModuloSchedDebugLevel_NoDebugInfo,
44 "none", "disable debug output"),
45 clEnumValN(ModuloSchedDebugLevel_PrintSchedule,
46 "psched", "print original and new schedule"),
47 clEnumValN(ModuloSchedDebugLevel_PrintScheduleProcess,
48 "pschedproc",
49 "print how the new schdule is produced"),
50 0));
Guochun Shif1c154f2003-03-27 17:57:44 +000051
Misha Brukman8baa01c2003-04-09 21:51:34 +000052// Computes the schedule and inserts epilogue and prologue
53//
54void ModuloScheduling::instrScheduling()
55{
Misha Brukman2c821cc2003-04-10 19:19:23 +000056 if (ModuloScheduling::printScheduleProcess())
57 DEBUG(std::cerr << "************ computing modulo schedule ***********\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000058
Misha Brukman8baa01c2003-04-09 21:51:34 +000059 const TargetSchedInfo & msi = target.getSchedInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +000060
61 //number of issue slots in the in each cycle
Misha Brukman8baa01c2003-04-09 21:51:34 +000062 int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +000063
64 //compute the schedule
Misha Brukman8baa01c2003-04-09 21:51:34 +000065 bool success = false;
66 while (!success) {
67 //clear memory from the last round and initialize if necessary
68 clearInitMem(msi);
Guochun Shif1c154f2003-03-27 17:57:44 +000069
Misha Brukman8baa01c2003-04-09 21:51:34 +000070 //compute schedule and coreSchedule with the current II
71 success = computeSchedule();
72
73 if (!success) {
74 II++;
Misha Brukman2c821cc2003-04-10 19:19:23 +000075 if (ModuloScheduling::printScheduleProcess())
76 DEBUG(std::cerr << "increase II to " << II << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000077 }
Misha Brukman8baa01c2003-04-09 21:51:34 +000078 }
79
Guochun Shif1c154f2003-03-27 17:57:44 +000080 //print the final schedule if necessary
Misha Brukman2c821cc2003-04-10 19:19:23 +000081 if (ModuloScheduling::printSchedule())
Guochun Shif1c154f2003-03-27 17:57:44 +000082 dumpScheduling();
Guochun Shif1c154f2003-03-27 17:57:44 +000083
84 //the schedule has been computed
85 //create epilogue, prologue and kernel BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000086
Guochun Shif1c154f2003-03-27 17:57:44 +000087 //find the successor for this BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000088 BasicBlock *succ_bb = getSuccBB(bb);
89
Guochun Shif1c154f2003-03-27 17:57:44 +000090 //print the original BasicBlock if necessary
Misha Brukman2c821cc2003-04-10 19:19:23 +000091 if (ModuloScheduling::printSchedule()) {
92 DEBUG(std::cerr << "dumping the orginal block\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000093 graph.dump(bb);
94 }
Guochun Shif1c154f2003-03-27 17:57:44 +000095 //construction of prologue, kernel and epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +000096 BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
97 BasicBlock *prologue = bb;
98 BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
99
100 // Construct prologue
Guochun Shif1c154f2003-03-27 17:57:44 +0000101 constructPrologue(prologue);
102
Misha Brukman8baa01c2003-04-09 21:51:34 +0000103 // Construct kernel
104 constructKernel(prologue, kernel, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000105
Misha Brukman8baa01c2003-04-09 21:51:34 +0000106 // Construct epilogue
107 constructEpilogue(epilogue, succ_bb);
Guochun Shif1c154f2003-03-27 17:57:44 +0000108
Guochun Shif1c154f2003-03-27 17:57:44 +0000109 //print the BasicBlocks if necessary
Misha Brukman2c821cc2003-04-10 19:19:23 +0000110 if (ModuloScheduling::printSchedule()) {
111 DEBUG(std::cerr << "dumping the prologue block:\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000112 graph.dump(prologue);
Misha Brukman2c821cc2003-04-10 19:19:23 +0000113 DEBUG(std::cerr << "dumping the kernel block\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000114 graph.dump(kernel);
Misha Brukman2c821cc2003-04-10 19:19:23 +0000115 DEBUG(std::cerr << "dumping the epilogue block\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000116 graph.dump(epilogue);
117 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000118}
119
Misha Brukman8baa01c2003-04-09 21:51:34 +0000120// Clear memory from the last round and initialize if necessary
121//
122void ModuloScheduling::clearInitMem(const TargetSchedInfo & msi)
123{
124 unsigned numIssueSlots = msi.maxNumIssueTotal;
125 // clear nodeScheduled from the last round
Misha Brukman2c821cc2003-04-10 19:19:23 +0000126 if (ModuloScheduling::printScheduleProcess()) {
127 DEBUG(std::cerr << "***** new round with II= " << II << " ***********\n");
128 DEBUG(std::cerr <<
129 " ************clear the vector nodeScheduled*************\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000130 }
131 nodeScheduled.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000132
Misha Brukman8baa01c2003-04-09 21:51:34 +0000133 // clear resourceTable from the last round and reset it
134 resourceTable.clear();
135 for (unsigned i = 0; i < II; ++i)
136 resourceTable.push_back(msi.resourceNumVector);
Guochun Shif1c154f2003-03-27 17:57:44 +0000137
Misha Brukman8baa01c2003-04-09 21:51:34 +0000138 // clear the schdule and coreSchedule from the last round
139 schedule.clear();
140 coreSchedule.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000141
Misha Brukman8baa01c2003-04-09 21:51:34 +0000142 // create a coreSchedule of size II*numIssueSlots
143 // each entry is NULL
144 while (coreSchedule.size() < II) {
145 std::vector < ModuloSchedGraphNode * >*newCycle =
146 new std::vector < ModuloSchedGraphNode * >();
147 for (unsigned k = 0; k < numIssueSlots; ++k)
148 newCycle->push_back(NULL);
149 coreSchedule.push_back(*newCycle);
150 }
151}
Guochun Shif1c154f2003-03-27 17:57:44 +0000152
Misha Brukman8baa01c2003-04-09 21:51:34 +0000153// Compute schedule and coreSchedule with the current II
154//
155bool ModuloScheduling::computeSchedule()
156{
Guochun Shif1c154f2003-03-27 17:57:44 +0000157
Misha Brukman2c821cc2003-04-10 19:19:23 +0000158 if (ModuloScheduling::printScheduleProcess())
159 DEBUG(std::cerr << "start to compute schedule\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000160
Misha Brukman8baa01c2003-04-09 21:51:34 +0000161 // Loop over the ordered nodes
162 for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
163 // Try to schedule for node I
Misha Brukman2c821cc2003-04-10 19:19:23 +0000164 if (ModuloScheduling::printScheduleProcess())
Misha Brukman8baa01c2003-04-09 21:51:34 +0000165 dumpScheduling();
166 ModuloSchedGraphNode *node = *I;
Guochun Shif1c154f2003-03-27 17:57:44 +0000167
Misha Brukman8baa01c2003-04-09 21:51:34 +0000168 // Compute whether this node has successor(s)
169 bool succ = true;
170
171 // Compute whether this node has predessor(s)
172 bool pred = true;
173
174 NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
175 if (schSucc.empty())
176 succ = false;
177 NodeVec schPred = graph.vectorConj(nodeScheduled, graph.predSet(node));
178 if (schPred.empty())
179 pred = false;
180
181 //startTime: the earliest time we will try to schedule this node
182 //endTime: the latest time we will try to schedule this node
183 int startTime, endTime;
184
185 //node's earlyStart: possible earliest time to schedule this node
186 //node's lateStart: possible latest time to schedule this node
187 node->setEarlyStart(-1);
188 node->setLateStart(9999);
189
190 //this node has predessor but no successor
191 if (!succ && pred) {
192 // This node's earlyStart is it's predessor's schedule time + the edge
193 // delay - the iteration difference* II
194 for (unsigned i = 0; i < schPred.size(); i++) {
195 ModuloSchedGraphNode *predNode = schPred[i];
196 SchedGraphEdge *edge =
197 graph.getMaxDelayEdge(predNode->getNodeId(),
198 node->getNodeId());
199 int temp =
200 predNode->getSchTime() + edge->getMinDelay() -
201 edge->getIteDiff() * II;
202 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
Guochun Shif1c154f2003-03-27 17:57:44 +0000203 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000204 startTime = node->getEarlyStart();
205 endTime = node->getEarlyStart() + II - 1;
Guochun Shif1c154f2003-03-27 17:57:44 +0000206 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000207 // This node has a successor but no predecessor
208 if (succ && !pred) {
209 for (unsigned i = 0; i < schSucc.size(); ++i) {
210 ModuloSchedGraphNode *succNode = schSucc[i];
211 SchedGraphEdge *edge =
212 graph.getMaxDelayEdge(succNode->getNodeId(),
213 node->getNodeId());
214 int temp =
215 succNode->getSchTime() - edge->getMinDelay() +
216 edge->getIteDiff() * II;
217 node->setLateStart(std::min(node->getEarlyStart(), temp));
218 }
219 startTime = node->getLateStart() - II + 1;
220 endTime = node->getLateStart();
221 }
222 // This node has both successors and predecessors
223 if (succ && pred) {
224 for (unsigned i = 0; i < schPred.size(); ++i) {
225 ModuloSchedGraphNode *predNode = schPred[i];
226 SchedGraphEdge *edge =
227 graph.getMaxDelayEdge(predNode->getNodeId(),
228 node->getNodeId());
229 int temp =
230 predNode->getSchTime() + edge->getMinDelay() -
231 edge->getIteDiff() * II;
232 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
233 }
234 for (unsigned i = 0; i < schSucc.size(); ++i) {
235 ModuloSchedGraphNode *succNode = schSucc[i];
236 SchedGraphEdge *edge =
237 graph.getMaxDelayEdge(succNode->getNodeId(),
238 node->getNodeId());
239 int temp =
240 succNode->getSchTime() - edge->getMinDelay() +
241 edge->getIteDiff() * II;
242 node->setLateStart(std::min(node->getEarlyStart(), temp));
243 }
244 startTime = node->getEarlyStart();
245 endTime = std::min(node->getLateStart(),
246 node->getEarlyStart() + ((int) II) - 1);
247 }
248 //this node has no successor or predessor
249 if (!succ && !pred) {
250 node->setEarlyStart(node->getASAP());
251 startTime = node->getEarlyStart();
252 endTime = node->getEarlyStart() + II - 1;
253 }
254 //try to schedule this node based on the startTime and endTime
Misha Brukman2c821cc2003-04-10 19:19:23 +0000255 if (ModuloScheduling::printScheduleProcess())
256 DEBUG(std::cerr << "scheduling the node " << (*I)->getNodeId() << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000257
258 bool success =
259 this->ScheduleNode(node, startTime, endTime, nodeScheduled);
260 if (!success)
261 return false;
262 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000263 return true;
264}
265
266
Misha Brukman8baa01c2003-04-09 21:51:34 +0000267// Get the successor of the BasicBlock
268//
269BasicBlock *ModuloScheduling::getSuccBB(BasicBlock *bb)
270{
271 BasicBlock *succ_bb;
272 for (unsigned i = 0; i < II; ++i)
273 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
274 if (coreSchedule[i][j]) {
275 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000276
Misha Brukman8baa01c2003-04-09 21:51:34 +0000277 //we can get successor from the BranchInst instruction
278 //assume we only have one successor (besides itself) here
279 if (BranchInst::classof(ist)) {
280 BranchInst *bi = (BranchInst *) ist;
281 assert(bi->isConditional() &&
282 "the branchInst is not a conditional one");
283 assert(bi->getNumSuccessors() == 2
284 && " more than two successors?");
285 BasicBlock *bb1 = bi->getSuccessor(0);
286 BasicBlock *bb2 = bi->getSuccessor(1);
287 assert((bb1 == bb || bb2 == bb) &&
288 " None of its successors is itself?");
289 if (bb1 == bb)
290 succ_bb = bb2;
291 else
292 succ_bb = bb1;
293 return succ_bb;
294 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000295 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000296 assert(0 && "NO Successor?");
Guochun Shif1c154f2003-03-27 17:57:44 +0000297 return NULL;
298}
299
300
Misha Brukman8baa01c2003-04-09 21:51:34 +0000301// Get the predecessor of the BasicBlock
302//
303BasicBlock *ModuloScheduling::getPredBB(BasicBlock *bb)
304{
305 BasicBlock *pred_bb;
306 for (unsigned i = 0; i < II; ++i)
307 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
308 if (coreSchedule[i][j]) {
309 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000310
Misha Brukman8baa01c2003-04-09 21:51:34 +0000311 //we can get predecessor from the PHINode instruction
312 //assume we only have one predecessor (besides itself) here
313 if (PHINode::classof(ist)) {
314 PHINode *phi = (PHINode *) ist;
315 assert(phi->getNumIncomingValues() == 2 &&
316 " the number of incoming value is not equal to two? ");
317 BasicBlock *bb1 = phi->getIncomingBlock(0);
318 BasicBlock *bb2 = phi->getIncomingBlock(1);
319 assert((bb1 == bb || bb2 == bb) &&
320 " None of its predecessor is itself?");
321 if (bb1 == bb)
322 pred_bb = bb2;
323 else
324 pred_bb = bb1;
325 return pred_bb;
326 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000327 }
328 assert(0 && " no predecessor?");
329 return NULL;
330}
331
332
Misha Brukman8baa01c2003-04-09 21:51:34 +0000333// Construct the prologue
334//
335void ModuloScheduling::constructPrologue(BasicBlock *prologue)
336{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000337 InstListType & prologue_ist = prologue->getInstList();
338 vvNodeType & tempSchedule_prologue =
Misha Brukman2c821cc2003-04-10 19:19:23 +0000339 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000340
Guochun Shif1c154f2003-03-27 17:57:44 +0000341 //compute the schedule for prologue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000342 unsigned round = 0;
343 unsigned scheduleSize = schedule.size();
344 while (round < scheduleSize / II) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000345 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000346 for (unsigned i = 0; i < scheduleSize; ++i) {
347 if (round * II + i >= scheduleSize)
348 break;
349 for (unsigned j = 0; j < schedule[i].size(); ++j) {
350 if (schedule[i][j]) {
351 assert(tempSchedule_prologue[round * II + i][j] == NULL &&
352 "table not consitent with core table");
353 // move the schedule one iteration ahead and overlap with the original
354 tempSchedule_prologue[round * II + i][j] = schedule[i][j];
355 }
356 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000357 }
358 }
359
Misha Brukman8baa01c2003-04-09 21:51:34 +0000360 // Clear the clone memory in the core schedule instructions
Guochun Shif1c154f2003-03-27 17:57:44 +0000361 clearCloneMemory();
Guochun Shif1c154f2003-03-27 17:57:44 +0000362
Misha Brukman8baa01c2003-04-09 21:51:34 +0000363 // Fill in the prologue
364 for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
365 for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
366 if (tempSchedule_prologue[i][j]) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000367
Misha Brukman8baa01c2003-04-09 21:51:34 +0000368 //get the instruction
369 Instruction *orn =
370 (Instruction *) tempSchedule_prologue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000371
Misha Brukman8baa01c2003-04-09 21:51:34 +0000372 //made a clone of it
373 Instruction *cln = cloneInstSetMemory(orn);
Guochun Shif1c154f2003-03-27 17:57:44 +0000374
Misha Brukman8baa01c2003-04-09 21:51:34 +0000375 //insert the instruction
376 prologue_ist.insert(prologue_ist.back(), cln);
377
378 //if there is PHINode in the prologue, the incoming value from itself
379 //should be removed because it is not a loop any longer
380 if (PHINode::classof(cln)) {
381 PHINode *phi = (PHINode *) cln;
382 phi->removeIncomingValue(phi->getParent());
383 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000384 }
385}
386
387
Misha Brukman8baa01c2003-04-09 21:51:34 +0000388// Construct the kernel BasicBlock
389//
390void ModuloScheduling::constructKernel(BasicBlock *prologue,
391 BasicBlock *kernel,
392 BasicBlock *epilogue)
393{
Guochun Shif1c154f2003-03-27 17:57:44 +0000394 //*************fill instructions in the kernel****************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000395 InstListType & kernel_ist = kernel->getInstList();
396 BranchInst *brchInst;
397 PHINode *phiInst, *phiCln;
Guochun Shif1c154f2003-03-27 17:57:44 +0000398
Misha Brukman8baa01c2003-04-09 21:51:34 +0000399 for (unsigned i = 0; i < coreSchedule.size(); ++i)
400 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
401 if (coreSchedule[i][j]) {
402
403 // Take care of branch instruction differently with normal instructions
404 if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
405 brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
406 continue;
407 }
408 // Take care of PHINode instruction differently with normal instructions
409 if (PHINode::classof(coreSchedule[i][j]->getInst())) {
410 phiInst = (PHINode *) coreSchedule[i][j]->getInst();
411 Instruction *cln = cloneInstSetMemory(phiInst);
412 kernel_ist.insert(kernel_ist.back(), cln);
413 phiCln = (PHINode *) cln;
414 continue;
415 }
416 //for normal instructions: made a clone and insert it in the kernel_ist
417 Instruction *cln =
418 cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
419 getInst());
420 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000421 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000422 // The two incoming BasicBlock for PHINode is the prologue and the kernel
423 // (itself)
424 phiCln->setIncomingBlock(0, prologue);
425 phiCln->setIncomingBlock(1, kernel);
Guochun Shif1c154f2003-03-27 17:57:44 +0000426
Misha Brukman8baa01c2003-04-09 21:51:34 +0000427 // The incoming value for the kernel (itself) is the new value which is
428 // computed in the kernel
429 Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000430 phiCln->setIncomingValue(1, originalVal->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000431
Misha Brukman8baa01c2003-04-09 21:51:34 +0000432 // Make a clone of the branch instruction and insert it in the end
433 BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
434 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000435
Misha Brukman8baa01c2003-04-09 21:51:34 +0000436 // delete the unconditional branch instruction, which is generated when
437 // splitting the basicBlock
438 kernel_ist.erase(--kernel_ist.end());
Guochun Shif1c154f2003-03-27 17:57:44 +0000439
Misha Brukman8baa01c2003-04-09 21:51:34 +0000440 // set the first successor to itself
441 ((BranchInst *) cln)->setSuccessor(0, kernel);
442 // set the second successor to eiplogue
443 ((BranchInst *) cln)->setSuccessor(1, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000444
445 //*****change the condition*******
446
447 //get the condition instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000448 Instruction *cond = (Instruction *) cln->getCondition();
Guochun Shif1c154f2003-03-27 17:57:44 +0000449
450 //get the condition's second operand, it should be a constant
Misha Brukman8baa01c2003-04-09 21:51:34 +0000451 Value *operand = cond->getOperand(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000452 assert(ConstantSInt::classof(operand));
453
454 //change the constant in the condtion instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000455 ConstantSInt *iteTimes =
456 ConstantSInt::get(operand->getType(),
457 ((ConstantSInt *) operand)->getValue() - II + 1);
458 cond->setOperand(1, iteTimes);
Guochun Shif1c154f2003-03-27 17:57:44 +0000459
460}
461
462
Misha Brukman8baa01c2003-04-09 21:51:34 +0000463// Construct the epilogue
464//
465void ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
466 BasicBlock *succ_bb)
467{
Guochun Shif1c154f2003-03-27 17:57:44 +0000468
Guochun Shif1c154f2003-03-27 17:57:44 +0000469 //compute the schedule for epilogue
Misha Brukman2c821cc2003-04-10 19:19:23 +0000470 vvNodeType &tempSchedule_epilogue =
471 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000472 unsigned scheduleSize = schedule.size();
473 int round = 0;
474 while (round < ceil(1.0 * scheduleSize / II) - 1) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000475 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000476 for (unsigned i = 0; i < scheduleSize; i++) {
477 if (i + round * II >= scheduleSize)
478 break;
479 for (unsigned j = 0; j < schedule[i].size(); j++)
480 if (schedule[i + round * II][j]) {
481 assert(tempSchedule_epilogue[i][j] == NULL
482 && "table not consitant with core table");
Guochun Shif1c154f2003-03-27 17:57:44 +0000483
Misha Brukman8baa01c2003-04-09 21:51:34 +0000484 //move the schdule one iteration behind and overlap
485 tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
486 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000487 }
488 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000489
Guochun Shif1c154f2003-03-27 17:57:44 +0000490 //fill in the epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000491 InstListType & epilogue_ist = epilogue->getInstList();
492 for (unsigned i = II; i < scheduleSize; i++)
493 for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
494 if (tempSchedule_epilogue[i][j]) {
495 Instruction *inst =
496 (Instruction *) tempSchedule_epilogue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000497
Misha Brukman8baa01c2003-04-09 21:51:34 +0000498 //BranchInst and PHINode should be treated differently
499 //BranchInst:unecessary, simly omitted
500 //PHINode: omitted
501 if (!BranchInst::classof(inst) && !PHINode::classof(inst)) {
502 //make a clone instruction and insert it into the epilogue
503 Instruction *cln = cloneInstSetMemory(inst);
504 epilogue_ist.push_front(cln);
505 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000506 }
507
Guochun Shif1c154f2003-03-27 17:57:44 +0000508 //*************delete the original instructions****************//
509 //to delete the original instructions, we have to make sure their use is zero
Misha Brukman8baa01c2003-04-09 21:51:34 +0000510
Guochun Shif1c154f2003-03-27 17:57:44 +0000511 //update original core instruction's uses, using its clone instread
Misha Brukman8baa01c2003-04-09 21:51:34 +0000512 for (unsigned i = 0; i < II; i++)
513 for (unsigned j = 0; j < coreSchedule[i].size(); j++) {
514 if (coreSchedule[i][j])
515 updateUseWithClone((Instruction *) coreSchedule[i][j]->getInst());
Guochun Shif1c154f2003-03-27 17:57:44 +0000516 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000517
Guochun Shif1c154f2003-03-27 17:57:44 +0000518 //erase these instructions
Misha Brukman8baa01c2003-04-09 21:51:34 +0000519 for (unsigned i = 0; i < II; i++)
520 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
521 if (coreSchedule[i][j]) {
522 Instruction *ist = (Instruction *) coreSchedule[i][j]->getInst();
523 ist->getParent()->getInstList().erase(ist);
Guochun Shif1c154f2003-03-27 17:57:44 +0000524 }
525 //**************************************************************//
526
527
528 //finally, insert an unconditional branch instruction at the end
529 epilogue_ist.push_back(new BranchInst(succ_bb));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000530
Guochun Shif1c154f2003-03-27 17:57:44 +0000531}
532
533
Misha Brukman8baa01c2003-04-09 21:51:34 +0000534//------------------------------------------------------------------------------
535//this function replace the value(instruction) ist in other instructions with
536//its latest clone i.e. after this function is called, the ist is not used
537//anywhere and it can be erased.
538//------------------------------------------------------------------------------
539void ModuloScheduling::updateUseWithClone(Instruction * ist)
540{
541
542 while (ist->use_size() > 0) {
543 bool destroyed = false;
544
Guochun Shif1c154f2003-03-27 17:57:44 +0000545 //other instruction is using this value ist
546 assert(Instruction::classof(*ist->use_begin()));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000547 Instruction *inst = (Instruction *) (*ist->use_begin());
Guochun Shif1c154f2003-03-27 17:57:44 +0000548
Misha Brukman8baa01c2003-04-09 21:51:34 +0000549 for (unsigned i = 0; i < inst->getNumOperands(); i++)
550 if (inst->getOperand(i) == ist && ist->getClone()) {
551 // if the instruction is TmpInstruction, simly delete it because it has
552 // no parent and it does not belongs to any BasicBlock
553 if (TmpInstruction::classof(inst)) {
554 delete inst;
555 destroyed = true;
556 break;
557 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000558
Misha Brukman8baa01c2003-04-09 21:51:34 +0000559 //otherwise, set the instruction's operand to the value's clone
560 inst->setOperand(i, ist->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000561
Misha Brukman8baa01c2003-04-09 21:51:34 +0000562 //the use from the original value ist is destroyed
563 destroyed = true;
564 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000565 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000566 if (!destroyed) {
567 //if the use can not be destroyed , something is wrong
568 inst->dump();
569 assert(0 && "this use can not be destroyed");
570 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000571 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000572
Guochun Shif1c154f2003-03-27 17:57:44 +0000573}
574
575
576//********************************************************
577//this function clear all clone mememoy
578//i.e. set all instruction's clone memory to NULL
579//*****************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000580void ModuloScheduling::clearCloneMemory()
581{
582 for (unsigned i = 0; i < coreSchedule.size(); i++)
583 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
584 if (coreSchedule[i][j])
585 ((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
586
Guochun Shif1c154f2003-03-27 17:57:44 +0000587}
588
589
Misha Brukman8baa01c2003-04-09 21:51:34 +0000590//******************************************************************************
591// this function make a clone of the instruction orn the cloned instruction will
592// use the orn's operands' latest clone as its operands it is done this way
593// because LLVM is in SSA form and we should use the correct value
Guochun Shif1c154f2003-03-27 17:57:44 +0000594//this fuction also update the instruction orn's latest clone memory
Misha Brukman8baa01c2003-04-09 21:51:34 +0000595//******************************************************************************
596Instruction *ModuloScheduling::cloneInstSetMemory(Instruction * orn)
597{
598 // make a clone instruction
599 Instruction *cln = orn->clone();
Guochun Shif1c154f2003-03-27 17:57:44 +0000600
Misha Brukman8baa01c2003-04-09 21:51:34 +0000601 // update the operands
602 for (unsigned k = 0; k < orn->getNumOperands(); k++) {
603 const Value *op = orn->getOperand(k);
604 if (Instruction::classof(op) && ((Instruction *) op)->getClone()) {
605 Instruction *op_inst = (Instruction *) op;
Guochun Shif1c154f2003-03-27 17:57:44 +0000606 cln->setOperand(k, op_inst->getClone());
607 }
608 }
609
Misha Brukman8baa01c2003-04-09 21:51:34 +0000610 // update clone memory
Guochun Shif1c154f2003-03-27 17:57:44 +0000611 orn->setClone(cln);
612 return cln;
613}
614
615
616
Misha Brukman8baa01c2003-04-09 21:51:34 +0000617bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
618 unsigned start, unsigned end,
619 NodeVec & nodeScheduled)
Guochun Shif1c154f2003-03-27 17:57:44 +0000620{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000621 const TargetSchedInfo & msi = target.getSchedInfo();
622 unsigned int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +0000623
Misha Brukman2c821cc2003-04-10 19:19:23 +0000624 if (ModuloScheduling::printScheduleProcess())
625 DEBUG(std::cerr << "startTime= " << start << " endTime= " << end << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000626 bool isScheduled = false;
627 for (unsigned i = start; i <= end; i++) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000628 if (ModuloScheduling::printScheduleProcess())
629 DEBUG(std::cerr << " now try cycle " << i << ":" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000630 for (unsigned j = 0; j < numIssueSlots; j++) {
631 unsigned int core_i = i % II;
632 unsigned int core_j = j;
Misha Brukman2c821cc2003-04-10 19:19:23 +0000633 if (ModuloScheduling::printScheduleProcess())
634 DEBUG(std::cerr << "\t Trying slot " << j << "...........");
Guochun Shif1c154f2003-03-27 17:57:44 +0000635 //check the resouce table, make sure there is no resource conflicts
Misha Brukman8baa01c2003-04-09 21:51:34 +0000636 const Instruction *instr = node->getInst();
637 MachineCodeForInstruction & tempMvec =
638 MachineCodeForInstruction::get(instr);
639 bool resourceConflict = false;
640 const TargetInstrInfo & mii = msi.getInstrInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000641
Misha Brukman8baa01c2003-04-09 21:51:34 +0000642 if (coreSchedule.size() < core_i + 1
643 || !coreSchedule[core_i][core_j]) {
644 //this->dumpResourceUsageTable();
645 int latency = 0;
646 for (unsigned k = 0; k < tempMvec.size(); k++) {
647 MachineInstr *minstr = tempMvec[k];
648 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
649 std::vector < std::vector < resourceId_t > >resources
650 = rUsage.resourcesByCycle;
651 updateResourceTable(resources, i + latency);
652 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
653 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000654
Misha Brukman8baa01c2003-04-09 21:51:34 +0000655 //this->dumpResourceUsageTable();
Guochun Shif1c154f2003-03-27 17:57:44 +0000656
Misha Brukman8baa01c2003-04-09 21:51:34 +0000657 latency = 0;
658 if (resourceTableNegative()) {
659
660 //undo-update the resource table
661 for (unsigned k = 0; k < tempMvec.size(); k++) {
662 MachineInstr *minstr = tempMvec[k];
663 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
664 std::vector < std::vector < resourceId_t > >resources
665 = rUsage.resourcesByCycle;
666 undoUpdateResourceTable(resources, i + latency);
667 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
668 }
669 resourceConflict = true;
670 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000671 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000672 if (!resourceConflict && !coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000673 if (ModuloScheduling::printScheduleProcess()) {
674 DEBUG(std::cerr << " OK!" << "\n");
675 DEBUG(std::cerr << "Node " << node->getNodeId() << " scheduled.\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000676 }
677 //schedule[i][j]=node;
678 while (schedule.size() <= i) {
679 std::vector < ModuloSchedGraphNode * >*newCycle =
680 new std::vector < ModuloSchedGraphNode * >();
681 for (unsigned k = 0; k < numIssueSlots; k++)
682 newCycle->push_back(NULL);
683 schedule.push_back(*newCycle);
684 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000685 std::vector<ModuloSchedGraphNode*>::iterator startIterator;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000686 startIterator = schedule[i].begin();
687 schedule[i].insert(startIterator + j, node);
688 startIterator = schedule[i].begin();
689 schedule[i].erase(startIterator + j + 1);
690
691 //update coreSchedule
692 //coreSchedule[core_i][core_j]=node;
693 while (coreSchedule.size() <= core_i) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000694 std::vector<ModuloSchedGraphNode*> *newCycle =
695 new std::vector<ModuloSchedGraphNode*>();
Misha Brukman8baa01c2003-04-09 21:51:34 +0000696 for (unsigned k = 0; k < numIssueSlots; k++)
697 newCycle->push_back(NULL);
698 coreSchedule.push_back(*newCycle);
699 }
700
701 startIterator = coreSchedule[core_i].begin();
702 coreSchedule[core_i].insert(startIterator + core_j, node);
703 startIterator = coreSchedule[core_i].begin();
704 coreSchedule[core_i].erase(startIterator + core_j + 1);
705
706 node->setSchTime(i);
707 isScheduled = true;
708 nodeScheduled.push_back(node);
709
710 break;
711 } else if (coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000712 if (ModuloScheduling::printScheduleProcess())
713 DEBUG(std::cerr << " Slot not available\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000714 } else {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000715 if (ModuloScheduling::printScheduleProcess())
716 DEBUG(std::cerr << " Resource conflicts\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000717 }
718 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000719 if (isScheduled)
720 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000721 }
722 //assert(nodeScheduled &&"this node can not be scheduled?");
723 return isScheduled;
724}
725
Misha Brukman8baa01c2003-04-09 21:51:34 +0000726
727void ModuloScheduling::updateResourceTable(Resources useResources,
728 int startCycle)
729{
730 for (unsigned i = 0; i < useResources.size(); i++) {
731 int absCycle = startCycle + i;
732 int coreCycle = absCycle % II;
733 std::vector<std::pair<int,int> > &resourceRemained =
734 resourceTable[coreCycle];
735 std::vector < unsigned int >&resourceUsed = useResources[i];
736 for (unsigned j = 0; j < resourceUsed.size(); j++) {
737 for (unsigned k = 0; k < resourceRemained.size(); k++)
738 if ((int) resourceUsed[j] == resourceRemained[k].first) {
739 resourceRemained[k].second--;
740 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000741 }
742 }
743}
744
Misha Brukman8baa01c2003-04-09 21:51:34 +0000745void ModuloScheduling::undoUpdateResourceTable(Resources useResources,
746 int startCycle)
747{
748 for (unsigned i = 0; i < useResources.size(); i++) {
749 int absCycle = startCycle + i;
750 int coreCycle = absCycle % II;
751 std::vector<std::pair<int,int> > &resourceRemained =
752 resourceTable[coreCycle];
753 std::vector < unsigned int >&resourceUsed = useResources[i];
754 for (unsigned j = 0; j < resourceUsed.size(); j++) {
755 for (unsigned k = 0; k < resourceRemained.size(); k++)
756 if ((int) resourceUsed[j] == resourceRemained[k].first) {
757 resourceRemained[k].second++;
758 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000759 }
760 }
761}
762
763
764//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000765// Function: resourceTableNegative
766// return value:
767// return false if any element in the resouceTable is negative
768// otherwise return true
769// Purpose:
Guochun Shif1c154f2003-03-27 17:57:44 +0000770
Misha Brukman8baa01c2003-04-09 21:51:34 +0000771// this function is used to determine if an instruction is eligible for
772// schedule at certain cycle
773//-----------------------------------------------------------------------
774
775
776bool ModuloScheduling::resourceTableNegative()
777{
778 assert(resourceTable.size() == (unsigned) II
779 && "resouceTable size must be equal to II");
780 bool isNegative = false;
781 for (unsigned i = 0; i < resourceTable.size(); i++)
782 for (unsigned j = 0; j < resourceTable[i].size(); j++) {
783 if (resourceTable[i][j].second < 0) {
784 isNegative = true;
785 break;
786 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000787 }
788 return isNegative;
789}
790
791
792//----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000793// Function: dumpResouceUsageTable
794// Purpose:
795// print out ResouceTable for debug
Guochun Shif1c154f2003-03-27 17:57:44 +0000796//
797//------------------------------------------------------------------------
798
Misha Brukman8baa01c2003-04-09 21:51:34 +0000799void ModuloScheduling::dumpResourceUsageTable()
800{
Misha Brukman2c821cc2003-04-10 19:19:23 +0000801 DEBUG(std::cerr << "dumping resource usage table\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000802 for (unsigned i = 0; i < resourceTable.size(); i++) {
803 for (unsigned j = 0; j < resourceTable[i].size(); j++)
Misha Brukman2c821cc2003-04-10 19:19:23 +0000804 DEBUG(std::cerr << resourceTable[i][j].first
805 << ":" << resourceTable[i][j].second << " ");
806 DEBUG(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000807 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000808
Guochun Shif1c154f2003-03-27 17:57:44 +0000809}
810
811//----------------------------------------------------------------------
812//Function: dumpSchedule
813//Purpose:
814// print out thisSchedule for debug
815//
816//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000817void ModuloScheduling::dumpSchedule(vvNodeType thisSchedule)
818{
819 const TargetSchedInfo & msi = target.getSchedInfo();
820 unsigned numIssueSlots = msi.maxNumIssueTotal;
821 for (unsigned i = 0; i < numIssueSlots; i++)
Misha Brukman2c821cc2003-04-10 19:19:23 +0000822 DEBUG(std::cerr << "\t#");
823 DEBUG(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000824 for (unsigned i = 0; i < thisSchedule.size(); i++) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000825 DEBUG(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000826 for (unsigned j = 0; j < thisSchedule[i].size(); j++)
827 if (thisSchedule[i][j] != NULL)
Misha Brukman2c821cc2003-04-10 19:19:23 +0000828 DEBUG(std::cerr << thisSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000829 else
Misha Brukman2c821cc2003-04-10 19:19:23 +0000830 DEBUG(std::cerr << "\t");
831 DEBUG(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000832 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000833}
834
835
836//----------------------------------------------------
837//Function: dumpScheduling
838//Purpose:
839// print out the schedule and coreSchedule for debug
840//
841//-------------------------------------------------------
842
Misha Brukman8baa01c2003-04-09 21:51:34 +0000843void ModuloScheduling::dumpScheduling()
844{
Misha Brukman2c821cc2003-04-10 19:19:23 +0000845 DEBUG(std::cerr << "dump schedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000846 const TargetSchedInfo & msi = target.getSchedInfo();
847 unsigned numIssueSlots = msi.maxNumIssueTotal;
848 for (unsigned i = 0; i < numIssueSlots; i++)
Misha Brukman2c821cc2003-04-10 19:19:23 +0000849 DEBUG(std::cerr << "\t#");
850 DEBUG(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000851 for (unsigned i = 0; i < schedule.size(); i++) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000852 DEBUG(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000853 for (unsigned j = 0; j < schedule[i].size(); j++)
854 if (schedule[i][j] != NULL)
Misha Brukman2c821cc2003-04-10 19:19:23 +0000855 DEBUG(std::cerr << schedule[i][j]->getNodeId() << "\t");
Guochun Shif1c154f2003-03-27 17:57:44 +0000856 else
Misha Brukman2c821cc2003-04-10 19:19:23 +0000857 DEBUG(std::cerr << "\t");
858 DEBUG(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000859 }
860
Misha Brukman2c821cc2003-04-10 19:19:23 +0000861 DEBUG(std::cerr << "dump coreSchedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000862 for (unsigned i = 0; i < numIssueSlots; i++)
Misha Brukman2c821cc2003-04-10 19:19:23 +0000863 DEBUG(std::cerr << "\t#");
864 DEBUG(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000865 for (unsigned i = 0; i < coreSchedule.size(); i++) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000866 DEBUG(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000867 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
868 if (coreSchedule[i][j] != NULL)
Misha Brukman2c821cc2003-04-10 19:19:23 +0000869 DEBUG(std::cerr << coreSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000870 else
Misha Brukman2c821cc2003-04-10 19:19:23 +0000871 DEBUG(std::cerr << "\t");
872 DEBUG(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000873 }
874}
875
876
877
878//---------------------------------------------------------------------------
879// Function: ModuloSchedulingPass
880//
881// Purpose:
882// Entry point for Modulo Scheduling
883// Schedules LLVM instruction
884//
885//---------------------------------------------------------------------------
886
887namespace {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000888 class ModuloSchedulingPass:public FunctionPass {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000889 const TargetMachine &target;
890
Guochun Shif1c154f2003-03-27 17:57:44 +0000891 public:
Misha Brukman2c821cc2003-04-10 19:19:23 +0000892 ModuloSchedulingPass(const TargetMachine &T):target(T) {}
893
894 const char *getPassName() const {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000895 return "Modulo Scheduling";
Guochun Shif1c154f2003-03-27 17:57:44 +0000896 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000897
Misha Brukman8baa01c2003-04-09 21:51:34 +0000898 // getAnalysisUsage - We use LiveVarInfo...
899 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
900 //AU.addRequired(FunctionLiveVarInfo::ID);
901 } bool runOnFunction(Function & F);
Guochun Shif1c154f2003-03-27 17:57:44 +0000902 };
Misha Brukman8baa01c2003-04-09 21:51:34 +0000903} // end anonymous namespace
Guochun Shif1c154f2003-03-27 17:57:44 +0000904
905
906bool ModuloSchedulingPass::runOnFunction(Function &F)
907{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000908 ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
Guochun Shif1c154f2003-03-27 17:57:44 +0000909 ModuloSchedulingSet ModuloSchedulingSet(*graphSet);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000910
Guochun Shif1c154f2003-03-27 17:57:44 +0000911 return false;
912}
913
914
Misha Brukman8baa01c2003-04-09 21:51:34 +0000915Pass *createModuloSchedulingPass(const TargetMachine & tgt)
916{
Guochun Shif1c154f2003-03-27 17:57:44 +0000917 return new ModuloSchedulingPass(tgt);
918}