blob: 49f4246c022b438295868c07e7bffbd6acfe0487 [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 Shif1c154f2003-03-27 17:57:44 +00007#include "llvm/BasicBlock.h"
Misha Brukman8baa01c2003-04-09 21:51:34 +00008#include "llvm/Constants.h"
Guochun Shif1c154f2003-03-27 17:57:44 +00009#include "llvm/iTerminators.h"
10#include "llvm/iPHINode.h"
Misha Brukman8baa01c2003-04-09 21:51:34 +000011#include "llvm/CodeGen/MachineInstr.h"
12#include "llvm/CodeGen/MachineCodeForInstruction.h"
13#include "llvm/CodeGen/MachineFunction.h"
14#include "llvm/CodeGen/InstrSelection.h"
15#include "llvm/Target/TargetSchedInfo.h"
16#include "llvm/Target/TargetMachine.h"
17#include "Support/CommandLine.h"
Misha Brukman2c821cc2003-04-10 19:19:23 +000018#include "Support/Statistic.h"
Misha Brukman8baa01c2003-04-09 21:51:34 +000019#include "ModuloSchedGraph.h"
20#include "ModuloScheduling.h"
21#include <algorithm>
22#include <fstream>
Guochun Shif1c154f2003-03-27 17:57:44 +000023
24//************************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +000025// printing Debug information
26// ModuloSchedDebugLevel stores the value of debug level
27// modsched_os is the ostream to dump debug information, which is written into
28// the file 'moduloSchedDebugInfo.output'
29// see ModuloSchedulingPass::runOnFunction()
Guochun Shif1c154f2003-03-27 17:57:44 +000030//************************************************************
31
Guochun Shi139f0c22003-05-30 00:17:09 +000032ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
33
34cl::opt<ModuloSchedDebugLevel_t,true>
35SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
36 cl::desc("enable modulo scheduling debugging information"),
37 cl::values(clEnumValN(ModuloSchedDebugLevel_NoDebugInfo,
38 "none", "disable debug output"),
39 clEnumValN(ModuloSchedDebugLevel_PrintSchedule,
40 "psched", "print original and new schedule"),
41 clEnumValN(ModuloSchedDebugLevel_PrintScheduleProcess,
42 "pschedproc",
43 "print how the new schdule is produced"),
44 0));
Guochun Shif1c154f2003-03-27 17:57:44 +000045
Misha Brukman8baa01c2003-04-09 21:51:34 +000046// Computes the schedule and inserts epilogue and prologue
47//
Guochun Shi0e936872003-06-10 20:04:30 +000048void
49ModuloScheduling::instrScheduling(){
Guochun Shi33280522003-06-08 20:40:47 +000050
Guochun Shi33280522003-06-08 20:40:47 +000051
Misha Brukman2c821cc2003-04-10 19:19:23 +000052 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +000053 DEBUG_PRINT(std::cerr << "************ computing modulo schedule ***********\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000054
Misha Brukman8baa01c2003-04-09 21:51:34 +000055 const TargetSchedInfo & msi = target.getSchedInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +000056
57 //number of issue slots in the in each cycle
Misha Brukman8baa01c2003-04-09 21:51:34 +000058 int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +000059
60 //compute the schedule
Misha Brukman8baa01c2003-04-09 21:51:34 +000061 bool success = false;
62 while (!success) {
63 //clear memory from the last round and initialize if necessary
64 clearInitMem(msi);
Guochun Shif1c154f2003-03-27 17:57:44 +000065
Misha Brukman8baa01c2003-04-09 21:51:34 +000066 //compute schedule and coreSchedule with the current II
67 success = computeSchedule();
68
69 if (!success) {
70 II++;
Misha Brukman2c821cc2003-04-10 19:19:23 +000071 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +000072 DEBUG_PRINT(std::cerr << "increase II to " << II << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000073 }
Misha Brukman8baa01c2003-04-09 21:51:34 +000074 }
75
Guochun Shi0e936872003-06-10 20:04:30 +000076 //print the final schedule
77 dumpFinalSchedule();
78
Guochun Shif1c154f2003-03-27 17:57:44 +000079 //the schedule has been computed
80 //create epilogue, prologue and kernel BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000081
Guochun Shif1c154f2003-03-27 17:57:44 +000082 //find the successor for this BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000083 BasicBlock *succ_bb = getSuccBB(bb);
84
Guochun Shif1c154f2003-03-27 17:57:44 +000085 //print the original BasicBlock if necessary
Misha Brukman2c821cc2003-04-10 19:19:23 +000086 if (ModuloScheduling::printSchedule()) {
Guochun Shi33280522003-06-08 20:40:47 +000087 DEBUG_PRINT(std::cerr << "dumping the orginal block\n");
Guochun Shif1c154f2003-03-27 17:57:44 +000088 graph.dump(bb);
89 }
Guochun Shif1c154f2003-03-27 17:57:44 +000090 //construction of prologue, kernel and epilogue
Guochun Shi8f1d4ab2003-06-08 23:16:07 +000091
92 /*
Misha Brukman8baa01c2003-04-09 21:51:34 +000093 BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
94 BasicBlock *prologue = bb;
95 BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
Guochun Shi8f1d4ab2003-06-08 23:16:07 +000096 */
Misha Brukman8baa01c2003-04-09 21:51:34 +000097
98 // Construct prologue
Guochun Shi8f1d4ab2003-06-08 23:16:07 +000099 /*constructPrologue(prologue);*/
Guochun Shif1c154f2003-03-27 17:57:44 +0000100
Misha Brukman8baa01c2003-04-09 21:51:34 +0000101 // Construct kernel
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000102
103 /*constructKernel(prologue, kernel, epilogue);*/
Guochun Shif1c154f2003-03-27 17:57:44 +0000104
Misha Brukman8baa01c2003-04-09 21:51:34 +0000105 // Construct epilogue
Guochun Shif1c154f2003-03-27 17:57:44 +0000106
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000107 /*constructEpilogue(epilogue, succ_bb);*/
108
Guochun Shif1c154f2003-03-27 17:57:44 +0000109 //print the BasicBlocks if necessary
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000110// if (0){
111// DEBUG_PRINT(std::cerr << "dumping the prologue block:\n");
112// graph.dump(prologue);
113// DEBUG_PRINT(std::cerr << "dumping the kernel block\n");
114// graph.dump(kernel);
115// DEBUG_PRINT(std::cerr << "dumping the epilogue block\n");
116// graph.dump(epilogue);
117// }
118
Guochun Shif1c154f2003-03-27 17:57:44 +0000119}
120
Guochun Shi0e936872003-06-10 20:04:30 +0000121
Misha Brukman8baa01c2003-04-09 21:51:34 +0000122// Clear memory from the last round and initialize if necessary
123//
Guochun Shi0e936872003-06-10 20:04:30 +0000124
125void
126ModuloScheduling::clearInitMem(const TargetSchedInfo & msi){
127
Misha Brukman8baa01c2003-04-09 21:51:34 +0000128 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//
Guochun Shi0e936872003-06-10 20:04:30 +0000159bool
160ModuloScheduling::computeSchedule(){
161
Guochun Shif1c154f2003-03-27 17:57:44 +0000162
Misha Brukman2c821cc2003-04-10 19:19:23 +0000163 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000164 DEBUG_PRINT(std::cerr << "start to compute schedule\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000165
Misha Brukman8baa01c2003-04-09 21:51:34 +0000166 // Loop over the ordered nodes
167 for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
168 // Try to schedule for node I
Misha Brukman2c821cc2003-04-10 19:19:23 +0000169 if (ModuloScheduling::printScheduleProcess())
Misha Brukman8baa01c2003-04-09 21:51:34 +0000170 dumpScheduling();
171 ModuloSchedGraphNode *node = *I;
Guochun Shif1c154f2003-03-27 17:57:44 +0000172
Misha Brukman8baa01c2003-04-09 21:51:34 +0000173 // Compute whether this node has successor(s)
174 bool succ = true;
175
176 // Compute whether this node has predessor(s)
177 bool pred = true;
178
179 NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
180 if (schSucc.empty())
181 succ = false;
182 NodeVec schPred = graph.vectorConj(nodeScheduled, graph.predSet(node));
183 if (schPred.empty())
184 pred = false;
185
186 //startTime: the earliest time we will try to schedule this node
187 //endTime: the latest time we will try to schedule this node
188 int startTime, endTime;
189
190 //node's earlyStart: possible earliest time to schedule this node
191 //node's lateStart: possible latest time to schedule this node
192 node->setEarlyStart(-1);
193 node->setLateStart(9999);
194
195 //this node has predessor but no successor
196 if (!succ && pred) {
197 // This node's earlyStart is it's predessor's schedule time + the edge
198 // delay - the iteration difference* II
199 for (unsigned i = 0; i < schPred.size(); i++) {
200 ModuloSchedGraphNode *predNode = schPred[i];
201 SchedGraphEdge *edge =
202 graph.getMaxDelayEdge(predNode->getNodeId(),
203 node->getNodeId());
204 int temp =
205 predNode->getSchTime() + edge->getMinDelay() -
206 edge->getIteDiff() * II;
207 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
Guochun Shif1c154f2003-03-27 17:57:44 +0000208 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000209 startTime = node->getEarlyStart();
210 endTime = node->getEarlyStart() + II - 1;
Guochun Shif1c154f2003-03-27 17:57:44 +0000211 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000212 // This node has a successor but no predecessor
213 if (succ && !pred) {
214 for (unsigned i = 0; i < schSucc.size(); ++i) {
215 ModuloSchedGraphNode *succNode = schSucc[i];
216 SchedGraphEdge *edge =
217 graph.getMaxDelayEdge(succNode->getNodeId(),
218 node->getNodeId());
219 int temp =
220 succNode->getSchTime() - edge->getMinDelay() +
221 edge->getIteDiff() * II;
222 node->setLateStart(std::min(node->getEarlyStart(), temp));
223 }
224 startTime = node->getLateStart() - II + 1;
225 endTime = node->getLateStart();
226 }
227 // This node has both successors and predecessors
228 if (succ && pred) {
229 for (unsigned i = 0; i < schPred.size(); ++i) {
230 ModuloSchedGraphNode *predNode = schPred[i];
231 SchedGraphEdge *edge =
232 graph.getMaxDelayEdge(predNode->getNodeId(),
233 node->getNodeId());
234 int temp =
235 predNode->getSchTime() + edge->getMinDelay() -
236 edge->getIteDiff() * II;
237 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
238 }
239 for (unsigned i = 0; i < schSucc.size(); ++i) {
240 ModuloSchedGraphNode *succNode = schSucc[i];
241 SchedGraphEdge *edge =
242 graph.getMaxDelayEdge(succNode->getNodeId(),
243 node->getNodeId());
244 int temp =
245 succNode->getSchTime() - edge->getMinDelay() +
246 edge->getIteDiff() * II;
247 node->setLateStart(std::min(node->getEarlyStart(), temp));
248 }
249 startTime = node->getEarlyStart();
250 endTime = std::min(node->getLateStart(),
251 node->getEarlyStart() + ((int) II) - 1);
252 }
253 //this node has no successor or predessor
254 if (!succ && !pred) {
255 node->setEarlyStart(node->getASAP());
256 startTime = node->getEarlyStart();
257 endTime = node->getEarlyStart() + II - 1;
258 }
259 //try to schedule this node based on the startTime and endTime
Misha Brukman2c821cc2003-04-10 19:19:23 +0000260 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000261 DEBUG_PRINT(std::cerr << "scheduling the node " << (*I)->getNodeId() << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000262
263 bool success =
264 this->ScheduleNode(node, startTime, endTime, nodeScheduled);
265 if (!success)
266 return false;
267 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000268 return true;
269}
270
271
Misha Brukman8baa01c2003-04-09 21:51:34 +0000272// Get the successor of the BasicBlock
273//
Guochun Shi0e936872003-06-10 20:04:30 +0000274BasicBlock *
275ModuloScheduling::getSuccBB(BasicBlock *bb){
276
Misha Brukman8baa01c2003-04-09 21:51:34 +0000277 BasicBlock *succ_bb;
278 for (unsigned i = 0; i < II; ++i)
279 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
280 if (coreSchedule[i][j]) {
281 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000282
Misha Brukman8baa01c2003-04-09 21:51:34 +0000283 //we can get successor from the BranchInst instruction
284 //assume we only have one successor (besides itself) here
285 if (BranchInst::classof(ist)) {
286 BranchInst *bi = (BranchInst *) ist;
287 assert(bi->isConditional() &&
288 "the branchInst is not a conditional one");
289 assert(bi->getNumSuccessors() == 2
290 && " more than two successors?");
291 BasicBlock *bb1 = bi->getSuccessor(0);
292 BasicBlock *bb2 = bi->getSuccessor(1);
293 assert((bb1 == bb || bb2 == bb) &&
294 " None of its successors is itself?");
295 if (bb1 == bb)
296 succ_bb = bb2;
297 else
298 succ_bb = bb1;
299 return succ_bb;
300 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000301 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000302 assert(0 && "NO Successor?");
Guochun Shif1c154f2003-03-27 17:57:44 +0000303 return NULL;
304}
305
306
Misha Brukman8baa01c2003-04-09 21:51:34 +0000307// Get the predecessor of the BasicBlock
308//
Guochun Shi0e936872003-06-10 20:04:30 +0000309BasicBlock *
310ModuloScheduling::getPredBB(BasicBlock *bb){
311
Misha Brukman8baa01c2003-04-09 21:51:34 +0000312 BasicBlock *pred_bb;
313 for (unsigned i = 0; i < II; ++i)
314 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
315 if (coreSchedule[i][j]) {
316 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000317
Misha Brukman8baa01c2003-04-09 21:51:34 +0000318 //we can get predecessor from the PHINode instruction
319 //assume we only have one predecessor (besides itself) here
320 if (PHINode::classof(ist)) {
321 PHINode *phi = (PHINode *) ist;
322 assert(phi->getNumIncomingValues() == 2 &&
323 " the number of incoming value is not equal to two? ");
324 BasicBlock *bb1 = phi->getIncomingBlock(0);
325 BasicBlock *bb2 = phi->getIncomingBlock(1);
326 assert((bb1 == bb || bb2 == bb) &&
327 " None of its predecessor is itself?");
328 if (bb1 == bb)
329 pred_bb = bb2;
330 else
331 pred_bb = bb1;
332 return pred_bb;
333 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000334 }
335 assert(0 && " no predecessor?");
336 return NULL;
337}
338
339
Misha Brukman8baa01c2003-04-09 21:51:34 +0000340// Construct the prologue
341//
Guochun Shi0e936872003-06-10 20:04:30 +0000342void
343ModuloScheduling::constructPrologue(BasicBlock *prologue){
344
Misha Brukman8baa01c2003-04-09 21:51:34 +0000345 InstListType & prologue_ist = prologue->getInstList();
346 vvNodeType & tempSchedule_prologue =
Misha Brukman2c821cc2003-04-10 19:19:23 +0000347 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000348
Guochun Shif1c154f2003-03-27 17:57:44 +0000349 //compute the schedule for prologue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000350 unsigned round = 0;
351 unsigned scheduleSize = schedule.size();
352 while (round < scheduleSize / II) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000353 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000354 for (unsigned i = 0; i < scheduleSize; ++i) {
355 if (round * II + i >= scheduleSize)
356 break;
357 for (unsigned j = 0; j < schedule[i].size(); ++j) {
358 if (schedule[i][j]) {
359 assert(tempSchedule_prologue[round * II + i][j] == NULL &&
360 "table not consitent with core table");
361 // move the schedule one iteration ahead and overlap with the original
362 tempSchedule_prologue[round * II + i][j] = schedule[i][j];
363 }
364 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000365 }
366 }
367
Misha Brukman8baa01c2003-04-09 21:51:34 +0000368 // Clear the clone memory in the core schedule instructions
Guochun Shif1c154f2003-03-27 17:57:44 +0000369 clearCloneMemory();
Guochun Shif1c154f2003-03-27 17:57:44 +0000370
Misha Brukman8baa01c2003-04-09 21:51:34 +0000371 // Fill in the prologue
372 for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
373 for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
374 if (tempSchedule_prologue[i][j]) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000375
Misha Brukman8baa01c2003-04-09 21:51:34 +0000376 //get the instruction
377 Instruction *orn =
378 (Instruction *) tempSchedule_prologue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000379
Misha Brukman8baa01c2003-04-09 21:51:34 +0000380 //made a clone of it
381 Instruction *cln = cloneInstSetMemory(orn);
Guochun Shif1c154f2003-03-27 17:57:44 +0000382
Misha Brukman8baa01c2003-04-09 21:51:34 +0000383 //insert the instruction
384 prologue_ist.insert(prologue_ist.back(), cln);
385
386 //if there is PHINode in the prologue, the incoming value from itself
387 //should be removed because it is not a loop any longer
388 if (PHINode::classof(cln)) {
389 PHINode *phi = (PHINode *) cln;
390 phi->removeIncomingValue(phi->getParent());
391 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000392 }
393}
394
395
Misha Brukman8baa01c2003-04-09 21:51:34 +0000396// Construct the kernel BasicBlock
397//
Guochun Shi0e936872003-06-10 20:04:30 +0000398void
399ModuloScheduling::constructKernel(BasicBlock *prologue,
Misha Brukman8baa01c2003-04-09 21:51:34 +0000400 BasicBlock *kernel,
Guochun Shi0e936872003-06-10 20:04:30 +0000401 BasicBlock *epilogue){
402
Guochun Shif1c154f2003-03-27 17:57:44 +0000403 //*************fill instructions in the kernel****************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000404 InstListType & kernel_ist = kernel->getInstList();
405 BranchInst *brchInst;
406 PHINode *phiInst, *phiCln;
Guochun Shif1c154f2003-03-27 17:57:44 +0000407
Misha Brukman8baa01c2003-04-09 21:51:34 +0000408 for (unsigned i = 0; i < coreSchedule.size(); ++i)
409 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
410 if (coreSchedule[i][j]) {
411
412 // Take care of branch instruction differently with normal instructions
413 if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
414 brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
415 continue;
416 }
417 // Take care of PHINode instruction differently with normal instructions
418 if (PHINode::classof(coreSchedule[i][j]->getInst())) {
419 phiInst = (PHINode *) coreSchedule[i][j]->getInst();
420 Instruction *cln = cloneInstSetMemory(phiInst);
421 kernel_ist.insert(kernel_ist.back(), cln);
422 phiCln = (PHINode *) cln;
423 continue;
424 }
425 //for normal instructions: made a clone and insert it in the kernel_ist
426 Instruction *cln =
427 cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
428 getInst());
429 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000430 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000431 // The two incoming BasicBlock for PHINode is the prologue and the kernel
432 // (itself)
433 phiCln->setIncomingBlock(0, prologue);
434 phiCln->setIncomingBlock(1, kernel);
Guochun Shif1c154f2003-03-27 17:57:44 +0000435
Misha Brukman8baa01c2003-04-09 21:51:34 +0000436 // The incoming value for the kernel (itself) is the new value which is
437 // computed in the kernel
438 Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000439 phiCln->setIncomingValue(1, originalVal->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000440
Misha Brukman8baa01c2003-04-09 21:51:34 +0000441 // Make a clone of the branch instruction and insert it in the end
442 BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
443 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000444
Misha Brukman8baa01c2003-04-09 21:51:34 +0000445 // delete the unconditional branch instruction, which is generated when
446 // splitting the basicBlock
447 kernel_ist.erase(--kernel_ist.end());
Guochun Shif1c154f2003-03-27 17:57:44 +0000448
Misha Brukman8baa01c2003-04-09 21:51:34 +0000449 // set the first successor to itself
Chris Lattner9daa8a12003-07-23 14:59:40 +0000450 cln->setSuccessor(0, kernel);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000451 // set the second successor to eiplogue
Chris Lattner9daa8a12003-07-23 14:59:40 +0000452 cln->setSuccessor(1, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000453
454 //*****change the condition*******
455
456 //get the condition instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000457 Instruction *cond = (Instruction *) cln->getCondition();
Guochun Shif1c154f2003-03-27 17:57:44 +0000458
459 //get the condition's second operand, it should be a constant
Misha Brukman8baa01c2003-04-09 21:51:34 +0000460 Value *operand = cond->getOperand(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000461 assert(ConstantSInt::classof(operand));
462
463 //change the constant in the condtion instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000464 ConstantSInt *iteTimes =
465 ConstantSInt::get(operand->getType(),
466 ((ConstantSInt *) operand)->getValue() - II + 1);
467 cond->setOperand(1, iteTimes);
Guochun Shif1c154f2003-03-27 17:57:44 +0000468
469}
470
471
Misha Brukman8baa01c2003-04-09 21:51:34 +0000472// Construct the epilogue
473//
Guochun Shi0e936872003-06-10 20:04:30 +0000474void
475ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
476 BasicBlock *succ_bb){
Guochun Shif1c154f2003-03-27 17:57:44 +0000477
Guochun Shif1c154f2003-03-27 17:57:44 +0000478 //compute the schedule for epilogue
Misha Brukman2c821cc2003-04-10 19:19:23 +0000479 vvNodeType &tempSchedule_epilogue =
480 *(new std::vector<std::vector<ModuloSchedGraphNode*> >(schedule));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000481 unsigned scheduleSize = schedule.size();
482 int round = 0;
483 while (round < ceil(1.0 * scheduleSize / II) - 1) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000484 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000485 for (unsigned i = 0; i < scheduleSize; i++) {
486 if (i + round * II >= scheduleSize)
487 break;
488 for (unsigned j = 0; j < schedule[i].size(); j++)
489 if (schedule[i + round * II][j]) {
490 assert(tempSchedule_epilogue[i][j] == NULL
491 && "table not consitant with core table");
Guochun Shif1c154f2003-03-27 17:57:44 +0000492
Misha Brukman8baa01c2003-04-09 21:51:34 +0000493 //move the schdule one iteration behind and overlap
494 tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
495 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000496 }
497 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000498
Guochun Shif1c154f2003-03-27 17:57:44 +0000499 //fill in the epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000500 InstListType & epilogue_ist = epilogue->getInstList();
501 for (unsigned i = II; i < scheduleSize; i++)
502 for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
503 if (tempSchedule_epilogue[i][j]) {
504 Instruction *inst =
505 (Instruction *) tempSchedule_epilogue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000506
Misha Brukman8baa01c2003-04-09 21:51:34 +0000507 //BranchInst and PHINode should be treated differently
508 //BranchInst:unecessary, simly omitted
509 //PHINode: omitted
510 if (!BranchInst::classof(inst) && !PHINode::classof(inst)) {
511 //make a clone instruction and insert it into the epilogue
512 Instruction *cln = cloneInstSetMemory(inst);
513 epilogue_ist.push_front(cln);
514 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000515 }
516
Guochun Shif1c154f2003-03-27 17:57:44 +0000517 //*************delete the original instructions****************//
518 //to delete the original instructions, we have to make sure their use is zero
Misha Brukman8baa01c2003-04-09 21:51:34 +0000519
Guochun Shif1c154f2003-03-27 17:57:44 +0000520 //update original core instruction's uses, using its clone instread
Misha Brukman8baa01c2003-04-09 21:51:34 +0000521 for (unsigned i = 0; i < II; i++)
522 for (unsigned j = 0; j < coreSchedule[i].size(); j++) {
523 if (coreSchedule[i][j])
524 updateUseWithClone((Instruction *) coreSchedule[i][j]->getInst());
Guochun Shif1c154f2003-03-27 17:57:44 +0000525 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000526
Guochun Shif1c154f2003-03-27 17:57:44 +0000527 //erase these instructions
Misha Brukman8baa01c2003-04-09 21:51:34 +0000528 for (unsigned i = 0; i < II; i++)
529 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
530 if (coreSchedule[i][j]) {
531 Instruction *ist = (Instruction *) coreSchedule[i][j]->getInst();
532 ist->getParent()->getInstList().erase(ist);
Guochun Shif1c154f2003-03-27 17:57:44 +0000533 }
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000534
Guochun Shif1c154f2003-03-27 17:57:44 +0000535
536
537 //finally, insert an unconditional branch instruction at the end
538 epilogue_ist.push_back(new BranchInst(succ_bb));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000539
Guochun Shif1c154f2003-03-27 17:57:44 +0000540}
541
542
Misha Brukman8baa01c2003-04-09 21:51:34 +0000543//------------------------------------------------------------------------------
544//this function replace the value(instruction) ist in other instructions with
545//its latest clone i.e. after this function is called, the ist is not used
546//anywhere and it can be erased.
547//------------------------------------------------------------------------------
Guochun Shi0e936872003-06-10 20:04:30 +0000548void
549ModuloScheduling::updateUseWithClone(Instruction * ist){
550
Misha Brukman8baa01c2003-04-09 21:51:34 +0000551
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//*****************************************************
Guochun Shi0e936872003-06-10 20:04:30 +0000590void
591ModuloScheduling::clearCloneMemory(){
592
Misha Brukman8baa01c2003-04-09 21:51:34 +0000593 for (unsigned i = 0; i < coreSchedule.size(); i++)
594 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
595 if (coreSchedule[i][j])
596 ((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
597
Guochun Shif1c154f2003-03-27 17:57:44 +0000598}
599
600
Misha Brukman8baa01c2003-04-09 21:51:34 +0000601//******************************************************************************
602// this function make a clone of the instruction orn the cloned instruction will
603// use the orn's operands' latest clone as its operands it is done this way
604// because LLVM is in SSA form and we should use the correct value
Guochun Shif1c154f2003-03-27 17:57:44 +0000605//this fuction also update the instruction orn's latest clone memory
Misha Brukman8baa01c2003-04-09 21:51:34 +0000606//******************************************************************************
Guochun Shi0e936872003-06-10 20:04:30 +0000607Instruction *
608ModuloScheduling::cloneInstSetMemory(Instruction * orn){
609
Misha Brukman8baa01c2003-04-09 21:51:34 +0000610 // make a clone instruction
611 Instruction *cln = orn->clone();
Guochun Shif1c154f2003-03-27 17:57:44 +0000612
Misha Brukman8baa01c2003-04-09 21:51:34 +0000613 // update the operands
614 for (unsigned k = 0; k < orn->getNumOperands(); k++) {
615 const Value *op = orn->getOperand(k);
616 if (Instruction::classof(op) && ((Instruction *) op)->getClone()) {
617 Instruction *op_inst = (Instruction *) op;
Guochun Shif1c154f2003-03-27 17:57:44 +0000618 cln->setOperand(k, op_inst->getClone());
619 }
620 }
621
Misha Brukman8baa01c2003-04-09 21:51:34 +0000622 // update clone memory
Guochun Shif1c154f2003-03-27 17:57:44 +0000623 orn->setClone(cln);
624 return cln;
625}
626
627
628
Guochun Shi0e936872003-06-10 20:04:30 +0000629bool
630ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
Misha Brukman8baa01c2003-04-09 21:51:34 +0000631 unsigned start, unsigned end,
Guochun Shi0e936872003-06-10 20:04:30 +0000632 NodeVec & nodeScheduled){
633
Misha Brukman8baa01c2003-04-09 21:51:34 +0000634 const TargetSchedInfo & msi = target.getSchedInfo();
635 unsigned int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +0000636
Misha Brukman2c821cc2003-04-10 19:19:23 +0000637 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000638 DEBUG_PRINT(std::cerr << "startTime= " << start << " endTime= " << end << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000639 bool isScheduled = false;
640 for (unsigned i = start; i <= end; i++) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000641 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000642 DEBUG_PRINT(std::cerr << " now try cycle " << i << ":" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000643 for (unsigned j = 0; j < numIssueSlots; j++) {
644 unsigned int core_i = i % II;
645 unsigned int core_j = j;
Misha Brukman2c821cc2003-04-10 19:19:23 +0000646 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000647 DEBUG_PRINT(std::cerr << "\t Trying slot " << j << "...........");
Guochun Shif1c154f2003-03-27 17:57:44 +0000648 //check the resouce table, make sure there is no resource conflicts
Misha Brukman8baa01c2003-04-09 21:51:34 +0000649 const Instruction *instr = node->getInst();
650 MachineCodeForInstruction & tempMvec =
651 MachineCodeForInstruction::get(instr);
652 bool resourceConflict = false;
653 const TargetInstrInfo & mii = msi.getInstrInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000654
Misha Brukman8baa01c2003-04-09 21:51:34 +0000655 if (coreSchedule.size() < core_i + 1
656 || !coreSchedule[core_i][core_j]) {
657 //this->dumpResourceUsageTable();
658 int latency = 0;
659 for (unsigned k = 0; k < tempMvec.size(); k++) {
660 MachineInstr *minstr = tempMvec[k];
661 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
662 std::vector < std::vector < resourceId_t > >resources
663 = rUsage.resourcesByCycle;
664 updateResourceTable(resources, i + latency);
665 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
666 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000667
Misha Brukman8baa01c2003-04-09 21:51:34 +0000668 //this->dumpResourceUsageTable();
Guochun Shif1c154f2003-03-27 17:57:44 +0000669
Misha Brukman8baa01c2003-04-09 21:51:34 +0000670 latency = 0;
671 if (resourceTableNegative()) {
672
673 //undo-update the resource table
674 for (unsigned k = 0; k < tempMvec.size(); k++) {
675 MachineInstr *minstr = tempMvec[k];
676 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
677 std::vector < std::vector < resourceId_t > >resources
678 = rUsage.resourcesByCycle;
679 undoUpdateResourceTable(resources, i + latency);
680 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
681 }
682 resourceConflict = true;
683 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000684 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000685 if (!resourceConflict && !coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000686 if (ModuloScheduling::printScheduleProcess()) {
Guochun Shi33280522003-06-08 20:40:47 +0000687 DEBUG_PRINT(std::cerr << " OK!" << "\n");
688 DEBUG_PRINT(std::cerr << "Node " << node->getNodeId() << " scheduled.\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000689 }
690 //schedule[i][j]=node;
691 while (schedule.size() <= i) {
692 std::vector < ModuloSchedGraphNode * >*newCycle =
693 new std::vector < ModuloSchedGraphNode * >();
694 for (unsigned k = 0; k < numIssueSlots; k++)
695 newCycle->push_back(NULL);
696 schedule.push_back(*newCycle);
697 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000698 std::vector<ModuloSchedGraphNode*>::iterator startIterator;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000699 startIterator = schedule[i].begin();
700 schedule[i].insert(startIterator + j, node);
701 startIterator = schedule[i].begin();
702 schedule[i].erase(startIterator + j + 1);
703
704 //update coreSchedule
705 //coreSchedule[core_i][core_j]=node;
706 while (coreSchedule.size() <= core_i) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000707 std::vector<ModuloSchedGraphNode*> *newCycle =
708 new std::vector<ModuloSchedGraphNode*>();
Misha Brukman8baa01c2003-04-09 21:51:34 +0000709 for (unsigned k = 0; k < numIssueSlots; k++)
710 newCycle->push_back(NULL);
711 coreSchedule.push_back(*newCycle);
712 }
713
714 startIterator = coreSchedule[core_i].begin();
715 coreSchedule[core_i].insert(startIterator + core_j, node);
716 startIterator = coreSchedule[core_i].begin();
717 coreSchedule[core_i].erase(startIterator + core_j + 1);
718
719 node->setSchTime(i);
720 isScheduled = true;
721 nodeScheduled.push_back(node);
722
723 break;
724 } else if (coreSchedule[core_i][core_j]) {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000725 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000726 DEBUG_PRINT(std::cerr << " Slot not available\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000727 } else {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000728 if (ModuloScheduling::printScheduleProcess())
Guochun Shi33280522003-06-08 20:40:47 +0000729 DEBUG_PRINT(std::cerr << " Resource conflicts\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000730 }
731 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000732 if (isScheduled)
733 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000734 }
735 //assert(nodeScheduled &&"this node can not be scheduled?");
736 return isScheduled;
737}
738
Misha Brukman8baa01c2003-04-09 21:51:34 +0000739
Guochun Shi0e936872003-06-10 20:04:30 +0000740void
741ModuloScheduling::updateResourceTable(Resources useResources,
742 int startCycle){
743
Misha Brukman8baa01c2003-04-09 21:51:34 +0000744 for (unsigned i = 0; i < useResources.size(); i++) {
745 int absCycle = startCycle + i;
746 int coreCycle = absCycle % II;
747 std::vector<std::pair<int,int> > &resourceRemained =
748 resourceTable[coreCycle];
749 std::vector < unsigned int >&resourceUsed = useResources[i];
750 for (unsigned j = 0; j < resourceUsed.size(); j++) {
751 for (unsigned k = 0; k < resourceRemained.size(); k++)
752 if ((int) resourceUsed[j] == resourceRemained[k].first) {
753 resourceRemained[k].second--;
754 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000755 }
756 }
757}
758
Guochun Shi0e936872003-06-10 20:04:30 +0000759void
760ModuloScheduling::undoUpdateResourceTable(Resources useResources,
761 int startCycle){
762
Misha Brukman8baa01c2003-04-09 21:51:34 +0000763 for (unsigned i = 0; i < useResources.size(); i++) {
764 int absCycle = startCycle + i;
765 int coreCycle = absCycle % II;
766 std::vector<std::pair<int,int> > &resourceRemained =
767 resourceTable[coreCycle];
768 std::vector < unsigned int >&resourceUsed = useResources[i];
769 for (unsigned j = 0; j < resourceUsed.size(); j++) {
770 for (unsigned k = 0; k < resourceRemained.size(); k++)
771 if ((int) resourceUsed[j] == resourceRemained[k].first) {
772 resourceRemained[k].second++;
773 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000774 }
775 }
776}
777
778
779//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000780// Function: resourceTableNegative
781// return value:
782// return false if any element in the resouceTable is negative
783// otherwise return true
784// Purpose:
Guochun Shif1c154f2003-03-27 17:57:44 +0000785
Misha Brukman8baa01c2003-04-09 21:51:34 +0000786// this function is used to determine if an instruction is eligible for
787// schedule at certain cycle
788//-----------------------------------------------------------------------
789
790
Guochun Shi0e936872003-06-10 20:04:30 +0000791bool
792ModuloScheduling::resourceTableNegative(){
793
Misha Brukman8baa01c2003-04-09 21:51:34 +0000794 assert(resourceTable.size() == (unsigned) II
795 && "resouceTable size must be equal to II");
796 bool isNegative = false;
797 for (unsigned i = 0; i < resourceTable.size(); i++)
798 for (unsigned j = 0; j < resourceTable[i].size(); j++) {
799 if (resourceTable[i][j].second < 0) {
800 isNegative = true;
801 break;
802 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000803 }
804 return isNegative;
805}
806
807
808//----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000809// Function: dumpResouceUsageTable
810// Purpose:
811// print out ResouceTable for debug
Guochun Shif1c154f2003-03-27 17:57:44 +0000812//
813//------------------------------------------------------------------------
814
Guochun Shi0e936872003-06-10 20:04:30 +0000815void
816ModuloScheduling::dumpResourceUsageTable(){
817
Guochun Shi33280522003-06-08 20:40:47 +0000818 DEBUG_PRINT(std::cerr << "dumping resource usage table\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000819 for (unsigned i = 0; i < resourceTable.size(); i++) {
820 for (unsigned j = 0; j < resourceTable[i].size(); j++)
Guochun Shi33280522003-06-08 20:40:47 +0000821 DEBUG_PRINT(std::cerr << resourceTable[i][j].first
Misha Brukman2c821cc2003-04-10 19:19:23 +0000822 << ":" << resourceTable[i][j].second << " ");
Guochun Shi33280522003-06-08 20:40:47 +0000823 DEBUG_PRINT(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000824 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000825
Guochun Shif1c154f2003-03-27 17:57:44 +0000826}
827
828//----------------------------------------------------------------------
829//Function: dumpSchedule
830//Purpose:
831// print out thisSchedule for debug
832//
833//-----------------------------------------------------------------------
Guochun Shi0e936872003-06-10 20:04:30 +0000834void
835ModuloScheduling::dumpSchedule(vvNodeType thisSchedule){
836
Misha Brukman8baa01c2003-04-09 21:51:34 +0000837 const TargetSchedInfo & msi = target.getSchedInfo();
838 unsigned numIssueSlots = msi.maxNumIssueTotal;
839 for (unsigned i = 0; i < numIssueSlots; i++)
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 for (unsigned i = 0; i < thisSchedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000843 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000844 for (unsigned j = 0; j < thisSchedule[i].size(); j++)
845 if (thisSchedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000846 DEBUG_PRINT(std::cerr << thisSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000847 else
Guochun Shi33280522003-06-08 20:40:47 +0000848 DEBUG_PRINT(std::cerr << "\t");
849 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000850 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000851}
852
853
854//----------------------------------------------------
855//Function: dumpScheduling
856//Purpose:
857// print out the schedule and coreSchedule for debug
858//
859//-------------------------------------------------------
860
Guochun Shi0e936872003-06-10 20:04:30 +0000861void
862ModuloScheduling::dumpScheduling(){
863
Guochun Shi33280522003-06-08 20:40:47 +0000864 DEBUG_PRINT(std::cerr << "dump schedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000865 const TargetSchedInfo & msi = target.getSchedInfo();
866 unsigned numIssueSlots = msi.maxNumIssueTotal;
867 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000868 DEBUG_PRINT(std::cerr << "\t#");
869 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000870 for (unsigned i = 0; i < schedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000871 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000872 for (unsigned j = 0; j < schedule[i].size(); j++)
873 if (schedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000874 DEBUG_PRINT(std::cerr << schedule[i][j]->getNodeId() << "\t");
Guochun Shif1c154f2003-03-27 17:57:44 +0000875 else
Guochun Shi33280522003-06-08 20:40:47 +0000876 DEBUG_PRINT(std::cerr << "\t");
877 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000878 }
879
Guochun Shi33280522003-06-08 20:40:47 +0000880 DEBUG_PRINT(std::cerr << "dump coreSchedule:" << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000881 for (unsigned i = 0; i < numIssueSlots; i++)
Guochun Shi33280522003-06-08 20:40:47 +0000882 DEBUG_PRINT(std::cerr << "\t#");
883 DEBUG_PRINT(std::cerr << "\n");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000884 for (unsigned i = 0; i < coreSchedule.size(); i++) {
Guochun Shi33280522003-06-08 20:40:47 +0000885 DEBUG_PRINT(std::cerr << "cycle" << i << ": ");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000886 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
887 if (coreSchedule[i][j] != NULL)
Guochun Shi33280522003-06-08 20:40:47 +0000888 DEBUG_PRINT(std::cerr << coreSchedule[i][j]->getNodeId() << "\t");
Misha Brukman8baa01c2003-04-09 21:51:34 +0000889 else
Guochun Shi33280522003-06-08 20:40:47 +0000890 DEBUG_PRINT(std::cerr << "\t");
891 DEBUG_PRINT(std::cerr << "\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000892 }
893}
894
Guochun Shi0e936872003-06-10 20:04:30 +0000895/*
896 print out final schedule
897*/
Guochun Shif1c154f2003-03-27 17:57:44 +0000898
Guochun Shi0e936872003-06-10 20:04:30 +0000899void
900ModuloScheduling::dumpFinalSchedule(){
901
Chris Lattner9daa8a12003-07-23 14:59:40 +0000902 std::cerr << "dump schedule:" << "\n";
Guochun Shi0e936872003-06-10 20:04:30 +0000903 const TargetSchedInfo & msi = target.getSchedInfo();
904 unsigned numIssueSlots = msi.maxNumIssueTotal;
905
906 for (unsigned i = 0; i < numIssueSlots; i++)
Chris Lattner9daa8a12003-07-23 14:59:40 +0000907 std::cerr << "\t#";
908 std::cerr << "\n";
Guochun Shi0e936872003-06-10 20:04:30 +0000909
910 for (unsigned i = 0; i < schedule.size(); i++) {
Chris Lattner9daa8a12003-07-23 14:59:40 +0000911 std::cerr << "cycle" << i << ": ";
Guochun Shi0e936872003-06-10 20:04:30 +0000912
913 for (unsigned j = 0; j < schedule[i].size(); j++)
914 if (schedule[i][j] != NULL)
Chris Lattner9daa8a12003-07-23 14:59:40 +0000915 std::cerr << schedule[i][j]->getNodeId() << "\t";
Guochun Shi0e936872003-06-10 20:04:30 +0000916 else
Chris Lattner9daa8a12003-07-23 14:59:40 +0000917 std::cerr << "\t";
918 std::cerr << "\n";
Guochun Shi0e936872003-06-10 20:04:30 +0000919 }
920
Chris Lattner9daa8a12003-07-23 14:59:40 +0000921 std::cerr << "dump coreSchedule:" << "\n";
Guochun Shi0e936872003-06-10 20:04:30 +0000922 for (unsigned i = 0; i < numIssueSlots; i++)
Chris Lattner9daa8a12003-07-23 14:59:40 +0000923 std::cerr << "\t#";
924 std::cerr << "\n";
Guochun Shi0e936872003-06-10 20:04:30 +0000925
926 for (unsigned i = 0; i < coreSchedule.size(); i++) {
Chris Lattner9daa8a12003-07-23 14:59:40 +0000927 std::cerr << "cycle" << i << ": ";
Guochun Shi0e936872003-06-10 20:04:30 +0000928 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
929 if (coreSchedule[i][j] != NULL)
Chris Lattner9daa8a12003-07-23 14:59:40 +0000930 std::cerr << coreSchedule[i][j]->getNodeId() << "\t";
Guochun Shi0e936872003-06-10 20:04:30 +0000931 else
Chris Lattner9daa8a12003-07-23 14:59:40 +0000932 std::cerr << "\t";
933 std::cerr << "\n";
Guochun Shi0e936872003-06-10 20:04:30 +0000934 }
935}
Guochun Shif1c154f2003-03-27 17:57:44 +0000936
937//---------------------------------------------------------------------------
938// Function: ModuloSchedulingPass
939//
940// Purpose:
941// Entry point for Modulo Scheduling
942// Schedules LLVM instruction
943//
944//---------------------------------------------------------------------------
945
946namespace {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000947 class ModuloSchedulingPass:public FunctionPass {
Misha Brukman2c821cc2003-04-10 19:19:23 +0000948 const TargetMachine &target;
949
Guochun Shif1c154f2003-03-27 17:57:44 +0000950 public:
Misha Brukman2c821cc2003-04-10 19:19:23 +0000951 ModuloSchedulingPass(const TargetMachine &T):target(T) {}
952
953 const char *getPassName() const {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000954 return "Modulo Scheduling";
Guochun Shif1c154f2003-03-27 17:57:44 +0000955 }
Misha Brukman2c821cc2003-04-10 19:19:23 +0000956
Misha Brukman8baa01c2003-04-09 21:51:34 +0000957 // getAnalysisUsage - We use LiveVarInfo...
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000958 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000959 //AU.addRequired(FunctionLiveVarInfo::ID);
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000960 }
961
962 bool runOnFunction(Function & F);
Guochun Shif1c154f2003-03-27 17:57:44 +0000963 };
Misha Brukman8baa01c2003-04-09 21:51:34 +0000964} // end anonymous namespace
Guochun Shif1c154f2003-03-27 17:57:44 +0000965
966
Guochun Shi0e936872003-06-10 20:04:30 +0000967bool
968ModuloSchedulingPass::runOnFunction(Function &F){
969
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000970 ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
971
Guochun Shif3252612003-06-10 19:09:00 +0000972 ModuloSchedulingSet ModuloSchedulingSet(*graphSet);
Guochun Shi8f1d4ab2003-06-08 23:16:07 +0000973
Chris Lattner9daa8a12003-07-23 14:59:40 +0000974 DEBUG_PRINT(std::cerr<<"runOnFunction in ModuloSchedulingPass returns\n"<<"\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000975 return false;
976}
977
978
Guochun Shi0e936872003-06-10 20:04:30 +0000979Pass *
980createModuloSchedulingPass(const TargetMachine & tgt){
Chris Lattner9daa8a12003-07-23 14:59:40 +0000981 DEBUG_PRINT(std::cerr<<"creating modulo scheduling\n");
Guochun Shif1c154f2003-03-27 17:57:44 +0000982 return new ModuloSchedulingPass(tgt);
983}