OpenASIP  2.0
CriticalPathBBMoveNodeSelector.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file CriticalPathBBMoveNodeSelector.cc
26  *
27  * Implementation of CriticalPathBBMoveNodeSelector interface.
28  *
29  * @author Pekka Jääskeläinen 2007 (pekka.jaaskelainen-no.spam-tut.fi)
30  * @note rating: red
31  */
32 
34 #include "DataDependenceGraph.hh"
36 #include "POMDisassembler.hh"
37 #include "ProgramOperation.hh"
38 #include "Procedure.hh"
39 #include "BasicBlock.hh"
40 #include "SpecialRegisterPort.hh"
41 #include "Terminal.hh"
42 
43 //#define DEBUG_OUTPUT__
44 //#define WRITE_DOT_SNAPSHOTS
45 
46 /**
47  * Add the unscheduled root nodes of the DDG to the ready list
48  */
49 void
52  for (DataDependenceGraph::NodeSet::iterator i = roots.begin();
53  i != roots.end();
54  ++i) {
55  MoveNode& node = **i;
56 
57  // a hack to avoid adding the root operations multiple times
58  // (the count of input moves): only "announce" the move to the first
59  // operand (every operation should have one input operand)
60  if (!node.isDestinationOperation())
61  mightBeReady(**i);
62  else if (node.move().destination().operationIndex() == 1) {
63  mightBeReady(**i);
64  }
65  }
66 
67 }
68 
69 /**
70  * Constructor. Creates subgraph of the given big graph
71  *
72  * @param bigDDG big ddg containing more than just the basic block
73  * @param bb basic block for this selector.
74  */
78  : ddgOwned_(true) {
79  try {
80  ddg_ = bigDDG.createSubgraph(bb);
82  } catch (InstanceNotFound& inf) {
84  __FILE__,__LINE__,__func__,"Creation of subgraph failed");
85  e.setCause(inf);
86  throw e;
87  }
89 }
90 
91 /**
92  * Constructor.
93  *
94  * @param bb The basic block from which to select moves.
95  */
98  ddgOwned_(true) {
99 
100  DataDependenceGraphBuilder ddgBuilder;
101  ddg_ = ddgBuilder.build(
104 
105 #ifdef WRITE_DOT_SNAPSHOTS
106  ddg_->setCycleGrouping(true);
107  ddg_->writeToDotFile("ddg.dot");
108 #endif
109 
111 }
112 
113 /**
114  * Constructor.
115  *
116  * @param ddg The data dependence graph from which to select moves.
117  * Selector does not take the ownership of the ddg.
118  */
121  ddg_(&ddg), ddgOwned_(false) {
122 
124 
125 #ifdef WRITE_DOT_SNAPSHOTS
126  ddg_->setCycleGrouping(true);
127  ddg_->writeToDotFile("ddg.dot");
128 #endif
129 
131 }
132 
133 /**
134  * Destructor.
135  */
137  if (ddgOwned_) {
138  delete ddg_;
139  }
140 }
141 
142 /**
143  * Returns a group of move nodes which should be scheduled next.
144  *
145  * @return Move node group.
146  */
149 
150  // find a MoveNodeGroup with unscheduled MoveNodes
151  while (readyList_.size() > 0) {
152  MoveNodeGroup moves = readyList_.top();
153  if (!moves.isAlive() || moves.isScheduled())
154  readyList_.pop();
155  else
156  return moves;
157  }
158  // nothing in ready list, let's see if there are "orphan" nodes
159  // still to schedule
160  if (ddg_->nodeCount() - ddg_->scheduledNodeCount() > 0) {
162  for (DataDependenceGraph::NodeSet::iterator i = unscheduled.begin();
163  i != unscheduled.end();
164  ++i) {
165  MoveNode& node = **i;
166  mightBeReady(node);
167  }
168  }
169 
170  // did we find new nodes?
171  while (readyList_.size() > 0) {
172  MoveNodeGroup moves = readyList_.top();
173  if (moves.isScheduled())
174  readyList_.pop();
175  else
176  return moves;
177  }
178 
179  // return an empty move node group
180  return MoveNodeGroup();
181 }
182 
183 /**
184  * Returns the DDG used internally.
185  *
186  * This is needed temporarily only until the MoveNodeManager is done.
187  *
188  * @return The DDG.
189  */
192  return *ddg_;
193 }
194 
195 /**
196  * This should be called by the client as soon as a MoveNode is scheduled
197  * in order to update the internal state of the selector.
198  *
199  * @param node The scheduled MoveNode.
200  */
201 void
203 
204  assert(node.isScheduled() && "Notifying scheduled even though it isn't.");
206  for (DataDependenceGraph::NodeSet::iterator i = succ.begin();
207  i != succ.end(); ++i) {
208  MoveNode& successor = **i;
209 
210  // we schedule operations as entities, so if the successor is a
211  // (result) move, it's already in the ready list along with the
212  // move itself
213  if (!successor.inSameOperation(node))
214  mightBeReady(**i);
215  }
216 
217 #ifdef WRITE_DOT_SNAPSHOTS
218  ddg_->setCycleGrouping(true);
219  ddg_->writeToDotFile("ddg.dot");
220 #endif
221 }
222 
223 /**
224  * Adds the given move node (along with the other possible move nodes in the
225  * same operation) to the ready list in case all its parents in the DDG have
226  * been scheduled.
227  *
228  * In case the node belongs to an operation, also checks that the other
229  * operand moves are also ready. In that case adds all the nodes in the said
230  * MoveOperation to the ready list in a single MoveNodeGroup.
231  *
232  * @param node Move node that might be ready.
233  */
234 void
236 
237  if (node.isScheduled()) {
238  return;
239  }
240 
241  if (!isReadyToBeScheduled(node))
242  return;
243 
244  if (node.isDestinationOperation() || node.isSourceOperation()) {
245  // it's a trigger, result, or operand move, let's see if all the
246  // moves of the operation are ready to be scheduled
247  ProgramOperation& operation =
248  (node.isDestinationOperation()?
249  (node.destinationOperation()) : node.sourceOperation());
250  bool allReady = true;
251  MoveNodeGroup moves(*ddg_);
252  for (int inputIndex = 0; inputIndex < operation.inputMoveCount();
253  ++inputIndex) {
254  MoveNode& m = operation.inputMove(inputIndex);
255  if (&m != &node) {
256  if (!isReadyToBeScheduled(m)) {
257  allReady = false;
258  break;
259  }
260  }
261  if (!m.isScheduled())
262  moves.addNode(m);
263  }
264  if (allReady) {
265  // let's add also the output move(s) to the MoveNodeGroup
266  for (int outputIndex = 0;
267  outputIndex < operation.outputMoveCount();
268  ++outputIndex) {
269  MoveNode& m = operation.outputMove(outputIndex);
270  if (&m != &node) {
271  if (!isReadyToBeScheduled(m)) {
272  allReady = false;
273  break;
274  }
275  }
276  if (!m.isScheduled())
277  moves.addNode(m);
278  }
279  if (allReady) {
280  readyList_.push(moves);
281  }
282  }
283  } else if ((node.isSourceVariable() || node.move().source().isRA()) &&
284  (node.isDestinationVariable() ||
285  node.move().destination().isRA())) {
286  // it's a register to register move, we can always schedule these
287  // as soon as all the dependencies are satisfied
288  // handle RA -> ireg also as a register to register move
289  if (isReadyToBeScheduled(node)) {
290  MoveNodeGroup move(*ddg_);
291  move.addNode(node);
292  readyList_.push(move);
293  }
294  } else if (node.isSourceConstant() && node.isDestinationVariable()) {
295  if (isReadyToBeScheduled(node)) {
296  MoveNodeGroup move(*ddg_);
297  move.addNode(node);
298  readyList_.push(move);
299  }
300 
301  } else {
302  throw IllegalProgram(
303  __FILE__, __LINE__, __func__,
304  (boost::format("Illegal move '%s'.") %
305  POMDisassembler::disassemble(node.move())).str());
306  }
307 }
308 
309 /**
310  * Returns true in case the move is "data ready", that is, all its
311  * predecessors have been scheduled.
312  *
313  * It should be noted that moves within same operation are treated
314  * specially. Result move is considered ready even if the operands
315  * moves are not to allow scheduling all moves in the same operation
316  * as a single entity. Additionally, as we are considering a basic block
317  * at a time, the branch operation is considered never ready before
318  * all the other moves in the basic block have been scheduled.
319  *
320  * @param node Move to check.
321  * @return True if the move is ready to be scheduled.
322  */
323 bool
325  const {
326 
327  // the control flow move(s) are ready only if all other moves have been
328  // scheduled. In rare case of conditional branching with SPU operation set
329  // branch operation can have 2 moves, condition register and destination.
330  if (node.move().isControlFlowMove() &&
331  ddg_->nodeCount() - ddg_->scheduledNodeCount() > 1) {
332  DataDependenceGraph::NodeSet unscheduledMoves = ddg_->unscheduledMoves();
333  for (DataDependenceGraph::NodeSet::iterator i = unscheduledMoves.begin();
334  i != unscheduledMoves.end(); ++i) {
335  if ((*i)->move().isControlFlowMove() == false) {
336  return false;
337  }
338  }
339  }
340  return ddg_->predecessorsReady(node);
341 }
DataDependenceGraph::predecessorsReady
bool predecessorsReady(MoveNode &node) const
Definition: DataDependenceGraph.cc:3176
CriticalPathBBMoveNodeSelector::ddg_
DataDependenceGraph * ddg_
The data dependence graph built from the basic block.
Definition: CriticalPathBBMoveNodeSelector.hh:96
MoveNodeGroup::isAlive
bool isAlive() const
Definition: MoveNodeGroup.cc:190
MoveNode::isDestinationVariable
bool isDestinationVariable() const
Definition: MoveNode.cc:264
DataDependenceGraph::scheduledNodeCount
int scheduledNodeCount() const
Definition: DataDependenceGraph.cc:1859
CriticalPathBBMoveNodeSelector.hh
machine
TTAMachine::Machine * machine
the architecture definition of the estimated processor
Definition: EstimatorCmdLineUI.cc:59
MoveNode::isDestinationOperation
bool isDestinationOperation() const
BoostGraph< MoveNode, DataDependenceEdge >::NodeSet
std::set< MoveNode *, typename MoveNode ::Comparator > NodeSet
Definition: BoostGraph.hh:86
Procedure.hh
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
Exception::setCause
void setCause(const Exception &cause)
Definition: Exception.cc:75
DataDependenceGraph.hh
ProgramOperation
Definition: ProgramOperation.hh:70
DataDependenceGraph::setMachine
void setMachine(const TTAMachine::Machine &machine)
Definition: DataDependenceGraph.cc:3116
MoveNode
Definition: MoveNode.hh:65
MoveNode::isSourceConstant
bool isSourceConstant() const
Definition: MoveNode.cc:238
Terminal.hh
POMDisassembler.hh
CriticalPathBBMoveNodeSelector::mightBeReady
void mightBeReady(MoveNode &node)
Definition: CriticalPathBBMoveNodeSelector.cc:235
DataDependenceGraph::setCycleGrouping
virtual void setCycleGrouping(bool flag)
Definition: DataDependenceGraph.cc:1738
CriticalPathBBMoveNodeSelector::dataDependenceGraph
virtual DataDependenceGraph & dataDependenceGraph()
Definition: CriticalPathBBMoveNodeSelector.cc:191
MoveNode::sourceOperation
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:453
assert
#define assert(condition)
Definition: Application.hh:86
DataDependenceGraph::createSubgraph
DataDependenceGraph * createSubgraph(NodeSet &nodes, bool includeLoops=false)
Definition: DataDependenceGraph.cc:3377
DataDependenceGraphBuilder.hh
TTAProgram::Terminal::operationIndex
virtual int operationIndex() const
Definition: Terminal.cc:364
TTAProgram::Move::isControlFlowMove
bool isControlFlowMove() const
Definition: Move.cc:233
CriticalPathBBMoveNodeSelector::readyList_
ReadyMoveNodeGroupList readyList_
The prioritized ready list.
Definition: CriticalPathBBMoveNodeSelector.hh:98
DataDependenceGraph::INTRA_BB_ANTIDEPS
@ INTRA_BB_ANTIDEPS
Definition: DataDependenceGraph.hh:80
IllegalProgram
Definition: Exception.hh:895
__func__
#define __func__
Definition: Application.hh:67
CriticalPathBBMoveNodeSelector::initializeReadylist
void initializeReadylist()
Initializes ready list from nodes that are ready.
Definition: CriticalPathBBMoveNodeSelector.cc:50
CriticalPathBBMoveNodeSelector::CriticalPathBBMoveNodeSelector
CriticalPathBBMoveNodeSelector(TTAProgram::BasicBlock &bb, const TTAMachine::Machine &machine)
Definition: CriticalPathBBMoveNodeSelector.cc:96
CriticalPathBBMoveNodeSelector::candidates
virtual MoveNodeGroup candidates()
Definition: CriticalPathBBMoveNodeSelector.cc:148
MoveNode::isSourceOperation
bool isSourceOperation() const
Definition: MoveNode.cc:168
ModuleRunTimeError
Definition: Exception.hh:1043
ProgramOperation::inputMoveCount
int inputMoveCount() const
Definition: ProgramOperation.cc:600
CriticalPathBBMoveNodeSelector::notifyScheduled
virtual void notifyScheduled(MoveNode &node)
Definition: CriticalPathBBMoveNodeSelector.cc:202
GraphBase::writeToDotFile
virtual void writeToDotFile(const TCEString &fileName) const
ProgramOperation::outputMoveCount
int outputMoveCount() const
Definition: ProgramOperation.cc:610
ProgramOperation.hh
MoveNodeGroup::addNode
void addNode(MoveNode &node)
Definition: MoveNodeGroup.cc:70
MoveNode::isSourceVariable
bool isSourceVariable() const
Definition: MoveNode.cc:196
MoveNode::destinationOperation
ProgramOperation & destinationOperation(unsigned int index=0) const
TTAProgram::BasicBlock
Definition: BasicBlock.hh:85
MoveNode::move
TTAProgram::Move & move()
POMDisassembler::disassemble
static std::string disassemble(const TTAProgram::Move &move)
Definition: POMDisassembler.cc:629
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
DataDependenceGraphBuilder
Definition: DataDependenceGraphBuilder.hh:70
CriticalPathBBMoveNodeSelector::isReadyToBeScheduled
bool isReadyToBeScheduled(MoveNode &node) const
Definition: CriticalPathBBMoveNodeSelector.cc:324
MoveNode::inSameOperation
bool inSameOperation(const MoveNode &other) const
Definition: MoveNode.cc:306
CriticalPathBBMoveNodeSelector::ddgOwned_
bool ddgOwned_
Definition: CriticalPathBBMoveNodeSelector.hh:100
BasicBlock.hh
DataDependenceGraph
Definition: DataDependenceGraph.hh:67
SpecialRegisterPort.hh
DataDependenceGraphBuilder::build
virtual DataDependenceGraph * build(ControlFlowGraph &cGraph, DataDependenceGraph::AntidependenceLevel antidependenceLevel, const TTAMachine::Machine &mach, const UniversalMachine *um=NULL, bool createMemAndFUDeps=true, bool createDeathInformation=true, llvm::AliasAnalysis *AA=NULL)
Definition: DataDependenceGraphBuilder.cc:2120
MoveNodeGroup::isScheduled
bool isScheduled() const
Definition: MoveNodeGroup.cc:164
MoveNode::isScheduled
bool isScheduled() const
Definition: MoveNode.cc:409
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
MoveNodeGroup
Definition: MoveNodeGroup.hh:48
BoostGraph::rootNodes
virtual NodeSet rootNodes() const
useful utility functions
TTAProgram::Terminal::isRA
virtual bool isRA() const
Definition: Terminal.cc:129
BoostGraph::nodeCount
int nodeCount() const
ProgramOperation::outputMove
MoveNode & outputMove(int index) const
Definition: ProgramOperation.cc:632
DataDependenceGraph::unscheduledMoves
NodeSet unscheduledMoves() const
Definition: DataDependenceGraph.cc:1355
BoostGraph::successors
virtual NodeSet successors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
InstanceNotFound
Definition: Exception.hh:304
ProgramOperation::inputMove
MoveNode & inputMove(int index) const
Definition: ProgramOperation.cc:621
TTAMachine::Machine
Definition: Machine.hh:73
CriticalPathBBMoveNodeSelector::~CriticalPathBBMoveNodeSelector
virtual ~CriticalPathBBMoveNodeSelector()
Definition: CriticalPathBBMoveNodeSelector.cc:136