blob: 84ce1cd0702f2a11c2db1989a4bf3ca3bade297e [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"
22#include "ModuloSchedGraph.h"
23#include "ModuloScheduling.h"
24#include <algorithm>
25#include <fstream>
Guochun Shif1c154f2003-03-27 17:57:44 +000026#include <iostream>
Guochun Shi6fbe5fb2003-04-06 23:56:19 +000027//#include <swig.h>
Guochun Shif1c154f2003-03-27 17:57:44 +000028
29//************************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +000030// printing Debug information
31// ModuloSchedDebugLevel stores the value of debug level
32// modsched_os is the ostream to dump debug information, which is written into
33// the file 'moduloSchedDebugInfo.output'
34// see ModuloSchedulingPass::runOnFunction()
Guochun Shif1c154f2003-03-27 17:57:44 +000035//************************************************************
36
37ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
Misha Brukman8baa01c2003-04-09 21:51:34 +000038static cl::opt<ModuloSchedDebugLevel_t,true>
Guochun Shif1c154f2003-03-27 17:57:44 +000039SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
40 cl::desc("enable modulo scheduling debugging information"),
Misha Brukman8baa01c2003-04-09 21:51:34 +000041 cl::values(clEnumValN
42 (ModuloSched_NoDebugInfo, "n", "disable debug output"),
43 clEnumValN(ModuloSched_Disable, "off",
44 "disable modulo scheduling"),
45 clEnumValN(ModuloSched_PrintSchedule, "psched",
46 "print original and new schedule"),
47 clEnumValN(ModuloSched_PrintScheduleProcess, "pschedproc",
48 "print how the new schdule is produced"), 0));
Guochun Shif1c154f2003-03-27 17:57:44 +000049
Misha Brukman8baa01c2003-04-09 21:51:34 +000050std::filebuf modSched_fb;
51std::ostream modSched_os(&modSched_fb);
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 Shif1c154f2003-03-27 17:57:44 +000057
Misha Brukman8baa01c2003-04-09 21:51:34 +000058 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
59 modSched_os << "*************** computing modulo schedule **************\n";
Guochun Shif1c154f2003-03-27 17:57:44 +000060
Misha Brukman8baa01c2003-04-09 21:51:34 +000061 const TargetSchedInfo & msi = target.getSchedInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +000062
63 //number of issue slots in the in each cycle
Misha Brukman8baa01c2003-04-09 21:51:34 +000064 int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +000065
66 //compute the schedule
Misha Brukman8baa01c2003-04-09 21:51:34 +000067 bool success = false;
68 while (!success) {
69 //clear memory from the last round and initialize if necessary
70 clearInitMem(msi);
Guochun Shif1c154f2003-03-27 17:57:44 +000071
Misha Brukman8baa01c2003-04-09 21:51:34 +000072 //compute schedule and coreSchedule with the current II
73 success = computeSchedule();
74
75 if (!success) {
76 II++;
77 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
78 modSched_os << "increase II to " << II << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +000079 }
Misha Brukman8baa01c2003-04-09 21:51:34 +000080 }
81
Guochun Shif1c154f2003-03-27 17:57:44 +000082 //print the final schedule if necessary
Misha Brukman8baa01c2003-04-09 21:51:34 +000083 if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule)
Guochun Shif1c154f2003-03-27 17:57:44 +000084 dumpScheduling();
Guochun Shif1c154f2003-03-27 17:57:44 +000085
86 //the schedule has been computed
87 //create epilogue, prologue and kernel BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000088
Guochun Shif1c154f2003-03-27 17:57:44 +000089 //find the successor for this BasicBlock
Misha Brukman8baa01c2003-04-09 21:51:34 +000090 BasicBlock *succ_bb = getSuccBB(bb);
91
Guochun Shif1c154f2003-03-27 17:57:44 +000092 //print the original BasicBlock if necessary
Misha Brukman8baa01c2003-04-09 21:51:34 +000093 if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) {
94 modSched_os << "dumping the orginal block\n";
Guochun Shif1c154f2003-03-27 17:57:44 +000095 graph.dump(bb);
96 }
Guochun Shif1c154f2003-03-27 17:57:44 +000097 //construction of prologue, kernel and epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +000098 BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
99 BasicBlock *prologue = bb;
100 BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
101
102 // Construct prologue
Guochun Shif1c154f2003-03-27 17:57:44 +0000103 constructPrologue(prologue);
104
Misha Brukman8baa01c2003-04-09 21:51:34 +0000105 // Construct kernel
106 constructKernel(prologue, kernel, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000107
Misha Brukman8baa01c2003-04-09 21:51:34 +0000108 // Construct epilogue
109 constructEpilogue(epilogue, succ_bb);
Guochun Shif1c154f2003-03-27 17:57:44 +0000110
Guochun Shif1c154f2003-03-27 17:57:44 +0000111 //print the BasicBlocks if necessary
Misha Brukman8baa01c2003-04-09 21:51:34 +0000112 if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) {
113 modSched_os << "dumping the prologue block:\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000114 graph.dump(prologue);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000115 modSched_os << "dumping the kernel block\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000116 graph.dump(kernel);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000117 modSched_os << "dumping the epilogue block\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000118 graph.dump(epilogue);
119 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000120}
121
Misha Brukman8baa01c2003-04-09 21:51:34 +0000122// Clear memory from the last round and initialize if necessary
123//
124void ModuloScheduling::clearInitMem(const TargetSchedInfo & msi)
125{
126 unsigned numIssueSlots = msi.maxNumIssueTotal;
127 // clear nodeScheduled from the last round
128 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
129 modSched_os << "***** new round with II= " << II <<
130 " *******************\n";
131 modSched_os <<
132 " ************clear the vector nodeScheduled*************\n";
133 }
134 nodeScheduled.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000135
Misha Brukman8baa01c2003-04-09 21:51:34 +0000136 // clear resourceTable from the last round and reset it
137 resourceTable.clear();
138 for (unsigned i = 0; i < II; ++i)
139 resourceTable.push_back(msi.resourceNumVector);
Guochun Shif1c154f2003-03-27 17:57:44 +0000140
Misha Brukman8baa01c2003-04-09 21:51:34 +0000141 // clear the schdule and coreSchedule from the last round
142 schedule.clear();
143 coreSchedule.clear();
Guochun Shif1c154f2003-03-27 17:57:44 +0000144
Misha Brukman8baa01c2003-04-09 21:51:34 +0000145 // create a coreSchedule of size II*numIssueSlots
146 // each entry is NULL
147 while (coreSchedule.size() < II) {
148 std::vector < ModuloSchedGraphNode * >*newCycle =
149 new std::vector < ModuloSchedGraphNode * >();
150 for (unsigned k = 0; k < numIssueSlots; ++k)
151 newCycle->push_back(NULL);
152 coreSchedule.push_back(*newCycle);
153 }
154}
Guochun Shif1c154f2003-03-27 17:57:44 +0000155
Misha Brukman8baa01c2003-04-09 21:51:34 +0000156// Compute schedule and coreSchedule with the current II
157//
158bool ModuloScheduling::computeSchedule()
159{
Guochun Shif1c154f2003-03-27 17:57:44 +0000160
Misha Brukman8baa01c2003-04-09 21:51:34 +0000161 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
162 modSched_os << "start to compute schedule\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000163
Misha Brukman8baa01c2003-04-09 21:51:34 +0000164 // Loop over the ordered nodes
165 for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
166 // Try to schedule for node I
167 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
168 dumpScheduling();
169 ModuloSchedGraphNode *node = *I;
Guochun Shif1c154f2003-03-27 17:57:44 +0000170
Misha Brukman8baa01c2003-04-09 21:51:34 +0000171 // Compute whether this node has successor(s)
172 bool succ = true;
173
174 // Compute whether this node has predessor(s)
175 bool pred = true;
176
177 NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
178 if (schSucc.empty())
179 succ = false;
180 NodeVec schPred = graph.vectorConj(nodeScheduled, graph.predSet(node));
181 if (schPred.empty())
182 pred = false;
183
184 //startTime: the earliest time we will try to schedule this node
185 //endTime: the latest time we will try to schedule this node
186 int startTime, endTime;
187
188 //node's earlyStart: possible earliest time to schedule this node
189 //node's lateStart: possible latest time to schedule this node
190 node->setEarlyStart(-1);
191 node->setLateStart(9999);
192
193 //this node has predessor but no successor
194 if (!succ && pred) {
195 // This node's earlyStart is it's predessor's schedule time + the edge
196 // delay - the iteration difference* II
197 for (unsigned i = 0; i < schPred.size(); i++) {
198 ModuloSchedGraphNode *predNode = schPred[i];
199 SchedGraphEdge *edge =
200 graph.getMaxDelayEdge(predNode->getNodeId(),
201 node->getNodeId());
202 int temp =
203 predNode->getSchTime() + edge->getMinDelay() -
204 edge->getIteDiff() * II;
205 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
Guochun Shif1c154f2003-03-27 17:57:44 +0000206 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000207 startTime = node->getEarlyStart();
208 endTime = node->getEarlyStart() + II - 1;
Guochun Shif1c154f2003-03-27 17:57:44 +0000209 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000210 // This node has a successor but no predecessor
211 if (succ && !pred) {
212 for (unsigned i = 0; i < schSucc.size(); ++i) {
213 ModuloSchedGraphNode *succNode = schSucc[i];
214 SchedGraphEdge *edge =
215 graph.getMaxDelayEdge(succNode->getNodeId(),
216 node->getNodeId());
217 int temp =
218 succNode->getSchTime() - edge->getMinDelay() +
219 edge->getIteDiff() * II;
220 node->setLateStart(std::min(node->getEarlyStart(), temp));
221 }
222 startTime = node->getLateStart() - II + 1;
223 endTime = node->getLateStart();
224 }
225 // This node has both successors and predecessors
226 if (succ && pred) {
227 for (unsigned i = 0; i < schPred.size(); ++i) {
228 ModuloSchedGraphNode *predNode = schPred[i];
229 SchedGraphEdge *edge =
230 graph.getMaxDelayEdge(predNode->getNodeId(),
231 node->getNodeId());
232 int temp =
233 predNode->getSchTime() + edge->getMinDelay() -
234 edge->getIteDiff() * II;
235 node->setEarlyStart(std::max(node->getEarlyStart(), temp));
236 }
237 for (unsigned i = 0; i < schSucc.size(); ++i) {
238 ModuloSchedGraphNode *succNode = schSucc[i];
239 SchedGraphEdge *edge =
240 graph.getMaxDelayEdge(succNode->getNodeId(),
241 node->getNodeId());
242 int temp =
243 succNode->getSchTime() - edge->getMinDelay() +
244 edge->getIteDiff() * II;
245 node->setLateStart(std::min(node->getEarlyStart(), temp));
246 }
247 startTime = node->getEarlyStart();
248 endTime = std::min(node->getLateStart(),
249 node->getEarlyStart() + ((int) II) - 1);
250 }
251 //this node has no successor or predessor
252 if (!succ && !pred) {
253 node->setEarlyStart(node->getASAP());
254 startTime = node->getEarlyStart();
255 endTime = node->getEarlyStart() + II - 1;
256 }
257 //try to schedule this node based on the startTime and endTime
258 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
259 modSched_os << "scheduling the node " << (*I)->getNodeId() << "\n";
260
261 bool success =
262 this->ScheduleNode(node, startTime, endTime, nodeScheduled);
263 if (!success)
264 return false;
265 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000266 return true;
267}
268
269
Misha Brukman8baa01c2003-04-09 21:51:34 +0000270// Get the successor of the BasicBlock
271//
272BasicBlock *ModuloScheduling::getSuccBB(BasicBlock *bb)
273{
274 BasicBlock *succ_bb;
275 for (unsigned i = 0; i < II; ++i)
276 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
277 if (coreSchedule[i][j]) {
278 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000279
Misha Brukman8baa01c2003-04-09 21:51:34 +0000280 //we can get successor from the BranchInst instruction
281 //assume we only have one successor (besides itself) here
282 if (BranchInst::classof(ist)) {
283 BranchInst *bi = (BranchInst *) ist;
284 assert(bi->isConditional() &&
285 "the branchInst is not a conditional one");
286 assert(bi->getNumSuccessors() == 2
287 && " more than two successors?");
288 BasicBlock *bb1 = bi->getSuccessor(0);
289 BasicBlock *bb2 = bi->getSuccessor(1);
290 assert((bb1 == bb || bb2 == bb) &&
291 " None of its successors is itself?");
292 if (bb1 == bb)
293 succ_bb = bb2;
294 else
295 succ_bb = bb1;
296 return succ_bb;
297 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000298 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000299 assert(0 && "NO Successor?");
Guochun Shif1c154f2003-03-27 17:57:44 +0000300 return NULL;
301}
302
303
Misha Brukman8baa01c2003-04-09 21:51:34 +0000304// Get the predecessor of the BasicBlock
305//
306BasicBlock *ModuloScheduling::getPredBB(BasicBlock *bb)
307{
308 BasicBlock *pred_bb;
309 for (unsigned i = 0; i < II; ++i)
310 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
311 if (coreSchedule[i][j]) {
312 const Instruction *ist = coreSchedule[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000313
Misha Brukman8baa01c2003-04-09 21:51:34 +0000314 //we can get predecessor from the PHINode instruction
315 //assume we only have one predecessor (besides itself) here
316 if (PHINode::classof(ist)) {
317 PHINode *phi = (PHINode *) ist;
318 assert(phi->getNumIncomingValues() == 2 &&
319 " the number of incoming value is not equal to two? ");
320 BasicBlock *bb1 = phi->getIncomingBlock(0);
321 BasicBlock *bb2 = phi->getIncomingBlock(1);
322 assert((bb1 == bb || bb2 == bb) &&
323 " None of its predecessor is itself?");
324 if (bb1 == bb)
325 pred_bb = bb2;
326 else
327 pred_bb = bb1;
328 return pred_bb;
329 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000330 }
331 assert(0 && " no predecessor?");
332 return NULL;
333}
334
335
Misha Brukman8baa01c2003-04-09 21:51:34 +0000336// Construct the prologue
337//
338void ModuloScheduling::constructPrologue(BasicBlock *prologue)
339{
340
341 InstListType & prologue_ist = prologue->getInstList();
342 vvNodeType & tempSchedule_prologue =
343 *(new vector < std::vector < ModuloSchedGraphNode * >>(schedule));
344
Guochun Shif1c154f2003-03-27 17:57:44 +0000345 //compute the schedule for prologue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000346 unsigned round = 0;
347 unsigned scheduleSize = schedule.size();
348 while (round < scheduleSize / II) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000349 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000350 for (unsigned i = 0; i < scheduleSize; ++i) {
351 if (round * II + i >= scheduleSize)
352 break;
353 for (unsigned j = 0; j < schedule[i].size(); ++j) {
354 if (schedule[i][j]) {
355 assert(tempSchedule_prologue[round * II + i][j] == NULL &&
356 "table not consitent with core table");
357 // move the schedule one iteration ahead and overlap with the original
358 tempSchedule_prologue[round * II + i][j] = schedule[i][j];
359 }
360 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000361 }
362 }
363
Misha Brukman8baa01c2003-04-09 21:51:34 +0000364 // Clear the clone memory in the core schedule instructions
Guochun Shif1c154f2003-03-27 17:57:44 +0000365 clearCloneMemory();
Guochun Shif1c154f2003-03-27 17:57:44 +0000366
Misha Brukman8baa01c2003-04-09 21:51:34 +0000367 // Fill in the prologue
368 for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
369 for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
370 if (tempSchedule_prologue[i][j]) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000371
Misha Brukman8baa01c2003-04-09 21:51:34 +0000372 //get the instruction
373 Instruction *orn =
374 (Instruction *) tempSchedule_prologue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000375
Misha Brukman8baa01c2003-04-09 21:51:34 +0000376 //made a clone of it
377 Instruction *cln = cloneInstSetMemory(orn);
Guochun Shif1c154f2003-03-27 17:57:44 +0000378
Misha Brukman8baa01c2003-04-09 21:51:34 +0000379 //insert the instruction
380 prologue_ist.insert(prologue_ist.back(), cln);
381
382 //if there is PHINode in the prologue, the incoming value from itself
383 //should be removed because it is not a loop any longer
384 if (PHINode::classof(cln)) {
385 PHINode *phi = (PHINode *) cln;
386 phi->removeIncomingValue(phi->getParent());
387 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000388 }
389}
390
391
Misha Brukman8baa01c2003-04-09 21:51:34 +0000392// Construct the kernel BasicBlock
393//
394void ModuloScheduling::constructKernel(BasicBlock *prologue,
395 BasicBlock *kernel,
396 BasicBlock *epilogue)
397{
Guochun Shif1c154f2003-03-27 17:57:44 +0000398
399 //*************fill instructions in the kernel****************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000400 InstListType & kernel_ist = kernel->getInstList();
401 BranchInst *brchInst;
402 PHINode *phiInst, *phiCln;
Guochun Shif1c154f2003-03-27 17:57:44 +0000403
Misha Brukman8baa01c2003-04-09 21:51:34 +0000404 for (unsigned i = 0; i < coreSchedule.size(); ++i)
405 for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
406 if (coreSchedule[i][j]) {
407
408 // Take care of branch instruction differently with normal instructions
409 if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
410 brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
411 continue;
412 }
413 // Take care of PHINode instruction differently with normal instructions
414 if (PHINode::classof(coreSchedule[i][j]->getInst())) {
415 phiInst = (PHINode *) coreSchedule[i][j]->getInst();
416 Instruction *cln = cloneInstSetMemory(phiInst);
417 kernel_ist.insert(kernel_ist.back(), cln);
418 phiCln = (PHINode *) cln;
419 continue;
420 }
421 //for normal instructions: made a clone and insert it in the kernel_ist
422 Instruction *cln =
423 cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
424 getInst());
425 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000426 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000427 // The two incoming BasicBlock for PHINode is the prologue and the kernel
428 // (itself)
429 phiCln->setIncomingBlock(0, prologue);
430 phiCln->setIncomingBlock(1, kernel);
Guochun Shif1c154f2003-03-27 17:57:44 +0000431
Misha Brukman8baa01c2003-04-09 21:51:34 +0000432 // The incoming value for the kernel (itself) is the new value which is
433 // computed in the kernel
434 Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000435 phiCln->setIncomingValue(1, originalVal->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000436
Misha Brukman8baa01c2003-04-09 21:51:34 +0000437 // Make a clone of the branch instruction and insert it in the end
438 BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
439 kernel_ist.insert(kernel_ist.back(), cln);
Guochun Shif1c154f2003-03-27 17:57:44 +0000440
Misha Brukman8baa01c2003-04-09 21:51:34 +0000441 // delete the unconditional branch instruction, which is generated when
442 // splitting the basicBlock
443 kernel_ist.erase(--kernel_ist.end());
Guochun Shif1c154f2003-03-27 17:57:44 +0000444
Misha Brukman8baa01c2003-04-09 21:51:34 +0000445 // set the first successor to itself
446 ((BranchInst *) cln)->setSuccessor(0, kernel);
447 // set the second successor to eiplogue
448 ((BranchInst *) cln)->setSuccessor(1, epilogue);
Guochun Shif1c154f2003-03-27 17:57:44 +0000449
450 //*****change the condition*******
451
452 //get the condition instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000453 Instruction *cond = (Instruction *) cln->getCondition();
Guochun Shif1c154f2003-03-27 17:57:44 +0000454
455 //get the condition's second operand, it should be a constant
Misha Brukman8baa01c2003-04-09 21:51:34 +0000456 Value *operand = cond->getOperand(1);
Guochun Shif1c154f2003-03-27 17:57:44 +0000457 assert(ConstantSInt::classof(operand));
458
459 //change the constant in the condtion instruction
Misha Brukman8baa01c2003-04-09 21:51:34 +0000460 ConstantSInt *iteTimes =
461 ConstantSInt::get(operand->getType(),
462 ((ConstantSInt *) operand)->getValue() - II + 1);
463 cond->setOperand(1, iteTimes);
Guochun Shif1c154f2003-03-27 17:57:44 +0000464
465}
466
467
Misha Brukman8baa01c2003-04-09 21:51:34 +0000468// Construct the epilogue
469//
470void ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
471 BasicBlock *succ_bb)
472{
Guochun Shif1c154f2003-03-27 17:57:44 +0000473
Guochun Shif1c154f2003-03-27 17:57:44 +0000474 //compute the schedule for epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000475 vvNodeType & tempSchedule_epilogue =
476 *(new vector < std::vector < ModuloSchedGraphNode * >>(schedule));
477 unsigned scheduleSize = schedule.size();
478 int round = 0;
479 while (round < ceil(1.0 * scheduleSize / II) - 1) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000480 round++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000481 for (unsigned i = 0; i < scheduleSize; i++) {
482 if (i + round * II >= scheduleSize)
483 break;
484 for (unsigned j = 0; j < schedule[i].size(); j++)
485 if (schedule[i + round * II][j]) {
486 assert(tempSchedule_epilogue[i][j] == NULL
487 && "table not consitant with core table");
Guochun Shif1c154f2003-03-27 17:57:44 +0000488
Misha Brukman8baa01c2003-04-09 21:51:34 +0000489 //move the schdule one iteration behind and overlap
490 tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
491 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000492 }
493 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000494
Guochun Shif1c154f2003-03-27 17:57:44 +0000495 //fill in the epilogue
Misha Brukman8baa01c2003-04-09 21:51:34 +0000496 InstListType & epilogue_ist = epilogue->getInstList();
497 for (unsigned i = II; i < scheduleSize; i++)
498 for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
499 if (tempSchedule_epilogue[i][j]) {
500 Instruction *inst =
501 (Instruction *) tempSchedule_epilogue[i][j]->getInst();
Guochun Shif1c154f2003-03-27 17:57:44 +0000502
Misha Brukman8baa01c2003-04-09 21:51:34 +0000503 //BranchInst and PHINode should be treated differently
504 //BranchInst:unecessary, simly omitted
505 //PHINode: omitted
506 if (!BranchInst::classof(inst) && !PHINode::classof(inst)) {
507 //make a clone instruction and insert it into the epilogue
508 Instruction *cln = cloneInstSetMemory(inst);
509 epilogue_ist.push_front(cln);
510 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000511 }
512
Guochun Shif1c154f2003-03-27 17:57:44 +0000513 //*************delete the original instructions****************//
514 //to delete the original instructions, we have to make sure their use is zero
Misha Brukman8baa01c2003-04-09 21:51:34 +0000515
Guochun Shif1c154f2003-03-27 17:57:44 +0000516 //update original core instruction's uses, using its clone instread
Misha Brukman8baa01c2003-04-09 21:51:34 +0000517 for (unsigned i = 0; i < II; i++)
518 for (unsigned j = 0; j < coreSchedule[i].size(); j++) {
519 if (coreSchedule[i][j])
520 updateUseWithClone((Instruction *) coreSchedule[i][j]->getInst());
Guochun Shif1c154f2003-03-27 17:57:44 +0000521 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000522
Guochun Shif1c154f2003-03-27 17:57:44 +0000523 //erase these instructions
Misha Brukman8baa01c2003-04-09 21:51:34 +0000524 for (unsigned i = 0; i < II; i++)
525 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
526 if (coreSchedule[i][j]) {
527 Instruction *ist = (Instruction *) coreSchedule[i][j]->getInst();
528 ist->getParent()->getInstList().erase(ist);
Guochun Shif1c154f2003-03-27 17:57:44 +0000529 }
530 //**************************************************************//
531
532
533 //finally, insert an unconditional branch instruction at the end
534 epilogue_ist.push_back(new BranchInst(succ_bb));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000535
Guochun Shif1c154f2003-03-27 17:57:44 +0000536}
537
538
Misha Brukman8baa01c2003-04-09 21:51:34 +0000539//------------------------------------------------------------------------------
540//this function replace the value(instruction) ist in other instructions with
541//its latest clone i.e. after this function is called, the ist is not used
542//anywhere and it can be erased.
543//------------------------------------------------------------------------------
544void ModuloScheduling::updateUseWithClone(Instruction * ist)
545{
546
547 while (ist->use_size() > 0) {
548 bool destroyed = false;
549
Guochun Shif1c154f2003-03-27 17:57:44 +0000550 //other instruction is using this value ist
551 assert(Instruction::classof(*ist->use_begin()));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000552 Instruction *inst = (Instruction *) (*ist->use_begin());
Guochun Shif1c154f2003-03-27 17:57:44 +0000553
Misha Brukman8baa01c2003-04-09 21:51:34 +0000554 for (unsigned i = 0; i < inst->getNumOperands(); i++)
555 if (inst->getOperand(i) == ist && ist->getClone()) {
556 // if the instruction is TmpInstruction, simly delete it because it has
557 // no parent and it does not belongs to any BasicBlock
558 if (TmpInstruction::classof(inst)) {
559 delete inst;
560 destroyed = true;
561 break;
562 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000563
Misha Brukman8baa01c2003-04-09 21:51:34 +0000564 //otherwise, set the instruction's operand to the value's clone
565 inst->setOperand(i, ist->getClone());
Guochun Shif1c154f2003-03-27 17:57:44 +0000566
Misha Brukman8baa01c2003-04-09 21:51:34 +0000567 //the use from the original value ist is destroyed
568 destroyed = true;
569 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000570 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000571 if (!destroyed) {
572 //if the use can not be destroyed , something is wrong
573 inst->dump();
574 assert(0 && "this use can not be destroyed");
575 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000576 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000577
Guochun Shif1c154f2003-03-27 17:57:44 +0000578}
579
580
581//********************************************************
582//this function clear all clone mememoy
583//i.e. set all instruction's clone memory to NULL
584//*****************************************************
Misha Brukman8baa01c2003-04-09 21:51:34 +0000585void ModuloScheduling::clearCloneMemory()
586{
587 for (unsigned i = 0; i < coreSchedule.size(); i++)
588 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
589 if (coreSchedule[i][j])
590 ((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
591
Guochun Shif1c154f2003-03-27 17:57:44 +0000592}
593
594
Misha Brukman8baa01c2003-04-09 21:51:34 +0000595//******************************************************************************
596// this function make a clone of the instruction orn the cloned instruction will
597// use the orn's operands' latest clone as its operands it is done this way
598// because LLVM is in SSA form and we should use the correct value
Guochun Shif1c154f2003-03-27 17:57:44 +0000599//this fuction also update the instruction orn's latest clone memory
Misha Brukman8baa01c2003-04-09 21:51:34 +0000600//******************************************************************************
601Instruction *ModuloScheduling::cloneInstSetMemory(Instruction * orn)
602{
603 // make a clone instruction
604 Instruction *cln = orn->clone();
Guochun Shif1c154f2003-03-27 17:57:44 +0000605
Misha Brukman8baa01c2003-04-09 21:51:34 +0000606 // update the operands
607 for (unsigned k = 0; k < orn->getNumOperands(); k++) {
608 const Value *op = orn->getOperand(k);
609 if (Instruction::classof(op) && ((Instruction *) op)->getClone()) {
610 Instruction *op_inst = (Instruction *) op;
Guochun Shif1c154f2003-03-27 17:57:44 +0000611 cln->setOperand(k, op_inst->getClone());
612 }
613 }
614
Misha Brukman8baa01c2003-04-09 21:51:34 +0000615 // update clone memory
Guochun Shif1c154f2003-03-27 17:57:44 +0000616 orn->setClone(cln);
617 return cln;
618}
619
620
621
Misha Brukman8baa01c2003-04-09 21:51:34 +0000622bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
623 unsigned start, unsigned end,
624 NodeVec & nodeScheduled)
Guochun Shif1c154f2003-03-27 17:57:44 +0000625{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000626 const TargetSchedInfo & msi = target.getSchedInfo();
627 unsigned int numIssueSlots = msi.maxNumIssueTotal;
Guochun Shif1c154f2003-03-27 17:57:44 +0000628
Misha Brukman8baa01c2003-04-09 21:51:34 +0000629 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
630 modSched_os << "startTime= " << start << " endTime= " << end << "\n";
631 bool isScheduled = false;
632 for (unsigned i = start; i <= end; i++) {
633 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
634 modSched_os << " now try cycle " << i << ":" << "\n";
635 for (unsigned j = 0; j < numIssueSlots; j++) {
636 unsigned int core_i = i % II;
637 unsigned int core_j = j;
638 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
639 modSched_os << "\t Trying slot " << j << "...........";
Guochun Shif1c154f2003-03-27 17:57:44 +0000640 //check the resouce table, make sure there is no resource conflicts
Misha Brukman8baa01c2003-04-09 21:51:34 +0000641 const Instruction *instr = node->getInst();
642 MachineCodeForInstruction & tempMvec =
643 MachineCodeForInstruction::get(instr);
644 bool resourceConflict = false;
645 const TargetInstrInfo & mii = msi.getInstrInfo();
Guochun Shif1c154f2003-03-27 17:57:44 +0000646
Misha Brukman8baa01c2003-04-09 21:51:34 +0000647 if (coreSchedule.size() < core_i + 1
648 || !coreSchedule[core_i][core_j]) {
649 //this->dumpResourceUsageTable();
650 int latency = 0;
651 for (unsigned k = 0; k < tempMvec.size(); k++) {
652 MachineInstr *minstr = tempMvec[k];
653 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
654 std::vector < std::vector < resourceId_t > >resources
655 = rUsage.resourcesByCycle;
656 updateResourceTable(resources, i + latency);
657 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
658 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000659
Misha Brukman8baa01c2003-04-09 21:51:34 +0000660 //this->dumpResourceUsageTable();
Guochun Shif1c154f2003-03-27 17:57:44 +0000661
Misha Brukman8baa01c2003-04-09 21:51:34 +0000662 latency = 0;
663 if (resourceTableNegative()) {
664
665 //undo-update the resource table
666 for (unsigned k = 0; k < tempMvec.size(); k++) {
667 MachineInstr *minstr = tempMvec[k];
668 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
669 std::vector < std::vector < resourceId_t > >resources
670 = rUsage.resourcesByCycle;
671 undoUpdateResourceTable(resources, i + latency);
672 latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
673 }
674 resourceConflict = true;
675 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000676 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000677 if (!resourceConflict && !coreSchedule[core_i][core_j]) {
678 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
679 modSched_os << " OK!" << "\n";
680 modSched_os << "Node " << node->
681 getNodeId() << " is scheduleed." << "\n";
682 }
683 //schedule[i][j]=node;
684 while (schedule.size() <= i) {
685 std::vector < ModuloSchedGraphNode * >*newCycle =
686 new std::vector < ModuloSchedGraphNode * >();
687 for (unsigned k = 0; k < numIssueSlots; k++)
688 newCycle->push_back(NULL);
689 schedule.push_back(*newCycle);
690 }
691 vector < ModuloSchedGraphNode * >::iterator startIterator;
692 startIterator = schedule[i].begin();
693 schedule[i].insert(startIterator + j, node);
694 startIterator = schedule[i].begin();
695 schedule[i].erase(startIterator + j + 1);
696
697 //update coreSchedule
698 //coreSchedule[core_i][core_j]=node;
699 while (coreSchedule.size() <= core_i) {
700 std::vector < ModuloSchedGraphNode * >*newCycle =
701 new std::vector < ModuloSchedGraphNode * >();
702 for (unsigned k = 0; k < numIssueSlots; k++)
703 newCycle->push_back(NULL);
704 coreSchedule.push_back(*newCycle);
705 }
706
707 startIterator = coreSchedule[core_i].begin();
708 coreSchedule[core_i].insert(startIterator + core_j, node);
709 startIterator = coreSchedule[core_i].begin();
710 coreSchedule[core_i].erase(startIterator + core_j + 1);
711
712 node->setSchTime(i);
713 isScheduled = true;
714 nodeScheduled.push_back(node);
715
716 break;
717 } else if (coreSchedule[core_i][core_j]) {
718 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
719 modSched_os << " Slot not available " << "\n";
720 } else {
721 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
722 modSched_os << " Resource conflicts" << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000723 }
724 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000725 if (isScheduled)
726 break;
Guochun Shif1c154f2003-03-27 17:57:44 +0000727 }
728 //assert(nodeScheduled &&"this node can not be scheduled?");
729 return isScheduled;
730}
731
Misha Brukman8baa01c2003-04-09 21:51:34 +0000732
733void ModuloScheduling::updateResourceTable(Resources useResources,
734 int startCycle)
735{
736 for (unsigned i = 0; i < useResources.size(); i++) {
737 int absCycle = startCycle + i;
738 int coreCycle = absCycle % II;
739 std::vector<std::pair<int,int> > &resourceRemained =
740 resourceTable[coreCycle];
741 std::vector < unsigned int >&resourceUsed = useResources[i];
742 for (unsigned j = 0; j < resourceUsed.size(); j++) {
743 for (unsigned k = 0; k < resourceRemained.size(); k++)
744 if ((int) resourceUsed[j] == resourceRemained[k].first) {
745 resourceRemained[k].second--;
746 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000747 }
748 }
749}
750
Misha Brukman8baa01c2003-04-09 21:51:34 +0000751void ModuloScheduling::undoUpdateResourceTable(Resources useResources,
752 int startCycle)
753{
754 for (unsigned i = 0; i < useResources.size(); i++) {
755 int absCycle = startCycle + i;
756 int coreCycle = absCycle % II;
757 std::vector<std::pair<int,int> > &resourceRemained =
758 resourceTable[coreCycle];
759 std::vector < unsigned int >&resourceUsed = useResources[i];
760 for (unsigned j = 0; j < resourceUsed.size(); j++) {
761 for (unsigned k = 0; k < resourceRemained.size(); k++)
762 if ((int) resourceUsed[j] == resourceRemained[k].first) {
763 resourceRemained[k].second++;
764 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000765 }
766 }
767}
768
769
770//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000771// Function: resourceTableNegative
772// return value:
773// return false if any element in the resouceTable is negative
774// otherwise return true
775// Purpose:
Guochun Shif1c154f2003-03-27 17:57:44 +0000776
Misha Brukman8baa01c2003-04-09 21:51:34 +0000777// this function is used to determine if an instruction is eligible for
778// schedule at certain cycle
779//-----------------------------------------------------------------------
780
781
782bool ModuloScheduling::resourceTableNegative()
783{
784 assert(resourceTable.size() == (unsigned) II
785 && "resouceTable size must be equal to II");
786 bool isNegative = false;
787 for (unsigned i = 0; i < resourceTable.size(); i++)
788 for (unsigned j = 0; j < resourceTable[i].size(); j++) {
789 if (resourceTable[i][j].second < 0) {
790 isNegative = true;
791 break;
792 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000793 }
794 return isNegative;
795}
796
797
798//----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000799// Function: dumpResouceUsageTable
800// Purpose:
801// print out ResouceTable for debug
Guochun Shif1c154f2003-03-27 17:57:44 +0000802//
803//------------------------------------------------------------------------
804
Misha Brukman8baa01c2003-04-09 21:51:34 +0000805void ModuloScheduling::dumpResourceUsageTable()
806{
807 modSched_os << "dumping resource usage table" << "\n";
808 for (unsigned i = 0; i < resourceTable.size(); i++) {
809 for (unsigned j = 0; j < resourceTable[i].size(); j++)
810 modSched_os << resourceTable[i][j].
811 first << ":" << resourceTable[i][j].second << " ";
812 modSched_os << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000813 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000814
Guochun Shif1c154f2003-03-27 17:57:44 +0000815}
816
817//----------------------------------------------------------------------
818//Function: dumpSchedule
819//Purpose:
820// print out thisSchedule for debug
821//
822//-----------------------------------------------------------------------
Misha Brukman8baa01c2003-04-09 21:51:34 +0000823void ModuloScheduling::dumpSchedule(vvNodeType thisSchedule)
824{
825 const TargetSchedInfo & msi = target.getSchedInfo();
826 unsigned numIssueSlots = msi.maxNumIssueTotal;
827 for (unsigned i = 0; i < numIssueSlots; i++)
828 modSched_os << "\t#";
829 modSched_os << "\n";
830 for (unsigned i = 0; i < thisSchedule.size(); i++) {
831 modSched_os << "cycle" << i << ": ";
832 for (unsigned j = 0; j < thisSchedule[i].size(); j++)
833 if (thisSchedule[i][j] != NULL)
834 modSched_os << thisSchedule[i][j]->getNodeId() << "\t";
835 else
836 modSched_os << "\t";
837 modSched_os << "\n";
838 }
839
Guochun Shif1c154f2003-03-27 17:57:44 +0000840}
841
842
843//----------------------------------------------------
844//Function: dumpScheduling
845//Purpose:
846// print out the schedule and coreSchedule for debug
847//
848//-------------------------------------------------------
849
Misha Brukman8baa01c2003-04-09 21:51:34 +0000850void ModuloScheduling::dumpScheduling()
851{
852 modSched_os << "dump schedule:" << "\n";
853 const TargetSchedInfo & msi = target.getSchedInfo();
854 unsigned numIssueSlots = msi.maxNumIssueTotal;
855 for (unsigned i = 0; i < numIssueSlots; i++)
856 modSched_os << "\t#";
857 modSched_os << "\n";
858 for (unsigned i = 0; i < schedule.size(); i++) {
859 modSched_os << "cycle" << i << ": ";
860 for (unsigned j = 0; j < schedule[i].size(); j++)
861 if (schedule[i][j] != NULL)
862 modSched_os << schedule[i][j]->getNodeId() << "\t";
Guochun Shif1c154f2003-03-27 17:57:44 +0000863 else
Misha Brukman8baa01c2003-04-09 21:51:34 +0000864 modSched_os << "\t";
865 modSched_os << "\n";
866 }
867
868 modSched_os << "dump coreSchedule:" << "\n";
869 for (unsigned i = 0; i < numIssueSlots; i++)
870 modSched_os << "\t#";
871 modSched_os << "\n";
872 for (unsigned i = 0; i < coreSchedule.size(); i++) {
873 modSched_os << "cycle" << i << ": ";
874 for (unsigned j = 0; j < coreSchedule[i].size(); j++)
875 if (coreSchedule[i][j] != NULL)
876 modSched_os << coreSchedule[i][j]->getNodeId() << "\t";
877 else
878 modSched_os << "\t";
879 modSched_os << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000880 }
881}
882
883
884
885//---------------------------------------------------------------------------
886// Function: ModuloSchedulingPass
887//
888// Purpose:
889// Entry point for Modulo Scheduling
890// Schedules LLVM instruction
891//
892//---------------------------------------------------------------------------
893
894namespace {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000895 class ModuloSchedulingPass:public FunctionPass {
896 const TargetMachine & target;
Guochun Shif1c154f2003-03-27 17:57:44 +0000897 public:
Misha Brukman8baa01c2003-04-09 21:51:34 +0000898 ModuloSchedulingPass(const TargetMachine &T):target(T) {
899 } const char *getPassName() const {
900 return "Modulo Scheduling";
Guochun Shif1c154f2003-03-27 17:57:44 +0000901 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000902 // getAnalysisUsage - We use LiveVarInfo...
903 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
904 //AU.addRequired(FunctionLiveVarInfo::ID);
905 } bool runOnFunction(Function & F);
Guochun Shif1c154f2003-03-27 17:57:44 +0000906 };
Misha Brukman8baa01c2003-04-09 21:51:34 +0000907} // end anonymous namespace
Guochun Shif1c154f2003-03-27 17:57:44 +0000908
909
910bool ModuloSchedulingPass::runOnFunction(Function &F)
911{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000912
Guochun Shif1c154f2003-03-27 17:57:44 +0000913 //if necessary , open the output for debug purpose
Misha Brukman8baa01c2003-04-09 21:51:34 +0000914 if (ModuloSchedDebugLevel == ModuloSched_Disable)
Guochun Shif1c154f2003-03-27 17:57:44 +0000915 return false;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000916
917 if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) {
918 modSched_fb.open("moduloSchedDebugInfo.output", std::ios::out);
919 modSched_os <<
920 "******************Modula Scheduling debug information****************"
921 << "\n ";
Guochun Shif1c154f2003-03-27 17:57:44 +0000922 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000923
924 ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
Guochun Shif1c154f2003-03-27 17:57:44 +0000925 ModuloSchedulingSet ModuloSchedulingSet(*graphSet);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000926
927 if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule)
Guochun Shif1c154f2003-03-27 17:57:44 +0000928 modSched_fb.close();
Misha Brukman8baa01c2003-04-09 21:51:34 +0000929
Guochun Shif1c154f2003-03-27 17:57:44 +0000930 return false;
931}
932
933
Misha Brukman8baa01c2003-04-09 21:51:34 +0000934Pass *createModuloSchedulingPass(const TargetMachine & tgt)
935{
Guochun Shif1c154f2003-03-27 17:57:44 +0000936 return new ModuloSchedulingPass(tgt);
937}