blob: 31c99c1f407ad8abb1a681ee8e2a77098431f1af [file] [log] [blame]
Misha Brukman8baa01c2003-04-09 21:51:34 +00001//===- ModuloSchedGraph.cpp - Graph datastructure for Modulo Scheduling ---===//
2//
3//
4//===----------------------------------------------------------------------===//
5
Guochun Shif1c154f2003-03-27 17:57:44 +00006#include "llvm/CodeGen/InstrSelection.h"
Guochun Shif1c154f2003-03-27 17:57:44 +00007#include "llvm/Function.h"
Misha Brukman8baa01c2003-04-09 21:51:34 +00008#include "llvm/Instructions.h"
Guochun Shif1c154f2003-03-27 17:57:44 +00009#include "llvm/Type.h"
10#include "llvm/CodeGen/MachineCodeForInstruction.h"
11#include "llvm/CodeGen/MachineInstr.h"
Guochun Shi6fbe5fb2003-04-06 23:56:19 +000012#include "llvm/Target/TargetSchedInfo.h"
Misha Brukman8baa01c2003-04-09 21:51:34 +000013#include "Support/StringExtras.h"
14#include "Support/STLExtras.h"
15#include "ModuloSchedGraph.h"
16#include <algorithm>
17#include <math.h>
18//#include <swig.h>
Guochun Shif1c154f2003-03-27 17:57:44 +000019
20#define UNIDELAY 1
Guochun Shif1c154f2003-03-27 17:57:44 +000021
Guochun Shif1c154f2003-03-27 17:57:44 +000022extern std::ostream modSched_os;
23extern ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
24//*********************** Internal Data Structures *************************/
25
26// The following two types need to be classes, not typedefs, so we can use
27// opaque declarations in SchedGraph.h
28//
Misha Brukman8baa01c2003-04-09 21:51:34 +000029struct RefVec:public std::vector < std::pair < ModuloSchedGraphNode *, int >> {
30 typedef std::vector<std::pair<ModuloSchedGraphNode*,
31 int> >::iterator iterator;
32 typedef std::vector<std::pair<ModuloSchedGraphNode*,
33 int> >::const_iterator const_iterator;
Guochun Shif1c154f2003-03-27 17:57:44 +000034};
35
Misha Brukman8baa01c2003-04-09 21:51:34 +000036struct RegToRefVecMap:public std::hash_map < int, RefVec > {
37 typedef std::hash_map<int,RefVec>::iterator iterator;
38 typedef std::hash_map<int,RefVec>::const_iterator const_iterator;
Guochun Shif1c154f2003-03-27 17:57:44 +000039};
40
Misha Brukman8baa01c2003-04-09 21:51:34 +000041struct ValueToDefVecMap:public std::hash_map < const Instruction *, RefVec > {
42 typedef std::hash_map<const Instruction*, RefVec>::iterator iterator;
43 typedef std::hash_map<const Instruction*,
44 RefVec>::const_iterator const_iterator;
Guochun Shif1c154f2003-03-27 17:57:44 +000045};
46
Guochun Shif1c154f2003-03-27 17:57:44 +000047// class Modulo SchedGraphNode
48
49/*ctor*/
50ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned int _nodeId,
Misha Brukman8baa01c2003-04-09 21:51:34 +000051 const BasicBlock * _bb,
52 const Instruction * _inst,
53 int indexInBB,
54 const TargetMachine & target)
55:SchedGraphNodeCommon(_nodeId, _bb, indexInBB), inst(_inst)
Guochun Shif1c154f2003-03-27 17:57:44 +000056{
Misha Brukman8baa01c2003-04-09 21:51:34 +000057 if (inst) {
58 //FIXME: find the latency
59 //currently setthe latency to zero
60 latency = 0;
61 }
Guochun Shif1c154f2003-03-27 17:57:44 +000062}
Misha Brukman8baa01c2003-04-09 21:51:34 +000063
Guochun Shif1c154f2003-03-27 17:57:44 +000064//class ModuloScheGraph
65
Misha Brukman8baa01c2003-04-09 21:51:34 +000066void ModuloSchedGraph::addDummyEdges()
Guochun Shif1c154f2003-03-27 17:57:44 +000067{
68 assert(graphRoot->outEdges.size() == 0);
Misha Brukman8baa01c2003-04-09 21:51:34 +000069
70 for (const_iterator I = begin(); I != end(); ++I) {
71 ModuloSchedGraphNode *node = (ModuloSchedGraphNode *) ((*I).second);
72 assert(node != graphRoot && node != graphLeaf);
73 if (node->beginInEdges() == node->endInEdges())
74 (void) new SchedGraphEdge(graphRoot, node, SchedGraphEdge::CtrlDep,
75 SchedGraphEdge::NonDataDep, 0);
76 if (node->beginOutEdges() == node->endOutEdges())
77 (void) new SchedGraphEdge(node, graphLeaf, SchedGraphEdge::CtrlDep,
78 SchedGraphEdge::NonDataDep, 0);
79 }
Guochun Shif1c154f2003-03-27 17:57:44 +000080}
81
Misha Brukman8baa01c2003-04-09 21:51:34 +000082bool isDefinition(const Instruction *I)
Guochun Shif1c154f2003-03-27 17:57:44 +000083{
84 //if(TerminatorInst::classof(I)||FreeInst::classof(I) || StoreInst::classof(I) || CallInst::classof(I))
Misha Brukman8baa01c2003-04-09 21:51:34 +000085 if (!I->hasName())
Guochun Shif1c154f2003-03-27 17:57:44 +000086 return false;
87 else
88 return true;
89}
90
Misha Brukman8baa01c2003-04-09 21:51:34 +000091void ModuloSchedGraph::addDefUseEdges(const BasicBlock *bb)
Guochun Shif1c154f2003-03-27 17:57:44 +000092{
93 //collect def instructions, store them in vector
Guochun Shi6fbe5fb2003-04-06 23:56:19 +000094 // const TargetInstrInfo& mii = target.getInstrInfo();
Misha Brukman8baa01c2003-04-09 21:51:34 +000095 const TargetInstrInfo & mii = target.getInstrInfo();
96
97 typedef std::vector < ModuloSchedGraphNode * >DefVec;
Guochun Shif1c154f2003-03-27 17:57:44 +000098 DefVec defVec;
Misha Brukman8baa01c2003-04-09 21:51:34 +000099
Guochun Shif1c154f2003-03-27 17:57:44 +0000100 //find those def instructions
Misha Brukman8baa01c2003-04-09 21:51:34 +0000101 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; ++I) {
102 if (I->getType() != Type::VoidTy) {
103 defVec.push_back(this->getGraphNodeForInst(I));
104 }
105 }
106
107 for (unsigned int i = 0; i < defVec.size(); i++) {
108 for (Value::use_const_iterator I = defVec[i]->getInst()->use_begin();
109 I != defVec[i]->getInst()->use_end(); I++) {
110 //for each use of a def, add a flow edge from the def instruction to the ref instruction
111
112
113 const Instruction *value = defVec[i]->getInst();
114 Instruction *inst = (Instruction *) (*I);
115 ModuloSchedGraphNode *node = NULL;
116
117 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end();
118 I != E; ++I)
119 if ((const Instruction *) I == inst) {
120 node = (*this)[inst];
121 break;
122 }
123
124 assert(inst != NULL && " Use not an Instruction ?");
125
126 if (node == NULL) //inst is not an instruction in this block
Guochun Shif1c154f2003-03-27 17:57:44 +0000127 {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000128 } else {
129 // Add a flow edge from the def instruction to the ref instruction
130
131 // self loop will not happen in SSA form
132 assert(defVec[i] != node && "same node?");
133
134 // This is a true dependence, so the delay is equal to the delay of the
135 // pred node.
136 int delay = 0;
137 MachineCodeForInstruction & tempMvec =
138 MachineCodeForInstruction::get(value);
139 for (unsigned j = 0; j < tempMvec.size(); j++) {
140 MachineInstr *temp = tempMvec[j];
141 //delay +=mii.minLatency(temp->getOpCode());
142 delay = std::max(delay, mii.minLatency(temp->getOpCode()));
143 }
144
145 SchedGraphEdge *trueEdge =
146 new SchedGraphEdge(defVec[i], node, value,
147 SchedGraphEdge::TrueDep, delay);
148
149 // if the ref instruction is before the def instrution
150 // then the def instruction must be a phi instruction
151 // add an anti-dependence edge to from the ref instruction to the def
152 // instruction
153 if (node->getOrigIndexInBB() < defVec[i]->getOrigIndexInBB()) {
154 assert(PHINode::classof(inst)
155 && "the ref instruction befre def is not PHINode?");
156 trueEdge->setIteDiff(1);
157 }
158
Guochun Shif1c154f2003-03-27 17:57:44 +0000159 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000160
Misha Brukman8baa01c2003-04-09 21:51:34 +0000161 }
162 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000163}
164
Misha Brukman8baa01c2003-04-09 21:51:34 +0000165void ModuloSchedGraph::addCDEdges(const BasicBlock * bb) {
166 // find the last instruction in the basic block
167 // see if it is an branch instruction.
168 // If yes, then add an edge from each node expcept the last node to the last
169 // node
170 const Instruction *inst = &(bb->back());
171 ModuloSchedGraphNode *lastNode = (*this)[inst];
172 if (TerminatorInst::classof(inst))
173 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E;
174 I++) {
175 if (inst != I) {
176 ModuloSchedGraphNode *node = (*this)[I];
177 //use latency of 0
178 (void) new SchedGraphEdge(node, lastNode, SchedGraphEdge::CtrlDep,
179 SchedGraphEdge::NonDataDep, 0);
Guochun Shif1c154f2003-03-27 17:57:44 +0000180 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000181
182 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000183}
184
Misha Brukman8baa01c2003-04-09 21:51:34 +0000185static const int SG_LOAD_REF = 0;
Guochun Shif1c154f2003-03-27 17:57:44 +0000186static const int SG_STORE_REF = 1;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000187static const int SG_CALL_REF = 2;
Guochun Shif1c154f2003-03-27 17:57:44 +0000188
189static const unsigned int SG_DepOrderArray[][3] = {
Misha Brukman8baa01c2003-04-09 21:51:34 +0000190 {SchedGraphEdge::NonDataDep,
191 SchedGraphEdge::AntiDep,
192 SchedGraphEdge::AntiDep},
193 {SchedGraphEdge::TrueDep,
194 SchedGraphEdge::OutputDep,
195 SchedGraphEdge::TrueDep | SchedGraphEdge::OutputDep},
196 {SchedGraphEdge::TrueDep,
197 SchedGraphEdge::AntiDep | SchedGraphEdge::OutputDep,
198 SchedGraphEdge::TrueDep | SchedGraphEdge::AntiDep
199 | SchedGraphEdge::OutputDep}
Guochun Shif1c154f2003-03-27 17:57:44 +0000200};
201
202
203// Add a dependence edge between every pair of machine load/store/call
204// instructions, where at least one is a store or a call.
205// Use latency 1 just to ensure that memory operations are ordered;
206// latency does not otherwise matter (true dependences enforce that).
207//
Misha Brukman8baa01c2003-04-09 21:51:34 +0000208void ModuloSchedGraph::addMemEdges(const BasicBlock * bb) {
209
210 std::vector<ModuloSchedGraphNode*> memNodeVec;
Guochun Shif1c154f2003-03-27 17:57:44 +0000211
212 //construct the memNodeVec
Misha Brukman8baa01c2003-04-09 21:51:34 +0000213 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; ++I) {
214 if (LoadInst::classof(I) || StoreInst::classof(I)
215 || CallInst::classof(I)) {
216 ModuloSchedGraphNode *node = (*this)[(const Instruction *) I];
217 memNodeVec.push_back(node);
218 }
219 }
220
Guochun Shif1c154f2003-03-27 17:57:44 +0000221 // Instructions in memNodeVec are in execution order within the basic block,
222 // so simply look at all pairs <memNodeVec[i], memNodeVec[j: j > i]>.
223 //
Misha Brukman8baa01c2003-04-09 21:51:34 +0000224 for (unsigned im = 0, NM = memNodeVec.size(); im < NM; im++) {
225 const Instruction *fromInst = memNodeVec[im]->getInst();
226 int fromType = CallInst::classof(fromInst) ? SG_CALL_REF
227 : LoadInst::classof(fromInst) ? SG_LOAD_REF : SG_STORE_REF;
228 for (unsigned jm = im + 1; jm < NM; jm++) {
229 const Instruction *toInst = memNodeVec[jm]->getInst();
230 int toType = CallInst::classof(toInst) ? SG_CALL_REF
231 : LoadInst::classof(toInst) ? SG_LOAD_REF : SG_STORE_REF;
232 if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF) {
233 (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm],
234 SchedGraphEdge::MemoryDep,
235 SG_DepOrderArray[fromType][toType], 1);
236
237 SchedGraphEdge *edge =
238 new SchedGraphEdge(memNodeVec[jm], memNodeVec[im],
239 SchedGraphEdge::MemoryDep,
240 SG_DepOrderArray[toType][fromType], 1);
241 edge->setIteDiff(1);
242
243 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000244 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000245 }
246}
Guochun Shif1c154f2003-03-27 17:57:44 +0000247
248
249
Misha Brukman8baa01c2003-04-09 21:51:34 +0000250void ModuloSchedGraph::buildNodesforBB(const TargetMachine &target,
251 const BasicBlock *bb,
252 std::vector<ModuloSchedGraphNode*> &memNode,
253 RegToRefVecMap &regToRefVecMap,
254 ValueToDefVecMap &valueToDefVecMap)
Guochun Shif1c154f2003-03-27 17:57:44 +0000255{
Guochun Shi6fbe5fb2003-04-06 23:56:19 +0000256 //const TargetInstrInfo& mii=target.getInstrInfo();
Misha Brukman8baa01c2003-04-09 21:51:34 +0000257
Guochun Shif1c154f2003-03-27 17:57:44 +0000258 //Build graph nodes for each LLVM instruction and gather def/use info.
259 //Do both together in a single pass over all machine instructions.
Misha Brukman8baa01c2003-04-09 21:51:34 +0000260
261 int i = 0;
262 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E;
263 ++I) {
264 ModuloSchedGraphNode *node =
265 new ModuloSchedGraphNode(getNumNodes(), bb, I, i, target);
266 i++;
267 this->noteModuloSchedGraphNodeForInst(I, node);
268 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000269
270 //this function finds some info about instruction in basic block for later use
Misha Brukman8baa01c2003-04-09 21:51:34 +0000271 //findDefUseInfoAtInstr(target, node,
272 //memNode,regToRefVecMap,valueToDefVecMap);
Guochun Shif1c154f2003-03-27 17:57:44 +0000273}
274
275
Misha Brukman8baa01c2003-04-09 21:51:34 +0000276bool ModuloSchedGraph::isLoop(const BasicBlock *bb) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000277 //only if the last instruction in the basicblock is branch instruction and
278 //there is at least an option to branch itself
279
Misha Brukman8baa01c2003-04-09 21:51:34 +0000280 const Instruction *inst = &(bb->back());
281 if (BranchInst::classof(inst)) {
282 for (unsigned i = 0; i < ((BranchInst *) inst)->getNumSuccessors();
283 i++) {
284 BasicBlock *sb = ((BranchInst *) inst)->getSuccessor(i);
285 if (sb == bb)
286 return true;
287 }
288 }
289
Guochun Shif1c154f2003-03-27 17:57:44 +0000290 return false;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000291
Guochun Shif1c154f2003-03-27 17:57:44 +0000292}
Misha Brukman8baa01c2003-04-09 21:51:34 +0000293
294bool ModuloSchedGraph::isLoop() {
Guochun Shif1c154f2003-03-27 17:57:44 +0000295 //only if the last instruction in the basicblock is branch instruction and
296 //there is at least an option to branch itself
Guochun Shif1c154f2003-03-27 17:57:44 +0000297
Misha Brukman8baa01c2003-04-09 21:51:34 +0000298 assert(bbVec.size() == 1 && "only 1 basicblock in a graph");
299 const BasicBlock *bb = bbVec[0];
300 const Instruction *inst = &(bb->back());
301 if (BranchInst::classof(inst))
302 for (unsigned i = 0; i < ((BranchInst *) inst)->getNumSuccessors();
303 i++) {
304 BasicBlock *sb = ((BranchInst *) inst)->getSuccessor(i);
305 if (sb == bb)
306 return true;
Guochun Shif1c154f2003-03-27 17:57:44 +0000307 }
308
Misha Brukman8baa01c2003-04-09 21:51:34 +0000309 return false;
310
311}
312
313void ModuloSchedGraph::computeNodeASAP(const BasicBlock *bb) {
314
315 //FIXME: now assume the only backward edges come from the edges from other
316 //nodes to the phi Node so i will ignore all edges to the phi node; after
317 //this, there shall be no recurrence.
318
319 unsigned numNodes = bb->size();
320 for (unsigned i = 2; i < numNodes + 2; i++) {
321 ModuloSchedGraphNode *node = getNode(i);
322 node->setPropertyComputed(false);
323 }
324
325 for (unsigned i = 2; i < numNodes + 2; i++) {
326 ModuloSchedGraphNode *node = getNode(i);
327 node->ASAP = 0;
328 if (i == 2 || node->getNumInEdges() == 0) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000329 node->setPropertyComputed(true);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000330 continue;
Guochun Shif1c154f2003-03-27 17:57:44 +0000331 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000332 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
333 node->endInEdges(); I != E; I++) {
334 SchedGraphEdge *edge = *I;
335 ModuloSchedGraphNode *pred =
336 (ModuloSchedGraphNode *) (edge->getSrc());
337 assert(pred->getPropertyComputed()
338 && "pred node property is not computed!");
339 int temp =
340 pred->ASAP + edge->getMinDelay() -
341 edge->getIteDiff() * this->MII;
342 node->ASAP = std::max(node->ASAP, temp);
343 }
344 node->setPropertyComputed(true);
345 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000346}
347
Misha Brukman8baa01c2003-04-09 21:51:34 +0000348void ModuloSchedGraph::computeNodeALAP(const BasicBlock *bb) {
349 unsigned numNodes = bb->size();
350 int maxASAP = 0;
351 for (unsigned i = numNodes + 1; i >= 2; i--) {
352 ModuloSchedGraphNode *node = getNode(i);
353 node->setPropertyComputed(false);
354 //cerr<< " maxASAP= " <<maxASAP<<" node->ASAP= "<< node->ASAP<<"\n";
355 maxASAP = std::max(maxASAP, node->ASAP);
356 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000357
358 //cerr<<"maxASAP is "<<maxASAP<<"\n";
Misha Brukman8baa01c2003-04-09 21:51:34 +0000359
360 for (unsigned i = numNodes + 1; i >= 2; i--) {
361 ModuloSchedGraphNode *node = getNode(i);
362 node->ALAP = maxASAP;
363 for (ModuloSchedGraphNode::const_iterator I =
364 node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) {
365 SchedGraphEdge *edge = *I;
366 ModuloSchedGraphNode *succ =
367 (ModuloSchedGraphNode *) (edge->getSink());
368 if (PHINode::classof(succ->getInst()))
369 continue;
370 assert(succ->getPropertyComputed()
371 && "succ node property is not computed!");
372 int temp =
373 succ->ALAP - edge->getMinDelay() +
374 edge->getIteDiff() * this->MII;
375 node->ALAP = std::min(node->ALAP, temp);
376 }
377 node->setPropertyComputed(true);
378 }
379}
380
381void ModuloSchedGraph::computeNodeMov(const BasicBlock *bb)
382{
383 unsigned numNodes = bb->size();
384 for (unsigned i = 2; i < numNodes + 2; i++) {
385 ModuloSchedGraphNode *node = getNode(i);
386 node->mov = node->ALAP - node->ASAP;
387 assert(node->mov >= 0
388 && "move freedom for this node is less than zero? ");
389 }
390}
391
392
393void ModuloSchedGraph::computeNodeDepth(const BasicBlock * bb)
394{
395
396 unsigned numNodes = bb->size();
397 for (unsigned i = 2; i < numNodes + 2; i++) {
398 ModuloSchedGraphNode *node = getNode(i);
399 node->setPropertyComputed(false);
400 }
401
402 for (unsigned i = 2; i < numNodes + 2; i++) {
403 ModuloSchedGraphNode *node = getNode(i);
404 node->depth = 0;
405 if (i == 2 || node->getNumInEdges() == 0) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000406 node->setPropertyComputed(true);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000407 continue;
Guochun Shif1c154f2003-03-27 17:57:44 +0000408 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000409 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
410 node->endInEdges(); I != E; I++) {
411 SchedGraphEdge *edge = *I;
412 ModuloSchedGraphNode *pred =
413 (ModuloSchedGraphNode *) (edge->getSrc());
414 assert(pred->getPropertyComputed()
415 && "pred node property is not computed!");
416 int temp = pred->depth + edge->getMinDelay();
417 node->depth = std::max(node->depth, temp);
Guochun Shif1c154f2003-03-27 17:57:44 +0000418 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000419 node->setPropertyComputed(true);
420 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000421
422}
423
424
Misha Brukman8baa01c2003-04-09 21:51:34 +0000425void ModuloSchedGraph::computeNodeHeight(const BasicBlock *bb)
Guochun Shif1c154f2003-03-27 17:57:44 +0000426{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000427 unsigned numNodes = bb->size();
428 for (unsigned i = numNodes + 1; i >= 2; i--) {
429 ModuloSchedGraphNode *node = getNode(i);
430 node->setPropertyComputed(false);
431 }
432
433 for (unsigned i = numNodes + 1; i >= 2; i--) {
434 ModuloSchedGraphNode *node = getNode(i);
435 node->height = 0;
436 for (ModuloSchedGraphNode::const_iterator I =
437 node->beginOutEdges(), E = node->endOutEdges(); I != E; ++I) {
438 SchedGraphEdge *edge = *I;
439 ModuloSchedGraphNode *succ =
440 (ModuloSchedGraphNode *) (edge->getSink());
441 if (PHINode::classof(succ->getInst()))
442 continue;
443 assert(succ->getPropertyComputed()
444 && "succ node property is not computed!");
445 node->height = std::max(node->height, succ->height + edge->getMinDelay());
446
Guochun Shif1c154f2003-03-27 17:57:44 +0000447 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000448 node->setPropertyComputed(true);
449
450 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000451
452}
453
Misha Brukman8baa01c2003-04-09 21:51:34 +0000454void ModuloSchedGraph::computeNodeProperty(const BasicBlock * bb)
Guochun Shif1c154f2003-03-27 17:57:44 +0000455{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000456 //FIXME: now assume the only backward edges come from the edges from other
457 //nodes to the phi Node so i will ignore all edges to the phi node; after
458 //this, there shall be no recurrence.
459
Guochun Shif1c154f2003-03-27 17:57:44 +0000460 this->computeNodeASAP(bb);
461 this->computeNodeALAP(bb);
462 this->computeNodeMov(bb);
463 this->computeNodeDepth(bb);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000464 this->computeNodeHeight(bb);
Guochun Shif1c154f2003-03-27 17:57:44 +0000465}
466
467
468//do not consider the backedge in these two functions:
469// i.e. don't consider the edge with destination in phi node
Misha Brukman8baa01c2003-04-09 21:51:34 +0000470std::vector<ModuloSchedGraphNode*>
471ModuloSchedGraph::predSet(std::vector<ModuloSchedGraphNode*> set,
472 unsigned backEdgeSrc,
473 unsigned
474 backEdgeSink)
Guochun Shif1c154f2003-03-27 17:57:44 +0000475{
476 std::vector<ModuloSchedGraphNode*> predS;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000477 for (unsigned i = 0; i < set.size(); i++) {
478 ModuloSchedGraphNode *node = set[i];
479 for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E =
480 node->endInEdges(); I != E; I++) {
481 SchedGraphEdge *edge = *I;
482 if (edge->getSrc()->getNodeId() == backEdgeSrc
483 && edge->getSink()->getNodeId() == backEdgeSink)
484 continue;
485 ModuloSchedGraphNode *pred =
486 (ModuloSchedGraphNode *) (edge->getSrc());
487 //if pred is not in the predSet, push it in vector
488 bool alreadyInset = false;
489 for (unsigned j = 0; j < predS.size(); ++j)
490 if (predS[j]->getNodeId() == pred->getNodeId()) {
491 alreadyInset = true;
492 break;
493 }
494
495 for (unsigned j = 0; j < set.size(); ++j)
496 if (set[j]->getNodeId() == pred->getNodeId()) {
497 alreadyInset = true;
498 break;
499 }
500
501 if (!alreadyInset)
502 predS.push_back(pred);
Guochun Shif1c154f2003-03-27 17:57:44 +0000503 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000504 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000505 return predS;
506}
507
508ModuloSchedGraph::NodeVec ModuloSchedGraph::predSet(NodeVec set)
509{
510 //node number increases from 2
Misha Brukman8baa01c2003-04-09 21:51:34 +0000511 return predSet(set, 0, 0);
Guochun Shif1c154f2003-03-27 17:57:44 +0000512}
513
Misha Brukman8baa01c2003-04-09 21:51:34 +0000514std::vector <ModuloSchedGraphNode*>
515ModuloSchedGraph::predSet(ModuloSchedGraphNode *_node,
516 unsigned backEdgeSrc, unsigned backEdgeSink)
Guochun Shif1c154f2003-03-27 17:57:44 +0000517{
Guochun Shif1c154f2003-03-27 17:57:44 +0000518 std::vector<ModuloSchedGraphNode*> set;
519 set.push_back(_node);
520 return predSet(set, backEdgeSrc, backEdgeSink);
Guochun Shif1c154f2003-03-27 17:57:44 +0000521}
522
Misha Brukman8baa01c2003-04-09 21:51:34 +0000523std::vector <ModuloSchedGraphNode*>
524ModuloSchedGraph::predSet(ModuloSchedGraphNode * _node)
Guochun Shif1c154f2003-03-27 17:57:44 +0000525{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000526 return predSet(_node, 0, 0);
Guochun Shif1c154f2003-03-27 17:57:44 +0000527}
528
Misha Brukman8baa01c2003-04-09 21:51:34 +0000529std::vector<ModuloSchedGraphNode*>
530ModuloSchedGraph::succSet(std::vector<ModuloSchedGraphNode*> set,
531 unsigned src, unsigned sink)
Guochun Shif1c154f2003-03-27 17:57:44 +0000532{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000533 std::vector<ModuloSchedGraphNode*> succS;
534 for (unsigned i = 0; i < set.size(); i++) {
535 ModuloSchedGraphNode *node = set[i];
536 for (ModuloSchedGraphNode::const_iterator I =
537 node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) {
538 SchedGraphEdge *edge = *I;
539 if (edge->getSrc()->getNodeId() == src
540 && edge->getSink()->getNodeId() == sink)
541 continue;
542 ModuloSchedGraphNode *succ =
543 (ModuloSchedGraphNode *) (edge->getSink());
544 //if pred is not in the predSet, push it in vector
545 bool alreadyInset = false;
546 for (unsigned j = 0; j < succS.size(); j++)
547 if (succS[j]->getNodeId() == succ->getNodeId()) {
548 alreadyInset = true;
549 break;
550 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000551
Misha Brukman8baa01c2003-04-09 21:51:34 +0000552 for (unsigned j = 0; j < set.size(); j++)
553 if (set[j]->getNodeId() == succ->getNodeId()) {
554 alreadyInset = true;
555 break;
556 }
557 if (!alreadyInset)
558 succS.push_back(succ);
Guochun Shif1c154f2003-03-27 17:57:44 +0000559 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000560 }
561 return succS;
Guochun Shif1c154f2003-03-27 17:57:44 +0000562}
563
564ModuloSchedGraph::NodeVec ModuloSchedGraph::succSet(NodeVec set)
565{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000566 return succSet(set, 0, 0);
Guochun Shif1c154f2003-03-27 17:57:44 +0000567}
568
569
Misha Brukman8baa01c2003-04-09 21:51:34 +0000570std::vector<ModuloSchedGraphNode*>
571ModuloSchedGraph::succSet(ModuloSchedGraphNode *_node,
572 unsigned src, unsigned sink)
Guochun Shif1c154f2003-03-27 17:57:44 +0000573{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000574 std::vector<ModuloSchedGraphNode*>set;
Guochun Shif1c154f2003-03-27 17:57:44 +0000575 set.push_back(_node);
576 return succSet(set, src, sink);
Guochun Shif1c154f2003-03-27 17:57:44 +0000577}
578
Misha Brukman8baa01c2003-04-09 21:51:34 +0000579std::vector<ModuloSchedGraphNode*>
580ModuloSchedGraph::succSet(ModuloSchedGraphNode * _node)
Guochun Shif1c154f2003-03-27 17:57:44 +0000581{
582 return succSet(_node, 0, 0);
583}
584
Misha Brukman8baa01c2003-04-09 21:51:34 +0000585SchedGraphEdge *ModuloSchedGraph::getMaxDelayEdge(unsigned srcId,
586 unsigned sinkId)
Guochun Shif1c154f2003-03-27 17:57:44 +0000587{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000588 ModuloSchedGraphNode *node = getNode(srcId);
589 SchedGraphEdge *maxDelayEdge = NULL;
590 int maxDelay = -1;
591 for (ModuloSchedGraphNode::const_iterator I = node->beginOutEdges(), E =
592 node->endOutEdges(); I != E; I++) {
593 SchedGraphEdge *edge = *I;
594 if (edge->getSink()->getNodeId() == sinkId)
595 if (edge->getMinDelay() > maxDelay) {
596 maxDelayEdge = edge;
597 maxDelay = edge->getMinDelay();
598 }
599 }
600 assert(maxDelayEdge != NULL && "no edge between the srcId and sinkId?");
Guochun Shif1c154f2003-03-27 17:57:44 +0000601 return maxDelayEdge;
602}
603
604void ModuloSchedGraph::dumpCircuits()
605{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000606 modSched_os << "dumping circuits for graph: " << "\n";
607 int j = -1;
608 while (circuits[++j][0] != 0) {
609 int k = -1;
610 while (circuits[j][++k] != 0)
611 modSched_os << circuits[j][k] << "\t";
612 modSched_os << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000613 }
614}
615
Misha Brukman8baa01c2003-04-09 21:51:34 +0000616void ModuloSchedGraph::dumpSet(std::vector < ModuloSchedGraphNode * >set)
Guochun Shif1c154f2003-03-27 17:57:44 +0000617{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000618 for (unsigned i = 0; i < set.size(); i++)
619 modSched_os << set[i]->getNodeId() << "\t";
620 modSched_os << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000621}
622
Misha Brukman8baa01c2003-04-09 21:51:34 +0000623std::vector<ModuloSchedGraphNode*>
624ModuloSchedGraph::vectorUnion(std::vector<ModuloSchedGraphNode*> set1,
625 std::vector<ModuloSchedGraphNode*> set2)
Guochun Shif1c154f2003-03-27 17:57:44 +0000626{
627 std::vector<ModuloSchedGraphNode*> unionVec;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000628 for (unsigned i = 0; i < set1.size(); i++)
Guochun Shif1c154f2003-03-27 17:57:44 +0000629 unionVec.push_back(set1[i]);
Misha Brukman8baa01c2003-04-09 21:51:34 +0000630 for (unsigned j = 0; j < set2.size(); j++) {
631 bool inset = false;
632 for (unsigned i = 0; i < unionVec.size(); i++)
633 if (set2[j] == unionVec[i])
634 inset = true;
635 if (!inset)
636 unionVec.push_back(set2[j]);
Guochun Shif1c154f2003-03-27 17:57:44 +0000637 }
638 return unionVec;
639}
Misha Brukman8baa01c2003-04-09 21:51:34 +0000640
641std::vector<ModuloSchedGraphNode*>
642ModuloSchedGraph::vectorConj(std::vector<ModuloSchedGraphNode*> set1,
643 std::vector<ModuloSchedGraphNode*> set2)
Guochun Shif1c154f2003-03-27 17:57:44 +0000644{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000645 std::vector<ModuloSchedGraphNode*> conjVec;
646 for (unsigned i = 0; i < set1.size(); i++)
647 for (unsigned j = 0; j < set2.size(); j++)
648 if (set1[i] == set2[j])
649 conjVec.push_back(set1[i]);
650 return conjVec;
Guochun Shif1c154f2003-03-27 17:57:44 +0000651}
652
Misha Brukman8baa01c2003-04-09 21:51:34 +0000653ModuloSchedGraph::NodeVec ModuloSchedGraph::vectorSub(NodeVec set1,
654 NodeVec set2)
Guochun Shif1c154f2003-03-27 17:57:44 +0000655{
656 NodeVec newVec;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000657 for (NodeVec::iterator I = set1.begin(); I != set1.end(); I++) {
658 bool inset = false;
659 for (NodeVec::iterator II = set2.begin(); II != set2.end(); II++)
660 if ((*I)->getNodeId() == (*II)->getNodeId()) {
661 inset = true;
662 break;
663 }
664 if (!inset)
665 newVec.push_back(*I);
Guochun Shif1c154f2003-03-27 17:57:44 +0000666 }
667 return newVec;
668}
Guochun Shif1c154f2003-03-27 17:57:44 +0000669
Misha Brukman8baa01c2003-04-09 21:51:34 +0000670void ModuloSchedGraph::orderNodes() {
671 oNodes.clear();
672
673 std::vector < ModuloSchedGraphNode * >set;
674 const BasicBlock *bb = bbVec[0];
675 unsigned numNodes = bb->size();
676
677 //first order all the sets
678 int j = -1;
679 int totalDelay = -1;
680 int preDelay = -1;
681 while (circuits[++j][0] != 0) {
682 int k = -1;
683 preDelay = totalDelay;
684
685 while (circuits[j][++k] != 0) {
686 ModuloSchedGraphNode *node = getNode(circuits[j][k]);
Guochun Shif1c154f2003-03-27 17:57:44 +0000687 unsigned nextNodeId;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000688 nextNodeId =
689 circuits[j][k + 1] != 0 ? circuits[j][k + 1] : circuits[j][0];
690 SchedGraphEdge *edge = getMaxDelayEdge(circuits[j][k], nextNodeId);
Guochun Shif1c154f2003-03-27 17:57:44 +0000691 totalDelay += edge->getMinDelay();
692 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000693 if (preDelay != -1 && totalDelay > preDelay) {
Guochun Shif1c154f2003-03-27 17:57:44 +0000694 //swap circuits[j][] and cuicuits[j-1][]
695 unsigned temp[MAXNODE];
Misha Brukman8baa01c2003-04-09 21:51:34 +0000696 for (int k = 0; k < MAXNODE; k++) {
697 temp[k] = circuits[j - 1][k];
698 circuits[j - 1][k] = circuits[j][k];
699 circuits[j][k] = temp[k];
Guochun Shif1c154f2003-03-27 17:57:44 +0000700 }
701 //restart
Misha Brukman8baa01c2003-04-09 21:51:34 +0000702 j = -1;
Guochun Shif1c154f2003-03-27 17:57:44 +0000703 }
704 }
705
706 //build the first set
707 int backEdgeSrc;
708 int backEdgeSink;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000709 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
710 modSched_os << "building the first set" << "\n";
711 int setSeq = -1;
712 int k = -1;
Guochun Shif1c154f2003-03-27 17:57:44 +0000713 setSeq++;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000714 while (circuits[setSeq][++k] != 0)
Guochun Shif1c154f2003-03-27 17:57:44 +0000715 set.push_back(getNode(circuits[setSeq][k]));
Misha Brukman8baa01c2003-04-09 21:51:34 +0000716 if (circuits[setSeq][0] != 0) {
717 backEdgeSrc = circuits[setSeq][k - 1];
718 backEdgeSink = circuits[setSeq][0];
Guochun Shif1c154f2003-03-27 17:57:44 +0000719 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000720 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
721 modSched_os << "the first set is:";
Guochun Shif1c154f2003-03-27 17:57:44 +0000722 dumpSet(set);
723 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000724 //implement the ordering algorithm
Misha Brukman8baa01c2003-04-09 21:51:34 +0000725 enum OrderSeq { bottom_up, top_down };
Guochun Shif1c154f2003-03-27 17:57:44 +0000726 OrderSeq order;
727 std::vector<ModuloSchedGraphNode*> R;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000728 while (!set.empty()) {
729 std::vector < ModuloSchedGraphNode * >pset = predSet(oNodes);
730 std::vector < ModuloSchedGraphNode * >sset = succSet(oNodes);
731
732 if (!pset.empty() && !vectorConj(pset, set).empty()) {
733 R = vectorConj(pset, set);
734 order = bottom_up;
735 } else if (!sset.empty() && !vectorConj(sset, set).empty()) {
736 R = vectorConj(sset, set);
737 order = top_down;
738 } else {
739 int maxASAP = -1;
740 int position = -1;
741 for (unsigned i = 0; i < set.size(); i++) {
742 int temp = set[i]->getASAP();
743 if (temp > maxASAP) {
744 maxASAP = temp;
745 position = i;
746 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000747 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000748 R.push_back(set[position]);
749 order = bottom_up;
750 }
751
752 while (!R.empty()) {
753 if (order == top_down) {
754 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
755 modSched_os << "in top_down round" << "\n";
756 while (!R.empty()) {
757 int maxHeight = -1;
758 NodeVec::iterator chosenI;
759 for (NodeVec::iterator I = R.begin(); I != R.end(); I++) {
760 int temp = (*I)->height;
761 if ((temp > maxHeight)
762 || (temp == maxHeight && (*I)->mov <= (*chosenI)->mov)) {
763
764 if ((temp > maxHeight)
765 || (temp == maxHeight && (*I)->mov < (*chosenI)->mov)) {
766 maxHeight = temp;
767 chosenI = I;
768 continue;
769 }
770 //possible case: instruction A and B has the same height and mov,
771 //but A has dependence to B e.g B is the branch instruction in the
772 //end, or A is the phi instruction at the beginning
773 if ((*I)->mov == (*chosenI)->mov)
774 for (ModuloSchedGraphNode::const_iterator oe =
775 (*I)->beginOutEdges(), end = (*I)->endOutEdges();
776 oe != end; oe++) {
777 if ((*oe)->getSink() == (*chosenI)) {
778 maxHeight = temp;
779 chosenI = I;
780 continue;
781 }
782 }
783 }
784 }
785 ModuloSchedGraphNode *mu = *chosenI;
786 oNodes.push_back(mu);
787 R.erase(chosenI);
788 std::vector<ModuloSchedGraphNode*> succ_mu =
789 succSet(mu, backEdgeSrc, backEdgeSink);
790 std::vector<ModuloSchedGraphNode*> comm =
791 vectorConj(succ_mu, set);
792 comm = vectorSub(comm, oNodes);
793 R = vectorUnion(comm, R);
794 }
795 order = bottom_up;
796 R = vectorConj(predSet(oNodes), set);
797 } else {
798 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
799 modSched_os << "in bottom up round" << "\n";
800 while (!R.empty()) {
801 int maxDepth = -1;
802 NodeVec::iterator chosenI;
803 for (NodeVec::iterator I = R.begin(); I != R.end(); I++) {
804 int temp = (*I)->depth;
805 if ((temp > maxDepth)
806 || (temp == maxDepth && (*I)->mov < (*chosenI)->mov)) {
807 maxDepth = temp;
808 chosenI = I;
809 }
810 }
811 ModuloSchedGraphNode *mu = *chosenI;
812 oNodes.push_back(mu);
813 R.erase(chosenI);
814 std::vector<ModuloSchedGraphNode*> pred_mu =
815 predSet(mu, backEdgeSrc, backEdgeSink);
816 std::vector<ModuloSchedGraphNode*> comm =
817 vectorConj(pred_mu, set);
818 comm = vectorSub(comm, oNodes);
819 R = vectorUnion(comm, R);
820 }
821 order = top_down;
822 R = vectorConj(succSet(oNodes), set);
Guochun Shif1c154f2003-03-27 17:57:44 +0000823 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000824 }
825 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
826 modSched_os << "order finished" << "\n";
827 modSched_os << "dumping the ordered nodes: " << "\n";
828 dumpSet(oNodes);
829 dumpCircuits();
830 }
831 //create a new set
832 //FIXME: the nodes between onodes and this circuit should also be include in
833 //this set
834 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
835 modSched_os << "building the next set" << "\n";
836 set.clear();
837 int k = -1;
838 setSeq++;
839 while (circuits[setSeq][++k] != 0)
840 set.push_back(getNode(circuits[setSeq][k]));
841 if (circuits[setSeq][0] != 0) {
842 backEdgeSrc = circuits[setSeq][k - 1];
843 backEdgeSink = circuits[setSeq][0];
844 }
845 if (set.empty()) {
846 //no circuits any more
847 //collect all other nodes
848 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
849 modSched_os << "no circuits any more, collect the rest nodes" <<
850 "\n";
851 for (unsigned i = 2; i < numNodes + 2; i++) {
852 bool inset = false;
853 for (unsigned j = 0; j < oNodes.size(); j++)
854 if (oNodes[j]->getNodeId() == i) {
855 inset = true;
856 break;
857 }
858 if (!inset)
859 set.push_back(getNode(i));
Guochun Shif1c154f2003-03-27 17:57:44 +0000860 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000861 }
862 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
863 modSched_os << "next set is: " << "\n";
864 dumpSet(set);
865 }
866 } //while(!set.empty())
867
Guochun Shif1c154f2003-03-27 17:57:44 +0000868}
869
870
871
872
873
874
Misha Brukman8baa01c2003-04-09 21:51:34 +0000875void ModuloSchedGraph::buildGraph(const TargetMachine & target)
Guochun Shif1c154f2003-03-27 17:57:44 +0000876{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000877 const BasicBlock *bb = bbVec[0];
Guochun Shif1c154f2003-03-27 17:57:44 +0000878
Misha Brukman8baa01c2003-04-09 21:51:34 +0000879 assert(bbVec.size() == 1 && "only handling a single basic block here");
Guochun Shif1c154f2003-03-27 17:57:44 +0000880
881 // Use this data structure to note all machine operands that compute
882 // ordinary LLVM values. These must be computed defs (i.e., instructions).
883 // Note that there may be multiple machine instructions that define
884 // each Value.
885 ValueToDefVecMap valueToDefVecMap;
886
887 // Use this data structure to note all memory instructions.
888 // We use this to add memory dependence edges without a second full walk.
889 //
890 // vector<const Instruction*> memVec;
Misha Brukman8baa01c2003-04-09 21:51:34 +0000891 std::vector < ModuloSchedGraphNode * >memNodeVec;
Guochun Shif1c154f2003-03-27 17:57:44 +0000892
Misha Brukman8baa01c2003-04-09 21:51:34 +0000893 // Use this data structure to note any uses or definitions of
Guochun Shif1c154f2003-03-27 17:57:44 +0000894 // machine registers so we can add edges for those later without
895 // extra passes over the nodes.
896 // The vector holds an ordered list of references to the machine reg,
897 // ordered according to control-flow order. This only works for a
898 // single basic block, hence the assertion. Each reference is identified
899 // by the pair: <node, operand-number>.
900 //
901 RegToRefVecMap regToRefVecMap;
Guochun Shif1c154f2003-03-27 17:57:44 +0000902
903
Misha Brukman8baa01c2003-04-09 21:51:34 +0000904
905 // Make a dummy root node. We'll add edges to the real roots later.
906 graphRoot = new ModuloSchedGraphNode(0, NULL, NULL, -1, target);
907 graphLeaf = new ModuloSchedGraphNode(1, NULL, NULL, -1, target);
908
909 //----------------------------------------------------------------
910 // First add nodes for all the LLVM instructions in the basic block because
911 // this greatly simplifies identifying which edges to add. Do this one VM
912 // instruction at a time since the ModuloSchedGraphNode needs that.
Guochun Shif1c154f2003-03-27 17:57:44 +0000913 // Also, remember the load/store instructions to add memory deps later.
914 //----------------------------------------------------------------
915
916 //FIXME:if there is call instruction, then we shall quit somewhere
917 // currently we leave call instruction and continue construct graph
918
919 //dump only the blocks which are from loops
920
921
Misha Brukman8baa01c2003-04-09 21:51:34 +0000922 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
Guochun Shif1c154f2003-03-27 17:57:44 +0000923 this->dump(bb);
924
Misha Brukman8baa01c2003-04-09 21:51:34 +0000925 if (!isLoop(bb)) {
926 modSched_os << " dumping non-loop BB:\n";
Guochun Shif1c154f2003-03-27 17:57:44 +0000927 dump(bb);
928 }
Misha Brukman8baa01c2003-04-09 21:51:34 +0000929 if (isLoop(bb)) {
930 buildNodesforBB(target, bb, memNodeVec, regToRefVecMap,
931 valueToDefVecMap);
932
933 this->addDefUseEdges(bb);
934 this->addCDEdges(bb);
935 this->addMemEdges(bb);
936
937 //this->dump();
938
939 int ResII = this->computeResII(bb);
940 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
941 modSched_os << "ResII is " << ResII << "\n";;
942 int RecII = this->computeRecII(bb);
943 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
944 modSched_os << "RecII is " << RecII << "\n";
945
946 this->MII = std::max(ResII, RecII);
947
948 this->computeNodeProperty(bb);
949 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
950 this->dumpNodeProperty();
951
952 this->orderNodes();
953
954 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
955 this->dump();
956 //this->instrScheduling();
957
958 //this->dumpScheduling();
959 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000960}
961
Misha Brukman8baa01c2003-04-09 21:51:34 +0000962ModuloSchedGraphNode *ModuloSchedGraph::getNode(const unsigned nodeId) const
Guochun Shif1c154f2003-03-27 17:57:44 +0000963{
Misha Brukman8baa01c2003-04-09 21:51:34 +0000964 for (const_iterator I = begin(), E = end(); I != E; I++)
965 if ((*I).second->getNodeId() == nodeId)
966 return (ModuloSchedGraphNode *) (*I).second;
Guochun Shif1c154f2003-03-27 17:57:44 +0000967 return NULL;
968}
969
Misha Brukman8baa01c2003-04-09 21:51:34 +0000970int ModuloSchedGraph::computeRecII(const BasicBlock *bb)
Guochun Shif1c154f2003-03-27 17:57:44 +0000971{
972
Misha Brukman8baa01c2003-04-09 21:51:34 +0000973 int RecII = 0;
Guochun Shif1c154f2003-03-27 17:57:44 +0000974
975 //os<<"begining computerRecII()"<<"\n";
976
977
Misha Brukman8baa01c2003-04-09 21:51:34 +0000978 //FIXME: only deal with circuits starting at the first node: the phi node
979 //nodeId=2;
Guochun Shif1c154f2003-03-27 17:57:44 +0000980
981 //search all elementary circuits in the dependance graph
982 //assume maximum number of nodes is MAXNODE
Misha Brukman8baa01c2003-04-09 21:51:34 +0000983
Guochun Shif1c154f2003-03-27 17:57:44 +0000984 unsigned path[MAXNODE];
985 unsigned stack[MAXNODE][MAXNODE];
986
987
Misha Brukman8baa01c2003-04-09 21:51:34 +0000988 for (int j = 0; j < MAXNODE; j++) {
989 path[j] = 0;
990 for (int k = 0; k < MAXNODE; k++)
991 stack[j][k] = 0;
992 }
Guochun Shif1c154f2003-03-27 17:57:44 +0000993 //in our graph, the node number starts at 2
994
995 //number of nodes, because each instruction will result in one node
Misha Brukman8baa01c2003-04-09 21:51:34 +0000996 const unsigned numNodes = bb->size();
Guochun Shif1c154f2003-03-27 17:57:44 +0000997
Misha Brukman8baa01c2003-04-09 21:51:34 +0000998 int i = 0;
999 path[i] = 2;
Guochun Shif1c154f2003-03-27 17:57:44 +00001000
Misha Brukman8baa01c2003-04-09 21:51:34 +00001001 ModuloSchedGraphNode *initNode = getNode(path[0]);
1002 unsigned initNodeId = initNode->getNodeId();
1003 ModuloSchedGraphNode *currentNode = initNode;
Guochun Shif1c154f2003-03-27 17:57:44 +00001004
Misha Brukman8baa01c2003-04-09 21:51:34 +00001005 while (currentNode != NULL) {
1006 unsigned currentNodeId = currentNode->getNodeId();
1007 // modSched_os<<"current node is "<<currentNodeId<<"\n";
Guochun Shif1c154f2003-03-27 17:57:44 +00001008
Misha Brukman8baa01c2003-04-09 21:51:34 +00001009 ModuloSchedGraphNode *nextNode = NULL;
1010 for (ModuloSchedGraphNode::const_iterator I =
1011 currentNode->beginOutEdges(), E = currentNode->endOutEdges();
1012 I != E; I++) {
1013 //modSched_os <<" searching in outgoint edges of node
1014 //"<<currentNodeId<<"\n";
1015 unsigned nodeId = ((SchedGraphEdge *) * I)->getSink()->getNodeId();
1016 bool inpath = false, instack = false;
1017 int k;
Guochun Shif1c154f2003-03-27 17:57:44 +00001018
Misha Brukman8baa01c2003-04-09 21:51:34 +00001019 //modSched_os<<"nodeId is "<<nodeId<<"\n";
Guochun Shif1c154f2003-03-27 17:57:44 +00001020
Misha Brukman8baa01c2003-04-09 21:51:34 +00001021 k = -1;
1022 while (path[++k] != 0)
1023 if (nodeId == path[k]) {
1024 inpath = true;
1025 break;
1026 }
Guochun Shif1c154f2003-03-27 17:57:44 +00001027
Misha Brukman8baa01c2003-04-09 21:51:34 +00001028 k = -1;
1029 while (stack[i][++k] != 0)
1030 if (nodeId == stack[i][k]) {
1031 instack = true;
1032 break;
1033 }
Guochun Shif1c154f2003-03-27 17:57:44 +00001034
Misha Brukman8baa01c2003-04-09 21:51:34 +00001035 if (nodeId > currentNodeId && !inpath && !instack) {
1036 nextNode =
1037 (ModuloSchedGraphNode *) ((SchedGraphEdge *) * I)->getSink();
1038 break;
1039 }
Guochun Shif1c154f2003-03-27 17:57:44 +00001040 }
Misha Brukman8baa01c2003-04-09 21:51:34 +00001041
1042 if (nextNode != NULL) {
1043 //modSched_os<<"find the next Node "<<nextNode->getNodeId()<<"\n";
1044
1045 int j = 0;
1046 while (stack[i][j] != 0)
1047 j++;
1048 stack[i][j] = nextNode->getNodeId();
1049
1050 i++;
1051 path[i] = nextNode->getNodeId();
1052 currentNode = nextNode;
1053 } else {
1054 //modSched_os<<"no expansion any more"<<"\n";
1055 //confirmCircuit();
1056 for (ModuloSchedGraphNode::const_iterator I =
1057 currentNode->beginOutEdges(), E = currentNode->endOutEdges();
1058 I != E; I++) {
1059 unsigned nodeId = ((SchedGraphEdge *) * I)->getSink()->getNodeId();
1060 if (nodeId == initNodeId) {
1061
1062 int j = -1;
1063 while (circuits[++j][0] != 0);
1064 for (int k = 0; k < MAXNODE; k++)
1065 circuits[j][k] = path[k];
1066
1067 }
1068 }
1069 //remove this node in the path and clear the corresponding entries in the
1070 //stack
1071 path[i] = 0;
1072 int j = 0;
1073 for (j = 0; j < MAXNODE; j++)
1074 stack[i][j] = 0;
1075 i--;
1076 currentNode = getNode(path[i]);
1077 }
1078 if (i == 0) {
1079
1080 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1081 modSched_os << "circuits found are: " << "\n";
1082 int j = -1;
1083 while (circuits[++j][0] != 0) {
1084 int k = -1;
1085 while (circuits[j][++k] != 0)
1086 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1087 modSched_os << circuits[j][k] << "\t";
1088 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1089 modSched_os << "\n";
1090
1091 //for this circuit, compute the sum of all edge delay
1092 int sumDelay = 0;
1093 k = -1;
1094 while (circuits[j][++k] != 0) {
1095 //ModuloSchedGraphNode* node =getNode(circuits[j][k]);
1096 unsigned nextNodeId;
1097 nextNodeId =
1098 circuits[j][k + 1] !=
1099 0 ? circuits[j][k + 1] : circuits[j][0];
1100
1101 /*
1102 for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(),
1103 E=node->endOutEdges();I !=E; I++)
1104 {
1105 SchedGraphEdge* edge= *I;
1106 if(edge->getSink()->getNodeId() == nextNodeId)
1107 {sumDelay += edge->getMinDelay();break;}
1108 }
1109 */
1110
1111 sumDelay +=
1112 getMaxDelayEdge(circuits[j][k], nextNodeId)->getMinDelay();
1113
1114 }
1115 // assume we have distance 1, in this case the sumDelay is RecII
1116 // this is correct for SSA form only
1117 //
1118 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1119 modSched_os << "The total Delay in the circuit is " << sumDelay
1120 << "\n";
1121
1122 RecII = RecII > sumDelay ? RecII : sumDelay;
1123
1124 }
1125 return RecII;
1126 }
1127
1128 }
1129
Guochun Shif1c154f2003-03-27 17:57:44 +00001130 return -1;
1131}
1132
Misha Brukman8baa01c2003-04-09 21:51:34 +00001133void ModuloSchedGraph::addResourceUsage(std::vector<std::pair<int,int> > &ruVec,
1134 int rid)
1135{
1136 //modSched_os<<"\nadding a resouce , current resouceUsage vector size is
1137 //"<<ruVec.size()<<"\n";
1138 bool alreadyExists = false;
1139 for (unsigned i = 0; i < ruVec.size(); i++) {
1140 if (rid == ruVec[i].first) {
Guochun Shif1c154f2003-03-27 17:57:44 +00001141 ruVec[i].second++;
Misha Brukman8baa01c2003-04-09 21:51:34 +00001142 alreadyExists = true;
Guochun Shif1c154f2003-03-27 17:57:44 +00001143 break;
1144 }
1145 }
Misha Brukman8baa01c2003-04-09 21:51:34 +00001146 if (!alreadyExists)
1147 ruVec.push_back(std::make_pair(rid, 1));
Guochun Shif1c154f2003-03-27 17:57:44 +00001148 //modSched_os<<"current resouceUsage vector size is "<<ruVec.size()<<"\n";
1149
1150}
Misha Brukman8baa01c2003-04-09 21:51:34 +00001151void ModuloSchedGraph::dumpResourceUsage(std::vector<std::pair<int,int> > &ru)
Guochun Shif1c154f2003-03-27 17:57:44 +00001152{
Misha Brukman8baa01c2003-04-09 21:51:34 +00001153 TargetSchedInfo & msi = (TargetSchedInfo &) target.getSchedInfo();
1154
1155 std::vector<std::pair<int,int>> resourceNumVector = msi.resourceNumVector;
1156 modSched_os << "resourceID\t" << "resourceNum" << "\n";
1157 for (unsigned i = 0; i < resourceNumVector.size(); i++)
1158 modSched_os << resourceNumVector[i].
1159 first << "\t" << resourceNumVector[i].second << "\n";
1160
1161 modSched_os << " maxNumIssueTotal(issue slot in one cycle) = " << msi.
1162 maxNumIssueTotal << "\n";
1163 modSched_os << "resourceID\t resourceUsage\t ResourceNum" << "\n";
1164 for (unsigned i = 0; i < ru.size(); i++) {
1165 modSched_os << ru[i].first << "\t" << ru[i].second;
1166 const unsigned resNum = msi.getCPUResourceNum(ru[i].first);
1167 modSched_os << "\t" << resNum << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +00001168 }
1169}
1170
Misha Brukman8baa01c2003-04-09 21:51:34 +00001171int ModuloSchedGraph::computeResII(const BasicBlock * bb)
Guochun Shif1c154f2003-03-27 17:57:44 +00001172{
Misha Brukman8baa01c2003-04-09 21:51:34 +00001173
1174 const TargetInstrInfo & mii = target.getInstrInfo();
1175 const TargetSchedInfo & msi = target.getSchedInfo();
1176
Guochun Shif1c154f2003-03-27 17:57:44 +00001177 int ResII;
Misha Brukman8baa01c2003-04-09 21:51:34 +00001178 std::vector<std::pair<int,int>> resourceUsage;
1179 //pair<int resourceid, int resourceUsageTimes_in_the_whole_block>
1180
1181 //FIXME: number of functional units the target machine can provide should be
1182 //get from Target here I temporary hardcode it
1183
1184 for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E;
1185 I++) {
1186 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
1187 modSched_os << "machine instruction for llvm instruction( node " <<
1188 getGraphNodeForInst(I)->getNodeId() << ")" << "\n";
1189 modSched_os << "\t" << *I;
Guochun Shif1c154f2003-03-27 17:57:44 +00001190 }
Misha Brukman8baa01c2003-04-09 21:51:34 +00001191 MachineCodeForInstruction & tempMvec =
1192 MachineCodeForInstruction::get(I);
1193 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1194 modSched_os << "size =" << tempMvec.size() << "\n";
1195 for (unsigned i = 0; i < tempMvec.size(); i++) {
1196 MachineInstr *minstr = tempMvec[i];
1197
1198 unsigned minDelay = mii.minLatency(minstr->getOpCode());
1199 InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
1200 InstrClassRUsage classRUsage =
1201 msi.getClassRUsage(mii.getSchedClass(minstr->getOpCode()));
1202 unsigned totCycles = classRUsage.totCycles;
1203
1204 std::vector<std::vector<resourceId_t>> resources =rUsage.resourcesByCycle;
1205 assert(totCycles == resources.size());
1206 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1207 modSched_os << "resources Usage for this Instr(totCycles=" <<
1208 totCycles << ",mindLatency=" << mii.minLatency(minstr->
1209 getOpCode()) <<
1210 "): " << *minstr << "\n";
1211 for (unsigned j = 0; j < resources.size(); j++) {
1212 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1213 modSched_os << "cycle " << j << ": ";
1214 for (unsigned k = 0; k < resources[j].size(); k++) {
1215 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1216 modSched_os << "\t" << resources[j][k];
1217 addResourceUsage(resourceUsage, resources[j][k]);
1218 }
1219 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
1220 modSched_os << "\n";
1221 }
1222 }
1223 }
1224 if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
Guochun Shif1c154f2003-03-27 17:57:44 +00001225 this->dumpResourceUsage(resourceUsage);
1226
1227 //compute ResII
Misha Brukman8baa01c2003-04-09 21:51:34 +00001228 ResII = 0;
1229 int issueSlots = msi.maxNumIssueTotal;
1230 for (unsigned i = 0; i < resourceUsage.size(); i++) {
1231 int resourceNum = msi.getCPUResourceNum(resourceUsage[i].first);
1232 int useNum = resourceUsage[i].second;
Guochun Shif1c154f2003-03-27 17:57:44 +00001233 double tempII;
Misha Brukman8baa01c2003-04-09 21:51:34 +00001234 if (resourceNum <= issueSlots)
1235 tempII = ceil(1.0 * useNum / resourceNum);
Guochun Shif1c154f2003-03-27 17:57:44 +00001236 else
Misha Brukman8baa01c2003-04-09 21:51:34 +00001237 tempII = ceil(1.0 * useNum / issueSlots);
1238 ResII = std::max((int) tempII, ResII);
Guochun Shif1c154f2003-03-27 17:57:44 +00001239 }
1240 return ResII;
1241}
1242
Misha Brukman8baa01c2003-04-09 21:51:34 +00001243ModuloSchedGraphSet::ModuloSchedGraphSet(const Function * function,
1244 const TargetMachine & target)
1245: method(function)
Guochun Shif1c154f2003-03-27 17:57:44 +00001246{
Misha Brukman8baa01c2003-04-09 21:51:34 +00001247 buildGraphsForMethod(method, target);
Guochun Shif1c154f2003-03-27 17:57:44 +00001248}
1249
1250
1251ModuloSchedGraphSet::~ModuloSchedGraphSet()
1252{
1253 //delete all the graphs
Misha Brukman8baa01c2003-04-09 21:51:34 +00001254 for (iterator I = begin(), E = end(); I != E; ++I)
Guochun Shif1c154f2003-03-27 17:57:44 +00001255 delete *I;
1256}
1257
Misha Brukman8baa01c2003-04-09 21:51:34 +00001258void ModuloSchedGraphSet::dump() const
Guochun Shif1c154f2003-03-27 17:57:44 +00001259{
Misha Brukman8baa01c2003-04-09 21:51:34 +00001260 modSched_os << " ====== ModuloSched graphs for function `" <<
1261 method->getName() << "' =========\n\n";
1262 for (const_iterator I = begin(); I != end(); ++I)
Guochun Shif1c154f2003-03-27 17:57:44 +00001263 (*I)->dump();
Misha Brukman8baa01c2003-04-09 21:51:34 +00001264
1265 modSched_os << "\n=========End graphs for funtion` " << method->getName()
1266 << "' ==========\n\n";
Guochun Shif1c154f2003-03-27 17:57:44 +00001267}
1268
Misha Brukman8baa01c2003-04-09 21:51:34 +00001269void ModuloSchedGraph::dump(const BasicBlock * bb)
Guochun Shif1c154f2003-03-27 17:57:44 +00001270{
Misha Brukman8baa01c2003-04-09 21:51:34 +00001271 modSched_os << "dumping basic block:";
1272 modSched_os << (bb->hasName()? bb->getName() : "block")
1273 << " (" << bb << ")" << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +00001274
1275}
1276
Misha Brukman8baa01c2003-04-09 21:51:34 +00001277void ModuloSchedGraph::dump(const BasicBlock * bb, std::ostream & os)
Guochun Shif1c154f2003-03-27 17:57:44 +00001278{
Misha Brukman8baa01c2003-04-09 21:51:34 +00001279 os << "dumping basic block:";
1280 os << (bb->hasName()? bb->getName() : "block")
1281 << " (" << bb << ")" << "\n";
Guochun Shif1c154f2003-03-27 17:57:44 +00001282}
1283
Misha Brukman8baa01c2003-04-09 21:51:34 +00001284void ModuloSchedGraph::dump() const
Guochun Shif1c154f2003-03-27 17:57:44 +00001285{
1286 modSched_os << " ModuloSchedGraph for basic Blocks:";
Misha Brukman8baa01c2003-04-09 21:51:34 +00001287 for (unsigned i = 0, N = bbVec.size(); i < N; i++) {
1288 modSched_os << (bbVec[i]->hasName()? bbVec[i]->getName() : "block")
1289 << " (" << bbVec[i] << ")" << ((i == N - 1) ? "" : ", ");
1290 }
1291
1292 modSched_os << "\n\n Actual Root nodes : ";
1293 for (unsigned i = 0, N = graphRoot->outEdges.size(); i < N; i++)
Guochun Shif1c154f2003-03-27 17:57:44 +00001294 modSched_os << graphRoot->outEdges[i]->getSink()->getNodeId()
Misha Brukman8baa01c2003-04-09 21:51:34 +00001295 << ((i == N - 1) ? "" : ", ");
Guochun Shif1c154f2003-03-27 17:57:44 +00001296
1297 modSched_os << "\n Graph Nodes:\n";
1298 //for (const_iterator I=begin(); I != end(); ++I)
1299 //modSched_os << "\n" << *I->second;
Misha Brukman8baa01c2003-04-09 21:51:34 +00001300 unsigned numNodes = bbVec[0]->size();
1301 for (unsigned i = 2; i < numNodes + 2; i++) {
1302 ModuloSchedGraphNode *node = getNode(i);
1303 modSched_os << "\n" << *node;
1304 }
Guochun Shif1c154f2003-03-27 17:57:44 +00001305
1306 modSched_os << "\n";
1307}
Misha Brukman8baa01c2003-04-09 21:51:34 +00001308
1309void ModuloSchedGraph::dumpNodeProperty() const
Guochun Shif1c154f2003-03-27 17:57:44 +00001310{
Misha Brukman8baa01c2003-04-09 21:51:34 +00001311 const BasicBlock *bb = bbVec[0];
1312 unsigned numNodes = bb->size();
1313 for (unsigned i = 2; i < numNodes + 2; i++) {
1314 ModuloSchedGraphNode *node = getNode(i);
1315 modSched_os << "NodeId " << node->getNodeId() << "\t";
1316 modSched_os << "ASAP " << node->getASAP() << "\t";
1317 modSched_os << "ALAP " << node->getALAP() << "\t";
1318 modSched_os << "mov " << node->getMov() << "\t";
1319 modSched_os << "depth " << node->getDepth() << "\t";
1320 modSched_os << "height " << node->getHeight() << "\t";
1321 modSched_os << "\n";
1322 }
Guochun Shif1c154f2003-03-27 17:57:44 +00001323}
1324
Misha Brukman8baa01c2003-04-09 21:51:34 +00001325void ModuloSchedGraphSet::buildGraphsForMethod(const Function * F,
1326 const TargetMachine &
1327 target)
Guochun Shif1c154f2003-03-27 17:57:44 +00001328{
Misha Brukman8baa01c2003-04-09 21:51:34 +00001329 for (Function::const_iterator BI = F->begin(); BI != F->end(); ++BI)
1330 addGraph(new ModuloSchedGraph(BI, target));
Guochun Shif1c154f2003-03-27 17:57:44 +00001331}
1332
Misha Brukman8baa01c2003-04-09 21:51:34 +00001333std::ostream & operator<<(std::ostream & os,
1334 const ModuloSchedGraphNode & node)
Guochun Shif1c154f2003-03-27 17:57:44 +00001335{
1336 os << std::string(8, ' ')
Misha Brukman8baa01c2003-04-09 21:51:34 +00001337 << "Node " << node.nodeId << " : "
1338 << "latency = " << node.latency << "\n" << std::string(12, ' ');
Guochun Shif1c154f2003-03-27 17:57:44 +00001339
1340 if (node.getInst() == NULL)
1341 os << "(Dummy node)\n";
Misha Brukman8baa01c2003-04-09 21:51:34 +00001342 else {
1343 os << *node.getInst() << "\n" << std::string(12, ' ');
1344 os << node.inEdges.size() << " Incoming Edges:\n";
1345 for (unsigned i = 0, N = node.inEdges.size(); i < N; i++)
1346 os << std::string(16, ' ') << *node.inEdges[i];
1347
1348 os << std::string(12, ' ') << node.outEdges.size()
1349 << " Outgoing Edges:\n";
1350 for (unsigned i = 0, N = node.outEdges.size(); i < N; i++)
1351 os << std::string(16, ' ') << *node.outEdges[i];
1352 }
1353
Guochun Shif1c154f2003-03-27 17:57:44 +00001354
1355 return os;
1356}