blob: 0acac3a88aa364bfa7e376e7eccf45b804eda1b0 [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 Shif1c154f2003-03-27 17:57:44 +000030
31//************************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +000032// printing Debug information
33// ModuloSchedDebugLevel stores the value of debug level
34// modsched_os is the ostream to dump debug information, which is written into
35// the file 'moduloSchedDebugInfo.output'
36// see ModuloSchedulingPass::runOnFunction()
Guochun Shif1c154f2003-03-27 17:57:44 +000037//************************************************************
38
Guochun Shi139f0c22003-05-30 00:17:09 +000039ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
40
41cl::opt<ModuloSchedDebugLevel_t,true>
42SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
43 cl::desc("enable modulo scheduling debugging information"),
44 cl::values(clEnumValN(ModuloSchedDebugLevel_NoDebugInfo,
45 "none", "disable debug output"),
46 clEnumValN(ModuloSchedDebugLevel_PrintSchedule,
47 "psched", "print original and new schedule"),
48 clEnumValN(ModuloSchedDebugLevel_PrintScheduleProcess,
49 "pschedproc",
50 "print how the new schdule is produced"),
51 0));
Guochun Shif1c154f2003-03-27 17:57:44 +000052
Misha Brukman8baa01c2003-04-09 21:51:34 +000053// Computes the schedule and inserts epilogue and prologue
54//
55void ModuloScheduling::instrScheduling()
56{
Guochun Shi33280522003-06-08 20:40:47 +000057
58 printf(" instrScheduling \n");
59
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 Shif1c154f2003-03-27 17:57:44 +000084 //print the final schedule if necessary
Misha Brukman2c821cc2003-04-10 19:19:23 +000085 if (ModuloScheduling::printSchedule())
Guochun Shif1c154f2003-03-27 17:57:44 +000086 dumpScheduling();
Guochun Shif1c154f2003-03-27 17:57:44 +000087
88 //the schedule has been computed
89 //create epilogue, prologue and kernel BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000090
Guochun Shif1c154f2003-03-27 17:57:44 +000091 //find the successor for this BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000092 BasicBlock *succ_bb = getSuccBB(bb);
93
Guochun Shif1c154f2003-03-27 17:57:44 +000094 //print the original BasicBlock if necessary
Misha Brukman2c821cc2003-04-10 19:19:23 +000095 if (ModuloScheduling::printSchedule()) {
Guochun Shi33280522003-06-08 20:40:47 +000096 DEBUG_PRINT(std::cerr << "dumping the orginal block\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000097 graph.dump(bb);
98 }
Guochun Shif1c154f2003-03-27 17:57:44 +000099 //construction of prologue, kernel and epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000100 BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
101 BasicBlock *prologue = bb;
102 BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
103
104 // Construct prologue
Guochun Shif1c154f2003-03-27 17:57:44 +0000105 constructPrologue(prologue);
106
Misha Brukman8baa01c2003-04-09 21:51:34 +0000107 // Construct kernel
108 constructKernel(prologue, kernel, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000109
Misha Brukman8baa01c2003-04-09 21:51:34 +0000110 // Construct epilogue
111 constructEpilogue(epilogue, succ_bb);
Guochun Shif1c154f2003-03-27 17:57:44 +0000112
Guochun Shif1c154f2003-03-27 17:57:44 +0000113 //print the BasicBlocks if necessary
Misha Brukman2c821cc2003-04-10 19:19:23 +0000114 if (ModuloScheduling::printSchedule()) {
Guochun Shi33280522003-06-08 20:40:47 +0000115 DEBUG_PRINT(std::cerr << "dumping the prologue block:\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000116 graph.dump(prologue);
Guochun Shi33280522003-06-08 20:40:47 +0000117 DEBUG_PRINT(std::cerr << "dumping the kernel block\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000118 graph.dump(kernel);
Guochun Shi33280522003-06-08 20:40:47 +0000119 DEBUG_PRINT(std::cerr << "dumping the epilogue block\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000120 graph.dump(epilogue);
121 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000122}
123
Misha Brukman8baa01c2003-04-09 21:51:34 +0000124// Clear memory from the last round and initialize if necessary
125//
126void ModuloScheduling::clearInitMem(const TargetSchedInfo & msi)
127{
128 unsigned numIssueSlots = msi.maxNumIssueTotal;
129 // clear nodeScheduled from the last round
Misha Brukman2c821cc2003-04-10 19:19:23 +0000130 if (ModuloScheduling::printScheduleProcess()) {
Guochun Shi33280522003-06-08 20:40:47 +0000131 DEBUG_PRINT(std::cerr << "***** new round with II= " << II << " ***********\n");
132 DEBUG_PRINT(std::cerr <<
Misha Brukman2c821cc2003-04-10 19:19:23 +0000133 " ************clear the vector nodeScheduled*************\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000134 }
135 nodeScheduled.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000136
Misha Brukman8baa01c2003-04-09 21:51:34 +0000137 // clear resourceTable from the last round and reset it
138 resourceTable.clear();
139 for (unsigned i = 0; i < II; ++i)
140 resourceTable.push_back(msi.resourceNumVector);
Guochun Shif1c154f2003-03-27 17:57:44 +0000141
Misha Brukman8baa01c2003-04-09 21:51:34 +0000142 // clear the schdule and coreSchedule from the last round
143 schedule.clear();
144 coreSchedule.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000145
Misha Brukman8baa01c2003-04-09 21:51:34 +0000146 // create a coreSchedule of size II*numIssueSlots
147 // each entry is NULL
148 while (coreSchedule.size() < II) {
149 std::vector < ModuloSchedGraphNode * >*newCycle =
150 new std::vector < ModuloSchedGraphNode * >();
151 for (unsigned k = 0; k < numIssueSlots; ++k)
152 newCycle->push_back(NULL);
153 coreSchedule.push_back(*newCycle);
154 }
155}
Guochun Shif1c154f2003-03-27 17:57:44 +0000156
Misha Brukman8baa01c2003-04-09 21:51:34 +0000157// Compute schedule and coreSchedule with the current II
158//
159bool ModuloScheduling::computeSchedule()
160{
Guochun Shif1c154f2003-03-27 17:57:44 +0000161
Misha Brukman2c821cc2003-04-10 19:19:23 +0000162 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000163 DEBUG_PRINT(std::cerr << "start to compute schedule\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000164
Misha Brukman8baa01c2003-04-09 21:51:34 +0000165 // Loop over the ordered nodes
166 for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
167 // Try to schedule for node I
Misha Brukman2c821cc2003-04-10 19:19:23 +0000168 if (ModuloScheduling::printScheduleProcess())
Misha Brukman8baa01c2003-04-09 21:51:34 +0000169 dumpScheduling();
170 ModuloSchedGraphNode *node = *I;
Guochun Shif1c154f2003-03-27 17:57:44 +0000171
Misha Brukman8baa01c2003-04-09 21:51:34 +0000172 // Compute whether this node has successor(s)
173 bool succ = true;
174
175 // Compute whether this node has predessor(s)
176 bool pred = true;
177
178 NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
179 if (schSucc.empty())
180 succ = false;
181 NodeVec schPred = graph.vectorConj(nodeScheduled, graph.predSet(node));
182 if (schPred.empty())
183 pred = false;
184
185 //startTime: the earliest time we will try to schedule this node
186 //endTime: the latest time we will try to schedule this node
187 int startTime, endTime;
188
189 //node's earlyStart: possible earliest time to schedule this node
190 //node's lateStart: possible latest time to schedule this node
191 node->setEarlyStart(-1);
192 node->setLateStart(9999);
193
194 //this node has predessor but no successor
195 if (!succ && pred) {
196 // This node's earlyStart is it's predessor's schedule time + the edge
197 // delay - the iteration difference* II
198 for (unsigned i = 0; i < schPred.size(); i++) {
199 ModuloSchedGraphNode *predNode = schPred[i];
200 SchedGraphEdge *edge =
201 graph.getMaxDelayEdge(predNode->getNodeId(),
202 node->getNodeId());
203 int temp =
204 predNode->getSchTime() + edge->getMinDelay() -
205 edge->getIteDiff() * II;
206 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
Guochun Shif1c154f2003-03-27 17:57:44 +0000207 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000208 startTime = node->getEarlyStart();
209 endTime = node->getEarlyStart() + II - 1;
Guochun Shif1c154f2003-03-27 17:57:44 +0000210 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000211 // This node has a successor but no predecessor
212 if (succ && !pred) {
213 for (unsigned i = 0; i < schSucc.size(); ++i) {
214 ModuloSchedGraphNode *succNode = schSucc[i];
215 SchedGraphEdge *edge =
216 graph.getMaxDelayEdge(succNode->getNodeId(),
217 node->getNodeId());
218 int temp =
219 succNode->getSchTime() - edge->getMinDelay() +
220 edge->getIteDiff() * II;
221 node->setLateStart(std::min(node->getEarlyStart(), temp));
222 }
223 startTime = node->getLateStart() - II + 1;
224 endTime = node->getLateStart();
225 }
226 // This node has both successors and predecessors
227 if (succ && pred) {
228 for (unsigned i = 0; i < schPred.size(); ++i) {
229 ModuloSchedGraphNode *predNode = schPred[i];
230 SchedGraphEdge *edge =
231 graph.getMaxDelayEdge(predNode->getNodeId(),
232 node->getNodeId());
233 int temp =
234 predNode->getSchTime() + edge->getMinDelay() -
235 edge->getIteDiff() * II;
236 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
237 }
238 for (unsigned i = 0; i < schSucc.size(); ++i) {
239 ModuloSchedGraphNode *succNode = schSucc[i];
240 SchedGraphEdge *edge =
241 graph.getMaxDelayEdge(succNode->getNodeId(),
242 node->getNodeId());
243 int temp =
244 succNode->getSchTime() - edge->getMinDelay() +
245 edge->getIteDiff() * II;
246 node->setLateStart(std::min(node->getEarlyStart(), temp));
247 }
248 startTime = node->getEarlyStart();
249 endTime = std::min(node->getLateStart(),
250 node->getEarlyStart() + ((int) II) - 1);
251 }
252 //this node has no successor or predessor
253 if (!succ && !pred) {
254 node->setEarlyStart(node->getASAP());
255 startTime = node->getEarlyStart();
256 endTime = node->getEarlyStart() + II - 1;
257 }
258 //try to schedule this node based on the startTime and endTime
Misha Brukman2c821cc2003-04-10 19:19:23 +0000259 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000260 DEBUG_PRINT(std::cerr << "scheduling the node " << (*I)->getNodeId() << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000261
262 bool success =
263 this->ScheduleNode(node, startTime, endTime, nodeScheduled);
264 if (!success)
265 return false;
266 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000267 return true;
268}
269
270
Misha Brukman8baa01c2003-04-09 21:51:34 +0000271// Get the successor of the BasicBlock
272//
273BasicBlock *ModuloScheduling::getSuccBB(BasicBlock *bb)
274{
275 BasicBlock *succ_bb;
276 for (unsigned i = 0; i < II; ++i)
277 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
278 if (coreSchedule[i][j]) {
279 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000280
Misha Brukman8baa01c2003-04-09 21:51:34 +0000281 //we can get successor from the BranchInst instruction
282 //assume we only have one successor (besides itself) here
283 if (BranchInst::classof(ist)) {
284 BranchInst *bi = (BranchInst *) ist;
285 assert(bi->isConditional() &&
286 "the branchInst is not a conditional one");
287 assert(bi->getNumSuccessors() == 2
288 && " more than two successors?");
289 BasicBlock *bb1 = bi->getSuccessor(0);
290 BasicBlock *bb2 = bi->getSuccessor(1);
291 assert((bb1 == bb || bb2 == bb) &&
292 " None of its successors is itself?");
293 if (bb1 == bb)
294 succ_bb = bb2;
295 else
296 succ_bb = bb1;
297 return succ_bb;
298 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000299 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000300 assert(0 && "NO Successor?");
Guochun Shif1c154f2003-03-27 17:57:44 +0000301 return NULL;
302}
303
304
Misha Brukman8baa01c2003-04-09 21:51:34 +0000305// Get the predecessor of the BasicBlock
306//
307BasicBlock *ModuloScheduling::getPredBB(BasicBlock *bb)
308{
309 BasicBlock *pred_bb;
310 for (unsigned i = 0; i < II; ++i)
311 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
312 if (coreSchedule[i][j]) {
313 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000314
Misha Brukman8baa01c2003-04-09 21:51:34 +0000315 //we can get predecessor from the PHINode instruction
316 //assume we only have one predecessor (besides itself) here
317 if (PHINode::classof(ist)) {
318 PHINode *phi = (PHINode *) ist;
319 assert(phi->getNumIncomingValues() == 2 &&
320 " the number of incoming value is not equal to two? ");
321 BasicBlock *bb1 = phi->getIncomingBlock(0);
322 BasicBlock *bb2 = phi->getIncomingBlock(1);
323 assert((bb1 == bb || bb2 == bb) &&
324 " None of its predecessor is itself?");
325 if (bb1 == bb)
326 pred_bb = bb2;
327 else
328 pred_bb = bb1;
329 return pred_bb;
330 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000331 }
332 assert(0 && " no predecessor?");
333 return NULL;
334}
335
336
Misha Brukman8baa01c2003-04-09 21:51:34 +0000337// Construct the prologue
338//
339void ModuloScheduling::constructPrologue(BasicBlock *prologue)
340{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000341 InstListType & prologue_ist = prologue->getInstList();
342 vvNodeType & tempSchedule_prologue =
Misha Brukman2c821cc2003-04-10 19:19:23 +0000343 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000344
Guochun Shif1c154f2003-03-27 17:57:44 +0000345 //compute the schedule for prologue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000346 unsigned round = 0;
347 unsigned scheduleSize = schedule.size();
348 while (round < scheduleSize / II) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000349 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000350 for (unsigned i = 0; i < scheduleSize; ++i) {
351 if (round * II + i >= scheduleSize)
352 break;
353 for (unsigned j = 0; j < schedule[i].size(); ++j) {
354 if (schedule[i][j]) {
355 assert(tempSchedule_prologue[round * II + i][j] == NULL &&
356 "table not consitent with core table");
357 // move the schedule one iteration ahead and overlap with the original
358 tempSchedule_prologue[round * II + i][j] = schedule[i][j];
359 }
360 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000361 }
362 }
363
Misha Brukman8baa01c2003-04-09 21:51:34 +0000364 // Clear the clone memory in the core schedule instructions
Guochun Shif1c154f2003-03-27 17:57:44 +0000365 clearCloneMemory();
Guochun Shif1c154f2003-03-27 17:57:44 +0000366
Misha Brukman8baa01c2003-04-09 21:51:34 +0000367 // Fill in the prologue
368 for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
369 for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
370 if (tempSchedule_prologue[i][j]) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000371
Misha Brukman8baa01c2003-04-09 21:51:34 +0000372 //get the instruction
373 Instruction *orn =
374 (Instruction *) tempSchedule_prologue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000375
Misha Brukman8baa01c2003-04-09 21:51:34 +0000376 //made a clone of it
377 Instruction *cln = cloneInstSetMemory(orn);
Guochun Shif1c154f2003-03-27 17:57:44 +0000378
Misha Brukman8baa01c2003-04-09 21:51:34 +0000379 //insert the instruction
380 prologue_ist.insert(prologue_ist.back(), cln);
381
382 //if there is PHINode in the prologue, the incoming value from itself
383 //should be removed because it is not a loop any longer
384 if (PHINode::classof(cln)) {
385 PHINode *phi = (PHINode *) cln;
386 phi->removeIncomingValue(phi->getParent());
387 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000388 }
389}
390
391
Misha Brukman8baa01c2003-04-09 21:51:34 +0000392// Construct the kernel BasicBlock
393//
394void ModuloScheduling::constructKernel(BasicBlock *prologue,
395 BasicBlock *kernel,
396 BasicBlock *epilogue)
397{
Guochun Shif1c154f2003-03-27 17:57:44 +0000398 //*************fill instructions in the kernel****************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000399 InstListType & kernel_ist = kernel->getInstList();
400 BranchInst *brchInst;
401 PHINode *phiInst, *phiCln;
Guochun Shif1c154f2003-03-27 17:57:44 +0000402
Misha Brukman8baa01c2003-04-09 21:51:34 +0000403 for (unsigned i = 0; i < coreSchedule.size(); ++i)
404 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
405 if (coreSchedule[i][j]) {
406
407 // Take care of branch instruction differently with normal instructions
408 if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
409 brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
410 continue;
411 }
412 // Take care of PHINode instruction differently with normal instructions
413 if (PHINode::classof(coreSchedule[i][j]->getInst())) {
414 phiInst = (PHINode *) coreSchedule[i][j]->getInst();
415 Instruction *cln = cloneInstSetMemory(phiInst);
416 kernel_ist.insert(kernel_ist.back(), cln);
417 phiCln = (PHINode *) cln;
418 continue;
419 }
420 //for normal instructions: made a clone and insert it in the kernel_ist
421 Instruction *cln =
422 cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
423 getInst());
424 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000425 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000426 // The two incoming BasicBlock for PHINode is the prologue and the kernel
427 // (itself)
428 phiCln->setIncomingBlock(0, prologue);
429 phiCln->setIncomingBlock(1, kernel);
Guochun Shif1c154f2003-03-27 17:57:44 +0000430
Misha Brukman8baa01c2003-04-09 21:51:34 +0000431 // The incoming value for the kernel (itself) is the new value which is
432 // computed in the kernel
433 Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000434 phiCln->setIncomingValue(1, originalVal->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000435
Misha Brukman8baa01c2003-04-09 21:51:34 +0000436 // Make a clone of the branch instruction and insert it in the end
437 BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
438 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000439
Misha Brukman8baa01c2003-04-09 21:51:34 +0000440 // delete the unconditional branch instruction, which is generated when
441 // splitting the basicBlock
442 kernel_ist.erase(--kernel_ist.end());
Guochun Shif1c154f2003-03-27 17:57:44 +0000443
Misha Brukman8baa01c2003-04-09 21:51:34 +0000444 // set the first successor to itself
445 ((BranchInst *) cln)->setSuccessor(0, kernel);
446 // set the second successor to eiplogue
447 ((BranchInst *) cln)->setSuccessor(1, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000448
449 //*****change the condition*******
450
451 //get the condition instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000452 Instruction *cond = (Instruction *) cln->getCondition();
Guochun Shif1c154f2003-03-27 17:57:44 +0000453
454 //get the condition's second operand, it should be a constant
Misha Brukman8baa01c2003-04-09 21:51:34 +0000455 Value *operand = cond->getOperand(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000456 assert(ConstantSInt::classof(operand));
457
458 //change the constant in the condtion instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000459 ConstantSInt *iteTimes =
460 ConstantSInt::get(operand->getType(),
461 ((ConstantSInt *) operand)->getValue() - II + 1);
462 cond->setOperand(1, iteTimes);
Guochun Shif1c154f2003-03-27 17:57:44 +0000463
464}
465
466
Misha Brukman8baa01c2003-04-09 21:51:34 +0000467// Construct the epilogue
468//
469void ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
470 BasicBlock *succ_bb)
471{
Guochun Shif1c154f2003-03-27 17:57:44 +0000472
Guochun Shif1c154f2003-03-27 17:57:44 +0000473 //compute the schedule for epilogue
Misha Brukman2c821cc2003-04-10 19:19:23 +0000474 vvNodeType &tempSchedule_epilogue =
475 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000476 unsigned scheduleSize = schedule.size();
477 int round = 0;
478 while (round < ceil(1.0 * scheduleSize / II) - 1) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000479 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000480 for (unsigned i = 0; i < scheduleSize; i++) {
481 if (i + round * II >= scheduleSize)
482 break;
483 for (unsigned j = 0; j < schedule[i].size(); j++)
484 if (schedule[i + round * II][j]) {
485 assert(tempSchedule_epilogue[i][j] == NULL
486 && "table not consitant with core table");
Guochun Shif1c154f2003-03-27 17:57:44 +0000487
Misha Brukman8baa01c2003-04-09 21:51:34 +0000488 //move the schdule one iteration behind and overlap
489 tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
490 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000491 }
492 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000493
Guochun Shif1c154f2003-03-27 17:57:44 +0000494 //fill in the epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000495 InstListType & epilogue_ist = epilogue->getInstList();
496 for (unsigned i = II; i < scheduleSize; i++)
497 for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
498 if (tempSchedule_epilogue[i][j]) {
499 Instruction *inst =
500 (Instruction *) tempSchedule_epilogue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000501
Misha Brukman8baa01c2003-04-09 21:51:34 +0000502 //BranchInst and PHINode should be treated differently
503 //BranchInst:unecessary, simly omitted
504 //PHINode: omitted
505 if (!BranchInst::classof(inst) && !PHINode::classof(inst)) {
506 //make a clone instruction and insert it into the epilogue
507 Instruction *cln = cloneInstSetMemory(inst);
508 epilogue_ist.push_front(cln);
509 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000510 }
511
Guochun Shif1c154f2003-03-27 17:57:44 +0000512 //*************delete the original instructions****************//
513 //to delete the original instructions, we have to make sure their use is zero
Misha Brukman8baa01c2003-04-09 21:51:34 +0000514
Guochun Shif1c154f2003-03-27 17:57:44 +0000515 //update original core instruction's uses, using its clone instread
Misha Brukman8baa01c2003-04-09 21:51:34 +0000516 for (unsigned i = 0; i < II; i++)
517 for (unsigned j = 0; j < coreSchedule[i].size(); j++) {
518 if (coreSchedule[i][j])
519 updateUseWithClone((Instruction *) coreSchedule[i][j]->getInst());
Guochun Shif1c154f2003-03-27 17:57:44 +0000520 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000521
Guochun Shif1c154f2003-03-27 17:57:44 +0000522 //erase these instructions
Misha Brukman8baa01c2003-04-09 21:51:34 +0000523 for (unsigned i = 0; i < II; i++)
524 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
525 if (coreSchedule[i][j]) {
526 Instruction *ist = (Instruction *) coreSchedule[i][j]->getInst();
527 ist->getParent()->getInstList().erase(ist);
Guochun Shif1c154f2003-03-27 17:57:44 +0000528 }
529 //**************************************************************//
530
531
532 //finally, insert an unconditional branch instruction at the end
533 epilogue_ist.push_back(new BranchInst(succ_bb));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000534
Guochun Shif1c154f2003-03-27 17:57:44 +0000535}
536
537
Misha Brukman8baa01c2003-04-09 21:51:34 +0000538//------------------------------------------------------------------------------
539//this function replace the value(instruction) ist in other instructions with
540//its latest clone i.e. after this function is called, the ist is not used
541//anywhere and it can be erased.
542//------------------------------------------------------------------------------
543void ModuloScheduling::updateUseWithClone(Instruction * ist)
544{
545
546 while (ist->use_size() > 0) {
547 bool destroyed = false;
548
Guochun Shif1c154f2003-03-27 17:57:44 +0000549 //other instruction is using this value ist
550 assert(Instruction::classof(*ist->use_begin()));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000551 Instruction *inst = (Instruction *) (*ist->use_begin());
Guochun Shif1c154f2003-03-27 17:57:44 +0000552
Misha Brukman8baa01c2003-04-09 21:51:34 +0000553 for (unsigned i = 0; i < inst->getNumOperands(); i++)
554 if (inst->getOperand(i) == ist && ist->getClone()) {
555 // if the instruction is TmpInstruction, simly delete it because it has
556 // no parent and it does not belongs to any BasicBlock
557 if (TmpInstruction::classof(inst)) {
558 delete inst;
559 destroyed = true;
560 break;
561 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000562
Misha Brukman8baa01c2003-04-09 21:51:34 +0000563 //otherwise, set the instruction's operand to the value's clone
564 inst->setOperand(i, ist->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000565
Misha Brukman8baa01c2003-04-09 21:51:34 +0000566 //the use from the original value ist is destroyed
567 destroyed = true;
568 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000569 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000570 if (!destroyed) {
571 //if the use can not be destroyed , something is wrong
572 inst->dump();
573 assert(0 && "this use can not be destroyed");
574 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000575 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000576
Guochun Shif1c154f2003-03-27 17:57:44 +0000577}
578
579
580//********************************************************
581//this function clear all clone mememoy
582//i.e. set all instruction's clone memory to NULL
583//*****************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000584void ModuloScheduling::clearCloneMemory()
585{
586 for (unsigned i = 0; i < coreSchedule.size(); i++)
587 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
588 if (coreSchedule[i][j])
589 ((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
590
Guochun Shif1c154f2003-03-27 17:57:44 +0000591}
592
593
Misha Brukman8baa01c2003-04-09 21:51:34 +0000594//******************************************************************************
595// this function make a clone of the instruction orn the cloned instruction will
596// use the orn's operands' latest clone as its operands it is done this way
597// because LLVM is in SSA form and we should use the correct value
Guochun Shif1c154f2003-03-27 17:57:44 +0000598//this fuction also update the instruction orn's latest clone memory
Misha Brukman8baa01c2003-04-09 21:51:34 +0000599//******************************************************************************
600Instruction *ModuloScheduling::cloneInstSetMemory(Instruction * orn)
601{
602 // make a clone instruction
603 Instruction *cln = orn->clone();
Guochun Shif1c154f2003-03-27 17:57:44 +0000604
Misha Brukman8baa01c2003-04-09 21:51:34 +0000605 // update the operands
606 for (unsigned k = 0; k < orn->getNumOperands(); k++) {
607 const Value *op = orn->getOperand(k);
608 if (Instruction::classof(op) && ((Instruction *) op)->getClone()) {
609 Instruction *op_inst = (Instruction *) op;
Guochun Shif1c154f2003-03-27 17:57:44 +0000610 cln->setOperand(k, op_inst->getClone());
611 }
612 }
613
Misha Brukman8baa01c2003-04-09 21:51:34 +0000614 // update clone memory
Guochun Shif1c154f2003-03-27 17:57:44 +0000615 orn->setClone(cln);
616 return cln;
617}
618
619
620
Misha Brukman8baa01c2003-04-09 21:51:34 +0000621bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
622 unsigned start, unsigned end,
623 NodeVec & nodeScheduled)
Guochun Shif1c154f2003-03-27 17:57:44 +0000624{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000625 const TargetSchedInfo & msi = target.getSchedInfo();
626 unsigned int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +0000627
Misha Brukman2c821cc2003-04-10 19:19:23 +0000628 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000629 DEBUG_PRINT(std::cerr << "startTime= " << start << " endTime= " << end << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000630 bool isScheduled = false;
631 for (unsigned i = start; i <= end; i++) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000632 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000633 DEBUG_PRINT(std::cerr << " now try cycle " << i << ":" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000634 for (unsigned j = 0; j < numIssueSlots; j++) {
635 unsigned int core_i = i % II;
636 unsigned int core_j = j;
Misha Brukman2c821cc2003-04-10 19:19:23 +0000637 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000638 DEBUG_PRINT(std::cerr << "\t Trying slot " << j << "...........");
Guochun Shif1c154f2003-03-27 17:57:44 +0000639 //check the resouce table, make sure there is no resource conflicts
Misha Brukman8baa01c2003-04-09 21:51:34 +0000640 const Instruction *instr = node->getInst();
641 MachineCodeForInstruction & tempMvec =
642 MachineCodeForInstruction::get(instr);
643 bool resourceConflict = false;
644 const TargetInstrInfo & mii = msi.getInstrInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000645
Misha Brukman8baa01c2003-04-09 21:51:34 +0000646 if (coreSchedule.size() < core_i + 1
647 || !coreSchedule[core_i][core_j]) {
648 //this->dumpResourceUsageTable();
649 int latency = 0;
650 for (unsigned k = 0; k < tempMvec.size(); k++) {
651 MachineInstr *minstr = tempMvec[k];
652 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
653 std::vector < std::vector < resourceId_t > >resources
654 = rUsage.resourcesByCycle;
655 updateResourceTable(resources, i + latency);
656 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
657 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000658
Misha Brukman8baa01c2003-04-09 21:51:34 +0000659 //this->dumpResourceUsageTable();
Guochun Shif1c154f2003-03-27 17:57:44 +0000660
Misha Brukman8baa01c2003-04-09 21:51:34 +0000661 latency = 0;
662 if (resourceTableNegative()) {
663
664 //undo-update the resource table
665 for (unsigned k = 0; k < tempMvec.size(); k++) {
666 MachineInstr *minstr = tempMvec[k];
667 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
668 std::vector < std::vector < resourceId_t > >resources
669 = rUsage.resourcesByCycle;
670 undoUpdateResourceTable(resources, i + latency);
671 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
672 }
673 resourceConflict = true;
674 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000675 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000676 if (!resourceConflict && !coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000677 if (ModuloScheduling::printScheduleProcess()) {
Guochun Shi33280522003-06-08 20:40:47 +0000678 DEBUG_PRINT(std::cerr << " OK!" << "\n");
679 DEBUG_PRINT(std::cerr << "Node " << node->getNodeId() << " scheduled.\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000680 }
681 //schedule[i][j]=node;
682 while (schedule.size() <= i) {
683 std::vector < ModuloSchedGraphNode * >*newCycle =
684 new std::vector < ModuloSchedGraphNode * >();
685 for (unsigned k = 0; k < numIssueSlots; k++)
686 newCycle->push_back(NULL);
687 schedule.push_back(*newCycle);
688 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000689 std::vector<ModuloSchedGraphNode*>::iterator startIterator;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000690 startIterator = schedule[i].begin();
691 schedule[i].insert(startIterator + j, node);
692 startIterator = schedule[i].begin();
693 schedule[i].erase(startIterator + j + 1);
694
695 //update coreSchedule
696 //coreSchedule[core_i][core_j]=node;
697 while (coreSchedule.size() <= core_i) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000698 std::vector<ModuloSchedGraphNode*> *newCycle =
699 new std::vector<ModuloSchedGraphNode*>();
Misha Brukman8baa01c2003-04-09 21:51:34 +0000700 for (unsigned k = 0; k < numIssueSlots; k++)
701 newCycle->push_back(NULL);
702 coreSchedule.push_back(*newCycle);
703 }
704
705 startIterator = coreSchedule[core_i].begin();
706 coreSchedule[core_i].insert(startIterator + core_j, node);
707 startIterator = coreSchedule[core_i].begin();
708 coreSchedule[core_i].erase(startIterator + core_j + 1);
709
710 node->setSchTime(i);
711 isScheduled = true;
712 nodeScheduled.push_back(node);
713
714 break;
715 } else if (coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000716 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000717 DEBUG_PRINT(std::cerr << " Slot not available\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000718 } else {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000719 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000720 DEBUG_PRINT(std::cerr << " Resource conflicts\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000721 }
722 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000723 if (isScheduled)
724 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000725 }
726 //assert(nodeScheduled &&"this node can not be scheduled?");
727 return isScheduled;
728}
729
Misha Brukman8baa01c2003-04-09 21:51:34 +0000730
731void ModuloScheduling::updateResourceTable(Resources useResources,
732 int startCycle)
733{
734 for (unsigned i = 0; i < useResources.size(); i++) {
735 int absCycle = startCycle + i;
736 int coreCycle = absCycle % II;
737 std::vector<std::pair<int,int> > &resourceRemained =
738 resourceTable[coreCycle];
739 std::vector < unsigned int >&resourceUsed = useResources[i];
740 for (unsigned j = 0; j < resourceUsed.size(); j++) {
741 for (unsigned k = 0; k < resourceRemained.size(); k++)
742 if ((int) resourceUsed[j] == resourceRemained[k].first) {
743 resourceRemained[k].second--;
744 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000745 }
746 }
747}
748
Misha Brukman8baa01c2003-04-09 21:51:34 +0000749void ModuloScheduling::undoUpdateResourceTable(Resources useResources,
750 int startCycle)
751{
752 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
767
768//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000769// Function: resourceTableNegative
770// return value:
771// return false if any element in the resouceTable is negative
772// otherwise return true
773// Purpose:
Guochun Shif1c154f2003-03-27 17:57:44 +0000774
Misha Brukman8baa01c2003-04-09 21:51:34 +0000775// this function is used to determine if an instruction is eligible for
776// schedule at certain cycle
777//-----------------------------------------------------------------------
778
779
780bool ModuloScheduling::resourceTableNegative()
781{
782 assert(resourceTable.size() == (unsigned) II
783 && "resouceTable size must be equal to II");
784 bool isNegative = false;
785 for (unsigned i = 0; i < resourceTable.size(); i++)
786 for (unsigned j = 0; j < resourceTable[i].size(); j++) {
787 if (resourceTable[i][j].second < 0) {
788 isNegative = true;
789 break;
790 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000791 }
792 return isNegative;
793}
794
795
796//----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000797// Function: dumpResouceUsageTable
798// Purpose:
799// print out ResouceTable for debug
Guochun Shif1c154f2003-03-27 17:57:44 +0000800//
801//------------------------------------------------------------------------
802
Misha Brukman8baa01c2003-04-09 21:51:34 +0000803void ModuloScheduling::dumpResourceUsageTable()
804{
Guochun Shi33280522003-06-08 20:40:47 +0000805 DEBUG_PRINT(std::cerr << "dumping resource usage table\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000806 for (unsigned i = 0; i < resourceTable.size(); i++) {
807 for (unsigned j = 0; j < resourceTable[i].size(); j++)
Guochun Shi33280522003-06-08 20:40:47 +0000808 DEBUG_PRINT(std::cerr << resourceTable[i][j].first
Misha Brukman2c821cc2003-04-10 19:19:23 +0000809 << ":" << resourceTable[i][j].second << " ");
Guochun Shi33280522003-06-08 20:40:47 +0000810 DEBUG_PRINT(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000811 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000812
Guochun Shif1c154f2003-03-27 17:57:44 +0000813}
814
815//----------------------------------------------------------------------
816//Function: dumpSchedule
817//Purpose:
818// print out thisSchedule for debug
819//
820//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000821void ModuloScheduling::dumpSchedule(vvNodeType thisSchedule)
822{
823 const TargetSchedInfo & msi = target.getSchedInfo();
824 unsigned numIssueSlots = msi.maxNumIssueTotal;
825 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000826 DEBUG_PRINT(std::cerr << "\t#");
827 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000828 for (unsigned i = 0; i < thisSchedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000829 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000830 for (unsigned j = 0; j < thisSchedule[i].size(); j++)
831 if (thisSchedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000832 DEBUG_PRINT(std::cerr << thisSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000833 else
Guochun Shi33280522003-06-08 20:40:47 +0000834 DEBUG_PRINT(std::cerr << "\t");
835 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000836 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000837}
838
839
840//----------------------------------------------------
841//Function: dumpScheduling
842//Purpose:
843// print out the schedule and coreSchedule for debug
844//
845//-------------------------------------------------------
846
Misha Brukman8baa01c2003-04-09 21:51:34 +0000847void ModuloScheduling::dumpScheduling()
848{
Guochun Shi33280522003-06-08 20:40:47 +0000849 DEBUG_PRINT(std::cerr << "dump schedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000850 const TargetSchedInfo & msi = target.getSchedInfo();
851 unsigned numIssueSlots = msi.maxNumIssueTotal;
852 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000853 DEBUG_PRINT(std::cerr << "\t#");
854 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000855 for (unsigned i = 0; i < schedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000856 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000857 for (unsigned j = 0; j < schedule[i].size(); j++)
858 if (schedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000859 DEBUG_PRINT(std::cerr << schedule[i][j]->getNodeId() << "\t");
Guochun Shif1c154f2003-03-27 17:57:44 +0000860 else
Guochun Shi33280522003-06-08 20:40:47 +0000861 DEBUG_PRINT(std::cerr << "\t");
862 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000863 }
864
Guochun Shi33280522003-06-08 20:40:47 +0000865 DEBUG_PRINT(std::cerr << "dump coreSchedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000866 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000867 DEBUG_PRINT(std::cerr << "\t#");
868 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000869 for (unsigned i = 0; i < coreSchedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000870 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000871 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
872 if (coreSchedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000873 DEBUG_PRINT(std::cerr << coreSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000874 else
Guochun Shi33280522003-06-08 20:40:47 +0000875 DEBUG_PRINT(std::cerr << "\t");
876 DEBUG_PRINT(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000877 }
878}
879
880
881
882//---------------------------------------------------------------------------
883// Function: ModuloSchedulingPass
884//
885// Purpose:
886// Entry point for Modulo Scheduling
887// Schedules LLVM instruction
888//
889//---------------------------------------------------------------------------
890
891namespace {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000892 class ModuloSchedulingPass:public FunctionPass {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000893 const TargetMachine &target;
894
Guochun Shif1c154f2003-03-27 17:57:44 +0000895 public:
Misha Brukman2c821cc2003-04-10 19:19:23 +0000896 ModuloSchedulingPass(const TargetMachine &T):target(T) {}
897
898 const char *getPassName() const {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000899 return "Modulo Scheduling";
Guochun Shif1c154f2003-03-27 17:57:44 +0000900 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000901
Misha Brukman8baa01c2003-04-09 21:51:34 +0000902 // getAnalysisUsage - We use LiveVarInfo...
903 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
904 //AU.addRequired(FunctionLiveVarInfo::ID);
905 } bool runOnFunction(Function & F);
Guochun Shif1c154f2003-03-27 17:57:44 +0000906 };
Misha Brukman8baa01c2003-04-09 21:51:34 +0000907} // end anonymous namespace
Guochun Shif1c154f2003-03-27 17:57:44 +0000908
909
910bool ModuloSchedulingPass::runOnFunction(Function &F)
911{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000912 ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
Guochun Shif1c154f2003-03-27 17:57:44 +0000913 ModuloSchedulingSet ModuloSchedulingSet(*graphSet);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000914
Guochun Shif1c154f2003-03-27 17:57:44 +0000915 return false;
916}
917
918
Misha Brukman8baa01c2003-04-09 21:51:34 +0000919Pass *createModuloSchedulingPass(const TargetMachine & tgt)
920{
Guochun Shif1c154f2003-03-27 17:57:44 +0000921 return new ModuloSchedulingPass(tgt);
922}