OpenASIP  2.0
BasicBlockScheduler.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 BasicBlockScheduler.cc
26  *
27  * Definition of BasicBlockScheduler class.
28  *
29  * @author Pekka Jääskeläinen 2006 (pjaaskel-no.spam-cs.tut.fi)
30  * @author Fabio Garzia 2010 (fabio.garzia-no.spam-tut.fi)
31  * @note rating: red
32  */
33 
34 #include <set>
35 #include <string>
36 #include <cstdlib>
37 
38 #include <boost/timer.hpp>
39 
40 #include "BasicBlockScheduler.hh"
41 #include "DataDependenceGraph.hh"
42 #include "SimpleResourceManager.hh"
43 #include "DDGMoveNodeSelector.hh"
44 #include "POMDisassembler.hh"
45 #include "ProgramOperation.hh"
46 #include "ControlUnit.hh"
47 #include "Machine.hh"
48 #include "UniversalMachine.hh"
49 #include "Guard.hh"
50 #include "MapTools.hh"
51 #include "Instruction.hh"
52 #include "InstructionReference.hh"
53 #include "BasicBlock.hh"
54 #include "RegisterCopyAdder.hh"
56 #include "TCEString.hh"
57 #include "Application.hh"
58 #include "LLVMTCECmdLineOptions.hh"
59 #include "HWOperation.hh"
60 #include "FUPort.hh"
61 #include "CodeGenerator.hh"
62 #include "TerminalImmediate.hh"
63 #include "InterPassData.hh"
64 #include "MoveNodeSet.hh"
65 #include "RegisterRenamer.hh"
66 #include "Operation.hh"
67 #include "FUPort.hh"
68 #include "HWOperation.hh"
69 
70 //#define DEBUG_OUTPUT
71 //#define DEBUG_REG_COPY_ADDER
72 
73 #define RESCHEDULE_NEXT_CYCLE_AFTER_DRE
74 
75 
77 
78 /**
79  * Constructs the basic block scheduler.
80  *
81  * @param data Interpass data
82  * @param bypasser Helper module implementing software bypassing
83  * @param delaySlotFiller Helper module implementing jump delay slot filling
84  */
86  InterPassData& data,
87  SoftwareBypasser* bypasser, RegisterRenamer* renamer) :
88  DDGPass(data), BasicBlockPass(data), ddg_(NULL), rm_(NULL),
89  softwareBypasser_(bypasser), renamer_(renamer), minCycle_(0),
90  jumpNode_(NULL) {
91  CmdLineOptions *cmdLineOptions = Application::cmdLineOptions();
92  options_ = dynamic_cast<LLVMTCECmdLineOptions*>(cmdLineOptions);
93 }
94 
96 }
97 
98 /**
99  * Schedules a piece of code in a DDG
100  *
101  * @param ddg The ddg containing the code
102  * @param rm Resource manager that is to be used.
103  * @param targetMachine The target machine.
104  * @return size of the produces schedule.
105  * @exception Exception several TCE exceptions can be thrown in case of
106  * a scheduling error.
107  */
108 int
111  const TTAMachine::Machine& targetMachine, int minCycle, bool test) {
112  tripCount_ = 0;
113  ddg_ = &ddg;
114  targetMachine_ = &targetMachine;
115  minCycle_ = minCycle;
116  schedulingTime_.restart();
117 
118  if (renamer_ != NULL) {
119  renamer_->initialize(ddg);
120  }
121 
122  if (options_ != NULL && options_->dumpDDGsDot()) {
123  ddgSnapshot(
124  ddg, std::string("0"), DataDependenceGraph::DUMP_DOT, false);
125  }
126 
127  if (options_ != NULL && options_->dumpDDGsXML()) {
128  ddgSnapshot(
129  ddg, std::string("0"), DataDependenceGraph::DUMP_XML, false);
130  }
131 
132  scheduledTempMoves_.clear();
133 
134  // empty DDGs can be ignored
135  if (ddg.nodeCount() == 0 ||
136  (ddg.nodeCount() == 1 && !ddg.node(0).isMove())) {
137  return 0;
138  }
139 
140  CriticalPathBBMoveNodeSelector selector(ddg, targetMachine);
141  selector_ = &selector;
142 
143  rm_ = &rm;
144 
145 
146  // register selector to bypasser for notfications.
147  if (softwareBypasser_ != NULL) {
148  softwareBypasser_->setSelector(&selector);
149  }
150 
151  if (renamer_ != NULL) {
152  renamer_->setSelector(&selector);
153  }
154 
155  MoveNodeGroup moves = selector.candidates();
156  while (moves.nodeCount() > 0) {
157  bool movesRemoved = false;
158  MoveNode& firstMove = moves.node(0);
159  if (firstMove.isOperationMove()) {
160  scheduleOperation(moves);
161  } else {
162  if (firstMove.move().destination().isRA()) {
163  scheduleMove(firstMove,0, true);
164  } else {
165  scheduleRRMove(firstMove);
166  int lastOperandFake = 0;
167  if (softwareBypasser_ != NULL) {
168  int rv =
170  firstMove, lastOperandFake, ddg, rm);
171  if (rv < 0) {
173  firstMove, ddg, rm, true);
174  scheduleRRMove(firstMove);
175  }
176 
177  // did the bypass cause a reg-to-itself copy?
178  // if it did, let's kill it.
179  if (firstMove.move().source().equals(
180  firstMove.move().destination())) {
181  movesRemoved = true;
182  }
183 
184  if (rv > 0) {
185  std::set<std::pair<TTAProgram::Move*, int> >
186  removedMoves;
188  moves, ddg, rm, removedMoves);
189  // TODO: disabled becaused may be problematic
190  // when rescheduled to different buses
191 // handleRemovedResultMoves(removedMoves);
192  }
193  }
194  }
195  }
196 
197  if (!movesRemoved) {
198  if (!moves.isScheduled()) {
199  std::string message = " Move(s) did not get scheduled: ";
200  for (int i = 0; i < moves.nodeCount(); i++) {
201  message += moves.node(i).toString() + " ";
202  }
203 
205 
206  throw ModuleRunTimeError(__FILE__,__LINE__,__func__,message);
207  }
208 
209  // notifies successors of the scheduled moves.
210  notifyScheduled(moves, selector);
211  }
212 
213  moves = selector.candidates();
214  }
215  int size = rm.largestCycle();
216  if (test) {
218  return size;
219  }
220  if (softwareBypasser_ != NULL) {
221  softwareBypasser_->clearCaches(ddg, true);
222  }
223 
224  if (ddg.nodeCount() !=
225  ddg.scheduledNodeCount()) {
226  ddg.writeToDotFile("failed_bb.dot");
227  std::cerr << ddg.nodeCount() << ", " << ddg.scheduledNodeCount()
228  << std::endl;
229  throw ModuleRunTimeError(__FILE__, __LINE__, __func__,
230  "All moves in the DDG didn't get scheduled.");
231  }
232 
233  if (options_ != NULL && options_->dumpDDGsDot()) {
234  ddgSnapshot(ddg, std::string("0"), DataDependenceGraph::DUMP_DOT, true);
235  }
236 
237  if (options_ != NULL && options_->dumpDDGsXML()) {
238  ddgSnapshot(ddg, std::string("0"), DataDependenceGraph::DUMP_XML, true);
239  }
240  return size;
241 }
242 
243 /**
244  * Schedules loop in a DDG
245  *
246  * @param ddg The ddg containing the loop
247  * @param rm Resource manager that is to be used.
248  * @param targetMachine The target machine.
249  * @exception Exception several TCE exceptions can be thrown in case of
250  * a scheduling error.
251  * @return negative if failed, else overlapcount.
252  */
253 int
256  const TTAMachine::Machine& targetMachine, int tripCount,
257  SimpleResourceManager*, bool testOnly) {
258  tripCount_ = tripCount;
259  ddg_ = &ddg;
260  targetMachine_ = &targetMachine;
261  minCycle_ = 0;
262  schedulingTime_.restart();
263 
264  if (renamer_ != NULL) {
265  renamer_->initialize(ddg);
266  }
267 
268  if (options_ != NULL && options_->dumpDDGsDot()) {
269  ddgSnapshot(
270  ddg, std::string("0"), DataDependenceGraph::DUMP_DOT, false, true);
271  }
272 
273  if (options_ != NULL && options_->dumpDDGsXML()) {
274  ddgSnapshot(
275  ddg, std::string("0"), DataDependenceGraph::DUMP_XML, false, true);
276  }
277 
278  scheduledTempMoves_.clear();
279 
280  // empty DDGs can be ignored
281  if (ddg.nodeCount() == 0 ||
282  (ddg.nodeCount() == 1 && !ddg.node(0).isMove())) {
283  return 0;
284  }
285 
286  CriticalPathBBMoveNodeSelector selector(ddg, targetMachine);
287 
288  rm_ = &rm;
289 
290  // register selector to bypasser for notfications.
291  if (softwareBypasser_ != NULL) {
292  softwareBypasser_->setSelector(&selector);
293  }
294 
295  if (renamer_ != NULL) {
296  renamer_->setSelector(&selector);
297  }
298 
299  for (int i = ddg.nodeCount()-1; i>= 0 ; i--) {
300  MoveNode& node = ddg.node(i);
301  if (node.move().isControlFlowMove()) {
302  jumpNode_ = &node;
303  MoveNodeGroup mng;
304  mng.addNode(node);
305  scheduleOperation(mng);
306  }
307  }
308 
309  MoveNodeGroup moves = selector.candidates();
310  while (moves.nodeCount() > 0) {
311 
312  MoveNode& firstMove = moves.node(0);
313  if (firstMove.isOperationMove()) {
314  scheduleOperation(moves);
315  } else {
316  if (firstMove.move().destination().isRA()) {
317  scheduleMove(firstMove,0, true);
318  } else {
319  scheduleRRMove(firstMove);
320  }
321  }
322 
323  if (!moves.isScheduled()) {
325  std::string("ii_") +
327  std::string("_dag.dot"));
328 
330 
331  return -1;
332  }
333 
334  // notifies successors of the scheduled moves.
335  notifyScheduled(moves, selector);
336 
337  moves = selector.candidates();
338  }
339 
340  if (ddg.nodeCount() !=
341  ddg.scheduledNodeCount()) {
342  debugLog("All moves in the DDG didn't get scheduled.");
343 // debugLog("Disassembly of the situation:");
344 // Application::logStream() << bb.disassemble() << std::endl;
345  ddg.writeToDotFile("failed_bb.dot");
346  abortWithError("Should not happen!");
347  }
348 
349  // loop schedulign did not help.
350  if (static_cast<unsigned>(ddg.largestCycle()) < rm.initiationInterval()
351  || testOnly) {
352  if (static_cast<unsigned>(ddg.largestCycle()) <
353  rm.initiationInterval()) {
355  << "No overlapping instructions."
356  << "Should Revert to ordinary scheduler."
357  << std::endl;
358  }
359  // this have to be calculated before unscheduling.
360  int rv = ddg.largestCycle() / rm.initiationInterval();
362  return rv;
363  }
364 
365  // test that ext-cond jump not in prolog (where it is skipped)
366  int overlap_count = ddg.largestCycle() / rm.initiationInterval();
367  if (overlap_count >= tripCount) {
369  return -1;
370  }
371 
372  if (softwareBypasser_ != NULL) {
373  softwareBypasser_->clearCaches(ddg, true);
374  }
375 
376  if (options_ != NULL && options_->dumpDDGsDot()) {
377  ddgSnapshot(ddg, std::string("0"), DataDependenceGraph::DUMP_DOT, true);
378  }
379 
380  if (options_ != NULL && options_->dumpDDGsXML()) {
381  ddgSnapshot(ddg, std::string("0"), DataDependenceGraph::DUMP_XML, true);
382  }
383 
384  return ddg.largestCycle() / rm.initiationInterval();
385 }
386 
387 #ifdef DEBUG_REG_COPY_ADDER
388 static int graphCount = 0;
389 #endif
390 
391 /**
392  * Schedules moves in a single operation execution.
393  *
394  * Assumes the given MoveNodeGroup contains all moves in the operation
395  * execution. Also assumes that all inputs to the MoveNodeGroup have
396  * been scheduled.
397  *
398  * @param moves Moves of the operation execution.
399  */
400 void
402  ProgramOperation& po =
403  (moves.node(0).isSourceOperation())?
404  (moves.node(0).sourceOperation()):
405  (moves.node(0).destinationOperation());
406 
407  // may switch operands of commutative operations. Do it before
408  // regcopyadder because it's easier here.
409  // cooperation with regcopyadder might make it perform better though.
410  tryToSwitchInputs(po);
411 
412 #ifdef DEBUG_REG_COPY_ADDER
413  ddg_->setCycleGrouping(true);
415  (boost::format("%s_before_ddg.dot") % ddg_->name()).str());
416 #endif
417 
418  RegisterCopyAdder regCopyAdder(
421  regCopyAdder.addMinimumRegisterCopies(po, *targetMachine_, ddg_);
422 #ifdef DEBUG_REG_COPY_ADDER
423  const int tempsAdded = copies.count_;
424 #endif
425 
426 #ifdef DEBUG_REG_COPY_ADDER
427  if (tempsAdded > 0) {
429  (boost::format("%s_after_regcopy_ddg.dot") % ddg_->name()).str());
430  }
431  ddg_->sanityCheck();
432 #endif
433 
434  MoveNodeSet tempSet;
435  for (int i = 0; i < moves.nodeCount(); i++) {
436  // MoveNodeGroup relates to DDG so we copy it to
437  // a simpler MoveNodeSet container
438  tempSet.addMoveNode(moves.node(i));
439  }
440 
441  bool operandsFailed = true;
442  bool resultsFailed = true;
443  int operandsStartCycle = 0;
444 
445  int maxFromRm = rm_->largestCycle();
446 
447  // Magic number defining how many times we should try to schedule
448  // operands and results. Should not be needed in final version of
449  // scheduler
450  const int retryCount = 20;
451  int minOperand = operandsStartCycle;
452 
453  bool tryBypassing = softwareBypasser_ != NULL;
454  bool bypassTrigger = true;
455 
456  while ((operandsFailed || resultsFailed) &&
457  operandsStartCycle < maxFromRm + retryCount) {
458 
459  minOperand = scheduleOperandWrites(operandsStartCycle, moves);
460  if (minOperand != -1) {
461  operandsFailed = false;
462  } else {
463  // Scheduling some operand failed, unschedule and try later cycle
464  for (int i = 0; i < moves.nodeCount(); i++){
465  MoveNode& moveNode = moves.node(i);
466  if (moveNode.isScheduled() &&
467  moveNode.isDestinationOperation()) {
468  unschedule(moveNode);
470  }
471  }
472  operandsFailed = true;
473  operandsStartCycle++;
474  continue;
475  }
476 
477  regCopyAdder.operandsScheduled(copies, *ddg_);
478 
479  int bypassedMoves = -1;
480  if (tryBypassing) {
481  bypassedMoves = softwareBypasser_->bypass(
482  moves, *ddg_, *rm_, bypassTrigger);
483  if (bypassedMoves == -1){
484  // bypassing failed try again without attempt to bypass
485  // this restores the original schedule of operands
486  // and disable bypassing
487  operandsFailed = true;
488  if (bypassTrigger == false) {
489  tryBypassing = false;
490  } else {
491  bypassTrigger = false;
492  }
494  continue;
495  }
496  // bypass was success
497  }
498 
499  // TODO: disabled because may cause fail if rescheduled
500  // to different bus.
501 // tryToDelayOperands(moves);
502 
503  if (scheduleResultReads(moves)) {
504  resultsFailed = false;
505  // Results were scheduled, we are not going to change schedule
506  // of this program operation. Lets check if some of the
507  // bypassed operands did not produce dead result moves
508  if (tryBypassing) {
509  try {
510  std::set<std::pair<TTAProgram::Move*, int> >
511  removedMoves;
513  moves, *ddg_, *rm_, removedMoves);
514  handleRemovedResultMoves(removedMoves);
515  } catch (const Exception& e) {
516  throw ModuleRunTimeError(
517  __FILE__, __LINE__, __func__, e.errorMessageStack());
518  }
519  }
520  } else {
521  // Scheduling results failed, most likely due to large distance
522  // between trigger and earliest result cycle
523  // Some other operation is overwritting result on same FU
524  for (int i = 0; i < moves.nodeCount(); i++){
525  MoveNode& moveNode = moves.node(i);
526  if (moveNode.isScheduled()) {
527  // Operands were scheduled successfully but result can
528  // not be, we unschedule everything
529  unschedule(moveNode);
530  if (moveNode.isDestinationOperation()) {
532  }
533  if (moveNode.isSourceOperation()) {
535  }
536  }
537  }
538  resultsFailed = true;
539  // If some operands were bypassed, we need to remove bypassing
540  if (tryBypassing) {
542  tryBypassing = false;
543  continue;
544  }
545  // We will try to schedule operands in later cycle
546  // taking larger strides
547  operandsStartCycle++;
548  minOperand++;
549  operandsStartCycle = std::max(minOperand, operandsStartCycle);
550  }
551  }
552  // This fails if there is "timeout" on retry count.
553  // Should not be needed in final version.
554 
555  if (operandsFailed) {
557  std::string("ii_") +
559  std::string("_dag.dot"));
560 
562  throw ModuleRunTimeError(
563  __FILE__, __LINE__, __func__,
564  "Operands scheduling failed for \'" + moves.toString());
565  }
566  if (resultsFailed) {
568  std::string("ii_") +
570  std::string("_dag.dot"));
571 
573  throw ModuleRunTimeError(
574  __FILE__, __LINE__, __func__,
575  "Results scheduling failed for \'" + moves.toString());
576  }
577 
578  if (options_ != NULL &&
580  (resultsFailed || operandsFailed)) {
581 
582  //static int failedCounter = 0;
583  if (options_->dumpDDGsDot()) {
584  ddgSnapshot(*ddg_, std::string("2_failed.dot"),
586  } else {
587  ddgSnapshot(*ddg_, std::string("2_failed.xml"),
589  }
590 
592  throw ModuleRunTimeError(
593  __FILE__, __LINE__, __func__,
594  (boost::format("Bad BB %s") % ddg_->name()).str());
595  }
596 
597  regCopyAdder.resultsScheduled(copies, *ddg_);
598 
599 #ifdef DEBUG_REG_COPY_ADDER
600  if (tempsAdded > 0) {
602  (boost::format("%s_after_scheduler_ddg.dot") %
603  ddg_->name()).str());
605  << "(operation fix #" << ddg_->name() << ")" << std::endl
606  << std::endl;
607 
608  ++graphCount;
609  }
610 #endif
611 }
612 
613 // #define DEBUG_SCHEDULE_OPERAND_WRITES
614 
615 /**
616  * Schedules operand moves of an operation execution.
617  *
618  * Assumes the given MoveNodeGroup contains all moves in the operation
619  * execution. Also assumes that all inputs to the MoveNodeGroup have
620  * been scheduled. Exception to this are the possible temporary register
621  * copies inserted before the operand move due to missing connectivity.
622  * If found, the temp moves are scheduled atomically with the operand move.
623  * Assumes top-down scheduling.
624  *
625  * @param cycle Earliest cycle for starting scheduling of operands. This
626  * parameter is modified to the highest cycle one
627  * should try next in case scheduling starting from the
628  * given cycle failed.
629  * @param moves Moves of the operation execution.
630  * @return The cycle the earliest of the operands got scheduled
631  */
632 int
634  const int MAX_OPERAND_CYCLE_DIFFERENCE = 15;
635 
636  const int MAX_OPERATION_START_BEFORE_EARLIEST_READ = 50;
637 
638  int lastOperandCycle = 0;
639  int earliestScheduledOperand = INT_MAX;
640  int startCycle = 0;
641  MoveNode* trigger = NULL;
642  MoveNode* firstToSchedule = NULL;
643 
644  // find the movenode which has highest DDG->earliestCycle and limit
645  // the starting cycle of all operands close to that.
646  // this should prevent trying to schedule immediate writes very early
647  // and having lots of retries until the cycle has risen to the level of
648  // other moves.
649  // this might make SCHEDULING_WINDOW or SimpleBrokerDirector unnecessary /
650  // allow groving it much smaller without scheduler slowdown.
651  for (int i = 0; i < moves.nodeCount(); i++) {
652  int limit = 0;
653  if (moves.node(i).isDestinationOperation()) {
654  limit = ddg_->earliestCycle(
655  moves.node(i), rm_->initiationInterval()) -
656  MAX_OPERAND_CYCLE_DIFFERENCE;
657  } else if (moves.node(i).isSourceOperation()) {
658  limit = ddg_->earliestCycle(
659  moves.node(i), rm_->initiationInterval()) -
660  MAX_OPERATION_START_BEFORE_EARLIEST_READ;
661  } else {
662  continue;
663  }
664  if (limit < 0) {
665  limit = 0;
666  }
667  if (limit > cycle) {
668  cycle = limit;
669  }
670  }
671 
672  // Find and schedule moveNode which has highest "earliest Cycle"
673  // other moveNodes could be scheduled in earlier cycle but this
674  // makes sure there will be no problems with operands overwritting
675  // and assignment failures. At least it reduced a count of such.
676  // Also find smallest of all earliest cycles,
677  // make no sense to start from 0
678  for (int i = 0; i < moves.nodeCount(); i++) {
679  if (!moves.node(i).isDestinationOperation()) {
680  continue;
681  }
682 
683  // Temporary moves needs to be scheduled so DDG can find
684  // earliest cycle
685  // TODO: this should also have cycle limit?
686  scheduleInputOperandTempMoves(moves.node(i), moves.node(i));
687  int earliestDDG = ddg_->earliestCycle(
688  moves.node(i), rm_->initiationInterval());
689 
690  if (earliestDDG == INT_MAX) {
691  ddg_->writeToDotFile("failed_bb.dot");
693  throw InvalidData(
694  __FILE__, __LINE__, __func__,
695  (boost::format("InputTempMoves failed to schedule "
696  "successfully for '%s' ") % moves.node(i).toString()).str());
697  }
698 
699  // passed argument could be larger than what DDG thinks is earliest
700  earliestDDG = std::max(earliestDDG, cycle);
701  int earliest = rm_->earliestCycle(earliestDDG, moves.node(i));
702  if (earliest == -1) {
704  continue;
705  }
706  if (earliest >= startCycle) {
707  // Find first moveNode that will be scheduled
708  startCycle = earliest;
709  firstToSchedule = &moves.node(i);
710  }
712 
713  // Find also smallest of earliestCycles
714  cycle = std::min(cycle, earliest);
715  }
716 
717  if (firstToSchedule != NULL) {
718  // start cycle could be null if there was problem scheduling
719  // all input temp operands
720  scheduleInputOperandTempMoves(*firstToSchedule, *firstToSchedule);
721  // earliestCycle gave us the startCycle so this must pass
722  scheduleMove(*firstToSchedule, startCycle, true);
723  if (!firstToSchedule->isScheduled()) {
725  std::string("ii_") +
727  std::string("_dag.dot"));
728 
730  throw ModuleRunTimeError(
731  __FILE__, __LINE__, __func__,
732  (boost::format("Move '%s' failed to schedule")
733  % firstToSchedule->toString()).str());
734  }
735  startCycle = firstToSchedule->cycle();
736  if (firstToSchedule->move().destination().isTriggering()) {
737  trigger = firstToSchedule;
738  } else {
739  lastOperandCycle = std::max(lastOperandCycle, startCycle);
740  }
741  } else {
743  std::string("ii_") +
745  std::string("_dag.dot"));
746 
748  throw ModuleRunTimeError(
749  __FILE__, __LINE__, __func__,
750  (boost::format(
751  "Unable to schedule '%s' is there enough resources?")
752  % moves.toString()).str());
753  }
754 
755  // try to schedule all input moveNodes, except trigger
756  for (int moveIndex = 0; moveIndex < moves.nodeCount(); ++moveIndex) {
757  MoveNode& moveNode = moves.node(moveIndex);
758  // skip the result reads
759  if (!moveNode.isDestinationOperation()) {
760  continue;
761  }
762 
763  if (moveNode.isScheduled()) {
764  earliestScheduledOperand =
765  std::min(earliestScheduledOperand, moveNode.cycle());
766  if (moveNode.move().destination().isTriggering()) {
767  trigger = &moveNode;
768  }
769  continue;
770  }
771 
772  // in case the operand move requires register copies due to
773  // missing connectivity, schedule them first
774  scheduleInputOperandTempMoves(moveNode, moveNode);
775  scheduleMove(moveNode, cycle, true);
776 
777  if (moveNode.isScheduled()) {
778  earliestScheduledOperand =
779  std::min(earliestScheduledOperand, moveNode.cycle());
780  if (moveNode.move().destination().isTriggering()) {
781  trigger = &moveNode;
782  earliestScheduledOperand =
783  std::min(earliestScheduledOperand, moveNode.cycle());
784  } else {
785  lastOperandCycle =
786  std::max(lastOperandCycle, moveNode.cycle());
787  }
788  } else {
789  // Movenode scheduling failed.
791  // try to unschedule trigger and then schedule this operand.
792  if (trigger != NULL && trigger->isScheduled()) {
793  unschedule(*trigger);
795  scheduleInputOperandTempMoves(moveNode, moveNode);
796  scheduleMove(moveNode, cycle, true);
797  if (!moveNode.isScheduled()) {
798  // if still failed return -1
800  // but make sure high-level loop advances some more cycles
801  if (earliestScheduledOperand != INT_MAX) {
802  cycle = earliestScheduledOperand;
803  }
804  return -1;
805  }
806  earliestScheduledOperand =
807  std::min(earliestScheduledOperand, moveNode.cycle());
808  lastOperandCycle =
809  std::max(lastOperandCycle, moveNode.cycle());
810  } else {
811  // failed even though no trigger scheduled.
812  // but make sure high-level loop advances some more cycles
813  if (earliestScheduledOperand != INT_MAX) {
814  cycle = earliestScheduledOperand;
815  }
816  return -1;
817  }
818  }
819  }
820 
821  // if trigger unscheduled, schedule it again.
822  assert(trigger != NULL);
823  if (!trigger->isScheduled()) {
824  scheduleInputOperandTempMoves(*trigger, *trigger);
825  scheduleMove(*trigger, lastOperandCycle, true);
826 
827  if (!trigger->isScheduled()) {
828  // trigger scheduling failed.
830  return -1;
831  }
832  earliestScheduledOperand =
833  std::min(earliestScheduledOperand, trigger->cycle());
834  }
835 
836  return earliestScheduledOperand;
837 }
838 /**
839  * Schedules the result read moves of an operation execution.
840  *
841  * Assumes the given MoveNodeGroup contains all moves in the operation
842  * execution. Also assumes that all operand moves have been scheduled.
843  *
844  * @param moves Moves of the operation execution.
845  */
846 bool
848  int tempRegLimitCycle = 0;
849 
850  for (int moveIndex = 0; moveIndex < moves.nodeCount(); ++moveIndex) {
851  MoveNode& moveNode = moves.node(moveIndex);
852 
853  if (!moveNode.isScheduled()) {
854  if (!moveNode.isSourceOperation()) {
855  throw InvalidData(
856  __FILE__, __LINE__, __func__,
857  (boost::format("Move to schedule '%s' is not "
858  "result move!") % moveNode.toString()).str());
859  }
860  if (succeedingTempMove(moveNode) != NULL) {
861 
862  MoveNode* lastRead =
864  moveNode.move().destination().registerFile(),
865  moveNode.move().destination().index());
866  if (lastRead != NULL) {
867  tempRegLimitCycle = lastRead->cycle();
868  }
869  }
870 
871  scheduleMove(moveNode, tempRegLimitCycle, true);
872  if (!moveNode.isScheduled()) {
873  // Result can not be scheduled even when operands were,
874  // usually caused by operands too early (data dependencies
875  // ok) and result forced to be scheduled much later
876  // because of data dependencies (WA{R,W} dependence with
877  // target register in most cases)
878  return false;
879  }
880  scheduleResultReadTempMoves(moveNode, moveNode, 0);
881  if (!moveNode.isScheduled()) {
882  throw InvalidData(
883  __FILE__, __LINE__, __func__,
884  (boost::format("Move '%s' did not get scheduled!")
885  % moveNode.toString()).str());
886  }
887  }
888  }
889  return true;
890 }
891 
892 /**
893  * Schedules moves in a single operation execution.
894  *
895  * Assumes the given MoveNodeGroup contains all moves in the operation
896  * execution. Also assumes that all inputs to the MoveNodeGroup have
897  * been scheduled.
898  *
899  * @param moveNode R-R Move to schedule.
900  */
901 void
903 #ifdef DEBUG_REG_COPY_ADDER
904  ddg_->setCycleGrouping(true);
906  (boost::format("%s_before_ddg.dot") % ddg_->name()).str());
907 #endif
908 
909  RegisterCopyAdder regCopyAdder(
911 
912 #ifdef DEBUG_REG_COPY_ADDER
913  const int tempsAdded =
914 #endif
915 
916  regCopyAdder.addRegisterCopiesToRRMove(moveNode, ddg_)
917 #ifdef DEBUG_REG_COPY_ADDER
918  .count_
919 #endif
920  ;
921 #ifdef DEBUG_REG_COPY_ADDER
922  if (tempsAdded > 0) {
924  (boost::format("%s_after_regcopy_ddg.dot") % ddg_->name()).str());
925  }
926  ddg_->sanityCheck();
927 #endif
928 
929  scheduleMove(moveNode, 0, true);
930  scheduleRRTempMoves(moveNode, moveNode, 0); //Fabio: 0 or more?!?
931 }
932 
933 /**
934  * Schedules a single move to the earliest possible cycle, taking in
935  * account the DDG, resource constraints, and latencies in producing
936  * source values.
937  *
938  * This method assumes the move is possible to schedule with regards to
939  * connectivity and resources. Short immediates are converted to long
940  * immediates when needed.
941  *
942  * @param move The move to schedule.
943  * @param earliestCycle The earliest cycle to try.
944  * @param allowPredicationAndRenaming Whether allowed to remove guard from
945  * the move being scheduled. Checks again side-effects are still made,
946  * this can be done only to operand moves and triggers without mem
947  * write or side-effects.
948  */
949 void
951  MoveNode& moveNode, int earliestCycle, bool allowPredicationAndRenaming) {
952  if (moveNode.isScheduled()) {
953  throw InvalidData(
954  __FILE__, __LINE__, __func__,
955  (boost::format("Move '%s' is already scheduled!")
956  % moveNode.toString()).str());
957  }
958 
959  int sourceReadyCycle = 0;
960  if (moveNode.isSourceOperation()) {
961  sourceReadyCycle = moveNode.earliestResultReadCycle();
962  }
963 
964  int ddgCycle = 0;
965 
966  unsigned int ii = rm_->initiationInterval();
967 
968  // schedule jumps and calls...
969  if (moveNode.move().isControlFlowMove()) {
970 
971  // the branch should get scheduled last, so the DDG should have
972  // only the branch move(s) at hand unscheduled. For software
973  // pipelining (ii > 0), branches might be scheduled earlier.
974  if (ii == 0 && ddg_->nodeCount() != ddg_->scheduledNodeCount() + 1) {
975  // in rare case the branch moves can have 2 parameters (SPU)
976  // and therefore 2 nodes unscheduled. Check if the unscheduled
977  // moves are all control flow moves.
978  DataDependenceGraph::NodeSet unscheduledMoves =
980  for (DataDependenceGraph::NodeSet::iterator i = unscheduledMoves.begin();
981  i != unscheduledMoves.end(); ++i) {
982  if (!(*i)->move().isControlFlowMove()) {
983  TCEString msg =
984  "Control Flow Move is not last of the unscheduled moves! ";
985  msg += "Scheduled count=" +
987  msg += " Node count=" +
989  throw InvalidData(__FILE__, __LINE__, __func__, msg);
990  }
991  }
992  }
993 
994  // try to fill the delay slots with moves within the same basic
995  // block
996  // @TODO: ignore argument/rv register deps in case of call as they
997  // are not really used by the call instruction but by the called
998  // procedure, thus we can schedule them at the delay slots
999 
1000  // largest cycle of DDG is the highest cycle where something
1001  // was scheduled, however such a move can have pipeline
1002  // that spans more cycles and we should not change
1003  // the control flow while something is still in pipeline
1004  int largest = std::max(rm_->largestCycle(), ddg_->largestCycle());
1005  if (ii == 0) {
1006  ddgCycle =
1007  std::max(
1008  ddg_->earliestCycle(moveNode),
1009  largest - targetMachine_->controlUnit()->delaySlots());
1010  } else {
1011  unsigned int delaySlots =
1013  // is the jump in first or later iteration?
1014  MoveNode* jumpLimit = ddg_->findLoopLimitAndIndex(moveNode).first;
1015 
1016  ddgCycle = (((ddg_->earliestCycle(moveNode, ii) +
1017  delaySlots) / ii) + 1)*ii - 1 - delaySlots;
1018  if ((unsigned)ddgCycle >= ii - delaySlots) {
1019 
1020  int jumpOverlapCount = (ddgCycle + delaySlots) / ii;
1021  if (jumpLimit == NULL) {
1022  // allow jump only in first iteration if we could
1023  // not find the limit
1024  return;
1025  } else {
1026  // update loop limit counter.
1027  TTAProgram::TerminalImmediate& ti = dynamic_cast<
1028  TTAProgram::TerminalImmediate&>(jumpLimit->move().source());
1029  int jumpLimitValue = ti.value().unsignedValue();
1030  int loopCounterStep = 1;
1031  if (jumpLimitValue != tripCount_) {
1032  if (jumpLimitValue == 2 * tripCount_) {
1033  loopCounterStep = 2;
1034  } else {
1035  if (jumpLimitValue == 4 * tripCount_) {
1036  loopCounterStep = 4;
1037  } else {
1038  // don't know how much to decr. counter.
1039  return;
1040  }
1041  }
1042  }
1043 
1044  if (tripCount_ > jumpOverlapCount) {
1045  jumpLimit->move().setSource(
1047  SimValue(
1048  jumpLimitValue -
1049  (jumpOverlapCount * loopCounterStep),
1050  ti.value().width())));
1051  } else {
1052  // loop limit is too short.
1053  // would be always executed too many times.
1054  return;
1055  }
1056  }
1057  }
1058  }
1059  } else { // not a control flow move:
1060  ddgCycle = ddg_->earliestCycle(moveNode, ii);
1061 
1062  // <pekka> This is now always called even though renaming is disabled?
1063  int minRenamedEC = std::max(
1064  sourceReadyCycle, ddg_->earliestCycle(moveNode, ii, true, true));
1065 
1066  // rename if can and may alow scheuduling earlier.
1067  if (renamer_ != NULL && minRenamedEC < ddgCycle &&
1068  allowPredicationAndRenaming) {
1069  minRenamedEC = rm_->earliestCycle(minRenamedEC, moveNode);
1070  if (minRenamedEC < ddgCycle) {
1071 
1073  moveNode, ii != 0, true, true, minRenamedEC)) {
1074  ddgCycle = ddg_->earliestCycle(moveNode, ii);
1075  } else {
1076 #ifdef THIS_IS_BUGGY_WITH_REGCOPY_ADDER
1077  // renaming already scheduled ones may fail if
1078  // loop scheudling.
1079  if (rm_->initiationInterval() == 0) {
1080  MoveNode *limitingAdep =
1082  if (limitingAdep != NULL) {
1083  // don't try to rename is same operation.
1084  // as it would not help at all.
1085  if (!moveNode.isSourceOperation() ||
1086  !limitingAdep->isDestinationOperation() ||
1087  &moveNode.sourceOperation() !=
1088  &limitingAdep->destinationOperation()) {
1090  *limitingAdep, false, true, true)) {
1091  ddgCycle = ddg_->earliestCycle(
1092  moveNode);
1093  }
1094  }
1095  }
1096  }
1097 #endif
1098  }
1099  }
1100  }
1101  }
1102 
1103  // if it's a conditional move then we have to be sure that the guard
1104  // is defined before executing the move.
1105  // this is already handled by DDGs earliestCycle, except cases
1106  // where the guard is defined in a previous BB.
1107  // So this prevents scheduling unconditional moves at the beginning
1108  // of a BB.
1109 
1110  if (!moveNode.move().isUnconditional()) {
1111  ddgCycle = std::max(ddgCycle, moveNode.guardLatency()-1);
1112 
1113  if (allowPredicationAndRenaming) {
1114  // try to get rid of the guard if it gives earlier earliestcycle.
1115  if (ddg_->earliestCycle(moveNode, ii, false, false, true)
1116  < ddgCycle) {
1117  bool guardNeeded = false;
1118  if (moveNode.move().destination().isGPR() ||
1119  moveNode.move().isControlFlowMove()) {
1120  guardNeeded = true;
1121  } else {
1122  // this would be needed only for trigger,
1123  // but trigger may change during scheduling.
1124  // so lets just limit all operands, it seems
1125  // this does not make the schedule any worse.
1126  if (moveNode.isDestinationOperation()) {
1127  const Operation& o =
1128  moveNode.destinationOperation().operation();
1129  if (o.writesMemory() || o.hasSideEffects() ||
1130  o.affectsCount() != 0) {
1131  guardNeeded = true;
1132  }
1133  }
1134  }
1135  if (!guardNeeded) {
1136  moveNode.move().setGuard(NULL);
1137  ddg_->removeIncomingGuardEdges(moveNode);
1138  ddgCycle = ddg_->earliestCycle(moveNode, ii);
1139  assert(moveNode.move().isUnconditional());
1140  }
1141  }
1142 
1143  if (ii == 0 && tryToOptimizeWaw(moveNode)) {
1144  ddgCycle = std::max(ddg_->earliestCycle(moveNode, ii),
1145  moveNode.guardLatency()-1);
1146  }
1147 
1148  }
1149  }
1150 
1151  // Earliest cycle from which to start, could depend on result ready
1152  // for result moves.
1153  int minCycle = std::max(std::max(earliestCycle, ddgCycle), minCycle_);
1154  minCycle = std::max(minCycle, sourceReadyCycle);
1155 
1156  // RM hasConnection takes MoveNodeSet, however is called only for one
1157  // moveNode here.
1158  MoveNodeSet tempSet;
1159  tempSet.addMoveNode(moveNode);
1160  if (moveNode.isSourceConstant() &&
1161  !moveNode.move().hasAnnotations(
1163  // If source is constant and node does not have annotation already,
1164  // we add it if constant can not be transported so IU broker and
1165  // OutputPSocket brokers will add Immediate
1166  // Example : 999999 -> integer0.2
1167  if (!rm_->canTransportImmediate(moveNode)){
1168  TTAProgram::ProgramAnnotation annotation(
1170  moveNode.move().setAnnotation(annotation);
1171 
1172  } else if (!moveNode.isDestinationOperation() &&
1173  rm_->earliestCycle(rm_->largestCycle() + 1, moveNode) == -1
1174  && rm_->initiationInterval() == 0) {
1175 
1176  // If source is constant and node does not have annotation already,
1177  // we add it if node has no connection, so IU broker and
1178  // OutputPSocket brokers will add Immediate
1179  // Example: 27 -> integer0.2
1180  // With bus capable of transporting 27 as short immediate but
1181  // no connection from that bus to integer0 unit
1182  // this may mess up modulo scheduling.
1183  // TODO: do this more cleanly, this is a kludge.
1184  TTAProgram::ProgramAnnotation annotation(
1186  moveNode.move().setAnnotation(annotation);
1187  }
1188  }
1189  // annotate the return move otherwise it might get undetected in the
1190  // simulator after the short to long immediate conversion and thus
1191  // stopping simulation automatically might not work
1192  if (moveNode.isSourceConstant() &&
1193  moveNode.move().isReturn() &&
1194  !rm_->canTransportImmediate(moveNode)) {
1195  TTAProgram::ProgramAnnotation annotation(
1197  moveNode.move().setAnnotation(annotation);
1198  }
1199 
1200  minCycle = rm_->earliestCycle(minCycle, moveNode);
1201  if (minCycle == -1 || minCycle == INT_MAX) {
1202  if (moveNode.isSourceConstant() &&
1203  !moveNode.isDestinationOperation() &&
1204  moveNode.move().hasAnnotations(
1206  // If earliest cycle returns -1 and source is constant and moveNode
1207  // needs long immediate there is most likely missing long immediate
1208  // unit
1209  std::string msg = "Assignment of MoveNode " + moveNode.toString();
1210  msg += " failed! Most likely missing Long Immediate Unit";
1211  msg += " or Instruction Template!";
1212  if (rm_->initiationInterval() == 0) {
1213  ddg_->writeToDotFile("illegalmach.dot");
1214  throw IllegalMachine(
1215  __FILE__, __LINE__, __func__, msg);
1216  } else {
1218  std::string("ii_") +
1220  std::string("_dag.dot"));
1221 
1223  throw ModuleRunTimeError(
1224  __FILE__, __LINE__, __func__, msg);
1225  }
1226  }
1227  return;
1228  }
1229 
1230  int latestDDG = ddg_->latestCycle(moveNode, ii);
1231 
1232  if (ii != 0 && (minCycle > latestDDG)) {
1233 
1234  if (ddg_->latestCycle(moveNode, ii, true) > latestDDG) {
1235 
1236  if (renamer_ != NULL && allowPredicationAndRenaming) {
1237  // todo: do also otherway
1238  if (renamer_->renameSourceRegister(moveNode,true, true, true)) {
1239  latestDDG = ddg_->latestCycle(moveNode, ii);
1240  }
1241  }
1242  }
1243  }
1244 
1245  // test again after renaming?
1246 
1247  if (ii != 0 && (minCycle > latestDDG)) {
1248 
1249  // if we pre-scheduled jump, unschedule it and try to schdule
1250  // the node again.
1251  if (jumpNode_ != NULL) {
1252  ddg_->writeToDotFile("unschedJump.dot");
1254  jumpNode_ = NULL;
1255  scheduleMove(moveNode, earliestCycle, allowPredicationAndRenaming);
1256  return;
1257  }
1258 
1260  std::string("ii_") + Conversion::toString(ii) +
1261  std::string("_dag.dot"));
1262 
1264  throw ModuleRunTimeError(
1265  __FILE__, __LINE__, __func__, "Schedule failed try bigger ii.");
1266  }
1267 
1268  try {
1269  rm_->assign(minCycle, moveNode);
1270  } catch (const Exception& e) {
1271  throw ModuleRunTimeError(
1272  __FILE__, __LINE__, __func__, e.errorMessageStack());
1273  }
1274 
1275  if (!moveNode.isScheduled()) {
1276  throw ModuleRunTimeError(
1277  __FILE__, __LINE__, __func__,
1278  (boost::format("Assignment of MoveNode '%s' failed!")
1279  % moveNode.toString()).str());
1280  }
1281  assert(moveNode.cycle() >= minCycle_);
1282 }
1283 
1284 /**
1285  * Schedules the (possible) temporary register copy moves (due to missing
1286  * connectivity) succeeding the given RR move.
1287  *
1288  * The function recursively goes through all the temporary moves added to
1289  * the given RR move.
1290  *
1291  * @param regToRegMove A temp move whose successor has to be scheduled.
1292  * @param firstMove The original move of which temp moves to schedule.
1293  * @param lastUse Recursive function parameter, it should be set as 0
1294  * for the first function call.
1295  */
1296 void
1298  MoveNode& regToRegMove, MoveNode& firstMove, int lastUse) {
1299  /* Because temporary register moves do not have WaR/WaW dependency edges
1300  between the other possible uses of the same temp register in
1301  the same operation, we have to limit the scheduling of the new
1302  temp reg move to the last use of the same temp register so
1303  we don't overwrite the temp registers of the other operands. */
1304 
1305  // find all unscheduled succeeding moves of the result read move
1306  // there should be only only one with the only dependence edge (RaW) to
1307  // the result move
1308 
1309  MoveNode* tempMove1 = succeedingTempMove(regToRegMove);
1310  if (tempMove1 == NULL)
1311  return; // no temp moves found
1312 
1313  MoveNode* tempMove2 = succeedingTempMove(*tempMove1);
1314  if (tempMove2 != NULL) {
1315  MoveNode* lastRead =
1317  tempMove1->move().destination().registerFile(),
1318  tempMove1->move().destination().index());
1319  if (lastRead != NULL)
1320  lastUse = lastRead->cycle();
1321  }
1322 
1323  scheduleMove(*tempMove1, lastUse, true);
1324  assert(tempMove1->isScheduled());
1325  scheduledTempMoves_[&firstMove].insert(tempMove1);
1326 
1327  // the temp move should have maximum of one unscheduled
1328  // succeeding additional reg to reg copy (in case of two temp reg copies),
1329  // schedule it also if found
1330  scheduleResultReadTempMoves(*tempMove1, firstMove, lastUse+1);
1331 }
1332 
1333 /**
1334  * Schedules the (possible) temporary register copy moves (due to missing
1335  * connectivity) preceeding the given input move.
1336  *
1337  * The function recursively goes through all the temporary moves added to
1338  * the given input move.
1339  *
1340  * @param operandMove A temp move whose predecessor has to be scheduled.
1341  * @param operandWrite The original move of which temp moves to schedule.
1342  */
1343 void
1345  MoveNode& operandMove, MoveNode& operandWrite) {
1346  /* Because temporary register moves do not have WaR dependency edges
1347  between the other possible uses of the same temp register in
1348  the same operation, we have to limit the scheduling of the new
1349  temp reg move to the last use of the same temp register so
1350  we don't overwrite the temp registers of other operands. */
1351 
1352  /* <pekka> TODO: this could be improved by allowing to schedule also
1353  *before* the previous use, in the "holes" where it's unused. Now in effect
1354  the copies serialize the code quite badly. */
1355  int lastUse = 0;
1356 
1357  // find all unscheduled preceeding temp moves of the operand move
1358  DataDependenceGraph::EdgeSet inEdges = ddg_->inEdges(operandMove);
1359  MoveNode* tempMove = NULL;
1360  for (DataDependenceGraph::EdgeSet::iterator i = inEdges.begin();
1361  i != inEdges.end(); ++i) {
1362  if ((**i).edgeReason() != DataDependenceEdge::EDGE_REGISTER ||
1363  (**i).guardUse() ||
1364  (**i).dependenceType() != DataDependenceEdge::DEP_RAW) {
1365  continue;
1366  }
1367 
1368  MoveNode& m = ddg_->tailNode(**i);
1369  if (m.isScheduled() ||
1370  !m.move().hasAnnotations(
1372  continue;
1373  }
1374 
1375  assert(tempMove == NULL &&
1376  "Multiple unscheduled moves for the operand move, should have "
1377  "max. one (the temporary move)!");
1378  tempMove = &m;
1379  MoveNode* lastRead =
1381  tempMove->move().destination().registerFile(),
1382  tempMove->move().destination().index());
1383  if (lastRead != NULL)
1384  lastUse = lastRead->cycle();
1385  }
1386 
1387  if (tempMove == NULL)
1388  return; // no temp moves found
1389 
1390  // the temp move should have maximum of one unscheduled
1391  // preceeding reg to reg copy (in case of an additional temp reg copy),
1392  // schedule it first if found, calling recursively this function
1393  scheduleInputOperandTempMoves(*tempMove, operandWrite);
1394 
1395  // TODO: is the true correct here?
1396  scheduleMove(*tempMove, lastUse, true);
1397  assert(tempMove->isScheduled());
1398  scheduledTempMoves_[&operandWrite].insert(tempMove);
1399 }
1400 
1401 /**
1402  * Finds the temp move succeeding the given movenode.
1403  *
1404  * If it does not have one , returns null.
1405  *
1406  * @param current MoveNode whose tempmoves we are searching
1407  * @return tempMove succeeding given node, or null if does not exist.
1408  */
1409 MoveNode*
1411 
1412  DataDependenceGraph::NodeSet succ = ddg_->successors(current);
1413  MoveNode* result = NULL;
1414  for (DataDependenceGraph::NodeSet::iterator i = succ.begin();
1415  i != succ.end(); ++i) {
1416  MoveNode& m = **i;
1417  if (m.isScheduled() ||
1418  !m.move().hasAnnotations(
1420  continue;
1421 
1422  assert(result == NULL &&
1423  "Multiple candidates for the temp move of result read.");
1424  result = &m;
1425  }
1426  return result;
1427 }
1428 
1429 /**
1430  * Schedules the (possible) temporary register copy moves (due to missing
1431  * connectivity) succeeding the given result read move.
1432  *
1433  * The function recursively goes through all the temporary moves added to
1434  * the given input move.
1435  *
1436  * @param resultMove A temp move whose successor has to be scheduled.
1437  * @param resultRead The original move of which temp moves to schedule.
1438  * @param lastUse Recursive function parameter, it should be set as 0
1439  * for the first function call.
1440  */
1441 void
1443  MoveNode& resultMove, MoveNode& resultRead, int lastUse) {
1444  /* Because temporary register moves do not have WaR/WaW dependency edges
1445  between the other possible uses of the same temp register in
1446  the same operation, we have to limit the scheduling of the new
1447  temp reg move to the last use of the same temp register so
1448  we don't overwrite the temp registers of the other operands. */
1449 
1450 
1451  // find all unscheduled succeeding moves of the result read move
1452  // there should be only only one with the only dependence edge (RaW) to
1453  // the result move
1454 
1455  MoveNode* tempMove1 = succeedingTempMove(resultMove);
1456  if (tempMove1 == NULL)
1457  return; // no temp moves found
1458 
1459  MoveNode* tempMove2 = succeedingTempMove(*tempMove1);
1460  if (tempMove2 != NULL) {
1461  MoveNode* lastRead =
1463  tempMove1->move().destination().registerFile(),
1464  tempMove1->move().destination().index());
1465  if (lastRead != NULL)
1466  lastUse = lastRead->cycle();
1467  }
1468 
1469  scheduleMove(*tempMove1, lastUse, true);
1470  assert(tempMove1->isScheduled());
1471  scheduledTempMoves_[&resultRead].insert(tempMove1);
1472 
1473  // the temp move should have maximum of one unscheduled
1474  // succeeding additional reg to reg copy (in case of two temp reg copies),
1475  // schedule it also if found
1476  scheduleResultReadTempMoves(*tempMove1, resultRead, lastUse+1);
1477 }
1478 
1479 /**
1480  * Unschedules the given move.
1481  *
1482  * Also restores a possible short immediate source in case it was converted
1483  * to a long immediate register read during scheduling.
1484  *
1485  * @param moveNode Move to unschedule.
1486  */
1487 void
1489  if (moveNode.isScheduled()) {
1490  rm_->unassign(moveNode);
1491  }
1492 
1493  if (moveNode.move().hasAnnotations(
1495  // If we added annotation during scheduleMove delete it
1496  moveNode.move().removeAnnotations(
1498  }
1499  if (moveNode.isScheduled() || moveNode.isPlaced()) {
1500  throw InvalidData(
1501  __FILE__, __LINE__, __func__,
1502  (boost::format("Unscheduling of move '%s' failed!")
1503  % moveNode.toString()).str());
1504  }
1505 }
1506 
1507 /**
1508  * Calls unschedule() for all ddg nodes, which are scheduled.
1509  */
1510 void
1513  for (DataDependenceGraph::NodeSet::iterator i = scheduled.begin();
1514  i != scheduled.end(); ++i) {
1515  if (softwareBypasser_ != NULL) {
1516  softwareBypasser_->removeBypass(**i, *ddg_, *rm_, false);
1517  }
1518  unschedule(**i);
1519  }
1520  if (softwareBypasser_ != NULL) {
1522  }
1523 }
1524 
1525 /**
1526  * Unschedules the (possible) temporary register copy moves (due to missing
1527  * connectivity) preceeding the given move.
1528  *
1529  * @param operandMove The move of which temp moves to unschedule.
1530  */
1531 void
1533 
1534  if (!MapTools::containsKey(scheduledTempMoves_, &operandMove))
1535  return; // nothing to unschedule
1536 
1537  DataDependenceGraph::NodeSet tempMoves = scheduledTempMoves_[&operandMove];
1538 
1539  for (DataDependenceGraph::NodeSet::iterator i = tempMoves.begin();
1540  i != tempMoves.end(); ++i) {
1541  unschedule(**i);
1542  }
1543  scheduledTempMoves_.erase(&operandMove);
1544 }
1545 
1546 /**
1547  * Unschedules the (possible) temporary register copy moves (due to missing
1548  * connectivity) succeeding the given result read move.
1549  *
1550  * @param resultMove The move of which temp moves to unschedule.
1551  */
1552 void
1554 
1555  if (!MapTools::containsKey(scheduledTempMoves_, &resultMove))
1556  return; // nothing to unschedule
1557 
1558  DataDependenceGraph::NodeSet tempMoves = scheduledTempMoves_[&resultMove];
1559 
1560  for (DataDependenceGraph::NodeSet::iterator i = tempMoves.begin();
1561  i != tempMoves.end(); ++i) {
1562  unschedule(**i);
1563  }
1564  scheduledTempMoves_.erase(&resultMove);
1565 }
1566 
1567 /**
1568  * A short description of the pass, usually the optimization name,
1569  * such as "basic block scheduler".
1570  *
1571  * @return The description as a string.
1572  */
1573 std::string
1575  return "Instruction scheduler with a basic block scope.";
1576 }
1577 
1578 /**
1579  * Optional longer description of the pass.
1580  *
1581  * This description can include usage instructions, details of choice of
1582  * algorithmic details, etc.
1583  *
1584  * @return The description as a string.
1585  */
1586 std::string
1588  return
1589  "Basic block scheduler that uses the longest path information of "
1590  "data dependency graph to prioritize the ready list. Assumes that "
1591  "the input has registers allocated and no connectivity missing.";
1592 }
1593 
1594 /**
1595  * Notifies to the selector that given nodes and their temp reg copies are
1596  * scheduled .
1597  *
1598  * @param nodes nodes which are scheduled.
1599  * @param selector selector which to notify.
1600  */
1601 void
1603  MoveNodeGroup& moves, MoveNodeSelector& selector) {
1604 
1605  for (int moveIndex = 0; moveIndex < moves.nodeCount(); ++moveIndex) {
1606  MoveNode& moveNode = moves.node(moveIndex);
1607  selector.notifyScheduled(moveNode);
1608  std::map<const MoveNode*, DataDependenceGraph::NodeSet>::
1609  iterator tmIter = scheduledTempMoves_.find(&moveNode);
1610  if (tmIter != scheduledTempMoves_.end()) {
1611  DataDependenceGraph::NodeSet& tempMoves = tmIter->second;
1612  for (DataDependenceGraph::NodeSet::iterator i =
1613  tempMoves.begin(); i != tempMoves.end(); i++) {
1614  if ((**i).isScheduled()) {
1615  selector.notifyScheduled(**i);
1616  }
1617  }
1618  }
1619  }
1620 }
1621 
1622 /**
1623  * Prints DDG to a dot file before and after scheudling
1624  *
1625  * @param ddg to print
1626  * @param name operation name for ddg
1627  * @param final specify if ddg is after scheduling
1628  * @param resetCounter
1629  * @param format format of the file
1630  * @return number of cycles/instructions copied.
1631  */
1632 void
1634  DataDependenceGraph& ddg,
1635  const std::string& name,
1637  bool final,
1638  bool resetCounter) const {
1639 
1640  static int bbCounter = 0;
1641 
1642  if (resetCounter) {
1643  bbCounter = 0;
1644  }
1645 
1646  if (final) {
1647  if (format == DataDependenceGraph::DUMP_DOT) {
1648  ddg.writeToDotFile(
1649  (boost::format("bb_%s_%s_after_scheduling.dot") %
1650  ddg_->name() % name).str());
1651  } else {
1652  ddg.writeToXMLFile(
1653  (boost::format("bb_%s_%s_after_scheduling.xml") %
1654  ddg_->name() % name).str());
1655  }
1656 
1657  } else {
1658  if (format == DataDependenceGraph::DUMP_DOT) {
1659  ddg.writeToDotFile(
1660  (boost::format("bb_%s_%d_%s_before_scheduling.dot")
1661  % ddg.name() % bbCounter % name).str());
1662  DataDependenceGraph* criticalPath = ddg.criticalPathGraph();
1663  criticalPath->writeToDotFile(
1664  (boost::format(
1665  "bb_%s_%d_%s_before_scheduling_critical_path.dot")
1666  % ddg.name() % bbCounter % name).str());
1667  delete criticalPath;
1668  } else {
1669  ddg.writeToXMLFile(
1670  (boost::format("bb_%s_%d_%s_before_scheduling.xml")
1671  % ddg.name() % bbCounter % name).str());
1672  }
1673  }
1674  ++bbCounter;
1675 }
1676 
1677 /**
1678  *
1679  * Returns the operand which is triggering in all FU's which support
1680  * the operation. If operation not found, is not gcu or
1681  * multiple FU's have different triggers, returns 0
1682  */
1683 int
1685  const Operation& operation,
1686  const TTAMachine::Machine& machine) {
1687 
1688  const TCEString& opName = operation.name();
1691 
1692  int trigger = 0;
1693  for (int i = 0; i < fuNav.count(); i++) {
1694  TTAMachine::FunctionUnit& fu = *fuNav.item(i);
1695  if (fu.hasOperation(opName)) {
1696  TTAMachine::HWOperation& hwop = *fu.operation(opName);
1697  for (int j = 1; j <= operation.numberOfInputs(); j++) {
1698  TTAMachine::FUPort& port = *hwop.port(j);
1699  if (port.isTriggering()) {
1700  if (trigger == 0) {
1701  trigger = j;
1702  } else {
1703  if (trigger != j) {
1704  return 0;
1705  }
1706  }
1707  }
1708  }
1709  }
1710  }
1711  return trigger;
1712 }
1713 
1714 /**
1715  * If the operation is commutative, tries to change the operands so that
1716  * the scheduler can schedule it better.
1717  *
1718  * If the operation is not commutative, does nothing.
1719  *
1720  * Which is better depends lots on the code being compiled and architecture
1721  * which we are compiling for.
1722  *
1723  * Current implementation tries to make constants triggers,
1724  * and if there are no constant inputs, try to also change inputs so
1725  * that last ready operand becomes trigger if it's near,
1726  * but first ready operand becomes trigger if it's further
1727  * (allows better bypassing of other operands)
1728  * This seems to work in practice
1729  *
1730  * @param po programoperation whose inputs to switch
1731  * @return true if changed inputs, false if not.
1732  */
1733 bool
1735  const Operation& op = po.operation();
1736  if (op.numberOfInputs() == 2 && op.canSwap(1, 2)) {
1737 
1738  int triggerOperand = getTriggerOperand(op, *targetMachine_);
1739 
1740  if (triggerOperand != 0) {
1741  MoveNode* latest = NULL;
1742  int latestMinCycle = -1;
1743  int firstMinCycle = INT_MAX;
1744 
1745  //check all input moves.
1746  for (int i = 0; i < po.inputMoveCount(); i++) {
1747  MoveNode& node = po.inputMove(i);
1748  // always make constants triggers.
1749  // todo: shoudl do this only with short imms?
1750  if (node.isSourceConstant()) {
1751  int operandIndex =
1752  node.move().destination().operationIndex();
1753  if (operandIndex != triggerOperand) {
1754  po.switchInputs();
1755  return true;
1756  } else {
1757  return false;
1758  }
1759  }
1760 
1761  int minCycle = ddg_->earliestCycle(
1762  node, rm_->initiationInterval(), false, false, true, true);
1763  if (minCycle > latestMinCycle) {
1764  latest = &node;
1765  latestMinCycle = minCycle;
1766  }
1767  if (minCycle < firstMinCycle) {
1768  firstMinCycle = minCycle;
1769  }
1770  }
1771 
1772  int lastOperand = latest->move().destination().operationIndex();
1773 
1774  // don't change if min cycles of first and alst are equal.
1775  if (latestMinCycle == firstMinCycle) {
1776  return false;
1777  }
1778  if (latestMinCycle - firstMinCycle > 1) { // reverse logic if far.
1779  if (lastOperand == triggerOperand) {
1780  po.switchInputs();
1781  return true;
1782  }
1783  } else {
1784  if (lastOperand != triggerOperand) {
1785  po.switchInputs();
1786  return true;
1787  }
1788  }
1789  }
1790  }
1791  return false;
1792 }
1793 
1794 /**
1795  * Checks if the result moves that were removed might remove some
1796  * resource bottleneck of already scheduled moves.
1797  *
1798  * This situation happens at least when a result move used the last RF write
1799  * port for a cycle and limited the earliest cycle of a previously scheduled
1800  * move. Thus, after the last use of that result was scheduled and bypassed,
1801  * the RF write port is freed as the result move becomes unnecessary, thus
1802  * the move that was scheduled before could be scheduled earlier. Same
1803  * thing can happen for bus (move slot) contrained moves and also moves
1804  * that were restricted by a WaR edge due to the result move, etc.
1805  */
1806 void
1808  std::set<std::pair<TTAProgram::Move*, int> > removedMoves) {
1809 
1810  if (removedMoves.size() == 0)
1811  return;
1812 
1813 #ifndef RESCHEDULE_NEXT_CYCLE_AFTER_DRE
1814  return;
1815 #endif
1816 
1817  const bool DEBUG_PRINT = false; //Application::verboseLevel() > 0;
1818 
1819  if (DEBUG_PRINT) {
1821  << removedMoves.size() << " dead results eliminated: "
1822  << std::endl;
1823  }
1824 
1825  for (std::set<std::pair<TTAProgram::Move*, int> >::
1826  const_iterator i = removedMoves.begin();
1827  i != removedMoves.end(); ++i) {
1828 
1829  TTAProgram::Move& eliminatedMove = *(*i).first;
1830  int cycle = (*i).second;
1831 
1832  if (DEBUG_PRINT) {
1834  << eliminatedMove.toString() << " (cycle " << cycle << ") ";
1835  }
1836 
1837  int oldCycle = cycle + 1;
1838  // look for already scheduled moves that were scheduled after
1839  // the cycle of the result move, thus potentially were limited by
1840  // the result move earlier
1841  DataDependenceGraph::NodeSet nextCycleMoves =
1842  ddg_->movesAtCycle(oldCycle);
1843 
1844  // if true, try to reschedule all moves at the next cycle (slower,
1845  // but handles the case when the cycle was bus constrained previously),
1846  // if false, tries to schedule only potentially RF write port
1847  // constrained moves (faster)
1848  bool rescheduleAllSucceedingMoves = false;
1849  for (DataDependenceGraph::NodeSet::const_iterator m =
1850  nextCycleMoves.begin(); m != nextCycleMoves.end(); ++m) {
1851  MoveNode& moveNode = **m;
1852 
1853  if (rescheduleAllSucceedingMoves ||
1854  (moveNode.move().destination().isGPR() &&
1855  &eliminatedMove.destination().registerFile() ==
1856  &moveNode.move().destination().registerFile())) {
1857 
1858  if (DEBUG_PRINT) {
1860  << "Trying to reschedule "
1861  << moveNode.toString() << " " << std::endl;
1862  }
1863 
1864  assert(moveNode.isScheduled() && moveNode.cycle() == oldCycle);
1865 
1866  unschedule(moveNode);
1867  // because a pontially removed WaR, we might be able to
1868  // schedule this move (write to the same reg) even earlier
1869  // than the dead result move cycle
1870  scheduleMove(moveNode, std::max(oldCycle - 10, 0), false);
1871 
1872  if (!moveNode.isScheduled()) {
1873  for (int c = 4; c >= 0; --c) {
1875  << "\t\t" << oldCycle - c << ": "
1876  << rm_->instruction(
1877  std::max(oldCycle - c, 0))->toString()
1878  << std::endl;
1879  }
1880  assert(moveNode.isScheduled());
1881  }
1882 
1883  if (moveNode.cycle() < oldCycle) {
1884  if (DEBUG_PRINT) {
1886  << " OK at cycle " << moveNode.cycle() << ". " << std::endl;
1887  }
1888  } else {
1889  // should not get worse schedule!
1890  assert(moveNode.cycle() == oldCycle);
1891  if (DEBUG_PRINT) {
1892  Application::logStream() << " NO change. " << std::endl;
1893  }
1894  }
1895 
1896  }
1897  /// @todo: reschedule also the moves dependent from the
1898  /// rescheduled ones that got earlier
1899  }
1900 
1901  if (DEBUG_PRINT) {
1902  Application::logStream() << std::endl;
1903  }
1904  }
1905 }
1906 
1907 void
1909  if (Application::verboseLevel() > 0) {
1910  }
1911 }
1912 
1913 /**
1914  * Tries to get rid of WaW dependence from unconditional to conditional.
1915  *
1916  * if the conditional move's result is overwritten by the cond for
1917  * all users, make the unconditional move conditional, with opposite guard.
1918  */
1919 bool
1921 
1922  if (ddg_->earliestCycle(moveNode, 0 , false, true) >=
1923  ddg_->earliestCycle(moveNode)) {
1924  return false;
1925  }
1926 
1927  MoveNode* wawPred = NULL;
1928  DataDependenceEdge* wawEdge = NULL;
1929 
1930  DataDependenceGraph::EdgeSet inEdges = ddg_->inEdges(moveNode);
1931  for (DataDependenceGraph::EdgeSet::iterator i = inEdges.begin();
1932  i != inEdges.end(); i++) {
1933  DataDependenceEdge* e = *i;
1934 
1937  !e->tailPseudo()) {
1938  if (wawPred == NULL) {
1939  wawPred = &ddg_->tailNode(**i);
1940  wawEdge = e;
1941  } else {
1942  return false;
1943  }
1944  }
1945  }
1946  if (wawPred == NULL) {
1947  return false;
1948  }
1949 
1950  assert(wawPred->isScheduled());
1951  int wawPredCycle = wawPred->cycle();
1952 
1953  if (!wawPred->move().isUnconditional()) {
1954  return false;
1955  }
1956 
1957  DataDependenceGraph::NodeSet gdMoves = ddg_->guardDefMoves(moveNode);
1958  for (DataDependenceGraph::NodeSet::iterator i = gdMoves.begin();
1959  i != gdMoves.end(); i++) {
1960  MoveNode& mn = **i;
1961  assert(mn.isScheduled());
1962  if (mn.cycle() + moveNode.guardLatency() > wawPredCycle) {
1963  return false;
1964  }
1965  }
1966 
1967  // check that no other usage of the data.
1968  DataDependenceGraph::NodeSet consumers = ddg_->regRawSuccessors(*wawPred);
1969  DataDependenceGraph::NodeSet consumers2 = ddg_->regRawSuccessors(moveNode);
1970  for (DataDependenceGraph::NodeSet::iterator i = consumers.begin();
1971  i != consumers.end(); i++) {
1972  MoveNode* mn = *i;
1973  if (consumers2.find(mn) == consumers2.end() &&
1974  (mn->move().isUnconditional() ||
1975  !ddg_->exclusingGuards(*mn, moveNode))) {
1976  return false;
1977  }
1978  }
1979 
1980  unschedule(*wawPred);
1981 
1983  wawPred->move().setGuard(cg.createInverseGuard(moveNode.move().guard()));
1984 
1985  ddg_->copyDepsOver(*wawPred, true, false);
1986 
1987  ddg_->copyIncomingGuardEdges(moveNode, *wawPred);
1988  ddg_->copyOutgoingGuardWarEdges(moveNode, *wawPred);
1989 
1990  ddg_->removeEdge(*wawEdge);
1991 
1992  bool revert = false;
1993 
1994  try {
1995  scheduleMove(*wawPred, wawPredCycle, false);
1996 
1997  if (!wawPred->isScheduled()) {
1998  revert = true;
1999  }
2000  if (wawPred->isScheduled() && wawPred->cycle() > wawPredCycle) {
2001  unschedule(*wawPred);
2002  revert = true;
2003  }
2004  } catch (Exception&e) {
2005  revert = true;
2006  }
2007 
2008  if (revert) {
2009  wawPred->move().setGuard(NULL);
2010  ddg_->removeIncomingGuardEdges(*wawPred);
2011  ddg_->removeOutgoingGuardWarEdges(*wawPred);
2012  scheduleMove(*wawPred, wawPredCycle, false);
2013  ddg_->connectNodes(*wawPred, moveNode, *wawEdge);
2014  return false;
2015  }
2016 
2017  return true;
2018 }
2019 
2020 void
2022 
2023  // try to then push non-triggers back
2024  // to as close as possible to tirggers.
2025  // this frees up the FU to be used fr other operations before
2026  // this operation.
2027  // first search first cycle when this FU is used.
2028 
2029  int ec = INT_MAX;
2030  MoveNode* trigger = NULL;
2031  for (int i = 0; i < moves.nodeCount(); i++) {
2032  MoveNode& moveNode = moves.node(i);
2033  if (!moveNode.isDestinationOperation()) {
2034  continue;
2035  }
2036  if (moveNode.move().isTriggering()) {
2037  trigger = &moveNode;
2038  } else {
2039  int oldCycle = moveNode.cycle();
2040  if (oldCycle < ec) {
2041  ec = oldCycle;
2042  }
2043  }
2044  }
2045 
2046  int triggerCycle = trigger->cycle();
2047 
2048  bool failed = false;
2049  while (ec < triggerCycle && !failed) {
2050  for (int i = 0; i < moves.nodeCount(); i++) {
2051  MoveNode& moveNode = moves.node(i);
2052  if (!moveNode.isDestinationOperation()) {
2053  continue;
2054  }
2055  if (&moveNode != trigger) {
2056  int oldCycle = moveNode.cycle();
2057  if (oldCycle == ec) {
2058  int latest = ddg_->latestCycle(moveNode);
2059  if (latest > oldCycle) {
2060  latest = std::min(latest, triggerCycle);
2061  assert(latest >= ec);
2062  rm_->unassign(moveNode);
2063  int latestrm = rm_->latestCycle(latest, moveNode);
2064  if (latestrm == ec) {
2065  failed = true;
2066  }
2067  assert(latestrm >= ec);
2068  rm_->assign(latestrm, moveNode);
2069  } else {
2070  failed = true;
2071  }
2072  }
2073  }
2074  }
2075  ec = INT_MAX;
2076  // first earliest scheduled operands.
2077  for (int i = 0; i < moves.nodeCount(); i++) {
2078  MoveNode& moveNode = moves.node(i);
2079  if (!moveNode.isDestinationOperation()) {
2080  continue;
2081  }
2082  if (&moveNode != trigger) {
2083  int oldCycle = moveNode.cycle();
2084  if (oldCycle < ec) {
2085  ec = oldCycle;
2086  }
2087  }
2088  }
2089  }
2090 }
2091 
2092 // find which movenode is the trigger of an operation.
2093 MoveNode*
2095  const ProgramOperation& po, const TTAMachine::Machine& mach) {
2096 
2097  MoveNode* triggerFromPO = po.triggeringMove();
2098  if (triggerFromPO) {
2099  return triggerFromPO;
2100  }
2101 
2102  // no scheduled moves. getting harder.
2103 
2105  mach.functionUnitNavigator();
2106  MoveNode* candidate = NULL;
2107  for (int i = 0; i < nav.count(); i++) {
2108  TTAMachine::FunctionUnit* fu = nav.item(i);
2109  if (fu->hasOperation(po.operation().name())) {
2110  if (candidate == NULL) {
2111  candidate = findTriggerFromUnit(po, *fu);
2112  } else {
2113  // make sure two different FU's don't have different
2114  // trigger ports.
2115  if (findTriggerFromUnit(po, *fu) != candidate) {
2116  return NULL;
2117  }
2118  }
2119  }
2120  }
2121 
2122  if (mach.controlUnit()->hasOperation(po.operation().name())) {
2123  return findTriggerFromUnit(po, *mach.controlUnit());
2124  }
2125  return candidate;
2126 
2127 }
2128 
2129 MoveNode*
2131  const ProgramOperation& po, const TTAMachine::Unit& unit) {
2132  const TTAMachine::FunctionUnit* fu =
2133  dynamic_cast<const TTAMachine::FunctionUnit*>(&unit);
2134  int ioIndex = -1;
2135 
2136  int portC = fu->portCount();
2137  for (int i = 0; i < portC; i++) {
2138  auto p = fu->port(i);
2139  const TTAMachine::FUPort* port = dynamic_cast<const TTAMachine::FUPort*>(p);
2140  if (port != nullptr && port->isTriggering()) {
2141  const TTAMachine::HWOperation* hwop =
2142  fu->operation(po.operation().name());
2143  ioIndex = hwop->io(*port);
2144  return &po.inputNode(ioIndex).at(0);
2145  }
2146  }
2147  return NULL;
2148 }
ProgramOperation::operation
const Operation & operation() const
Definition: ProgramOperation.cc:590
CriticalPathBBMoveNodeSelector
Definition: CriticalPathBBMoveNodeSelector.hh:70
DataDependenceGraph::lastScheduledRegisterRead
MoveNode * lastScheduledRegisterRead(const TTAMachine::BaseRegisterFile &rf, int registerIndex, int lastCycleToTest=INT_MAX) const
Definition: DataDependenceGraph.cc:766
RegisterCopyAdder::AddedRegisterCopies
Definition: RegisterCopyAdder.hh:104
TTAProgram::Terminal::isTriggering
virtual bool isTriggering() const
Definition: Terminal.cc:298
BasicBlockScheduler::ddg_
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
Definition: BasicBlockScheduler.hh:152
SoftwareBypasser::setSelector
virtual void setSelector(MoveNodeSelector *selector)
Definition: SoftwareBypasser.cc:143
BoostGraph::connectNodes
virtual void connectNodes(const Node &nTail, const Node &nHead, Edge &e)
Operation::writesMemory
virtual bool writesMemory() const
Definition: Operation.cc:252
TTAProgram::Move::isTriggering
bool isTriggering() const
Definition: Move.cc:284
DataDependenceGraph::removeIncomingGuardEdges
void removeIncomingGuardEdges(MoveNode &node)
Definition: DataDependenceGraph.cc:5466
BasicBlockScheduler::unschedule
void unschedule(MoveNode &moveNode)
Definition: BasicBlockScheduler.cc:1488
BoostGraph::removeEdge
virtual void removeEdge(Edge &e)
DataDependenceGraph::regRawSuccessors
NodeSet regRawSuccessors(const MoveNode &node) const
Definition: DataDependenceGraph.cc:4272
BasicBlockScheduler::~BasicBlockScheduler
virtual ~BasicBlockScheduler()
Definition: BasicBlockScheduler.cc:95
BoostGraph::tailNode
virtual Node & tailNode(const Edge &edge) const
SimpleResourceManager::largestCycle
virtual int largestCycle() const override
Definition: SimpleResourceManager.cc:463
DataDependenceGraph::scheduledNodeCount
int scheduledNodeCount() const
Definition: DataDependenceGraph.cc:1859
MoveNode::toString
std::string toString() const
Definition: MoveNode.cc:576
Operation::hasSideEffects
virtual bool hasSideEffects() const
Definition: Operation.cc:272
MoveNodeGroup::node
MoveNode & node(int index) const
Definition: MoveNodeGroup.cc:152
TTAProgram::Terminal::index
virtual int index() const
Definition: Terminal.cc:274
BasicBlockScheduler::succeedingTempMove
MoveNode * succeedingTempMove(MoveNode &current)
Definition: BasicBlockScheduler.cc:1410
RegisterCopyAdder
Definition: RegisterCopyAdder.hh:91
machine
TTAMachine::Machine * machine
the architecture definition of the estimated processor
Definition: EstimatorCmdLineUI.cc:59
TTAMachine::HWOperation
Definition: HWOperation.hh:52
BoostGraph::node
Node & node(const int index) const
TTAProgram::Terminal::registerFile
virtual const TTAMachine::RegisterFile & registerFile() const
Definition: Terminal.cc:225
MoveNode::isDestinationOperation
bool isDestinationOperation() const
TTAProgram::Move::isReturn
bool isReturn() const
Definition: Move.cc:259
DataDependenceGraph::findLimitingAntidependenceSource
MoveNode * findLimitingAntidependenceSource(MoveNode &mn)
Definition: DataDependenceGraph.cc:5272
DataDependenceGraph::findLoopLimitAndIndex
std::pair< MoveNode *, MoveNode * > findLoopLimitAndIndex(MoveNode &jumpMove)
Definition: DataDependenceGraph.cc:4618
BoostGraph< MoveNode, DataDependenceEdge >::NodeSet
std::set< MoveNode *, typename MoveNode ::Comparator > NodeSet
Definition: BoostGraph.hh:86
BasicBlockScheduler::selector_
MoveNodeSelector * selector_
Definition: BasicBlockScheduler.hh:167
TTAProgram::Move::isUnconditional
bool isUnconditional() const
Definition: Move.cc:154
MapTools.hh
TTAProgram::AnnotatedInstructionElement::setAnnotation
void setAnnotation(const ProgramAnnotation &annotation)
Definition: AnnotatedInstructionElement.cc:79
BasicBlockScheduler::scheduleResultReadTempMoves
void scheduleResultReadTempMoves(MoveNode &resultMove, MoveNode &resultRead, int lastUse)
Definition: BasicBlockScheduler.cc:1442
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
DataDependenceGraph::scheduledMoves
NodeSet scheduledMoves() const
Definition: DataDependenceGraph.cc:1375
Operation::numberOfInputs
virtual int numberOfInputs() const
Definition: Operation.cc:192
TTAProgram::Instruction::toString
std::string toString() const
Definition: Instruction.cc:576
ProgramOperation::switchInputs
void switchInputs(int idx1=1, int idx2=2)
Definition: ProgramOperation.cc:795
DataDependenceGraph.hh
ProgramOperation
Definition: ProgramOperation.hh:70
TTAProgram::Move::setGuard
void setGuard(MoveGuard *guard)
Definition: Move.cc:360
TTAProgram::Move::toString
std::string toString() const
Definition: Move.cc:436
MoveNode
Definition: MoveNode.hh:65
MoveNode::isSourceConstant
bool isSourceConstant() const
Definition: MoveNode.cc:238
BasicBlockScheduler::unscheduleResultReadTempMoves
void unscheduleResultReadTempMoves(MoveNode &resultMove)
Definition: BasicBlockScheduler.cc:1553
BasicBlockScheduler::BasicBlockScheduler
BasicBlockScheduler(InterPassData &data, SoftwareBypasser *bypasser=NULL, RegisterRenamer *renamer=NULL)
Definition: BasicBlockScheduler.cc:85
BasicBlockScheduler::longDescription
virtual std::string longDescription() const
Definition: BasicBlockScheduler.cc:1587
MoveNodeSelector::notifyScheduled
virtual void notifyScheduled(MoveNode &node)=0
Definition: MoveNodeSelector.cc:70
TTAMachine::FunctionUnit::port
virtual BaseFUPort * port(const std::string &name) const
Definition: FunctionUnit.cc:145
Application::verboseLevel
static int verboseLevel()
Definition: Application.hh:176
BasicBlockScheduler::options_
LLVMTCECmdLineOptions * options_
Definition: BasicBlockScheduler.hh:173
SimpleResourceManager::assign
virtual void assign(int cycle, MoveNode &node, const TTAMachine::Bus *bus=NULL, const TTAMachine::FunctionUnit *srcFU=NULL, const TTAMachine::FunctionUnit *dstFU=NULL, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) override
Definition: SimpleResourceManager.cc:221
DataDependenceEdge::EDGE_REGISTER
@ EDGE_REGISTER
Definition: DataDependenceEdge.hh:53
Application::logStream
static std::ostream & logStream()
Definition: Application.cc:155
TTAMachine::Machine::Navigator::count
int count() const
MoveNodeGroup::nodeCount
int nodeCount() const
Definition: MoveNodeGroup.cc:140
DataDependenceGraph::sanityCheck
void sanityCheck() const
Definition: DataDependenceGraph.cc:1399
SimpleResourceManager::initiationInterval
virtual unsigned initiationInterval() const
Definition: SimpleResourceManager.hh:135
TTAMachine::FUPort::isTriggering
virtual bool isTriggering() const
Definition: FUPort.cc:182
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
DataDependenceEdge::dependenceType
DependenceType dependenceType() const
Definition: DataDependenceEdge.hh:88
BasicBlockScheduler.hh
SimpleResourceManager::unassign
virtual void unassign(MoveNode &node) override
Definition: SimpleResourceManager.cc:252
LLVMTCECmdLineOptions::dumpDDGsDot
virtual bool dumpDDGsDot() const
Definition: LLVMTCECmdLineOptions.cc:359
BasicBlockScheduler::findTriggerFromUnit
static MoveNode * findTriggerFromUnit(const ProgramOperation &po, const TTAMachine::Unit &unit)
Definition: BasicBlockScheduler.cc:2130
Conversion::toString
static std::string toString(const T &source)
DataDependenceEdge::tailPseudo
bool tailPseudo() const
Definition: DataDependenceEdge.hh:109
BasicBlockScheduler::handleLoopDDG
virtual int handleLoopDDG(DataDependenceGraph &ddg, SimpleResourceManager &rm, const TTAMachine::Machine &targetMachine, int tripCount, SimpleResourceManager *prologRM, bool testOnly=false) override
Definition: BasicBlockScheduler.cc:254
ProgramOperation::triggeringMove
MoveNode * triggeringMove() const
Definition: ProgramOperation.cc:643
BasicBlockScheduler::scheduleMove
void scheduleMove(MoveNode &move, int earliestCycle, bool allowPredicationAndRenaming)
Definition: BasicBlockScheduler.cc:950
BasicBlockScheduler::minCycle_
int minCycle_
The earliest cycle to schedule moves in. Used to leave room for sched_yield() by the sched_yield() em...
Definition: BasicBlockScheduler.hh:165
BasicBlockScheduler::tripCount_
int tripCount_
Definition: BasicBlockScheduler.hh:177
BasicBlockScheduler::scheduleOperandWrites
int scheduleOperandWrites(int &cycle, MoveNodeGroup &moves)
Definition: BasicBlockScheduler.cc:633
DataDependenceGraph::guardDefMoves
NodeSet guardDefMoves(const MoveNode &moveNode)
Definition: DataDependenceGraph.cc:743
SoftwareBypasser::bypassNode
virtual int bypassNode(MoveNode &moveNode, int &lastOperandCycle, DataDependenceGraph &ddg, ResourceManager &rm)=0
SimValue
Definition: SimValue.hh:96
SoftwareBypasser::removeBypass
virtual void removeBypass(MoveNodeGroup &candidates, DataDependenceGraph &ddg, ResourceManager &rm)=0
Definition: SoftwareBypasser.cc:89
POMDisassembler.hh
DataDependenceGraph::setCycleGrouping
virtual void setCycleGrouping(bool flag)
Definition: DataDependenceGraph.cc:1738
Operation::canSwap
virtual bool canSwap(int id1, int id2) const
Definition: Operation.cc:470
MoveNode::isPlaced
bool isPlaced() const
Definition: MoveNode.cc:352
BasicBlockScheduler::findTrigger
static MoveNode * findTrigger(const ProgramOperation &po, const TTAMachine::Machine &mach)
Definition: BasicBlockScheduler.cc:2094
TCEString.hh
BasicBlockScheduler::scheduleRRMove
void scheduleRRMove(MoveNode &moveNode)
Definition: BasicBlockScheduler.cc:902
BasicBlockScheduler::targetMachine_
const TTAMachine::Machine * targetMachine_
The target machine we are scheduling the program against.
Definition: BasicBlockScheduler.hh:150
MoveNode::sourceOperation
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:453
BasicBlockPass
Definition: BasicBlockPass.hh:60
assert
#define assert(condition)
Definition: Application.hh:86
TTAProgram::TerminalImmediate::value
virtual SimValue value() const
Definition: TerminalImmediate.cc:75
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
TTAMachine::HWOperation::port
virtual FUPort * port(int operand) const
Definition: HWOperation.cc:320
UniversalMachine.hh
TTAMachine::FUPort
Definition: FUPort.hh:46
BasicBlockScheduler::shortDescription
virtual std::string shortDescription() const
Definition: BasicBlockScheduler.cc:1574
MoveNode::isMove
bool isMove() const
DataDependenceGraph::writeToXMLFile
void writeToXMLFile(std::string fileName) const
Definition: DataDependenceGraph.cc:1747
BasicBlockScheduler::ddgSnapshot
void ddgSnapshot(DataDependenceGraph &ddg, const std::string &name, DataDependenceGraph::DumpFileFormat format, bool final, bool resetCounter=false) const
Definition: BasicBlockScheduler.cc:1633
MoveNode::earliestResultReadCycle
int earliestResultReadCycle() const
Definition: MoveNode.cc:652
TTAMachine::Machine::controlUnit
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:345
TTAProgram::Terminal::operationIndex
virtual int operationIndex() const
Definition: Terminal.cc:364
CycleLookBackSoftwareBypasser.hh
TTAMachine::HWOperation::io
int io(const FUPort &port) const
Definition: HWOperation.cc:364
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
MoveNode::cycle
int cycle() const
Definition: MoveNode.cc:421
HWOperation.hh
MoveNode::guardLatency
int guardLatency() const
Definition: MoveNode.cc:779
TTAMachine::Unit
Definition: Unit.hh:51
TTAProgram::Move::isControlFlowMove
bool isControlFlowMove() const
Definition: Move.cc:233
BasicBlockScheduler::printStats
virtual void printStats() const
Definition: BasicBlockScheduler.cc:1908
DataDependenceGraph::largestCycle
int largestCycle() const
Definition: DataDependenceGraph.cc:1838
InvalidData
Definition: Exception.hh:149
BoostGraph< MoveNode, DataDependenceEdge >::EdgeSet
std::set< DataDependenceEdge *, typename DataDependenceEdge ::Comparator > EdgeSet
Definition: BoostGraph.hh:87
RegisterCopyAdder::addRegisterCopiesToRRMove
AddedRegisterCopies addRegisterCopiesToRRMove(MoveNode &moveNode, DataDependenceGraph *ddg)
Definition: RegisterCopyAdder.cc:212
Instruction.hh
MoveNodeSet::at
MoveNode & at(int index)
DataDependenceEdge::DEP_RAW
@ DEP_RAW
Definition: DataDependenceEdge.hh:47
LLVMTCECmdLineOptions.hh
RegisterRenamer::initialize
void initialize(DataDependenceGraph &ddg)
Definition: RegisterRenamer.cc:81
BasicBlockScheduler::handleRemovedResultMoves
void handleRemovedResultMoves(std::set< std::pair< TTAProgram::Move *, int > > removedMoves)
Definition: BasicBlockScheduler.cc:1807
DataDependenceGraph::DUMP_XML
@ DUMP_XML
Definition: DataDependenceGraph.hh:87
CmdLineOptions
Definition: CmdLineOptions.hh:54
Application.hh
TTAProgram::Move::guard
MoveGuard & guard() const
Definition: Move.cc:345
Application::cmdLineOptions
static CmdLineOptions * cmdLineOptions()
Definition: Application.cc:397
__func__
#define __func__
Definition: Application.hh:67
TTAMachine::Machine::functionUnitNavigator
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition: Machine.cc:380
CopyingDelaySlotFiller
Definition: CopyingDelaySlotFiller.hh:71
RegisterCopyAdder::operandsScheduled
void operandsScheduled(AddedRegisterCopies &copies, DataDependenceGraph &ddg)
Definition: RegisterCopyAdder.cc:2079
RegisterRenamer::renameSourceRegister
bool renameSourceRegister(MoveNode &node, bool loopScheduling, bool allowSameRf, bool differentRfOnlyDirectlyReachable, int latestCycle=INT_MAX)
Definition: RegisterRenamer.cc:617
RegisterCopyAdder::AddedRegisterCopies::count_
int count_
Definition: RegisterCopyAdder.hh:107
SimpleResourceManager::earliestCycle
virtual int earliestCycle(MoveNode &node, const TTAMachine::Bus *bus=NULL, const TTAMachine::FunctionUnit *srcFU=NULL, const TTAMachine::FunctionUnit *dstFU=NULL, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) const override
Definition: SimpleResourceManager.cc:278
TTAProgram::Terminal::isGPR
virtual bool isGPR() const
Definition: Terminal.cc:107
InterPassData
Definition: InterPassData.hh:48
Guard.hh
Exception::errorMessageStack
std::string errorMessageStack(bool messagesOnly=false) const
Definition: Exception.cc:138
CriticalPathBBMoveNodeSelector::candidates
virtual MoveNodeGroup candidates()
Definition: CriticalPathBBMoveNodeSelector.cc:148
Operation.hh
MoveNode::isSourceOperation
bool isSourceOperation() const
Definition: MoveNode.cc:168
DataDependenceGraph::copyIncomingGuardEdges
void copyIncomingGuardEdges(const MoveNode &src, MoveNode &dst)
Definition: DataDependenceGraph.cc:3865
TTAProgram::ProgramAnnotation::ANN_REQUIRES_LIMM
@ ANN_REQUIRES_LIMM
Definition: ProgramAnnotation.hh:125
DataDependenceGraph::DUMP_DOT
@ DUMP_DOT
Definition: DataDependenceGraph.hh:86
BasicBlockScheduler::unscheduleInputOperandTempMoves
void unscheduleInputOperandTempMoves(MoveNode &operandMove)
Definition: BasicBlockScheduler.cc:1532
BasicBlockScheduler::scheduleRRTempMoves
void scheduleRRTempMoves(MoveNode &regToRegMove, MoveNode &firstMove, int lastUse)
Definition: BasicBlockScheduler.cc:1297
TTAProgram::Move
Definition: Move.hh:55
BasicBlockScheduler::unscheduleAllNodes
void unscheduleAllNodes()
Definition: BasicBlockScheduler.cc:1511
TTAMachine::ControlUnit::delaySlots
int delaySlots() const
SoftwareBypasser::bypass
virtual int bypass(MoveNodeGroup &candidates, DataDependenceGraph &ddg, ResourceManager &rm, bool bypassTrigger)=0
Definition: SoftwareBypasser.cc:65
TTAMachine::FunctionUnit::hasOperation
virtual bool hasOperation(const std::string &name) const
Definition: FunctionUnit.cc:330
MoveNodeSelector
Definition: MoveNodeSelector.hh:45
Machine.hh
BasicBlockScheduler::handleDDG
virtual int handleDDG(DataDependenceGraph &ddg, SimpleResourceManager &rm, const TTAMachine::Machine &targetMachine, int minCycle=0, bool testOnly=false) override
Definition: BasicBlockScheduler.cc:109
Exception
Definition: Exception.hh:54
ModuleRunTimeError
Definition: Exception.hh:1043
SoftwareBypasser::removeDeadResults
virtual int removeDeadResults(MoveNodeGroup &candidates, DataDependenceGraph &ddg, ResourceManager &rm, std::set< std::pair< TTAProgram::Move *, int > > &removedMoves)=0
Definition: SoftwareBypasser.cc:116
MoveNodeSet
Definition: MoveNodeSet.hh:41
BasicBlockScheduler::scheduleInputOperandTempMoves
void scheduleInputOperandTempMoves(MoveNode &operandMove, MoveNode &operandWrite)
Definition: BasicBlockScheduler.cc:1344
LLVMTCECmdLineOptions
Definition: LLVMTCECmdLineOptions.hh:48
ProgramOperation::inputMoveCount
int inputMoveCount() const
Definition: ProgramOperation.cc:600
LLVMTCECmdLineOptions::dumpDDGsXML
virtual bool dumpDDGsXML() const
Definition: LLVMTCECmdLineOptions.cc:364
DataDependenceEdge::DEP_WAW
@ DEP_WAW
Definition: DataDependenceEdge.hh:49
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
Operation
Definition: Operation.hh:59
TTAProgram::AnnotatedInstructionElement::hasAnnotations
bool hasAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
Definition: AnnotatedInstructionElement.cc:165
MoveNodeGroup::toString
std::string toString() const
Definition: MoveNodeGroup.cc:248
BoostGraph::inEdges
virtual EdgeSet inEdges(const Node &node) const
GraphBase::writeToDotFile
virtual void writeToDotFile(const TCEString &fileName) const
BasicBlockScheduler::renamer_
RegisterRenamer * renamer_
Definition: BasicBlockScheduler.hh:161
DataDependenceGraph::earliestCycle
int earliestCycle(const MoveNode &moveNode, unsigned int ii=UINT_MAX, bool ignoreRegWaRs=false, bool ignoreRegWaWs=false, bool ignoreGuards=false, bool ignoreFUDeps=false, bool ignoreSameOperationEdges=false, bool assumeBypassing=false) const
Definition: DataDependenceGraph.cc:388
DataDependenceGraph::movesAtCycle
NodeSet movesAtCycle(int cycle) const
Definition: DataDependenceGraph.cc:699
ProgramOperation.hh
MoveNodeGroup::addNode
void addNode(MoveNode &node)
Definition: MoveNodeGroup.cc:70
SimValue::unsignedValue
unsigned int unsignedValue() const
Definition: SimValue.cc:919
BasicBlockScheduler::rm_
SimpleResourceManager * rm_
Resource Manager of the currently scheduled BB.
Definition: BasicBlockScheduler.hh:154
TTAProgram::TerminalImmediate
Definition: TerminalImmediate.hh:44
MoveNode::destinationOperation
ProgramOperation & destinationOperation(unsigned int index=0) const
DDGPass
Definition: DDGPass.hh:51
MoveNode::move
TTAProgram::Move & move()
SchedulerPass::interPassData
InterPassData & interPassData()
Definition: SchedulerPass.cc:53
SimValue::width
int width() const
Definition: SimValue.cc:103
MapTools::containsKey
static bool containsKey(const MapType &aMap, const KeyType &aKey)
CodeGenerator.hh
TTAProgram::ProgramAnnotation::ANN_STACKFRAME_PROCEDURE_RETURN
@ ANN_STACKFRAME_PROCEDURE_RETURN
precedure return jmp
Definition: ProgramAnnotation.hh:76
IllegalMachine
Definition: Exception.hh:878
TerminalImmediate.hh
RegisterCopyAdder::resultsScheduled
void resultsScheduled(AddedRegisterCopies &copies, DataDependenceGraph &ddg)
Definition: RegisterCopyAdder.cc:2108
BasicBlockScheduler::getTriggerOperand
int getTriggerOperand(const Operation &operation, const TTAMachine::Machine &machine)
Definition: BasicBlockScheduler.cc:1684
MoveNodeSet::addMoveNode
void addMoveNode(MoveNode &)
Definition: MoveNodeSet.cc:62
SimpleResourceManager::canTransportImmediate
virtual bool canTransportImmediate(const MoveNode &node, const TTAMachine::Bus *preAssignedBus=NULL) const
Definition: SimpleResourceManager.cc:411
DataDependenceGraph::exclusingGuards
bool exclusingGuards(const MoveNode &mn1, const MoveNode &mn2) const
Definition: DataDependenceGraph.cc:4480
InterPassData.hh
MoveNodeSet.hh
RegisterRenamer::renameDestinationRegister
bool renameDestinationRegister(MoveNode &node, bool loopScheduling, bool allowSameRf, bool differentRfOnlyDirectlyReachable, int earliestCycle=-1)
Definition: RegisterRenamer.cc:458
InstructionReference.hh
TCEString
Definition: TCEString.hh:53
FUPort.hh
BasicBlock.hh
ControlUnit.hh
BasicBlockScheduler::softwareBypasser_
SoftwareBypasser * softwareBypasser_
The software bypasser to use to bypass registers when possible.
Definition: BasicBlockScheduler.hh:159
DataDependenceGraph
Definition: DataDependenceGraph.hh:67
SoftwareBypasser
Definition: SoftwareBypasser.hh:52
RegisterRenamer::setSelector
void setSelector(MoveNodeSelector *selector)
Definition: RegisterRenamer.cc:1126
DataDependenceGraph::copyOutgoingGuardWarEdges
void copyOutgoingGuardWarEdges(const MoveNode &src, MoveNode &dst)
Definition: DataDependenceGraph.cc:3897
SimpleResourceManager::latestCycle
virtual int latestCycle(MoveNode &node, const TTAMachine::Bus *bus=NULL, const TTAMachine::FunctionUnit *srcFU=NULL, const TTAMachine::FunctionUnit *dstFU=NULL, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) const override
Definition: SimpleResourceManager.cc:349
DataDependenceGraph::criticalPathGraph
DataDependenceGraph * criticalPathGraph()
Definition: DataDependenceGraph.cc:3458
BasicBlockScheduler::scheduledTempMoves_
std::map< const MoveNode *, DataDependenceGraph::NodeSet > scheduledTempMoves_
Stores the MoveNodes that were scheduled as temp moves during scheduling of the operand move.
Definition: BasicBlockScheduler.hh:157
MoveNode::isOperationMove
bool isOperationMove() const
Definition: MoveNode.cc:253
TTAProgram::CodeGenerator
Definition: CodeGenerator.hh:53
ProgramOperation::inputNode
MoveNodeSet & inputNode(int in) const
Definition: ProgramOperation.cc:513
BasicBlockScheduler::scheduleResultReads
bool scheduleResultReads(MoveNodeGroup &moves)
Definition: BasicBlockScheduler.cc:847
RegisterCopyAdder.hh
SimpleResourceManager.hh
TTAProgram::Terminal::equals
virtual bool equals(const Terminal &other) const =0
MoveNodeGroup::isScheduled
bool isScheduled() const
Definition: MoveNodeGroup.cc:164
DataDependenceEdge
Definition: DataDependenceEdge.hh:43
MoveNode::isScheduled
bool isScheduled() const
Definition: MoveNode.cc:409
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
SimpleResourceManager
Definition: SimpleResourceManager.hh:58
BasicBlockScheduler::tryToSwitchInputs
bool tryToSwitchInputs(ProgramOperation &op)
Definition: BasicBlockScheduler.cc:1734
TTAProgram::ProgramAnnotation::ANN_CONNECTIVITY_MOVE
@ ANN_CONNECTIVITY_MOVE
A reg to reg move that was added because of missing connectivity between the original target and dest...
Definition: ProgramAnnotation.hh:123
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
TTAMachine::FunctionUnit::operation
virtual HWOperation * operation(const std::string &name) const
Definition: FunctionUnit.cc:363
BasicBlockScheduler::tryToOptimizeWaw
bool tryToOptimizeWaw(const MoveNode &moveNode)
Definition: BasicBlockScheduler.cc:1920
DataDependenceGraph::removeOutgoingGuardWarEdges
void removeOutgoingGuardWarEdges(MoveNode &node)
Definition: DataDependenceGraph.cc:5496
TTAProgram::ProgramAnnotation
Definition: ProgramAnnotation.hh:49
MoveNodeGroup
Definition: MoveNodeGroup.hh:48
TTAProgram::AnnotatedInstructionElement::removeAnnotations
void removeAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID)
Definition: AnnotatedInstructionElement.cc:146
DataDependenceGraph::DumpFileFormat
DumpFileFormat
Definition: DataDependenceGraph.hh:85
TTAProgram::CodeGenerator::createInverseGuard
static TTAProgram::MoveGuard * createInverseGuard(const TTAProgram::MoveGuard &mg, const TTAMachine::Bus *bus=NULL)
Definition: CodeGenerator.cc:837
SoftwareBypasser::clearCaches
virtual void clearCaches(DataDependenceGraph &ddg, bool removeDeadResults)=0
BasicBlockScheduler::tryToDelayOperands
void tryToDelayOperands(MoveNodeGroup &moves)
Definition: BasicBlockScheduler.cc:2021
TTAProgram::Terminal::isRA
virtual bool isRA() const
Definition: Terminal.cc:129
BoostGraph::name
virtual const TCEString & name() const
debugLog
#define debugLog(text)
Definition: Application.hh:95
DataDependenceGraph::copyDepsOver
EdgeSet copyDepsOver(MoveNode &node, bool anti, bool raw)
Definition: DataDependenceGraph.cc:2422
BoostGraph::nodeCount
int nodeCount() const
DataDependenceGraph::unscheduledMoves
NodeSet unscheduledMoves() const
Definition: DataDependenceGraph.cc:1355
BoostGraph::successors
virtual NodeSet successors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
RegisterRenamer
Definition: RegisterRenamer.hh:59
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
RegisterRenamer.hh
Operation::affectsCount
virtual int affectsCount() const
Definition: Operation.cc:402
DataDependenceEdge::edgeReason
EdgeReason edgeReason() const
Definition: DataDependenceEdge.hh:91
BasicBlockScheduler::notifyScheduled
void notifyScheduled(MoveNodeGroup &moves, MoveNodeSelector &selector)
Definition: BasicBlockScheduler.cc:1602
DDGMoveNodeSelector.hh
TTAProgram::Move::setSource
void setSource(Terminal *src)
Definition: Move.cc:312
ProgramOperation::inputMove
MoveNode & inputMove(int index) const
Definition: ProgramOperation.cc:621
TTAMachine::Machine
Definition: Machine.hh:73
BasicBlockScheduler::scheduleOperation
void scheduleOperation(MoveNodeGroup &moves)
Definition: BasicBlockScheduler.cc:401
CopyingDelaySlotFiller::ddg_
DataDependenceGraph * ddg_
Definition: CopyingDelaySlotFiller.hh:185
BasicBlockScheduler::schedulingTime_
boost::timer schedulingTime_
Time for getting the scheduling time for current basic block.
Definition: BasicBlockScheduler.hh:169
SimpleResourceManager::instruction
virtual TTAProgram::Instruction * instruction(int cycle) const override
Definition: SimpleResourceManager.cc:442
DataDependenceGraph::latestCycle
int latestCycle(const MoveNode &moveNode, unsigned int ii=UINT_MAX, bool ignoreRegAntideps=false, bool ignoreUnscheduledSuccessors=true, bool ignoreGuards=false, bool ignoreFUDeps=false, bool ignoreSameOperationEdges=false) const
Definition: DataDependenceGraph.cc:543
RegisterCopyAdder::addMinimumRegisterCopies
AddedRegisterCopies addMinimumRegisterCopies(ProgramOperation &programOperation, const TTAMachine::Machine &targetMachine, DataDependenceGraph *ddg)
Definition: RegisterCopyAdder.cc:139
BasicBlockScheduler::jumpNode_
MoveNode * jumpNode_
Definition: BasicBlockScheduler.hh:175