blob: 8645e752499e633125e069ba4291ef05f0f2376b [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
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000100
101 /*
Misha Brukman8baa01c2003-04-09 21:51:34 +0000102 BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
103 BasicBlock *prologue = bb;
104 BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000105 */
Misha Brukman8baa01c2003-04-09 21:51:34 +0000106
107 // Construct prologue
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000108 /*constructPrologue(prologue);*/
Guochun Shif1c154f2003-03-27 17:57:44 +0000109
Misha Brukman8baa01c2003-04-09 21:51:34 +0000110 // Construct kernel
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000111
112 /*constructKernel(prologue, kernel, epilogue);*/
Guochun Shif1c154f2003-03-27 17:57:44 +0000113
Misha Brukman8baa01c2003-04-09 21:51:34 +0000114 // Construct epilogue
Guochun Shif1c154f2003-03-27 17:57:44 +0000115
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000116 /*constructEpilogue(epilogue, succ_bb);*/
117
Guochun Shif1c154f2003-03-27 17:57:44 +0000118 //print the BasicBlocks if necessary
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000119// if (0){
120// DEBUG_PRINT(std::cerr << "dumping the prologue block:\n");
121// graph.dump(prologue);
122// DEBUG_PRINT(std::cerr << "dumping the kernel block\n");
123// graph.dump(kernel);
124// DEBUG_PRINT(std::cerr << "dumping the epilogue block\n");
125// graph.dump(epilogue);
126// }
127
Guochun Shif1c154f2003-03-27 17:57:44 +0000128}
129
Misha Brukman8baa01c2003-04-09 21:51:34 +0000130// Clear memory from the last round and initialize if necessary
131//
132void ModuloScheduling::clearInitMem(const TargetSchedInfo & msi)
133{
134 unsigned numIssueSlots = msi.maxNumIssueTotal;
135 // clear nodeScheduled from the last round
Misha Brukman2c821cc2003-04-10 19:19:23 +0000136 if (ModuloScheduling::printScheduleProcess()) {
Guochun Shi33280522003-06-08 20:40:47 +0000137 DEBUG_PRINT(std::cerr << "***** new round with II= " << II << " ***********\n");
138 DEBUG_PRINT(std::cerr <<
Misha Brukman2c821cc2003-04-10 19:19:23 +0000139 " ************clear the vector nodeScheduled*************\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000140 }
141 nodeScheduled.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000142
Misha Brukman8baa01c2003-04-09 21:51:34 +0000143 // clear resourceTable from the last round and reset it
144 resourceTable.clear();
145 for (unsigned i = 0; i < II; ++i)
146 resourceTable.push_back(msi.resourceNumVector);
Guochun Shif1c154f2003-03-27 17:57:44 +0000147
Misha Brukman8baa01c2003-04-09 21:51:34 +0000148 // clear the schdule and coreSchedule from the last round
149 schedule.clear();
150 coreSchedule.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000151
Misha Brukman8baa01c2003-04-09 21:51:34 +0000152 // create a coreSchedule of size II*numIssueSlots
153 // each entry is NULL
154 while (coreSchedule.size() < II) {
155 std::vector < ModuloSchedGraphNode * >*newCycle =
156 new std::vector < ModuloSchedGraphNode * >();
157 for (unsigned k = 0; k < numIssueSlots; ++k)
158 newCycle->push_back(NULL);
159 coreSchedule.push_back(*newCycle);
160 }
161}
Guochun Shif1c154f2003-03-27 17:57:44 +0000162
Misha Brukman8baa01c2003-04-09 21:51:34 +0000163// Compute schedule and coreSchedule with the current II
164//
165bool ModuloScheduling::computeSchedule()
166{
Guochun Shif1c154f2003-03-27 17:57:44 +0000167
Misha Brukman2c821cc2003-04-10 19:19:23 +0000168 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000169 DEBUG_PRINT(std::cerr << "start to compute schedule\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000170
Misha Brukman8baa01c2003-04-09 21:51:34 +0000171 // Loop over the ordered nodes
172 for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
173 // Try to schedule for node I
Misha Brukman2c821cc2003-04-10 19:19:23 +0000174 if (ModuloScheduling::printScheduleProcess())
Misha Brukman8baa01c2003-04-09 21:51:34 +0000175 dumpScheduling();
176 ModuloSchedGraphNode *node = *I;
Guochun Shif1c154f2003-03-27 17:57:44 +0000177
Misha Brukman8baa01c2003-04-09 21:51:34 +0000178 // Compute whether this node has successor(s)
179 bool succ = true;
180
181 // Compute whether this node has predessor(s)
182 bool pred = true;
183
184 NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
185 if (schSucc.empty())
186 succ = false;
187 NodeVec schPred = graph.vectorConj(nodeScheduled, graph.predSet(node));
188 if (schPred.empty())
189 pred = false;
190
191 //startTime: the earliest time we will try to schedule this node
192 //endTime: the latest time we will try to schedule this node
193 int startTime, endTime;
194
195 //node's earlyStart: possible earliest time to schedule this node
196 //node's lateStart: possible latest time to schedule this node
197 node->setEarlyStart(-1);
198 node->setLateStart(9999);
199
200 //this node has predessor but no successor
201 if (!succ && pred) {
202 // This node's earlyStart is it's predessor's schedule time + the edge
203 // delay - the iteration difference* II
204 for (unsigned i = 0; i < schPred.size(); i++) {
205 ModuloSchedGraphNode *predNode = schPred[i];
206 SchedGraphEdge *edge =
207 graph.getMaxDelayEdge(predNode->getNodeId(),
208 node->getNodeId());
209 int temp =
210 predNode->getSchTime() + edge->getMinDelay() -
211 edge->getIteDiff() * II;
212 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
Guochun Shif1c154f2003-03-27 17:57:44 +0000213 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000214 startTime = node->getEarlyStart();
215 endTime = node->getEarlyStart() + II - 1;
Guochun Shif1c154f2003-03-27 17:57:44 +0000216 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000217 // This node has a successor but no predecessor
218 if (succ && !pred) {
219 for (unsigned i = 0; i < schSucc.size(); ++i) {
220 ModuloSchedGraphNode *succNode = schSucc[i];
221 SchedGraphEdge *edge =
222 graph.getMaxDelayEdge(succNode->getNodeId(),
223 node->getNodeId());
224 int temp =
225 succNode->getSchTime() - edge->getMinDelay() +
226 edge->getIteDiff() * II;
227 node->setLateStart(std::min(node->getEarlyStart(), temp));
228 }
229 startTime = node->getLateStart() - II + 1;
230 endTime = node->getLateStart();
231 }
232 // This node has both successors and predecessors
233 if (succ && pred) {
234 for (unsigned i = 0; i < schPred.size(); ++i) {
235 ModuloSchedGraphNode *predNode = schPred[i];
236 SchedGraphEdge *edge =
237 graph.getMaxDelayEdge(predNode->getNodeId(),
238 node->getNodeId());
239 int temp =
240 predNode->getSchTime() + edge->getMinDelay() -
241 edge->getIteDiff() * II;
242 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
243 }
244 for (unsigned i = 0; i < schSucc.size(); ++i) {
245 ModuloSchedGraphNode *succNode = schSucc[i];
246 SchedGraphEdge *edge =
247 graph.getMaxDelayEdge(succNode->getNodeId(),
248 node->getNodeId());
249 int temp =
250 succNode->getSchTime() - edge->getMinDelay() +
251 edge->getIteDiff() * II;
252 node->setLateStart(std::min(node->getEarlyStart(), temp));
253 }
254 startTime = node->getEarlyStart();
255 endTime = std::min(node->getLateStart(),
256 node->getEarlyStart() + ((int) II) - 1);
257 }
258 //this node has no successor or predessor
259 if (!succ && !pred) {
260 node->setEarlyStart(node->getASAP());
261 startTime = node->getEarlyStart();
262 endTime = node->getEarlyStart() + II - 1;
263 }
264 //try to schedule this node based on the startTime and endTime
Misha Brukman2c821cc2003-04-10 19:19:23 +0000265 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000266 DEBUG_PRINT(std::cerr << "scheduling the node " << (*I)->getNodeId() << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000267
268 bool success =
269 this->ScheduleNode(node, startTime, endTime, nodeScheduled);
270 if (!success)
271 return false;
272 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000273 return true;
274}
275
276
Misha Brukman8baa01c2003-04-09 21:51:34 +0000277// Get the successor of the BasicBlock
278//
279BasicBlock *ModuloScheduling::getSuccBB(BasicBlock *bb)
280{
281 BasicBlock *succ_bb;
282 for (unsigned i = 0; i < II; ++i)
283 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
284 if (coreSchedule[i][j]) {
285 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000286
Misha Brukman8baa01c2003-04-09 21:51:34 +0000287 //we can get successor from the BranchInst instruction
288 //assume we only have one successor (besides itself) here
289 if (BranchInst::classof(ist)) {
290 BranchInst *bi = (BranchInst *) ist;
291 assert(bi->isConditional() &&
292 "the branchInst is not a conditional one");
293 assert(bi->getNumSuccessors() == 2
294 && " more than two successors?");
295 BasicBlock *bb1 = bi->getSuccessor(0);
296 BasicBlock *bb2 = bi->getSuccessor(1);
297 assert((bb1 == bb || bb2 == bb) &&
298 " None of its successors is itself?");
299 if (bb1 == bb)
300 succ_bb = bb2;
301 else
302 succ_bb = bb1;
303 return succ_bb;
304 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000305 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000306 assert(0 && "NO Successor?");
Guochun Shif1c154f2003-03-27 17:57:44 +0000307 return NULL;
308}
309
310
Misha Brukman8baa01c2003-04-09 21:51:34 +0000311// Get the predecessor of the BasicBlock
312//
313BasicBlock *ModuloScheduling::getPredBB(BasicBlock *bb)
314{
315 BasicBlock *pred_bb;
316 for (unsigned i = 0; i < II; ++i)
317 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
318 if (coreSchedule[i][j]) {
319 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000320
Misha Brukman8baa01c2003-04-09 21:51:34 +0000321 //we can get predecessor from the PHINode instruction
322 //assume we only have one predecessor (besides itself) here
323 if (PHINode::classof(ist)) {
324 PHINode *phi = (PHINode *) ist;
325 assert(phi->getNumIncomingValues() == 2 &&
326 " the number of incoming value is not equal to two? ");
327 BasicBlock *bb1 = phi->getIncomingBlock(0);
328 BasicBlock *bb2 = phi->getIncomingBlock(1);
329 assert((bb1 == bb || bb2 == bb) &&
330 " None of its predecessor is itself?");
331 if (bb1 == bb)
332 pred_bb = bb2;
333 else
334 pred_bb = bb1;
335 return pred_bb;
336 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000337 }
338 assert(0 && " no predecessor?");
339 return NULL;
340}
341
342
Misha Brukman8baa01c2003-04-09 21:51:34 +0000343// Construct the prologue
344//
345void ModuloScheduling::constructPrologue(BasicBlock *prologue)
346{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000347 InstListType & prologue_ist = prologue->getInstList();
348 vvNodeType & tempSchedule_prologue =
Misha Brukman2c821cc2003-04-10 19:19:23 +0000349 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000350
Guochun Shif1c154f2003-03-27 17:57:44 +0000351 //compute the schedule for prologue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000352 unsigned round = 0;
353 unsigned scheduleSize = schedule.size();
354 while (round < scheduleSize / II) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000355 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000356 for (unsigned i = 0; i < scheduleSize; ++i) {
357 if (round * II + i >= scheduleSize)
358 break;
359 for (unsigned j = 0; j < schedule[i].size(); ++j) {
360 if (schedule[i][j]) {
361 assert(tempSchedule_prologue[round * II + i][j] == NULL &&
362 "table not consitent with core table");
363 // move the schedule one iteration ahead and overlap with the original
364 tempSchedule_prologue[round * II + i][j] = schedule[i][j];
365 }
366 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000367 }
368 }
369
Misha Brukman8baa01c2003-04-09 21:51:34 +0000370 // Clear the clone memory in the core schedule instructions
Guochun Shif1c154f2003-03-27 17:57:44 +0000371 clearCloneMemory();
Guochun Shif1c154f2003-03-27 17:57:44 +0000372
Misha Brukman8baa01c2003-04-09 21:51:34 +0000373 // Fill in the prologue
374 for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
375 for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
376 if (tempSchedule_prologue[i][j]) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000377
Misha Brukman8baa01c2003-04-09 21:51:34 +0000378 //get the instruction
379 Instruction *orn =
380 (Instruction *) tempSchedule_prologue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000381
Misha Brukman8baa01c2003-04-09 21:51:34 +0000382 //made a clone of it
383 Instruction *cln = cloneInstSetMemory(orn);
Guochun Shif1c154f2003-03-27 17:57:44 +0000384
Misha Brukman8baa01c2003-04-09 21:51:34 +0000385 //insert the instruction
386 prologue_ist.insert(prologue_ist.back(), cln);
387
388 //if there is PHINode in the prologue, the incoming value from itself
389 //should be removed because it is not a loop any longer
390 if (PHINode::classof(cln)) {
391 PHINode *phi = (PHINode *) cln;
392 phi->removeIncomingValue(phi->getParent());
393 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000394 }
395}
396
397
Misha Brukman8baa01c2003-04-09 21:51:34 +0000398// Construct the kernel BasicBlock
399//
400void ModuloScheduling::constructKernel(BasicBlock *prologue,
401 BasicBlock *kernel,
402 BasicBlock *epilogue)
403{
Guochun Shif1c154f2003-03-27 17:57:44 +0000404 //*************fill instructions in the kernel****************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000405 InstListType & kernel_ist = kernel->getInstList();
406 BranchInst *brchInst;
407 PHINode *phiInst, *phiCln;
Guochun Shif1c154f2003-03-27 17:57:44 +0000408
Misha Brukman8baa01c2003-04-09 21:51:34 +0000409 for (unsigned i = 0; i < coreSchedule.size(); ++i)
410 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
411 if (coreSchedule[i][j]) {
412
413 // Take care of branch instruction differently with normal instructions
414 if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
415 brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
416 continue;
417 }
418 // Take care of PHINode instruction differently with normal instructions
419 if (PHINode::classof(coreSchedule[i][j]->getInst())) {
420 phiInst = (PHINode *) coreSchedule[i][j]->getInst();
421 Instruction *cln = cloneInstSetMemory(phiInst);
422 kernel_ist.insert(kernel_ist.back(), cln);
423 phiCln = (PHINode *) cln;
424 continue;
425 }
426 //for normal instructions: made a clone and insert it in the kernel_ist
427 Instruction *cln =
428 cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
429 getInst());
430 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000431 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000432 // The two incoming BasicBlock for PHINode is the prologue and the kernel
433 // (itself)
434 phiCln->setIncomingBlock(0, prologue);
435 phiCln->setIncomingBlock(1, kernel);
Guochun Shif1c154f2003-03-27 17:57:44 +0000436
Misha Brukman8baa01c2003-04-09 21:51:34 +0000437 // The incoming value for the kernel (itself) is the new value which is
438 // computed in the kernel
439 Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000440 phiCln->setIncomingValue(1, originalVal->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000441
Misha Brukman8baa01c2003-04-09 21:51:34 +0000442 // Make a clone of the branch instruction and insert it in the end
443 BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
444 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000445
Misha Brukman8baa01c2003-04-09 21:51:34 +0000446 // delete the unconditional branch instruction, which is generated when
447 // splitting the basicBlock
448 kernel_ist.erase(--kernel_ist.end());
Guochun Shif1c154f2003-03-27 17:57:44 +0000449
Misha Brukman8baa01c2003-04-09 21:51:34 +0000450 // set the first successor to itself
451 ((BranchInst *) cln)->setSuccessor(0, kernel);
452 // set the second successor to eiplogue
453 ((BranchInst *) cln)->setSuccessor(1, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000454
455 //*****change the condition*******
456
457 //get the condition instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000458 Instruction *cond = (Instruction *) cln->getCondition();
Guochun Shif1c154f2003-03-27 17:57:44 +0000459
460 //get the condition's second operand, it should be a constant
Misha Brukman8baa01c2003-04-09 21:51:34 +0000461 Value *operand = cond->getOperand(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000462 assert(ConstantSInt::classof(operand));
463
464 //change the constant in the condtion instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000465 ConstantSInt *iteTimes =
466 ConstantSInt::get(operand->getType(),
467 ((ConstantSInt *) operand)->getValue() - II + 1);
468 cond->setOperand(1, iteTimes);
Guochun Shif1c154f2003-03-27 17:57:44 +0000469
470}
471
472
Misha Brukman8baa01c2003-04-09 21:51:34 +0000473// Construct the epilogue
474//
475void ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
476 BasicBlock *succ_bb)
477{
Guochun Shif1c154f2003-03-27 17:57:44 +0000478
Guochun Shif1c154f2003-03-27 17:57:44 +0000479 //compute the schedule for epilogue
Misha Brukman2c821cc2003-04-10 19:19:23 +0000480 vvNodeType &tempSchedule_epilogue =
481 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000482 unsigned scheduleSize = schedule.size();
483 int round = 0;
484 while (round < ceil(1.0 * scheduleSize / II) - 1) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000485 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000486 for (unsigned i = 0; i < scheduleSize; i++) {
487 if (i + round * II >= scheduleSize)
488 break;
489 for (unsigned j = 0; j < schedule[i].size(); j++)
490 if (schedule[i + round * II][j]) {
491 assert(tempSchedule_epilogue[i][j] == NULL
492 && "table not consitant with core table");
Guochun Shif1c154f2003-03-27 17:57:44 +0000493
Misha Brukman8baa01c2003-04-09 21:51:34 +0000494 //move the schdule one iteration behind and overlap
495 tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
496 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000497 }
498 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000499
Guochun Shif1c154f2003-03-27 17:57:44 +0000500 //fill in the epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000501 InstListType & epilogue_ist = epilogue->getInstList();
502 for (unsigned i = II; i < scheduleSize; i++)
503 for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
504 if (tempSchedule_epilogue[i][j]) {
505 Instruction *inst =
506 (Instruction *) tempSchedule_epilogue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000507
Misha Brukman8baa01c2003-04-09 21:51:34 +0000508 //BranchInst and PHINode should be treated differently
509 //BranchInst:unecessary, simly omitted
510 //PHINode: omitted
511 if (!BranchInst::classof(inst) && !PHINode::classof(inst)) {
512 //make a clone instruction and insert it into the epilogue
513 Instruction *cln = cloneInstSetMemory(inst);
514 epilogue_ist.push_front(cln);
515 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000516 }
517
Guochun Shif1c154f2003-03-27 17:57:44 +0000518 //*************delete the original instructions****************//
519 //to delete the original instructions, we have to make sure their use is zero
Misha Brukman8baa01c2003-04-09 21:51:34 +0000520
Guochun Shif1c154f2003-03-27 17:57:44 +0000521 //update original core instruction's uses, using its clone instread
Misha Brukman8baa01c2003-04-09 21:51:34 +0000522 for (unsigned i = 0; i < II; i++)
523 for (unsigned j = 0; j < coreSchedule[i].size(); j++) {
524 if (coreSchedule[i][j])
525 updateUseWithClone((Instruction *) coreSchedule[i][j]->getInst());
Guochun Shif1c154f2003-03-27 17:57:44 +0000526 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000527
Guochun Shif1c154f2003-03-27 17:57:44 +0000528 //erase these instructions
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 Instruction *ist = (Instruction *) coreSchedule[i][j]->getInst();
533 ist->getParent()->getInstList().erase(ist);
Guochun Shif1c154f2003-03-27 17:57:44 +0000534 }
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000535
Guochun Shif1c154f2003-03-27 17:57:44 +0000536
537
538 //finally, insert an unconditional branch instruction at the end
539 epilogue_ist.push_back(new BranchInst(succ_bb));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000540
Guochun Shif1c154f2003-03-27 17:57:44 +0000541}
542
543
Misha Brukman8baa01c2003-04-09 21:51:34 +0000544//------------------------------------------------------------------------------
545//this function replace the value(instruction) ist in other instructions with
546//its latest clone i.e. after this function is called, the ist is not used
547//anywhere and it can be erased.
548//------------------------------------------------------------------------------
549void ModuloScheduling::updateUseWithClone(Instruction * ist)
550{
551
552 while (ist->use_size() > 0) {
553 bool destroyed = false;
554
Guochun Shif1c154f2003-03-27 17:57:44 +0000555 //other instruction is using this value ist
556 assert(Instruction::classof(*ist->use_begin()));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000557 Instruction *inst = (Instruction *) (*ist->use_begin());
Guochun Shif1c154f2003-03-27 17:57:44 +0000558
Misha Brukman8baa01c2003-04-09 21:51:34 +0000559 for (unsigned i = 0; i < inst->getNumOperands(); i++)
560 if (inst->getOperand(i) == ist && ist->getClone()) {
561 // if the instruction is TmpInstruction, simly delete it because it has
562 // no parent and it does not belongs to any BasicBlock
563 if (TmpInstruction::classof(inst)) {
564 delete inst;
565 destroyed = true;
566 break;
567 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000568
Misha Brukman8baa01c2003-04-09 21:51:34 +0000569 //otherwise, set the instruction's operand to the value's clone
570 inst->setOperand(i, ist->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000571
Misha Brukman8baa01c2003-04-09 21:51:34 +0000572 //the use from the original value ist is destroyed
573 destroyed = true;
574 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000575 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000576 if (!destroyed) {
577 //if the use can not be destroyed , something is wrong
578 inst->dump();
579 assert(0 && "this use can not be destroyed");
580 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000581 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000582
Guochun Shif1c154f2003-03-27 17:57:44 +0000583}
584
585
586//********************************************************
587//this function clear all clone mememoy
588//i.e. set all instruction's clone memory to NULL
589//*****************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000590void ModuloScheduling::clearCloneMemory()
591{
592 for (unsigned i = 0; i < coreSchedule.size(); i++)
593 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
594 if (coreSchedule[i][j])
595 ((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
596
Guochun Shif1c154f2003-03-27 17:57:44 +0000597}
598
599
Misha Brukman8baa01c2003-04-09 21:51:34 +0000600//******************************************************************************
601// this function make a clone of the instruction orn the cloned instruction will
602// use the orn's operands' latest clone as its operands it is done this way
603// because LLVM is in SSA form and we should use the correct value
Guochun Shif1c154f2003-03-27 17:57:44 +0000604//this fuction also update the instruction orn's latest clone memory
Misha Brukman8baa01c2003-04-09 21:51:34 +0000605//******************************************************************************
606Instruction *ModuloScheduling::cloneInstSetMemory(Instruction * orn)
607{
608 // make a clone instruction
609 Instruction *cln = orn->clone();
Guochun Shif1c154f2003-03-27 17:57:44 +0000610
Misha Brukman8baa01c2003-04-09 21:51:34 +0000611 // update the operands
612 for (unsigned k = 0; k < orn->getNumOperands(); k++) {
613 const Value *op = orn->getOperand(k);
614 if (Instruction::classof(op) && ((Instruction *) op)->getClone()) {
615 Instruction *op_inst = (Instruction *) op;
Guochun Shif1c154f2003-03-27 17:57:44 +0000616 cln->setOperand(k, op_inst->getClone());
617 }
618 }
619
Misha Brukman8baa01c2003-04-09 21:51:34 +0000620 // update clone memory
Guochun Shif1c154f2003-03-27 17:57:44 +0000621 orn->setClone(cln);
622 return cln;
623}
624
625
626
Misha Brukman8baa01c2003-04-09 21:51:34 +0000627bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
628 unsigned start, unsigned end,
629 NodeVec & nodeScheduled)
Guochun Shif1c154f2003-03-27 17:57:44 +0000630{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000631 const TargetSchedInfo & msi = target.getSchedInfo();
632 unsigned int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +0000633
Misha Brukman2c821cc2003-04-10 19:19:23 +0000634 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000635 DEBUG_PRINT(std::cerr << "startTime= " << start << " endTime= " << end << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000636 bool isScheduled = false;
637 for (unsigned i = start; i <= end; i++) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000638 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000639 DEBUG_PRINT(std::cerr << " now try cycle " << i << ":" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000640 for (unsigned j = 0; j < numIssueSlots; j++) {
641 unsigned int core_i = i % II;
642 unsigned int core_j = j;
Misha Brukman2c821cc2003-04-10 19:19:23 +0000643 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000644 DEBUG_PRINT(std::cerr << "\t Trying slot " << j << "...........");
Guochun Shif1c154f2003-03-27 17:57:44 +0000645 //check the resouce table, make sure there is no resource conflicts
Misha Brukman8baa01c2003-04-09 21:51:34 +0000646 const Instruction *instr = node->getInst();
647 MachineCodeForInstruction & tempMvec =
648 MachineCodeForInstruction::get(instr);
649 bool resourceConflict = false;
650 const TargetInstrInfo & mii = msi.getInstrInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000651
Misha Brukman8baa01c2003-04-09 21:51:34 +0000652 if (coreSchedule.size() < core_i + 1
653 || !coreSchedule[core_i][core_j]) {
654 //this->dumpResourceUsageTable();
655 int latency = 0;
656 for (unsigned k = 0; k < tempMvec.size(); k++) {
657 MachineInstr *minstr = tempMvec[k];
658 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
659 std::vector < std::vector < resourceId_t > >resources
660 = rUsage.resourcesByCycle;
661 updateResourceTable(resources, i + latency);
662 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
663 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000664
Misha Brukman8baa01c2003-04-09 21:51:34 +0000665 //this->dumpResourceUsageTable();
Guochun Shif1c154f2003-03-27 17:57:44 +0000666
Misha Brukman8baa01c2003-04-09 21:51:34 +0000667 latency = 0;
668 if (resourceTableNegative()) {
669
670 //undo-update the resource table
671 for (unsigned k = 0; k < tempMvec.size(); k++) {
672 MachineInstr *minstr = tempMvec[k];
673 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
674 std::vector < std::vector < resourceId_t > >resources
675 = rUsage.resourcesByCycle;
676 undoUpdateResourceTable(resources, i + latency);
677 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
678 }
679 resourceConflict = true;
680 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000681 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000682 if (!resourceConflict && !coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000683 if (ModuloScheduling::printScheduleProcess()) {
Guochun Shi33280522003-06-08 20:40:47 +0000684 DEBUG_PRINT(std::cerr << " OK!" << "\n");
685 DEBUG_PRINT(std::cerr << "Node " << node->getNodeId() << " scheduled.\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000686 }
687 //schedule[i][j]=node;
688 while (schedule.size() <= i) {
689 std::vector < ModuloSchedGraphNode * >*newCycle =
690 new std::vector < ModuloSchedGraphNode * >();
691 for (unsigned k = 0; k < numIssueSlots; k++)
692 newCycle->push_back(NULL);
693 schedule.push_back(*newCycle);
694 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000695 std::vector<ModuloSchedGraphNode*>::iterator startIterator;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000696 startIterator = schedule[i].begin();
697 schedule[i].insert(startIterator + j, node);
698 startIterator = schedule[i].begin();
699 schedule[i].erase(startIterator + j + 1);
700
701 //update coreSchedule
702 //coreSchedule[core_i][core_j]=node;
703 while (coreSchedule.size() <= core_i) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000704 std::vector<ModuloSchedGraphNode*> *newCycle =
705 new std::vector<ModuloSchedGraphNode*>();
Misha Brukman8baa01c2003-04-09 21:51:34 +0000706 for (unsigned k = 0; k < numIssueSlots; k++)
707 newCycle->push_back(NULL);
708 coreSchedule.push_back(*newCycle);
709 }
710
711 startIterator = coreSchedule[core_i].begin();
712 coreSchedule[core_i].insert(startIterator + core_j, node);
713 startIterator = coreSchedule[core_i].begin();
714 coreSchedule[core_i].erase(startIterator + core_j + 1);
715
716 node->setSchTime(i);
717 isScheduled = true;
718 nodeScheduled.push_back(node);
719
720 break;
721 } else if (coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000722 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000723 DEBUG_PRINT(std::cerr << " Slot not available\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000724 } else {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000725 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000726 DEBUG_PRINT(std::cerr << " Resource conflicts\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000727 }
728 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000729 if (isScheduled)
730 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000731 }
732 //assert(nodeScheduled &&"this node can not be scheduled?");
733 return isScheduled;
734}
735
Misha Brukman8baa01c2003-04-09 21:51:34 +0000736
737void ModuloScheduling::updateResourceTable(Resources useResources,
738 int startCycle)
739{
740 for (unsigned i = 0; i < useResources.size(); i++) {
741 int absCycle = startCycle + i;
742 int coreCycle = absCycle % II;
743 std::vector<std::pair<int,int> > &resourceRemained =
744 resourceTable[coreCycle];
745 std::vector < unsigned int >&resourceUsed = useResources[i];
746 for (unsigned j = 0; j < resourceUsed.size(); j++) {
747 for (unsigned k = 0; k < resourceRemained.size(); k++)
748 if ((int) resourceUsed[j] == resourceRemained[k].first) {
749 resourceRemained[k].second--;
750 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000751 }
752 }
753}
754
Misha Brukman8baa01c2003-04-09 21:51:34 +0000755void ModuloScheduling::undoUpdateResourceTable(Resources useResources,
756 int startCycle)
757{
758 for (unsigned i = 0; i < useResources.size(); i++) {
759 int absCycle = startCycle + i;
760 int coreCycle = absCycle % II;
761 std::vector<std::pair<int,int> > &resourceRemained =
762 resourceTable[coreCycle];
763 std::vector < unsigned int >&resourceUsed = useResources[i];
764 for (unsigned j = 0; j < resourceUsed.size(); j++) {
765 for (unsigned k = 0; k < resourceRemained.size(); k++)
766 if ((int) resourceUsed[j] == resourceRemained[k].first) {
767 resourceRemained[k].second++;
768 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000769 }
770 }
771}
772
773
774//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000775// Function: resourceTableNegative
776// return value:
777// return false if any element in the resouceTable is negative
778// otherwise return true
779// Purpose:
Guochun Shif1c154f2003-03-27 17:57:44 +0000780
Misha Brukman8baa01c2003-04-09 21:51:34 +0000781// this function is used to determine if an instruction is eligible for
782// schedule at certain cycle
783//-----------------------------------------------------------------------
784
785
786bool ModuloScheduling::resourceTableNegative()
787{
788 assert(resourceTable.size() == (unsigned) II
789 && "resouceTable size must be equal to II");
790 bool isNegative = false;
791 for (unsigned i = 0; i < resourceTable.size(); i++)
792 for (unsigned j = 0; j < resourceTable[i].size(); j++) {
793 if (resourceTable[i][j].second < 0) {
794 isNegative = true;
795 break;
796 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000797 }
798 return isNegative;
799}
800
801
802//----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000803// Function: dumpResouceUsageTable
804// Purpose:
805// print out ResouceTable for debug
Guochun Shif1c154f2003-03-27 17:57:44 +0000806//
807//------------------------------------------------------------------------
808
Misha Brukman8baa01c2003-04-09 21:51:34 +0000809void ModuloScheduling::dumpResourceUsageTable()
810{
Guochun Shi33280522003-06-08 20:40:47 +0000811 DEBUG_PRINT(std::cerr << "dumping resource usage table\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000812 for (unsigned i = 0; i < resourceTable.size(); i++) {
813 for (unsigned j = 0; j < resourceTable[i].size(); j++)
Guochun Shi33280522003-06-08 20:40:47 +0000814 DEBUG_PRINT(std::cerr << resourceTable[i][j].first
Misha Brukman2c821cc2003-04-10 19:19:23 +0000815 << ":" << resourceTable[i][j].second << " ");
Guochun Shi33280522003-06-08 20:40:47 +0000816 DEBUG_PRINT(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000817 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000818
Guochun Shif1c154f2003-03-27 17:57:44 +0000819}
820
821//----------------------------------------------------------------------
822//Function: dumpSchedule
823//Purpose:
824// print out thisSchedule for debug
825//
826//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000827void ModuloScheduling::dumpSchedule(vvNodeType thisSchedule)
828{
829 const TargetSchedInfo & msi = target.getSchedInfo();
830 unsigned numIssueSlots = msi.maxNumIssueTotal;
831 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000832 DEBUG_PRINT(std::cerr << "\t#");
833 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000834 for (unsigned i = 0; i < thisSchedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000835 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000836 for (unsigned j = 0; j < thisSchedule[i].size(); j++)
837 if (thisSchedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000838 DEBUG_PRINT(std::cerr << thisSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000839 else
Guochun Shi33280522003-06-08 20:40:47 +0000840 DEBUG_PRINT(std::cerr << "\t");
841 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000842 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000843}
844
845
846//----------------------------------------------------
847//Function: dumpScheduling
848//Purpose:
849// print out the schedule and coreSchedule for debug
850//
851//-------------------------------------------------------
852
Misha Brukman8baa01c2003-04-09 21:51:34 +0000853void ModuloScheduling::dumpScheduling()
854{
Guochun Shi33280522003-06-08 20:40:47 +0000855 DEBUG_PRINT(std::cerr << "dump schedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000856 const TargetSchedInfo & msi = target.getSchedInfo();
857 unsigned numIssueSlots = msi.maxNumIssueTotal;
858 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000859 DEBUG_PRINT(std::cerr << "\t#");
860 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000861 for (unsigned i = 0; i < schedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000862 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000863 for (unsigned j = 0; j < schedule[i].size(); j++)
864 if (schedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000865 DEBUG_PRINT(std::cerr << schedule[i][j]->getNodeId() << "\t");
Guochun Shif1c154f2003-03-27 17:57:44 +0000866 else
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 }
870
Guochun Shi33280522003-06-08 20:40:47 +0000871 DEBUG_PRINT(std::cerr << "dump coreSchedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000872 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000873 DEBUG_PRINT(std::cerr << "\t#");
874 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000875 for (unsigned i = 0; i < coreSchedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000876 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000877 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
878 if (coreSchedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000879 DEBUG_PRINT(std::cerr << coreSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000880 else
Guochun Shi33280522003-06-08 20:40:47 +0000881 DEBUG_PRINT(std::cerr << "\t");
882 DEBUG_PRINT(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000883 }
884}
885
886
887
888//---------------------------------------------------------------------------
889// Function: ModuloSchedulingPass
890//
891// Purpose:
892// Entry point for Modulo Scheduling
893// Schedules LLVM instruction
894//
895//---------------------------------------------------------------------------
896
897namespace {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000898 class ModuloSchedulingPass:public FunctionPass {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000899 const TargetMachine &target;
900
Guochun Shif1c154f2003-03-27 17:57:44 +0000901 public:
Misha Brukman2c821cc2003-04-10 19:19:23 +0000902 ModuloSchedulingPass(const TargetMachine &T):target(T) {}
903
904 const char *getPassName() const {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000905 return "Modulo Scheduling";
Guochun Shif1c154f2003-03-27 17:57:44 +0000906 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000907
Misha Brukman8baa01c2003-04-09 21:51:34 +0000908 // getAnalysisUsage - We use LiveVarInfo...
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000909 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000910 //AU.addRequired(FunctionLiveVarInfo::ID);
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000911 }
912
913 bool runOnFunction(Function & F);
Guochun Shif1c154f2003-03-27 17:57:44 +0000914 };
Misha Brukman8baa01c2003-04-09 21:51:34 +0000915} // end anonymous namespace
Guochun Shif1c154f2003-03-27 17:57:44 +0000916
917
918bool ModuloSchedulingPass::runOnFunction(Function &F)
919{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000920
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000921 ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
922
Guochun Shif3252612003-06-10 19:09:00 +0000923 ModuloSchedulingSet ModuloSchedulingSet(*graphSet);
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000924
925 printf("runOnFunction in ModuloSchedulingPass returns\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000926 return false;
927}
928
929
Misha Brukman8baa01c2003-04-09 21:51:34 +0000930Pass *createModuloSchedulingPass(const TargetMachine & tgt)
931{
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000932 printf("creating modulo scheduling \n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000933 return new ModuloSchedulingPass(tgt);
934}