OpenASIP  2.0
CopyingDelaySlotFiller.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2011 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 CopyingDelaySlotFiller.cc
26  *
27  * Implementation of of CopyingDelaySlotFiller class.
28  *
29  * @author Heikki Kultala 2007-2009 (hkultala-no.spam-cs.tut.fi)
30  * @note rating: red
31  */
32 
33 #include <set>
34 #include <vector>
35 #include <list>
36 
37 #include "Machine.hh"
38 #include "UniversalMachine.hh"
39 #include "ControlUnit.hh"
40 #include "Immediate.hh"
41 #include "ImmediateUnit.hh"
42 #include "Guard.hh"
43 #include "UniversalFunctionUnit.hh"
44 
46 
47 #include "Move.hh"
49 #include "InstructionReference.hh"
51 #include "TerminalRegister.hh"
52 #include "SpecialRegisterPort.hh"
53 #include "MoveGuard.hh"
54 #include "Instruction.hh"
55 #include "MoveNode.hh"
56 #include "ProgramOperation.hh"
57 #include "SimpleResourceManager.hh"
58 #include "ControlFlowGraph.hh"
59 #include "DataDependenceGraph.hh"
60 #include "BasicBlock.hh"
61 
62 #include "POMDisassembler.hh"
64 #include "Program.hh"
65 #include "InterPassDatum.hh"
66 #include "InterPassData.hh"
67 #include "TCEString.hh"
68 #include "CodeGenerator.hh"
69 #include "TerminalFUPort.hh"
70 #include "Operation.hh"
71 
72 //using std::set;
73 using std::list;
74 using std::vector;
75 using namespace TTAProgram;
76 using namespace TTAMachine;
77 
78 IGNORE_COMPILER_WARNING("-Wstrict-overflow")
79 
80 /**
81  * Fill delay slots of given BB.
82  *
83  * @param jumpingBB BB to fill delay slots.
84  * @param delaySlots number of delay slots in the machine.
85  * @param fillFallThru fill from Fall-thru of jump BB?
86  */
87 bool
88 CopyingDelaySlotFiller::fillDelaySlots(
89  BasicBlockNode& jumpingBB, int delaySlots, bool fillFallThru) {
90  if (cfg_->hasMultipleUnconditionalSuccessors(jumpingBB)) {
91  bbnStatus_[&jumpingBB] = BBN_BOTH_FILLED;
92  return false;
93  }
94 
95  // do not try to fill loop scheduled, also skip epilog and prolog.
96  if (jumpingBB.isLoopScheduled() || jumpingBB.isHWLoop()) {
97  bbnStatus_[&jumpingBB] = BBN_BOTH_FILLED;
98  return false;
99  }
100 
101  bool cfgChanged = false;
102 
103  if (fillFallThru) {
104  switch (bbnStatus_[&jumpingBB]) {
105  case BBN_SCHEDULED:
106  bbnStatus_[&jumpingBB] = BBN_FALLTHRU_FILLED;
107  break;
108  case BBN_JUMP_FILLED:
109  bbnStatus_[&jumpingBB] = BBN_BOTH_FILLED;
110  break;
111  default:
112  assert(false);
113  }
114  } else {
115  switch (bbnStatus_[&jumpingBB]) {
116  case BBN_SCHEDULED:
117  bbnStatus_[&jumpingBB] = BBN_JUMP_FILLED;
118  break;
119  case BBN_FALLTHRU_FILLED:
120  bbnStatus_[&jumpingBB] = BBN_BOTH_FILLED;
121  break;
122  default:
123  assert(false);
124  }
125  }
126 
127  ControlFlowGraph::EdgeSet outEdges = cfg_->outEdges(jumpingBB);
128 
130  cfg_->program()->instructionReferenceManager();
131 
132  TTAProgram::BasicBlock& thisBB = jumpingBB.basicBlock();
133  std::pair<int, TTAProgram::Move*> jumpData = findJump(thisBB);
134  std::pair<Move*, std::shared_ptr<Immediate> > jumpAddressData;
135 
136  // should be the same
137  int jumpIndex = jumpData.first;
138  Move* jumpMove = jumpData.second;
139 
140  // need for imm source only if filling jump, not imm.
141  if (!fillFallThru) {
142  // jump needed only when filling jump, not fall-thru.
143  // not found?
144  if (jumpMove == NULL) {
145  return false;
146  }
147 
148  if (!jumpMove->source().isInstructionAddress()) {
149  // address comes from LIMM, search the write to limm reg.
150  jumpAddressData = findJumpImmediate(jumpIndex, *jumpMove, irm);
151  if (jumpAddressData.first == NULL &&
152  jumpAddressData.second == NULL) {
153  //Imm source not found, aborting
154  return false;
155  }
156  } else {
157  jumpAddressData.first = jumpMove;
158  }
159  }
160 
161  const RegisterFile* grFile = NULL;
162  unsigned int grIndex = 0;
163 
164  // lets be aggressive, fill more than just branch slots?
165  int maxFillCount = std::min(
166  delaySlots + 12,
167  thisBB.instructionCount() - thisBB.skippedFirstInstructions());
168 
169  int maxGuardedFillCount = 0;
170 
171  // if we have references to instructions in target BB, cannot put anything
172  // before them, so limit how many slots to fill at maximum.
173  for (int i = 1 ; i < thisBB.instructionCount(); i++) {
174  if (irm.hasReference(thisBB.instructionAtIndex(i))) {
175  maxFillCount = std::min(maxFillCount, thisBB.instructionCount()-i);
176  }
177  }
178 
179  // if we have conditional jump, find the predicate register
180  if (jumpMove != NULL && !jumpMove->isUnconditional()) {
181  maxGuardedFillCount = INT_MAX;
182  const Guard& g = jumpMove->guard().guard();
183  const RegisterGuard* rg = dynamic_cast<const RegisterGuard*>(&g);
184  if (rg != NULL) {
185  grFile = rg->registerFile();
186  grIndex = rg->registerIndex();
187  }
188 
189  // find when the predicate reg is written to and use that
190  // to limit how many to bypass.
191  MoveNode& jumpNode = ddg_->nodeOfMove(*jumpMove);
192  DataDependenceGraph::NodeSet guardDefs =
193  ddg_->guardDefMoves(jumpNode);
194  if (guardDefs.size() != 1) {
195  // many defs, don't know which is the critical one.
196  // fill only slots+jump ins
197  maxGuardedFillCount = std::min(maxGuardedFillCount,delaySlots+1);
198  } else {
199  MoveNode& guardDefMove = **guardDefs.begin();
200  if (&ddg_->getBasicBlockNode(guardDefMove) == &jumpingBB) {
201  SimpleResourceManager& rm =
202  *resourceManagers_[&jumpingBB.basicBlock()];
203 
204  int earliestToFill = guardDefMove.cycle() -
205  rm.smallestCycle() +
206  jumpNode.guardLatency();
207 
208  maxGuardedFillCount =
209  std::min(maxGuardedFillCount,
210  thisBB.instructionCount() - earliestToFill);
211  } else {
212  // guard written in previous BB?
213  // make sure not filled to first insrt if
214  // guard latency 2
215  maxGuardedFillCount =
216  std::min(maxGuardedFillCount,
217  thisBB.instructionCount() -
218  std::max(0,jumpNode.guardLatency()-1));
219  }
220  }
221  } // jump conditional
222 
223  // 1 or two items, big loop. These may come in either order, grr.
224  for (ControlFlowGraph::EdgeSet::iterator iter = outEdges.begin();
225  iter != outEdges.end(); iter++) {
226  int slotsFilled = 0;
227  int myMaxGuardedFillCount = maxGuardedFillCount;
228 
229  ControlFlowEdge& edge = **iter;
230  if (edge.isFallThroughEdge() != fillFallThru) {
231  continue;
232  }
233  if (edge.isCallPassEdge()) {
234  continue;
235  }
236 
237  BasicBlockNode& nextBBN = cfg_->headNode(edge);
238 
239  // cannot fill if the next is not normal BB.
240  if (!nextBBN.isNormalBB() || nextBBN.isLoopScheduled() ||
241  nextBBN.isHWLoop()) {
242  continue;
243  }
244 
245  int nextInsCount = nextBBN.basicBlock().instructionCount();
246  if (&nextBBN == &jumpingBB) {
247  // jump to itself. may not fill from instructions
248  // which are itself being filled.
249  maxFillCount = std::min(maxFillCount, nextInsCount/2);
250  } else {
251  // otherwise may fill all other target bb
252  maxFillCount = std::min(maxFillCount,nextInsCount);
253  }
254 
255  if (fillFallThru) {
256  if (jumpMove != NULL) {
257  // test that we can create an inverse guard
258  if (jumpMove->isUnconditional()) {
259  continue;
260  }
262  jumpMove->guard());
263  if (invG == NULL) {
264  myMaxGuardedFillCount = 0;
265  } else {
266  delete invG;
267  }
268  }
269 
270  // cannot remove ins if it has refs.
271  // -> cannot fill fall instrs which have refs
272  for (int i = 0; i < maxFillCount; i++) {
273  if (irm.hasReference(
274  nextBBN.basicBlock().instructionAtIndex(i))) {
275  maxFillCount = i;
276  }
277  }
278  }
279 
280  if (maxFillCount == 0) {
281  continue;
282  }
283 
284  // register copy added leaves some inter-bb edges..
285  // TODO: remove when registercopyadder handles
286  // inter-BB-antideps..
287 
288  // also delay slot filler itself does not create
289  // all edges, at least if filling fall-thru jumps.
290  // so always run the routine until fixed,
291  // if-fall-thru jumps enabled.
292 
293  // temporaty solution: fix only if temp reg adder effective
294 // if (!fullyConnected) {
295  ddg_->fixInterBBAntiEdges(jumpingBB, nextBBN, edge.isBackEdge());
296 // }
297 
298  Move* skippedJump;
299  // also try to fill into jump instruction.
300  // fillSize = delaySlots still adpcm-3-full-fails, should be +1
301  for (int fillSize = maxFillCount; fillSize > 0; fillSize--) {
302  int removeGuards = (fillSize > myMaxGuardedFillCount) ?
303  fillSize - myMaxGuardedFillCount : 0;
304  // then try to do the filling.
305  bool ok = tryToFillSlots(
306  jumpingBB, nextBBN, fillFallThru, jumpMove, fillSize,
307  removeGuards, grIndex, grFile, skippedJump, delaySlots);
308  if (ok) {
309  slotsFilled = fillSize;
310  break;
311  }
312  }
313 
314  // filled some slots?
315  if (slotsFilled != 0) {
316 
317  // filled from jump dest or fal-thru?
318  if (!fillFallThru) {
319  // have to update jump destination
320  cfgChanged |= updateJumpsAndCfg(
321  jumpingBB, nextBBN, edge, jumpAddressData.first,
322  jumpAddressData.second, jumpMove, slotsFilled,
323  skippedJump);
324  } else { // fall-thru, skip first instructions.
325  cfgChanged |= updateFTBBAndCfg(
326  jumpingBB, nextBBN, edge, slotsFilled);
327  }
328  }
329  }
330  return cfgChanged;
331 }
332 
334  BasicBlockNode& jumpingBB, BasicBlockNode& nextBBN,
335  ControlFlowEdge& edge, int slotsFilled) {
336 
338  cfg_->program()->instructionReferenceManager();
339 
340  for (int i = 0; i < slotsFilled; i++) {
341  assert(!irm.hasReference(
342  nextBBN.basicBlock().instructionAtIndex(i)));
343  }
344 
345  if (slotsFilled == nextBBN.basicBlock().instructionCount() &&
346  cfg_->inDegree(nextBBN) == 1) {
347  auto oEdges = cfg_->outEdges(nextBBN);
348  assert(oEdges.size() == 1);
349  ControlFlowEdge& laterEdge = **oEdges.begin();
350  BasicBlockNode& newDestNode = cfg_->headNode(laterEdge);
351 
352  // update CFG because jump dest moved.
353  // the predicate is the same as the original
354  // fall-trhough, but if later is a jump or call pass.
355  // this is also a jump or call pass.
356  ControlFlowEdge* newEdge =
357  new ControlFlowEdge(
358  edge.edgePredicate(), laterEdge.edgeType());
359  cfg_->disconnectNodes(jumpingBB, nextBBN);
360  cfg_->connectNodes(jumpingBB, newDestNode, *newEdge);
361 
362  cfg_->removeNode(nextBBN);
363  finishBB(nextBBN, true);
364 
365  for (int i = 0;
366  i < nextBBN.basicBlock().instructionCount(); i++) {
367  Instruction& ins =
368  nextBBN.basicBlock().instructionAtIndex(i);
369  while(ins.moveCount()) {
370  Move& move = ins.move(0);
371  MoveNode & mn = ddg_->nodeOfMove(move);
372  ddg_->removeNode(mn);
373  delete &mn;
374  ins.removeMove(move);
375  }
376  while (ins.immediateCount()) {
377  Immediate& imm = ins.immediate(0);
378  ins.removeImmediate(imm);
379  }
380  }
381  delete &nextBBN;
382  // cfg changed
383  return true;
384  } else {
385  nextBBN.basicBlock().skipFirstInstructions(slotsFilled);
386  // cfg not changed
387  return false;
388  }
389 }
390 
391 /**
392  * Constructor.
393  */
395 }
396 
397 /**
398  *
399  * Fills all delay slots for all BB's in the CFG.
400  *
401  * @param cfg ControlFlowGraph where to fill delay slots.
402  * @param ddg DataDependenceGraph containing data dependencies.
403  */
404 void
407  const TTAMachine::Machine& machine) {
409  int delaySlots = machine.controlUnit()->delaySlots();
410 
411  cfg_ = &cfg;
412  ddg_ = &ddg;
413 
414  // first fill only jumps
415  for (int i = 0; i < cfg.nodeCount(); i++) {
416  BasicBlockNode& bbn = cfg.node(i);
417  if (bbn.isNormalBB()) {
418  if (bbnStatus_[&bbn] == BBN_SCHEDULED ||
419  bbnStatus_[&bbn] == BBN_FALLTHRU_FILLED) {
420  fillDelaySlots(
421  bbn, delaySlots, false);
422  }
423  }
424  }
425 
426  // then fill only fall-thru's.
427  for (int i = 0; i < cfg.nodeCount(); i++) {
428  BasicBlockNode& bbn = cfg.node(i);
429  if (bbn.isNormalBB()) {
430  if (bbnStatus_[&bbn] == BBN_JUMP_FILLED) {
431  fillDelaySlots(
432  bbn, delaySlots, true);
433  }
434  }
435  }
436 
437  // All is done. Then get rid of data which is no longer needed.
438  for (std::map<BasicBlockNode*, BBNStates>::iterator i =
439  bbnStatus_.begin(); i != bbnStatus_.end(); i++) {
440  if (i->second != BBN_ALL_DONE) {
441  // todo: why is true required here
442  finishBB(*i->first); //, true);
443  }
444  }
445  // TODO: why is this not empty? finishBB should clear these.
446  for (std::map<BasicBlock*, SimpleResourceManager*>::iterator i =
447  resourceManagers_.begin(); i != resourceManagers_.end(); i++) {
448  if (i->second != NULL) {
450  }
451  }
452  resourceManagers_.clear();
453 // assert(resourceManagers_.empty());
454  tempResultNodes_.clear();
455 }
456 
457 /**
458  * Deletes all removed basic blocks. Can be called after bigddg is deleted.
459  */
461  AssocTools::deleteAllItems(killedBBs_);
462 }
463 
464 /**
465  * Checks if all jumps into given basic blocks are filled.
466  *
467  * @param bbn node to check for incoming filled jumps.
468  * @return true if all incoming jumps are already filled.
469 */
471  bool allJumpPredsFilled = true;
472  ControlFlowGraph::EdgeSet inEdges = cfg_->inEdges(bbn);
473  for (ControlFlowGraph::EdgeSet::iterator inIter =
474  inEdges.begin(); inIter != inEdges.end();
475  inIter++) {
476  ControlFlowEdge& cfe = **inIter;
477  if (cfe.isJumpEdge()) {
478  BasicBlockNode& jumpOrigin = cfg_->tailNode(cfe);
479 
480  // if some jump to the ft-node has not been scheduled.
481  if (jumpOrigin.isNormalBB() &&
482  (bbnStatus_[&jumpOrigin] < BBN_JUMP_FILLED ||
483  bbnStatus_[&jumpOrigin] == BBN_FALLTHRU_FILLED)) {
484  allJumpPredsFilled = false;
485  }
486  }
487  }
488  return allJumpPredsFilled;
489 }
490 
491 /**
492  * Checks whether all incoming jump basic blocks are scheduled.
493  *
494  * @param bbn basic block whose predecessors we are checking.
495  * @return true if all BB's which jump into given BB are scheduled.
496  */
497 bool
499  bool allPredsScheduled = true;
500  ControlFlowGraph::EdgeSet inEdges = cfg_->inEdges(bbn);
501  for (ControlFlowGraph::EdgeSet::iterator inIter =
502  inEdges.begin(); inIter != inEdges.end();
503  inIter++) {
504  ControlFlowEdge& cfe = **inIter;
505  if (cfe.isJumpEdge()) {
506  BasicBlockNode& jumpOrigin = cfg_->tailNode(cfe);
507 
508  // if some jump to the ft-node has not been scheduled.
509  if (bbnStatus_[&jumpOrigin] == BBN_UNKNOWN &&
510  jumpOrigin.isNormalBB()) {
511  allPredsScheduled = false;
512  }
513  }
514  }
515  return allPredsScheduled;
516 }
517 
518 /**
519  * Executed after delay slots of a BB has been filled.
520  *
521  * If both jump and fal-thru are filled, reletes the resource manager.
522  */
523 void
525  if (bbnStatus_[&bbn] == BBN_BOTH_FILLED) {
526  finishBB(bbn);
527  }
528 }
529 
530 /**
531  * Checks if jumps and fall-thrus into BB can be filled and fills them
532  * if it can
533  *
534  * @param bbn just destination basic block.
535  * @return if anything was filled.
536  */
538  if (bbnStatus_[&bbn] == BBN_UNKNOWN) {
539  return false;
540  }
541  if (!areAllJumpPredsScheduled(bbn)) {
542  return false;
543  }
544 
545  bool cfgChanged = false;
546  bool cfgChangedAfterRecheck = false;
547 
548  ControlFlowGraph::EdgeSet jumpEdges = cfg_->incomingJumpEdges(bbn);
549 
550  // first fill all incoming jumps.
551  for (auto inIter = jumpEdges.begin(); inIter != jumpEdges.end();) {
552  ControlFlowEdge& cfe = **inIter;
553  BasicBlockNode& jumpOrigin = cfg_->tailNode(cfe);
554 
555  if (jumpOrigin.isNormalBB() &&
556  (bbnStatus_[&jumpOrigin] == BBN_SCHEDULED ||
557  bbnStatus_[&jumpOrigin] == BBN_FALLTHRU_FILLED)) {
558 
559  bool changed = fillDelaySlots(jumpOrigin, delaySlots_, false);
560  cfgChanged |= changed;
561  cfgChangedAfterRecheck |= changed;
562 
563  bbFilled(jumpOrigin);
564 
565  BasicBlockNode* fallThruSisterNode =
566  cfg_->fallThruSuccessor(jumpOrigin);
567 
568  // so we have some left-behind sister NODE
569  if (fallThruSisterNode != NULL &&
570  bbnStatus_[fallThruSisterNode] > BBN_UNKNOWN &&
571  bbnStatus_[&jumpOrigin] < BBN_TEMPS_CLEANED &&
572  areAllJumpPredsFilled(*fallThruSisterNode)) {
573  changed = fillDelaySlots(jumpOrigin, delaySlots_, true);
574  cfgChanged |= changed;
575  cfgChangedAfterRecheck |= changed;
576  bbFilled(jumpOrigin);
577  // may have been removed totally.
578  }
579 
580  // If we changed the cfg, loafd the inedges again.
581  if (cfgChangedAfterRecheck) {
582  if (!cfg_->hasNode(bbn)) {
583  return true;
584  }
585  cfgChangedAfterRecheck = false;
586  jumpEdges = cfg_->incomingJumpEdges(bbn);
587  inIter = jumpEdges.begin();
588  continue;
589  }
590  }
591  inIter++;
592  }
593 
594  // No Fts to fill if the whole Basic Block is gone!
595  if (cfgChanged && !cfg_->hasNode(bbn)) {
596  return true;
597  }
598 
599  // then all incoming jumps should be filled, fall-throughs can fill
600  auto ftEdge = cfg_->incomingFTEdge(bbn);
601  // may still be call pass, which is not allowed.
602  if (ftEdge != nullptr && ftEdge->isFallThroughEdge()) {
603  BasicBlockNode& ftOrigin = cfg_->tailNode(*ftEdge);
604 
605  // fall thru-predecessor can be filled if it's scheduled.
606  if (bbnStatus_[&ftOrigin] == BBN_JUMP_FILLED) {
607  cfgChanged |= fillDelaySlots(ftOrigin, delaySlots_, true);
608  bbFilled(ftOrigin);
609  } else {
610  // do not take space from backwards jumps, ie loop jumps.
611  if (bbnStatus_[&ftOrigin] == BBN_SCHEDULED) {
612  BasicBlockNode* jumpSisterNode =
613  cfg_->jumpSuccessor(bbn);
614  if (jumpSisterNode != NULL &&
615  jumpSisterNode->originalStartAddress() >
616  bbn.originalStartAddress() &&
617  areAllJumpPredsFilled(*jumpSisterNode)) {
618 
619  cfgChanged |= fillDelaySlots(ftOrigin, delaySlots_, true);
620  bbFilled(ftOrigin);
621  }
622  }
623  }
624  }
625  return cfgChanged;
626 }
627 
628 /**
629  * Report to the ds filler that a bb has been scheduled.
630  *
631  * tries to fill some delay slots and then tries to get rid of the
632  * resource managers when no longer needed.
633  *
634  * addResourceManager() for the BB should be called before this
635  * method.
636  *
637  * @param bbn BasicBlockNode which has been scheduled.
638  */
639 void
641 
642  assert(bbnStatus_[&bbn] == BBN_UNKNOWN);
643  // if we don't have the RM got the bb, cannot really do much with it.
644  if (resourceManagers_.find(&bbn.basicBlock())==resourceManagers_.end()) {
645  return;
646  }
647 
648  bbnStatus_[&bbn] = BBN_SCHEDULED;
649 
650  // all successors.
651  ControlFlowGraph::EdgeSet oEdges = cfg_->outEdges(bbn);
652 
653  bool fillableSuccessor = false;
654  for (ControlFlowGraph::EdgeSet::iterator outIter = oEdges.begin();
655  outIter != oEdges.end();) {
656  ControlFlowEdge& cfe = **outIter;
657 
658  // cannot fill calls.
659  if (!cfe.isCallPassEdge()) {
660  fillableSuccessor = true;
661  auto& head = cfg_->headNode(cfe);
662  if (mightFillIncomingTo(head)) {
663  // the filling might have removed the BBN.
664  if (!cfg_->hasNode(bbn)) {
665  return;
666  }
667  oEdges = cfg_->outEdges(bbn);
668  outIter = oEdges.begin();
669  continue;
670  }
671  }
672  outIter++;
673  }
674 
675  if (!fillableSuccessor && bbnStatus_[&bbn] != BBN_ALL_DONE) {
676  finishBB(bbn);
677  }
678 
679  // can fill incoming jumps if all incoming BBs scheduled.
680  mightFillIncomingTo(bbn);
681 }
682 
683 
684 /*
685  * Adds a resource manager to the filler.
686  *
687  * @param bb Basic block which the resource manager handles.
688  * @param rm Resource manager or the bb.
689  */
690 void
693  resourceManagers_[&bb] = &rm;
694  rm.setMaxCycle(INT_MAX);
695 }
696 
697 /**
698  * Finds the immediate which contains the jump address.
699  *
700  * @param jumpIndex index of the instruction containin the jump in the BB.
701  * @param jumpMove the move containing the jump.
702  * @return Immediate containing jump address or NULL if not found.
703  */
704 std::pair<TTAProgram::Move*, std::shared_ptr<TTAProgram::Immediate> >
706  int jumpIndex, Move& jumpMove, InstructionReferenceManager& irm) {
707  BasicBlock& bb = static_cast<BasicBlock&>(jumpMove.parent().parent());
708  Move* irMove = &jumpMove;
709  int irIndex = jumpIndex;
710 
711  // Register copy or some unknown source.
712  // should handle unlimited number of reg. copies.
713  // Note: the jump address can be written outside the BB
714  // if it's an indirect branch (e.g. LLVM address of label
715  // extension).
716  if (irMove->source().isGPR()) {
717  const RegisterFile* rf = &irMove->source().registerFile();
718  int regIndex = static_cast<int>(irMove->source().index());
719  int found = false;
720  int i;
721  // if has refernces, the imm may be written in another BB.
722  // we can not (yet) track that!
723  if (irm.hasReference(bb.instructionAtIndex(irIndex))) {
724  return std::pair<Move*,std::shared_ptr<Immediate> >(nullptr, nullptr);
725  }
726  for (i = irIndex -1 ; i >= bb.skippedFirstInstructions() && !found;
727  i-- ) {
728  Instruction &ins = bb.instructionAtIndex(i);
729  // if has refernces, the imm may be written in another BB.
730  // we can not (yet) track that!
731  if (irm.hasReference(ins)) {
732  return std::pair<Move*,std::shared_ptr<Immediate> >(
733  nullptr, nullptr);
734  }
735  for (int j = 0; j < ins.moveCount(); j++ ) {
736  Move& move = ins.move(j);
737  if (move.destination().isGPR()) {
738  if (&move.destination().registerFile() == rf &&
739  move.destination().index() == regIndex) {
740  irMove = &move;
741  irIndex = i;
742  found = true;
743  break;
744  }
745  }
746  }
747  }
748  // jump imm not found.
749  if (i < bb.skippedFirstInstructions() && !found) {
750  return std::pair<Move*,std::shared_ptr<Immediate> >(
751  nullptr, nullptr);
752  }
753  }
754  if (irMove->source().isImmediate()) {
755  return std::pair<Move*,std::shared_ptr<Immediate> >(irMove, nullptr);
756  }
757 
758  // then read the actual immediate
759  if (irMove->source().isImmediateRegister()) {
760  const ImmediateUnit& immu = irMove->source().immediateUnit();
761  int index = static_cast<int>(irMove->source().index());
762  for (int i = irIndex - immu.latency(); i >= 0; i--) {
763  Instruction &ins = bb.instructionAtIndex(i);
764  for (int j = 0; j < ins.immediateCount(); j++) {
765  auto imm = ins.immediatePtr(j);
766  if (imm->destination().index() == index &&
767  &imm->destination().immediateUnit() == &immu) {
768  return std::pair<Move*,std::shared_ptr<Immediate> >(
769  nullptr, imm);
770  }
771  }
772  // if has refernces, the imm may be written in another BB.
773  // we can not (yet) track that!
774  if (irm.hasReference(ins)) {
775  return std::pair<Move*,std::shared_ptr<Immediate> >(
776  nullptr, nullptr);
777  }
778  }
779  }
780  return std::pair<Move*, std::shared_ptr<Immediate> >(nullptr, nullptr);
781 }
782 /**
783  * Checks whether given move writes to given register
784  *
785  * @param move to check
786  * @param rf RegisterFile containing the register
787  * @param registerIndex index of the register.
788  */
790  Move& move, const RegisterFile* rf, unsigned int registerIndex) {
791  Terminal& term = move.destination();
792  if (term.isGPR()) {
793  TerminalRegister& rd = dynamic_cast<TerminalRegister&>(term);
794  if ( &rd.registerFile() == rf && rd.index() ==
795  static_cast<int>(registerIndex)) {
796  return true;
797  }
798  }
799  return false;
800 }
801 
802 /**
803  * Tries to fill n slots from other BB.
804  *
805  * Aborts cannot fill all of the slots
806  *
807  * @param blockToFill BB containing the delay slots.
808  * @param nextBB block where from to copy the instructions.
809  * @param slotsToFill how many slots tries to fill
810  * @param removeGuards how many first instructions need guard removed.
811  * @param grIndex index of the guard register of the jump
812  * @param grFile register file of the guard of the jump.
813  * @param skippedJump if we can skip BB which jumps, sets the skipped jump here
814  * @return of fill succeeded, false if failed.
815  */
816 bool
818  BasicBlockNode& blockToFillNode, BasicBlockNode& nextBBNode, bool fallThru,
819  Move* jumpMove, int slotsToFill, int removeGuards, int grIndex,
820  const RegisterFile* grFile, Move*& skippedJump, int delaySlots) {
821  skippedJump = NULL;
822  BasicBlock& blockToFill = blockToFillNode.basicBlock();
823  SimpleResourceManager& rm = *resourceManagers_[&blockToFill];
824  BasicBlock& nextBB = nextBBNode.basicBlock();
825  SimpleResourceManager* nextRm = resourceManagers_[&nextBB];
826 
827  if (nextRm == NULL) {
828  return false;
829  }
830 
831  int firstCycleToFill =
832  rm.smallestCycle() + blockToFill.instructionCount() - slotsToFill;
833  int nextBBStart = nextRm->smallestCycle();
834 
835  MoveNodeListVector moves(slotsToFill);
836 
837  // Collect all the moves to fill.
838  if (!collectMoves(
839  blockToFillNode, nextBBNode, moves, slotsToFill,fallThru,
840  removeGuards, jumpMove, grIndex, grFile, skippedJump,
841  delaySlots)) {
842  loseCopies(NULL);
843  return false;
844  }
845 
846  //check imm reads after (safeguard against same imm read twice)
847  if (!checkImmediatesAfter(nextBB, slotsToFill)) {
848  loseCopies(NULL);
849  return false;
850  }
851 
852  // now we have got all the movenodes we are going to fill.
853  // then try to assign them to the block where they are being filled to.
854 
855  // set containing po result moves etc.
856  DataDependenceGraph::NodeSet tempAssigns;
857  if (tryToAssignNodes(moves, slotsToFill, firstCycleToFill,rm, nextBBStart,
858  tempAssigns)) {
859  // we succeeded.
860  // delete temporaty copies of other movenodes.
861  loseCopies(&tempAssigns);
862 
863  AssocTools::append(tempAssigns, tempResultNodes_[&blockToFillNode]);
864  return true;
865  } else {
866  loseCopies(&tempAssigns);
867  unassignTempAssigns(tempAssigns, rm);
868  // failing. delete created movenodes and report failure
869  return false;
870  }
871 }
872 
873 /**
874  * Collects are moves which are to be filled
875  *
876  * @param blockToFillNode basic block node where to fill to
877  * @param nextBBN basic blocknode where to fill from
878  * @param moves place to store the collected nodes.
879  * @param slotsToFill how many delay slots to fill
880  * @param fallThru if filling fall-thru
881  * @param removeGuards how many first instructions need guard removed.
882  * @param jumpMove move which is the jump that is filled
883  * @param grIndex index of the guard register of the jump
884  * @param grFile register file of the guard of the jump.
885  * @param skippedJump if we can skip BB which jumps, sets the skipped jump here
886  *
887  * @return true if collecting ok, false if failed
888  */
889 bool
891  BasicBlockNode& blockToFillNode, BasicBlockNode& nextBBN,
892  MoveNodeListVector& moves, int slotsToFill, bool fallThru,
893  int removeGuards,
894  Move* jumpMove, int grIndex, const TTAMachine::RegisterFile* grFile,
895  Move*& skippedJump, int delaySlots) {
896  PendingImmediateMap pendingImmediateMap;
897 
898  ControlFlowEdge* connectingEdge =
899  *cfg_->connectingEdges(blockToFillNode, nextBBN).begin();
900  BasicBlock& bb = blockToFillNode.basicBlock();
901  BasicBlock& nextBB = nextBBN.basicBlock();
902  SimpleResourceManager& rm = *resourceManagers_[&bb];
903  SimpleResourceManager& nextRm = *resourceManagers_[&nextBB];
904 
905  int firstIndexToFill =
906  blockToFillNode.basicBlock().instructionCount() - slotsToFill;
907 
908  int cycleDiff = firstIndexToFill + rm.smallestCycle() - nextRm.smallestCycle();
909 
910  // Find all moves to copy and check their dependencies.
911  // Loop thru instructions first..
912  for (int i = 0; i < slotsToFill; i++) {
913  Instruction& filler = nextBB.instructionAtIndex(i);
914  if (filler.hasCall()) {
915  return false;
916  }
917 
918  // loop through all 0-latency immediates fo the instr.
919  for (int j = 0; j < filler.immediateCount(); j++) {
920  // TODO: why immediates not allowed here? what about allowing
921  // with 0-latency?
922  if (&blockToFillNode == &nextBBN) {
923  return false;
924  }
925 
926  TTAProgram::Immediate& imm = filler.immediate(j);
927  const TTAProgram::Terminal& dst = imm.destination();
928  const ImmediateUnit& immu = dst.immediateUnit();
929  if (immu.latency() == 0) {
930  TCEString immName = immu.name() + '.' +
932 
933  if (AssocTools::containsKey(pendingImmediateMap,immName)) {
934  // there already is write to this imm reg without
935  // a read to it? something is wrong, abort
936  return false;
937  }
938  pendingImmediateMap[immName] = &imm.value();
939  }
940  }
941 
942 
943  // loop thru all moves in the instr
944  for (int j = 0; j < filler.moveCount(); j++) {
945  Move& oldMove = filler.move(j);
946  bool dontGuard = i < removeGuards;
947  // may fill jump if fills the whole BB and updates the jump.
948  if (oldMove.isControlFlowMove()) {
949  if (oldMove.isJump()) {
950  if (!oldMove.isUnconditional()) {
951  // TODO: if first was uncond jump, and filling whole BB,
952  // this could be allowed.
953  return false;
954  }
955  if (fallThru) {
956  // Allow another jump only to same instruction
957  // than where the filled jump is.
958  if (i != slotsToFill - delaySlots -1) {
959  return false;
960  }
961  } else {
962  if (slotsToFill != nextBB.instructionCount() ||
963  // TODO: find a way to find the source imm of this jump
964  // even if LIMM or tempregcopy.
965  // then no need to abort here.
966  oldMove.source().isGPR() ||
967  oldMove.source().isImmediateRegister()) {
968  return false;
969  }
970  if (oldMove.source().isRA()) {
971  // If updating jumpMove with RA, it may result to an
972  // illegal instruction due to missing connectivity.
973  if (jumpMove == nullptr
975  jumpMove->bus(), oldMove.source().port())) {
976  return false;
977  }
978  }
979  skippedJump = &oldMove;
980  continue; // can be skipped
981  }
982  } else { // unknown cflow op
983  return false;
984  }
985 
986  }
987 
988  // TODO: should use guard latency here instead of -1
989  // check if it overwrites the guard of the jump
990  if (writesRegister(oldMove, grFile, grIndex)) {
991  // overwriting the guard reg as last thing does not matter,
992  // only allow it in last imported instruction.
993  if (i != slotsToFill-1) {
994  return false;
995  }
996  }
997 
998  // do not allow delay slot filling of lbufs op.
999  // this messes up at least the simulator.
1000  MoveNode& mnOld = ddg_->nodeOfMove(oldMove);
1001  if (mnOld.isDestinationOperation() &&
1002  mnOld.destinationOperation().operation().name() == "LBUFS"
1003  && slotsToFill != nextBB.instructionCount()) {
1004  return false;
1005  }
1006 
1007  // check all deps
1008  if (!oldMove.isUnconditional()) {
1009  // Do not fill with guarded moves, if jump is guarded,
1010  // might need 2 guards.
1011  // Only allowed if removing the guards anyway.
1012  if (jumpMove != NULL && !jumpMove->isUnconditional()) {
1013  dontGuard = true;
1014  }
1015  // don't allow unconditionals before
1016  // BB start + guard latency (if guard written in last move
1017  // of previous BB)
1018  if (firstIndexToFill < mnOld.guardLatency()-1) {
1019  return false;
1020  }
1021  }
1022 
1023  // if a move has no side effects, the guard can be omitted
1024  // and it can be scheduled before the guard is ready.
1025  if (dontGuard) {
1026  if (!allowedToSpeculate(mnOld)) {
1027  return false;
1028  }
1029  } else {
1030  // guard with a portguard? then do not (yet) allow src op.
1031  if (jumpMove != NULL && !jumpMove->isUnconditional() &&
1032  dynamic_cast<const PortGuard*>(&jumpMove->guard().guard())
1033  && mnOld.isSourceOperation()) {
1034  return false;
1035  }
1036  }
1037 
1038  // check DDG that no data hazards.
1039  if (!checkIncomingDeps(mnOld, blockToFillNode, cycleDiff)) {
1040  return false;
1041  }
1042 
1043  // also copies move
1044  MoveNode& mn = getMoveNode(
1045  mnOld, blockToFillNode, connectingEdge->isBackEdge());
1046  Move& newMove = mn.move();
1047 
1048  // reads immediate?
1049  if (newMove.source().isImmediateRegister()) {
1050  TTAProgram::Terminal& src = newMove.source();
1051  TCEString immName =
1052  src.immediateUnit().name() + '.'
1053  + Conversion::toString(src.index());
1054 
1055  PendingImmediateMap::iterator immWriteIter =
1056  pendingImmediateMap.find(immName);
1057 
1058  // if no write to the imm reg found, fail.
1059  if (immWriteIter == pendingImmediateMap.end()) {
1060  return false;
1061  }
1062  newMove.setSource(immWriteIter->second->copy());
1063  pendingImmediateMap.erase(immWriteIter);
1064  }
1065 
1066  if (jumpMove != NULL && !jumpMove->isUnconditional() &&
1067  !dontGuard) {
1068 
1069  if (fallThru) {
1070  auto g = CodeGenerator::createInverseGuard(jumpMove->guard());
1071  assert(g != nullptr);
1072  newMove.setGuard(g);
1073  } else {
1074  newMove.setGuard(jumpMove->guard().copy());
1075  }
1076  if (dynamic_cast<const PortGuard*>(
1077  &jumpMove->guard().guard())) {
1078  // TODO: set guard op from the jump?
1079  MoveNode& jumpNode = ddg_->nodeOfMove(*jumpMove);
1080  auto guardOp = jumpNode.guardOperationPtr();
1081  guardOp->addGuardOutputNode(mn);
1082  mn.setGuardOperationPtr(guardOp);
1083  }
1084 
1085  MoveNode& jumpNode = ddg_->nodeOfMove(*jumpMove);
1086  ddg_->copyIncomingGuardEdges(jumpNode, mn);
1087  }
1088  moves.at(i).push_back(&mn);
1089  } // move-loop
1090 
1091  for (int j = 0; j < filler.immediateCount(); j++) {
1092  if (&blockToFillNode == &nextBBN) {
1093  return false;
1094  }
1095 
1096  TTAProgram::Immediate& imm = filler.immediate(j);
1097  const TTAProgram::Terminal& dst = imm.destination();
1098  const ImmediateUnit& immu = dst.immediateUnit();
1099  if (immu.latency() == 1) {
1100  TCEString immName = immu.name() + '.' +
1101  Conversion::toString(dst.index());
1102 
1103  if (AssocTools::containsKey(pendingImmediateMap,immName)) {
1104  // there already is write to this imm reg without
1105  // a read to it? something is wrong, abort
1106  return false;
1107  }
1108  pendingImmediateMap[immName] = &imm.value();
1109  }
1110  }
1111  }
1112 
1113  // make sure long guard latencies dont cause trouble with following instructions.
1114  if (nextBB.instructionCount() > slotsToFill) {
1115  Instruction& firstNotToFill = nextBB.instructionAtIndex(slotsToFill);
1116  // loop thru all moves in the instr
1117  for (int j = 0; j < firstNotToFill.moveCount(); j++) {
1118  Move& move = firstNotToFill.move(j);
1119  if (move.isUnconditional()) {
1120  break;
1121  }
1122 
1123  MoveNode& mn = ddg_->nodeOfMove(move);
1124 
1125  // check DDG that no data hazards.
1126  if (!checkIncomingDeps(mn, blockToFillNode, cycleDiff)) {
1127  return false;
1128  }
1129  }
1130  }
1131 
1132  // ok if no pending immediates (ie limm written, not read)
1133  return pendingImmediateMap.empty();
1134 }
1135 
1136 /**
1137  * Checks that no later uses of long immediates written in instructions
1138  * which are being filled to previous basic block.
1139  *
1140  * @param nextBB The BB where to instructions are filled from
1141  * @param slotsToFill how many slots are filled
1142  *
1143  * @return true if everything ok, false if immediates prevent filling
1144  */
1145 bool
1147  BasicBlock& nextBB, int slotsToFill) {
1148  //check imm reads after (safeguard against same imm read twice)
1149  PendingImmediateMap pendingImmediateMap;
1150 
1151  for (int i = slotsToFill; i < nextBB.instructionCount(); i++) {
1152  Instruction& filler = nextBB.instructionAtIndex(i);
1153 
1154  // 0-latency immus
1155  for (int j = 0; j < filler.immediateCount(); j++) {
1156  TTAProgram::Immediate& imm = filler.immediate(j);
1157  const TTAProgram::Terminal& dst = imm.destination();
1158  const ImmediateUnit& immu = dst.immediateUnit();
1159  if (immu.latency() == 0) {
1160  TCEString immName =
1161  immu.name() + '.' +
1162  Conversion::toString(dst.index());
1163  if (pendingImmediateMap.find(immName) !=
1164  pendingImmediateMap.end()) {
1165  // same imm written twice without reading it. something wrong.
1166  return false;
1167  }
1168  pendingImmediateMap[immName] = &imm.value();
1169  }
1170  } // imm loop
1171 
1172 
1173  for (int j=0; j < filler. moveCount(); j++) {
1174  Move& move = filler.move(j);
1175  if (move.source().isImmediateRegister()) {
1176  TTAProgram::Terminal& src = move.source();
1177  TCEString immName =
1178  src.immediateUnit().name() + '.'
1179  + Conversion::toString(src.index());
1180 
1181  PendingImmediateMap::iterator immWriteIter =
1182  pendingImmediateMap.find(immName);
1183 
1184  if (immWriteIter == pendingImmediateMap.end()) {
1185  // read from immediate reg which ahs not been written
1186  // after the filled instructions, ie the limm
1187  // is at the instructions which are filled. do not allow
1188  return false;
1189  }
1190  pendingImmediateMap.erase(immWriteIter);
1191  }
1192  } // move loop
1193 
1194  // 1-latency immus
1195  for (int j = 0; j < filler.immediateCount(); j++) {
1196  TTAProgram::Immediate& imm = filler.immediate(j);
1197  const TTAProgram::Terminal& dst = imm.destination();
1198  const ImmediateUnit& immu = dst.immediateUnit();
1199  if (immu.latency() == 1) {
1200  TCEString immName = immu.name() + '.' +
1201  Conversion::toString(dst.index());
1202  if (pendingImmediateMap.find(immName) !=
1203  pendingImmediateMap.end()) {
1204  // same imm written twice without reading it. something wrong.
1205  return false;
1206  }
1207  pendingImmediateMap[immName] = &imm.value();
1208  }
1209  } // imm loop
1210  } // instruction-loop
1211 
1212  // if immediates unbalanced at end of the bb. something wrong.
1213  if (!pendingImmediateMap.empty()) {
1214  return false;
1215  }
1216  return true;
1217 }
1218 
1219 /**
1220  * Checks that no incoming deps prevent the filling, ie. no data hazards.
1221  *
1222  * @param mnOld movenode which to fill from successor bb
1223  * @param blockToFillNode block containing the jump being filled.
1224  * @param firstCycleToFill index of first instruction where to fill
1225  * @return true if no data hazards, false if cannot fill.
1226  */
1227 bool
1229  MoveNode& mnOld, BasicBlockNode& blockToFillNode, int cycleDiff) {
1230  DataDependenceGraph::EdgeSet inEdges = ddg_->inEdges(mnOld);
1231  for (DataDependenceGraph::EdgeSet::iterator ieIter =
1232  inEdges.begin(); ieIter != inEdges.end(); ieIter++) {
1233  int mnCycle = mnOld.cycle();
1234  // slow
1235  DataDependenceEdge& ddEdge = **ieIter;
1236  MoveNode& pred = ddg_->tailNode(ddEdge);
1237  if (pred.isMove()) {
1238  BasicBlockNode& predBlock = ddg_->getBasicBlockNode(pred);
1239  if (!pred.isScheduled()) {
1240  continue;
1241  }
1242 
1243  if (&predBlock == &blockToFillNode) {
1244  int nodeCycle;
1245  int delay = 1;
1246  // guard latency.
1247  if (ddEdge.dependenceType() ==
1249  if (ddEdge.guardUse()) {
1250  delay = pred.guardLatency();
1251  }
1252  nodeCycle = pred.cycle() - delay+1;
1253  } else {
1254  // if WAW, always 1
1255  if (ddEdge.dependenceType() !=
1257  if (ddEdge.guardUse()) {
1258  delay = mnOld.guardLatency();
1259  }
1260  }
1261  nodeCycle = pred.cycle()+delay;
1262  }
1263  if (nodeCycle > cycleDiff+mnCycle) {
1264  return false;
1265  }
1266  }
1267  }
1268  }
1269  return true;
1270 }
1271 
1272 /**
1273  * Assigns moves which have been copied to the succeeding basic block
1274  * into instructions in the basic block which is being filled.
1275  *
1276  * @param moves moves to assign
1277  * @param slotsToFill number of instructions to fill
1278  * @param firstCycleToFill cycle where to fill first instruction
1279  * @param rm resourcemanager to the bb being filled to.
1280  * @return true if the filling succeeded, false if failed.
1281  */
1282 bool
1284  MoveNodeListVector& moves,
1285  int slotsToFill, int firstCycleToFill, ResourceManager& rm,
1286  int nextBBStart, DataDependenceGraph::NodeSet& tempAssigns) {
1287  bool failed = false;
1288 
1289  // then try to assign the nodes
1290  for (unsigned int i = 0; i < (unsigned)slotsToFill &&
1291  i < moves.size() && !failed; i++) {
1292  list<MoveNode*>& movesInThisCycle = moves.at(i);
1293  int currentCycle = firstCycleToFill + i;
1294 
1295  for (std::list<MoveNode*>::iterator iter = movesInThisCycle.begin();
1296  iter != movesInThisCycle.end() && !failed; iter++) {
1297  MoveNode& mn = **iter;
1298 
1299  if (!mn.isScheduled()) {
1300 
1301  // if cannot assign move, try to remove
1302  // predicate(of allowed) and try again
1303  if (!rm.canAssign(currentCycle, mn)) {
1304  if (!mn.move().isUnconditional()) {
1305  MoveNode* old = oldMoveNodes_[&mn];
1306  if (old == NULL) {
1307  failed = true;
1308  break;
1309  }
1310  if (allowedToSpeculate(*old)) {
1311  if (mn.isGuardOperation()) {
1312  auto guardOp = mn.guardOperationPtr();
1313  guardOp->removeGuardOutputNode(mn);
1314  mn.unsetGuardOperation();
1315  }
1316  mn.move().setGuard(nullptr);
1317  } else {
1318  failed = true;
1319  break;
1320  }
1321  if (!rm.canAssign(currentCycle, mn)) {
1322  failed = true;
1323  break;
1324  }
1325  } else {
1326  failed = true;
1327  break;
1328  }
1329  }
1330 
1331  rm.assign(currentCycle, mn);
1332  } else {
1333  if (mn.cycle() != currentCycle) {
1334  failed = true;
1335  break;
1336  }
1337  }
1338  assert(mn.isScheduled());
1339  assert(mn.cycle() == currentCycle);
1340 
1341  if (mn.move().source().isImmediateRegister()) {
1342  const ImmediateUnit& immu = mn.move().source().immediateUnit();
1343  bool limmFound = false;
1344  for (int j = (firstCycleToFill+i-immu.latency());
1345  j >= firstCycleToFill && !limmFound; j--) {
1346  const Instruction* ins = rm.instruction(j);
1347  for (int k = 0; k < ins->immediateCount(); k++) {
1348  Immediate& imm = ins->immediate(k);
1349  if (imm.destination().equals(mn.move().source())) {
1350  limmFound = true;
1351  break;
1352  }
1353  }
1354  }
1355  // limm too early?
1356  if (!limmFound) {
1357  failed = true;
1358  break;
1359  }
1360  }
1361 
1362  // if not destination operand, no need to check
1363  // other moves of the operation.
1364  if (!mn.isDestinationOperation()) {
1365  continue;
1366  }
1367 
1368  // check that result and other operand scheduling is possible
1369  // if not, this can not be scheuduled either.
1370  // even though alone would be possible
1371  if (!tryToAssignOtherMovesOfDestOps(
1372  mn, firstCycleToFill, rm,
1373  firstCycleToFill + (slotsToFill-1), nextBBStart,
1374  tempAssigns)) {
1375  failed = true;
1376  break;
1377  }
1378  }
1379  }
1380  if (failed) {
1381 
1382  // and also movenodes assigned to delay slots.
1383  for (int i = 0; i < slotsToFill; i++) {
1384  list<MoveNode*>& movesInThisCycle = moves.at(i);
1385  for (std::list<MoveNode*>::iterator iter =
1386  movesInThisCycle.begin();
1387  iter != movesInThisCycle.end();iter++) {
1388  MoveNode& mn = **iter;
1389  if (mn.isScheduled()) {
1390  rm.unassign(mn);
1391  }
1392  }
1393  }
1394  return false;
1395  }
1396  return true;
1397 }
1398 
1399 /**
1400  * Checks that all other moves of an operation can be scheduled
1401  * at same relative cycles than they were in the another BB.
1402  */
1403 bool
1405  MoveNode& mn, int firstCycleToFill, ResourceManager& rm, int lastCycle,
1406  int nextBBStart, DataDependenceGraph::NodeSet& tempAssigns) {
1407 
1408  for (unsigned int i = 0; i < mn.destinationOperationCount(); i++) {
1410  if (!tryToAssignOtherMovesOfOp(po, firstCycleToFill, rm, lastCycle,
1411  nextBBStart, tempAssigns)) {
1412  return false;
1413  }
1414  }
1415  return true;
1416 }
1417 bool
1419  ProgramOperation& po, int firstCycleToFill, ResourceManager& rm, int lastCycle,
1420  int nextBBStart, DataDependenceGraph::NodeSet& tempAssigns) {
1421 
1422  // first inputs.
1423  if (!po.areInputsAssigned()) {
1424  for (int j = 0; j < po.inputMoveCount(); j++) {
1425  MoveNode& operMn = po.inputMove(j);
1426  // schedule only those not scheduled
1427  if (!operMn.isScheduled()) {
1428  int mnCycle =
1429  firstCycleToFill +
1430  oldMoveNodes_[&operMn]->cycle() -
1431  nextBBStart;
1432  const TTAMachine::Bus* bus =
1433  mnCycle > lastCycle ? moveNodeBuses_[&operMn] : nullptr;
1434  assert(operMn.isDestinationOperation());
1435  if (!rm.canAssign(mnCycle, operMn, bus)) {
1436  if (operMn.move().isUnconditional()) {
1437  return false;
1438  }
1439  if (!allowedToSpeculate(operMn)) {
1440  return false;
1441  }
1442  if (operMn.isGuardOperation()) {
1443  auto guardOp = operMn.guardOperationPtr();
1444  guardOp->removeGuardOutputNode(operMn);
1445  operMn.unsetGuardOperation();
1446  }
1447  operMn.move().setGuard(nullptr);
1448  if (!rm.canAssign(mnCycle, operMn, bus)) {
1449  return false;
1450  }
1451  }
1452 
1453  rm.assign(mnCycle, operMn);
1454  // need to be removed at end
1455  if (mnCycle > lastCycle) {
1456  tempAssigns.insert(&operMn);
1457  }
1458  }
1459  } // end for
1460  }
1461 
1462  // then outputs.
1463  for (int j = 0; j < po.outputMoveCount(); j++) {
1464  MoveNode& resMn = po.outputMove(j);
1465  if (!resMn.isScheduled()) {
1466  int mnCycle =
1467  firstCycleToFill + oldMoveNodes_[&resMn]->cycle() -
1468  nextBBStart;
1469 
1470  const TTAMachine::Bus* bus =
1471  mnCycle > lastCycle ? moveNodeBuses_[&resMn] : nullptr;
1472  if (!rm.canAssign(mnCycle, resMn, bus)) {
1473  return false;
1474  } else {
1475  rm.assign(mnCycle, resMn);
1476  if (mnCycle > lastCycle) {
1477  tempAssigns.insert(&resMn);
1478  }
1479  }
1480  }
1481  }
1482  return true;
1483 }
1484 
1485 
1486 /**
1487  *
1488  * Gets a corresponding MoveNode a given move in the next BB.
1489  *
1490  * If no corresponding MoveNode created, creates one
1491  *
1492  * @param old ProgramOperation in jump target BB.
1493  * @return new MoveNode for this BB.
1494  */
1495 
1496 MoveNode&
1498  MoveNode& old, BasicBlockNode& bbn, bool fillOverBackEdge) {
1499  if (AssocTools::containsKey(moveNodes_,&old)) {
1500  return *moveNodes_[&old];
1501  } else {
1502  auto movePtr = getMove(old.move());
1503  MoveNode *newMN = new MoveNode(movePtr);
1504  ddg_->addNode(*newMN, bbn);
1505  ddg_->copyDependencies(old,*newMN, false, fillOverBackEdge);
1506  moveNodeBuses_[newMN] = &old.move().bus();
1507 
1508  moveNodes_[&old] = newMN;
1509  oldMoveNodes_[newMN] = &old;
1510  mnOwned_[newMN] = true;
1511  if (old.isSourceOperation()) {
1512  newMN->setSourceOperationPtr(
1513  getProgramOperationPtr(
1514  old.sourceOperationPtr(), bbn, fillOverBackEdge));
1515  assert(newMN->isSourceOperation());
1516  }
1517  if (old.isGuardOperation()) {
1518  newMN->setGuardOperationPtr(
1519  getProgramOperationPtr(old.guardOperationPtr(), bbn, fillOverBackEdge));
1520  }
1521  if (old.isDestinationOperation()) {
1522  for (unsigned int i = 0; i < old.destinationOperationCount(); i++) {
1524  getProgramOperationPtr(
1525  old.destinationOperationPtr(i), bbn, fillOverBackEdge));
1526  }
1527  assert(newMN->isDestinationOperation());
1528  }
1529  return *newMN;
1530  }
1531 }
1532 
1533 /**
1534  * Gets a corresponding ProgramOperation to a given move in the next BB.
1535  *
1536  * If no corresponding ProgramOperation created, creates one
1537  *
1538  * @param old ProgramOperation in jump target BB.
1539  * @return new ProgramOperation for this BB.
1540  */
1543  ProgramOperationPtr old, BasicBlockNode& bbn, bool fillOverBackEdge) {
1544  if (AssocTools::containsKey(programOperations_, old.get())) {
1545  return programOperations_[old.get()];
1546  } else {
1547  ProgramOperationPtr po =
1549  new ProgramOperation(old->operation()));
1550  programOperations_[old.get()] = po;
1551  oldProgramOperations_[po.get()] = old;
1552  for (int i = 0; i < old->inputMoveCount();i++) {
1553  MoveNode& mn = old->inputMove(i);
1555  po->addInputNode(getMoveNode(mn, bbn, fillOverBackEdge));
1556  }
1557  for (int j = 0; j < old->outputMoveCount();j++) {
1558  MoveNode& mn = old->outputMove(j);
1559  if (mn.isSourceOperation()) {
1560  po->addOutputNode(getMoveNode(mn,bbn,fillOverBackEdge));
1561  } else {
1562  po->addGuardOutputNode(getMoveNode(mn,bbn, fillOverBackEdge));
1563  }
1564  }
1565  return po;
1566  }
1567 }
1568 
1569 /**
1570  * Gets a corresponding move to a given move in the next BB.
1571  *
1572  * If no corresponding move created, creates one
1573  *
1574  * @param old Move in jump target BB.
1575  * @return new Move for this BB.
1576  */
1577 std::shared_ptr<Move>
1579  if (AssocTools::containsKey(moves_,&old)) {
1580  return moves_[&old];
1581  } else {
1582  MoveNode& oldMN = ddg_->nodeOfMove(old);
1583 
1584  auto newMove = old.copy();
1585  newMove->setBus(um_->universalBus());
1586 
1587  Terminal& source = newMove->source();
1588  if (oldMN.isSourceOperation()) {
1589  assert(source.isFUPort());
1590  std::string fuName = source.functionUnit().name();
1591  //TODO: which is the correct annotation here?
1594  fuName);
1595  newMove->setAnnotation(srcUnit);
1596 
1597  const Operation &srcOp = oldMN.sourceOperation().operation();
1598  HWOperation& hwop = *um_->universalFunctionUnit().operation(
1599  srcOp.name());
1600  newMove->setSource(new TerminalFUPort(
1601  hwop, old.source().operationIndex()));
1602  } else {
1603  if (source.isRA()) {
1604  newMove->setSource(
1605  new TerminalFUPort(
1606  *um_->controlUnit()->returnAddressPort()));
1607  }
1608  }
1609 
1610  Terminal& dest = newMove->destination();
1611  if (oldMN.isDestinationOperation()) {
1612  assert(dest.isFUPort());
1613 
1614  std::string fuName = dest.functionUnit().name();
1615  //TODO: which is the correct annotation here?
1618  fuName);
1619  newMove->setAnnotation(dstUnit);
1620 
1621  const Operation &dstOp = oldMN.destinationOperation().operation();
1622  HWOperation& hwop = *um_->universalFunctionUnit().operation(
1623  dstOp.name());
1624  newMove->setDestination(new TerminalFUPort(
1625  hwop, old.destination().operationIndex()));
1626  } else {
1627  if (dest.isRA()) {
1628  newMove->setDestination(
1629  new TerminalFUPort(
1630  *um_->controlUnit()->returnAddressPort()));
1631  }
1632  }
1633 
1634 
1635  moves_[&old] = newMove;
1636 
1637  // set guard of new move to be same as old move.
1638  if (!old.isUnconditional()) {
1639  TTAProgram::MoveGuard* g = old.guard().copy();
1640  newMove->setGuard(g);
1641  }
1642  return newMove;
1643  }
1644 }
1645 
1646 /**
1647  * Deletes MoveNodes and programOperations not put into final graph.
1648  *
1649  * Loses all bookkeeping of corresponging stuff between BB's
1650  */
1652  DataDependenceGraph::NodeSet* keptTempNodes) {
1653 
1654  std::list<MoveNode*> toDeleteNodes;
1655  for (std::map<MoveNode*,MoveNode*,MoveNode::Comparator>::iterator mnIter =
1656  moveNodes_.begin(); mnIter != moveNodes_.end();
1657  mnIter++ ) {
1658  MoveNode* second = mnIter->second;
1659  if (mnOwned_[second] == true) {
1660  mnOwned_.erase(second);
1661 
1662  if ((keptTempNodes == NULL ||
1663  (keptTempNodes->find(second) == keptTempNodes->end()))
1664  && !second->isScheduled()) {
1665  // queue to be deleted
1666  toDeleteNodes.push_back(second);
1667  }
1668  }
1669  }
1670  moveNodes_.clear();
1671  moveNodeBuses_.clear();
1672  mnOwned_.clear();
1673  oldMoveNodes_.clear();
1674 
1675  // actually delete the movenodes.
1676  for (std::list<MoveNode*>::iterator i = toDeleteNodes.begin();
1677  i != toDeleteNodes.end(); i++) {
1678  assert (!(*i)->isScheduled());
1679  ddg_->removeNode(**i);
1680  delete *i;
1681  }
1682 
1683  moves_.clear();
1684 
1685  programOperations_.clear();
1686  oldProgramOperations_.clear();
1687 }
1688 
1689 /**
1690  * Destructor.
1691  */
1693  assert(programOperations_.size() == 0);
1694  assert(moveNodes_.size() == 0);
1695  assert(mnOwned_.size() == 0);
1696  assert(moves_.size() == 0);
1697 
1698  //should not be needed but lets be sure
1699 // loseCopies();
1700 }
1701 
1702 
1703 /**
1704  *
1705  * This method may get slow with a big machine
1706  *
1707  * Checks whether some of the moves in the given programOperation is copied
1708  * to the given BB. If they are, also the programOperation is copied to the
1709  * new BB.
1710  *
1711  * @param po ProgramOperation to check.
1712  * @movesToCopy all the moves that are copies from one BB to another
1713  * @return whether some of Moves referenced by po are in movesToCopy.
1714  */
1715 bool
1717  ProgramOperationPtr po, MoveNodeListVector& movesToCopy,
1718  DataDependenceGraph::NodeSet& tempAssigns) {
1719  for (int i = 0; i < po->inputMoveCount(); i++) {
1720  MoveNode& mn = po->inputMove(i);
1721  if (tempAssigns.find(&mn) != tempAssigns.end()) {
1722  return true;
1723  }
1724  for (unsigned int j = 0; j < movesToCopy.size(); j++) {
1725  std::list<MoveNode*>& moveList = movesToCopy.at(j);
1726  for (std::list<MoveNode*>::iterator iter = moveList.begin();
1727  iter != moveList.end(); iter++) {
1728  if (&mn == *iter) {
1729  return true;
1730  }
1731  }
1732  }
1733  }
1734  for (int i = 0; i < po->outputMoveCount(); i++) {
1735  MoveNode& mn = po->outputMove(i);
1736  if (tempAssigns.find(&mn) != tempAssigns.end()) {
1737  return true;
1738  }
1739  }
1740  return false;
1741 }
1742 
1743 /**
1744  * Finds the jump move and the index of the instruction where it is
1745  * from a basic block.
1746  *
1747  * @param bb basicBlock where to search the jump move
1748  */
1749 
1750 std::pair<int, TTAProgram::Move*>
1753 
1754  for (int i = bb.instructionCount()-1; i >= 0; i--) {
1755  Instruction& ins = bb.instructionAtIndex(i);
1756  for (int j = 0; j < ins.moveCount(); j++ ) {
1757  Move& move = ins.move(j);
1758  if (move.isJump()) {
1759  if (pred == nullptr) {
1760  return std::pair<int, TTAProgram::Move*>(i, &move);
1761  }
1762  if (move.isUnconditional()) {
1763  if (*pred == ControlFlowEdge::CFLOW_EDGE_NORMAL) {
1764  return std::pair<int, TTAProgram::Move*>(i, &move);
1765  }
1766  } else {
1767  auto& guard = move.guard().guard();
1768  if ((*pred == ControlFlowEdge::CFLOW_EDGE_FALSE)
1769  == (guard.isInverted())) {
1770  return std::pair<int, TTAProgram::Move*>(i, &move);
1771  }
1772  }
1773  }
1774  }
1775  //cal not handled
1776  if (ins.hasCall()) {
1777  return std::pair<int, TTAProgram::Move*>(-1,NULL);
1778  }
1779  }
1780  // not found.
1781  return std::pair<int, TTAProgram::Move*>(-1,NULL);
1782 }
1783 
1784 /**
1785  * Updates jump instruction jump address to the new one.
1786  * Also updates CFG if it is changed due completely skipped BB.
1787  *
1788  * @param jumpBBN basic block whose delay slots are filled
1789  * @param fillingBBN next basic block where the instructions are taken
1790  * @param fillEdge CFG edge connecting the basic blocks.
1791  * @param jumpAddress jump address being updated to new one.
1792  * @param slotsFilled how many delay slots were filled.
1793  * @return true if removed a basic block or an cfg edge.
1794  */
1795 bool
1797  BasicBlockNode& jumpBBN, BasicBlockNode& fillingBBN,
1798  ControlFlowEdge& fillEdge,
1799  Move* jumpAddressMove, std::shared_ptr<Immediate> jumpAddressImmediate,
1800  Move* jumpMove, int slotsFilled, Move* skippedJump) {
1801 
1802  bool cfgChanged = false;
1803  TerminalInstructionReference* jumpAddress = jumpAddressMove != NULL ?
1804  dynamic_cast<TerminalInstructionReference*>(
1805  &jumpAddressMove->source()) :
1806  dynamic_cast<TerminalInstructionReference*>(
1807  &jumpAddressImmediate->value());
1808 
1809  BasicBlock& nextBB = fillingBBN.basicBlock();
1810  InstructionReferenceManager& irm = cfg_->program()->
1811  instructionReferenceManager();
1812  // TODO: only the correct jump one, nto both
1813  assert(slotsFilled <= nextBB.instructionCount());
1814 
1815  // filled whole block, jumping to next bb.
1816  if (slotsFilled == nextBB.instructionCount()) {
1817 
1818  ControlFlowGraph::NodeSet nextBBs =
1819  cfg_->successors(fillingBBN);
1820  if (nextBBs.size() != 1) {
1821  std::string msg = "no succeessors but no jump";
1822  throw IllegalProgram(__FILE__,__LINE__,__func__, msg);
1823  }
1824 
1825  BasicBlockNode& newDestNode = **nextBBs.begin();
1826 
1827  // update CFG because jump dest moved.
1828  ControlFlowEdge* newEdge = new ControlFlowEdge(fillEdge);
1829  cfg_->disconnectNodes(jumpBBN, fillingBBN);
1830  cfg_->connectNodes(jumpBBN, newDestNode, *newEdge);
1831  cfgChanged = true;
1832 
1833  if (skippedJump != NULL) {
1834  // if we skipped a jump. that jump may have already been filled,
1835  // and then the dest is the dest of that jump,
1836  // not beginning of a bb.
1837  if (skippedJump->isReturn()) {
1838  assert(jumpMove != NULL);
1839  jumpMove->setSource(skippedJump->source().copy());
1840  TTAProgram::ProgramAnnotation annotation(
1842  ANN_STACKFRAME_PROCEDURE_RETURN);
1843  jumpMove->setAnnotation(annotation);
1844  if (jumpAddressMove != NULL && jumpAddressMove != jumpMove) {
1845  jumpAddressMove->parent().removeMove(
1846  *jumpAddressMove);
1847  } else {
1848  // get rid of the insructionreference by setting
1849  // value of the imm to 0.
1850  // better way would be deleting the imm but it's
1851  // much more complicated
1852  if (jumpAddressImmediate != NULL) {
1853  jumpAddressImmediate->setValue(
1854  new TerminalImmediate(SimValue(0,1)));
1855  }
1856  }
1857  }
1858  else {
1859  InstructionReference ir =
1860  skippedJump->source().instructionReference();
1861  jumpAddress->setInstructionReference(ir);
1862  }
1863  } else {
1864  // else the dest is the first instruction of the bb after the
1865  // filling bb, skipping the skipped instructions.
1867  newDestNode.basicBlock().instructionAtIndex(
1868  newDestNode.basicBlock().skippedFirstInstructions()));
1869  jumpAddress->setInstructionReference(ir);
1870  }
1871 
1872  // if filling block became dead, remove it.
1873  if (cfg_->inDegree(fillingBBN) == 0) {
1874  assert(!irm.hasReference(nextBB.instructionAtIndex(0)));
1875 
1876  // no fall-thru, removed only jump to bb.
1877  // remove whole bb then.
1878  cfg_->removeNode(fillingBBN);
1879  finishBB(fillingBBN, true);
1880 
1881  for (int i = 0; i < nextBB.instructionCount(); i++) {
1882  Instruction& ins = nextBB.instructionAtIndex(i);
1883  while(ins.moveCount()) {
1884  Move& move = ins.move(0);
1885  MoveNode & mn = ddg_->nodeOfMove(move);
1886  ddg_->removeNode(mn);
1887  delete &mn;
1888  ins.removeMove(move);
1889  }
1890  while (ins.immediateCount()) {
1891  Immediate& imm = ins.immediate(0);
1892  ins.removeImmediate(imm);
1893  }
1894 
1895  }
1896  delete &fillingBBN;
1897  }
1898 
1899  } else { // not filled whole block.
1900  assert(skippedJump == NULL);
1901  assert(slotsFilled >= nextBB.skippedFirstInstructions());
1903  nextBB.instructionAtIndex(slotsFilled));
1904  jumpAddress->setInstructionReference(ir);
1905 
1906  // remove the first instructions that are dead.
1907  if (cfg_->incomingFTEdge(fillingBBN) == nullptr
1908  && &fillingBBN != &cfg_->firstNormalNode()) {
1909  int deadInsCount = 0;
1910  while (nextBB.instructionCount() > deadInsCount &&
1911  !irm.hasReference(
1912  nextBB.instructionAtIndex(deadInsCount))) {
1913  deadInsCount++;
1914  }
1915  nextBB.skipFirstInstructions(deadInsCount);
1916  if (deadInsCount >= nextBB.instructionCount()) {
1917  throw IllegalProgram(
1918  __FILE__,__LINE__,__func__,
1919  "BB got empty illegally");
1920  }
1921  }
1922  }
1923  return cfgChanged;
1924 }
1925 
1926 /**
1927  * Initializes the delay slot filler for given procedure.
1928  *
1929  * Has to be called before it can be used.
1930  *
1931  * @param cfg ControlFlowGraph of the procedure.
1932  * @ddg ddg whole-procedure ddg of the procedure.
1933  * @param machine machine we are scheduling to.
1934  * @param um universalmachine.
1935  */
1936 void
1939  const TTAMachine::Machine& machine) {
1940  cfg_ = &cfg;
1941  ddg_ = &ddg;
1942  um_ = &UniversalMachine::instance();
1943 
1944  delaySlots_ = machine.controlUnit()->delaySlots();
1945  bbnStatus_.clear();
1946 }
1947 
1948 void
1950 
1951  std::map<BasicBlockNode*,DataDependenceGraph::NodeSet>::iterator
1952  i = tempResultNodes_.find(&bbn);
1953 
1954  if (i != tempResultNodes_.end()) {
1955  DataDependenceGraph::NodeSet& ns = i->second;
1956  if (!ns.empty()) {
1957  std::map<BasicBlock*,SimpleResourceManager*>::iterator rmi =
1958  resourceManagers_.find(&i->first->basicBlock());
1959  assert (rmi != resourceManagers_.end());
1960  SimpleResourceManager& rm = *rmi->second;
1961  unassignTempAssigns(ns, rm);
1962  }
1963  }
1964 
1965  bbnStatus_[&bbn] = BBN_TEMPS_CLEANED;
1966 
1967  if (!force) {
1968  // all predecessors. If some not scheduled, do not yet remove the rm.
1969  // then stay in state BBN_TEMPS_CLEANED;
1970  ControlFlowGraph::EdgeSet iEdges = cfg_->inEdges(bbn);
1971 
1972  for (ControlFlowGraph::EdgeSet::iterator inIter = iEdges.begin();
1973  inIter != iEdges.end(); inIter++) {
1974  ControlFlowEdge& cfe = **inIter;
1975  // cannot fill calls.
1976  if (!cfe.isCallPassEdge()) {
1977  BasicBlockNode& prevBBN = cfg_->tailNode(cfe);
1978  if (prevBBN.isNormalBB() &&
1979  bbnStatus_[&prevBBN] < BBN_BOTH_FILLED) {
1980  return;
1981  }
1982  }
1983  }
1984  }
1985 
1986  // delete the RM. go to state BBN_ALL_DONE
1987  std::map<BasicBlock*,SimpleResourceManager*>::iterator rmi =
1988  resourceManagers_.find(&bbn.basicBlock());
1989  if (rmi != resourceManagers_.end()) {
1990  if (rmi->second != NULL) {
1991  SimpleResourceManager::disposeRM(rmi->second);
1992  }
1993  resourceManagers_.erase(rmi);
1994  }
1995  bbnStatus_[&bbn] = BBN_ALL_DONE;
1996 
1997 }
1998 
1999 void
2001  DataDependenceGraph::NodeSet& tempAssigns,
2002  SimpleResourceManager& rm) {
2003  for (DataDependenceGraph::NodeSet::iterator j = tempAssigns.begin();
2004  j != tempAssigns.end(); j++) {
2005  assert((**j).isScheduled());
2006  rm.unassign(**j);
2007  ddg_->removeNode(**j);
2008  delete *j;
2009  }
2010  tempAssigns.clear();
2011 }
2012 
2014  Move& move = mn.move();
2015  // TODO: allow even writes if the reg is not alive?
2016  if (!mn.isDestinationOperation()) {
2017  return false;
2018  }
2019  if (move.isTriggering()) {
2020  Operation& o = move.destination().operation();
2021  if (o.writesMemory() || o.hasSideEffects() ||
2022  o.affectsCount() != 0) {
2023  return false;
2024  }
2025 
2026  // also may not read memory, because the address may be invalid,
2027  // if the address comes with bypass from operation with different guard.
2028  if (o.readsMemory()) {
2029  if (mn.isSourceOperation() &&
2031  return false;
2032  }
2033  // and if the address comes from a variable.
2034  if (mn.isSourceVariable()) {
2035  return false;
2036  }
2037  }
2038  }
2039  return true;
2040 }
TTAProgram::Move::copy
std::shared_ptr< Move > copy() const
Definition: Move.cc:413
CopyingDelaySlotFiller::addResourceManager
void addResourceManager(TTAProgram::BasicBlock &bbn, SimpleResourceManager &rm)
Definition: CopyingDelaySlotFiller.cc:691
TTAMachine::Guard
Definition: Guard.hh:55
ProgramOperation::operation
const Operation & operation() const
Definition: ProgramOperation.cc:590
TTAProgram::Terminal::isFUPort
virtual bool isFUPort() const
Definition: Terminal.cc:118
TerminalInstructionReference.hh
TTAProgram
Definition: Estimator.hh:65
TTAProgram::Immediate::value
TerminalImmediate & value() const
Definition: Immediate.cc:103
CopyingDelaySlotFiller::allowedToSpeculate
bool allowedToSpeculate(MoveNode &mn) const
Definition: CopyingDelaySlotFiller.cc:2013
TTAProgram::Instruction::removeMove
void removeMove(Move &move)
Definition: Instruction.cc:536
Operation::writesMemory
virtual bool writesMemory() const
Definition: Operation.cc:252
TTAProgram::Move::isTriggering
bool isTriggering() const
Definition: Move.cc:284
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
CopyingDelaySlotFiller.hh
MachineConnectivityCheck.hh
Operation::hasSideEffects
virtual bool hasSideEffects() const
Definition: Operation.cc:272
TTAProgram::Instruction::move
Move & move(int i) const
Definition: Instruction.cc:193
CopyingDelaySlotFiller::writesRegister
bool writesRegister(TTAProgram::Move &move, const TTAMachine::RegisterFile *rf, unsigned int registerIndex)
Definition: CopyingDelaySlotFiller.cc:789
MoveNode::guardOperationPtr
ProgramOperationPtr guardOperationPtr() const
Definition: MoveNode.cc:484
TTAProgram::Terminal::index
virtual int index() const
Definition: Terminal.cc:274
TTAProgram::Terminal::isInstructionAddress
virtual bool isInstructionAddress() const
Definition: Terminal.cc:87
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
TTAMachine::RegisterGuard::registerIndex
int registerIndex() const
CopyingDelaySlotFiller::bbnScheduled
void bbnScheduled(BasicBlockNode &bbn)
Definition: CopyingDelaySlotFiller.cc:640
BasicBlockNode::isLoopScheduled
bool isLoopScheduled() const
Definition: BasicBlockNode.hh:101
TTAProgram::Terminal::registerFile
virtual const TTAMachine::RegisterFile & registerFile() const
Definition: Terminal.cc:225
MoveNode::isDestinationOperation
bool isDestinationOperation() const
ControlFlowEdge::isJumpEdge
bool isJumpEdge() const
Definition: ControlFlowEdge.cc:148
TTAProgram::Move::isReturn
bool isReturn() const
Definition: Move.cc:259
ControlFlowEdge::edgeType
CFGEdgeType edgeType()
Definition: ControlFlowEdge.hh:84
ResourceManager::unassign
virtual void unassign(MoveNode &node)=0
AssocTools::containsKey
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
BoostGraph< MoveNode, DataDependenceEdge >::NodeSet
std::set< MoveNode *, typename MoveNode ::Comparator > NodeSet
Definition: BoostGraph.hh:86
TTAProgram::Instruction
Definition: Instruction.hh:57
SimpleResourceManager::smallestCycle
virtual int smallestCycle() const override
Definition: SimpleResourceManager.cc:480
TTAProgram::Move::isUnconditional
bool isUnconditional() const
Definition: Move.cc:154
TTAMachine::Bus
Definition: Bus.hh:53
TTAProgram::AnnotatedInstructionElement::setAnnotation
void setAnnotation(const ProgramAnnotation &annotation)
Definition: AnnotatedInstructionElement.cc:79
CopyingDelaySlotFiller::findJump
static std::pair< int, TTAProgram::Move * > findJump(TTAProgram::BasicBlock &bb, ControlFlowEdge::CFGEdgePredicate *pred=nullptr)
Definition: CopyingDelaySlotFiller.cc:1751
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
CopyingDelaySlotFiller::updateJumpsAndCfg
bool updateJumpsAndCfg(BasicBlockNode &jumpBBN, BasicBlockNode &fillingBBN, ControlFlowEdge &fillEdge, TTAProgram::Move *jumpAddressMove, std::shared_ptr< TTAProgram::Immediate > jumpAddressImmediate, TTAProgram::Move *jumpMove, int slotsFilled, TTAProgram::Move *skippedJump)
Definition: CopyingDelaySlotFiller.cc:1796
CopyingDelaySlotFiller::getProgramOperationPtr
ProgramOperationPtr getProgramOperationPtr(ProgramOperationPtr old, BasicBlockNode &bbn, bool fillOverBackEdge)
Definition: CopyingDelaySlotFiller.cc:1542
CopyingDelaySlotFiller::getMove
std::shared_ptr< TTAProgram::Move > getMove(TTAProgram::Move &old)
Definition: CopyingDelaySlotFiller.cc:1578
TTAProgram::InstructionReferenceManager::createReference
InstructionReference createReference(Instruction &ins)
Definition: InstructionReferenceManager.cc:73
TTAProgram::Instruction::removeImmediate
void removeImmediate(Immediate &imm)
Definition: Instruction.cc:560
ProgramOperation::areInputsAssigned
bool areInputsAssigned()
Definition: ProgramOperation.cc:435
UniversalMachine::instance
static UniversalMachine & instance()
Definition: UniversalMachine.cc:73
ControlFlowEdge::CFGEdgePredicate
CFGEdgePredicate
Definition: ControlFlowEdge.hh:52
TTAProgram::Move::bus
const TTAMachine::Bus & bus() const
Definition: Move.cc:373
DataDependenceGraph.hh
ProgramOperation
Definition: ProgramOperation.hh:70
TTAProgram::Move::setGuard
void setGuard(MoveGuard *guard)
Definition: Move.cc:360
MoveNode
Definition: MoveNode.hh:65
ImmediateUnit.hh
ControlFlowEdge::isBackEdge
bool isBackEdge() const
Definition: ControlFlowEdge.cc:179
TTAProgram::Terminal::instructionReference
virtual const InstructionReference & instructionReference() const
Definition: Terminal.cc:188
TTAProgram::TerminalRegister::index
virtual int index() const
CopyingDelaySlotFiller::initialize
void initialize(ControlFlowGraph &cfg, DataDependenceGraph &ddg, const TTAMachine::Machine &machine)
Definition: CopyingDelaySlotFiller.cc:1937
CopyingDelaySlotFiller::checkIncomingDeps
bool checkIncomingDeps(MoveNode &mnOld, BasicBlockNode &blockToFillNode, int cycleDiff)
Definition: CopyingDelaySlotFiller.cc:1228
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
DataDependenceEdge::dependenceType
DependenceType dependenceType() const
Definition: DataDependenceEdge.hh:88
CopyingDelaySlotFiller::tryToAssignNodes
bool tryToAssignNodes(MoveNodeListVector &moves, int slotsToFill, int firstCycleToFill, ResourceManager &rm, int nextBBStart, DataDependenceGraph::NodeSet &tempAssigns)
Definition: CopyingDelaySlotFiller.cc:1283
SimpleResourceManager::unassign
virtual void unassign(MoveNode &node) override
Definition: SimpleResourceManager.cc:252
TTAProgram::Instruction::hasCall
bool hasCall() const
Definition: Instruction.cc:438
Conversion::toString
static std::string toString(const T &source)
ProgramOperation::triggeringMove
MoveNode * triggeringMove() const
Definition: ProgramOperation.cc:643
TTAMachine::ImmediateUnit::latency
virtual int latency() const
Definition: ImmediateUnit.cc:155
ControlFlowEdge
Definition: ControlFlowEdge.hh:50
SimValue
Definition: SimValue.hh:96
ProgramOperationPtr
std::shared_ptr< ProgramOperation > ProgramOperationPtr
Definition: MoveNode.hh:52
TerminalRegister.hh
ControlFlowEdge::CFLOW_EDGE_NORMAL
@ CFLOW_EDGE_NORMAL
Definition: ControlFlowEdge.hh:53
POMDisassembler.hh
TTAProgram::Terminal::operation
virtual Operation & operation() const
Definition: Terminal.cc:319
TCEString.hh
MoveNode::setSourceOperationPtr
void setSourceOperationPtr(ProgramOperationPtr po)
Definition: MoveNode.cc:541
BasicBlockNode::basicBlock
TTAProgram::BasicBlock & basicBlock()
Definition: BasicBlockNode.cc:126
CopyingDelaySlotFiller::checkImmediatesAfter
bool checkImmediatesAfter(TTAProgram::BasicBlock &nextBB, int slotsToFill)
Definition: CopyingDelaySlotFiller.cc:1146
MoveNode::sourceOperation
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:453
TTAProgram::Immediate::destination
const Terminal & destination() const
Definition: Immediate.cc:92
assert
#define assert(condition)
Definition: Application.hh:86
UniversalMachine.hh
TTAProgram::Terminal::isImmediateRegister
virtual bool isImmediateRegister() const
Definition: Terminal.cc:97
MoveNode::isMove
bool isMove() const
MoveNode::isGuardOperation
bool isGuardOperation() const
Definition: MoveNode.cc:181
TTAProgram::ProgramAnnotation::ANN_CONN_CANDIDATE_UNIT_SRC
@ ANN_CONN_CANDIDATE_UNIT_SRC
Src. unit candidate.
Definition: ProgramAnnotation.hh:115
CopyingDelaySlotFiller::bbFilled
void bbFilled(BasicBlockNode &bbn)
Definition: CopyingDelaySlotFiller.cc:524
ResourceManager::instruction
virtual TTAProgram::Instruction * instruction(int cycle) const =0
TTAProgram::Immediate
Definition: Immediate.hh:54
TTAMachine::Machine::controlUnit
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:345
TTAProgram::Terminal::operationIndex
virtual int operationIndex() const
Definition: Terminal.cc:364
TTAProgram::BasicBlock::skippedFirstInstructions
int skippedFirstInstructions() const
Definition: BasicBlock.cc:88
CopyingDelaySlotFiller::fillDelaySlots
void fillDelaySlots(ControlFlowGraph &cfg, DataDependenceGraph &ddg, const TTAMachine::Machine &machine)
Definition: CopyingDelaySlotFiller.cc:405
MoveNode::cycle
int cycle() const
Definition: MoveNode.cc:421
MoveNode::guardLatency
int guardLatency() const
Definition: MoveNode.cc:779
TTAProgram::BasicBlock::skipFirstInstructions
void skipFirstInstructions(int count)
Definition: BasicBlock.cc:98
TTAProgram::Move::isControlFlowMove
bool isControlFlowMove() const
Definition: Move.cc:233
BoostGraph< BasicBlockNode, ControlFlowEdge >::EdgeSet
std::set< ControlFlowEdge *, typename ControlFlowEdge ::Comparator > EdgeSet
Definition: BoostGraph.hh:87
TTAProgram::TerminalInstructionReference::setInstructionReference
virtual void setInstructionReference(InstructionReference ref)
Definition: TerminalInstructionReference.cc:100
Instruction.hh
MoveNode::addDestinationOperationPtr
void addDestinationOperationPtr(ProgramOperationPtr po)
Definition: MoveNode.cc:533
TTAProgram::CodeSnippet::instructionCount
virtual int instructionCount() const
Definition: CodeSnippet.cc:205
ControlFlowGraph.hh
UniversalFunctionUnit.hh
CopyingDelaySlotFiller::unassignTempAssigns
void unassignTempAssigns(DataDependenceGraph::NodeSet &tempAssigns, SimpleResourceManager &rm)
Definition: CopyingDelaySlotFiller.cc:2000
InterPassDatum.hh
TTAMachine::RegisterGuard
Definition: Guard.hh:137
AssocTools::deleteAllItems
static void deleteAllItems(ContainerType &aMap)
TTAProgram::InstructionReferenceManager::hasReference
bool hasReference(Instruction &ins) const
Definition: InstructionReferenceManager.cc:143
TTAProgram::Move::guard
MoveGuard & guard() const
Definition: Move.cc:345
MachineConnectivityCheck::isConnected
static bool isConnected(const TTAMachine::Port &sourcePort, const TTAMachine::Port &destinationPort, const TTAMachine::Guard *guard=NULL)
Definition: MachineConnectivityCheck.cc:128
IllegalProgram
Definition: Exception.hh:895
__func__
#define __func__
Definition: Application.hh:67
CopyingDelaySlotFiller::tryToFillSlots
bool tryToFillSlots(BasicBlockNode &blockToFillNode, BasicBlockNode &nextBBNode, bool fallThru, TTAProgram::Move *jumpMove, int slotsToFill, int removeGuards, int grIndex, const TTAMachine::RegisterFile *grFile, TTAProgram::Move *&skippedJump, int delaySlots)
Definition: CopyingDelaySlotFiller.cc:817
TTAProgram::Instruction::parent
CodeSnippet & parent() const
Definition: Instruction.cc:109
ResourceManager
Definition: ResourceManager.hh:53
CopyingDelaySlotFiller
Definition: CopyingDelaySlotFiller.hh:71
CopyingDelaySlotFiller::finalizeProcedure
void finalizeProcedure()
Definition: CopyingDelaySlotFiller.cc:460
BasicBlockNode
Definition: BasicBlockNode.hh:64
TTAProgram::TerminalInstructionReference
Definition: TerminalInstructionReference.hh:48
CopyingDelaySlotFiller::CopyingDelaySlotFiller
CopyingDelaySlotFiller()
Definition: CopyingDelaySlotFiller.cc:394
BasicBlockNode::isNormalBB
bool isNormalBB() const
Definition: BasicBlockNode.cc:239
BasicBlockNode::isHWLoop
bool isHWLoop() const
Definition: BasicBlockNode.hh:114
TTAProgram::Terminal::isGPR
virtual bool isGPR() const
Definition: Terminal.cc:107
Guard.hh
Operation.hh
MoveNode::isSourceOperation
bool isSourceOperation() const
Definition: MoveNode.cc:168
TTAProgram::Terminal::immediateUnit
virtual const TTAMachine::ImmediateUnit & immediateUnit() const
Definition: Terminal.cc:240
SimpleResourceManager::disposeRM
static void disposeRM(SimpleResourceManager *rm, bool allowReuse=true)
Definition: SimpleResourceManager.cc:92
ResourceManager::canAssign
virtual bool canAssign(int cycle, MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) const =0
Operation::readsMemory
virtual bool readsMemory() const
Definition: Operation.cc:242
TerminalFUPort.hh
CopyingDelaySlotFiller::collectMoves
bool collectMoves(BasicBlockNode &blockToFillNode, BasicBlockNode &nextBBN, MoveNodeListVector &moves, int slotsToFill, bool fallThru, int removeGuards, TTAProgram::Move *jumpMove, int grIndex, const TTAMachine::RegisterFile *grFile, TTAProgram::Move *&skippedJump, int delaySlots)
Definition: CopyingDelaySlotFiller.cc:890
TTAProgram::Move
Definition: Move.hh:55
TTAMachine::ControlUnit::delaySlots
int delaySlots() const
Machine.hh
ControlFlowEdge::isFallThroughEdge
bool isFallThroughEdge() const
Definition: ControlFlowEdge.cc:158
MoveNode::unsetGuardOperation
void unsetGuardOperation()
Definition: MoveNode.cc:771
MoveNode::destinationOperationCount
unsigned int destinationOperationCount() const
ProgramOperation::inputMoveCount
int inputMoveCount() const
Definition: ProgramOperation.cc:600
CopyingDelaySlotFiller::findJumpImmediate
static std::pair< TTAProgram::Move *, std::shared_ptr< TTAProgram::Immediate > > findJumpImmediate(int jumpIndex, TTAProgram::Move &jumpMove, TTAProgram::InstructionReferenceManager &irm)
Definition: CopyingDelaySlotFiller.cc:705
CopyingDelaySlotFiller::MoveNodeListVector
std::vector< std::list< MoveNode * > > MoveNodeListVector
Definition: CopyingDelaySlotFiller.hh:105
DataDependenceEdge::DEP_WAW
@ DEP_WAW
Definition: DataDependenceEdge.hh:49
TTAProgram::Instruction::immediatePtr
std::shared_ptr< Immediate > immediatePtr(int i) const
Definition: Instruction.cc:309
Operation
Definition: Operation.hh:59
TTAProgram::Instruction::immediate
Immediate & immediate(int i) const
Definition: Instruction.cc:285
TTAProgram::Immediate::setValue
void setValue(TerminalImmediate *value)
Definition: Immediate.cc:114
CopyingDelaySlotFiller::mightFillIncomingTo
bool mightFillIncomingTo(BasicBlockNode &bbn)
Definition: CopyingDelaySlotFiller.cc:537
ProgramOperation::outputMoveCount
int outputMoveCount() const
Definition: ProgramOperation.cc:610
TTAProgram::TerminalFUPort
Definition: TerminalFUPort.hh:56
ProgramOperation.hh
TTAProgram::Terminal::functionUnit
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition: Terminal.cc:251
ControlFlowEdge::edgePredicate
CFGEdgePredicate edgePredicate() const
Definition: ControlFlowEdge.hh:83
MoveNode::isSourceVariable
bool isSourceVariable() const
Definition: MoveNode.cc:196
TTAProgram::TerminalImmediate
Definition: TerminalImmediate.hh:44
DataDependenceEdge::guardUse
bool guardUse() const
Definition: DataDependenceEdge.hh:100
MoveNode::destinationOperation
ProgramOperation & destinationOperation(unsigned int index=0) const
MoveNode::destinationOperationPtr
ProgramOperationPtr destinationOperationPtr(unsigned int index=0) const
TTAProgram::BasicBlock
Definition: BasicBlock.hh:85
MoveNode::move
TTAProgram::Move & move()
CopyingDelaySlotFiller::tryToAssignOtherMovesOfOp
bool tryToAssignOtherMovesOfOp(ProgramOperation &po, int firstCycleToFill, ResourceManager &rm, int lastCycle, int nextBBStart, DataDependenceGraph::NodeSet &tempAssigns)
Definition: CopyingDelaySlotFiller.cc:1418
IGNORE_COMPILER_WARNING
#define IGNORE_COMPILER_WARNING(X)
Definition: CompilerWarnings.hh:51
TTAProgram::TerminalRegister::registerFile
virtual const TTAMachine::RegisterFile & registerFile() const
Definition: TerminalRegister.cc:78
TTAProgram::Move::parent
Instruction & parent() const
Definition: Move.cc:115
CodeGenerator.hh
TTAProgram::InstructionReferenceManager
Definition: InstructionReferenceManager.hh:82
ControlFlowEdge::isCallPassEdge
bool isCallPassEdge() const
Definition: ControlFlowEdge.cc:138
CopyingDelaySlotFiller::PendingImmediateMap
std::map< TCEString, TTAProgram::TerminalImmediate * > PendingImmediateMap
Definition: CopyingDelaySlotFiller.hh:98
Program.hh
Immediate.hh
SimpleResourceManager::setMaxCycle
void setMaxCycle(unsigned int maxCycle)
Definition: SimpleResourceManager.cc:647
AssocTools::append
static void append(const ContainerType &src, ContainerType &dest)
InterPassData.hh
ResourceManager::assign
virtual void assign(int cycle, MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1)=0
InstructionReference.hh
CopyingDelaySlotFiller::getMoveNode
MoveNode & getMoveNode(MoveNode &old, BasicBlockNode &bbn, bool fillOverBackEdge)
Definition: CopyingDelaySlotFiller.cc:1497
TCEString
Definition: TCEString.hh:53
BasicBlock.hh
TTAProgram::Instruction::immediateCount
int immediateCount() const
Definition: Instruction.cc:267
ControlUnit.hh
CopyingDelaySlotFiller::poMoved
bool poMoved(ProgramOperationPtr po, MoveNodeListVector &movesToCopy, DataDependenceGraph::NodeSet &tempAssigns)
Definition: CopyingDelaySlotFiller.cc:1716
DataDependenceGraph
Definition: DataDependenceGraph.hh:67
SpecialRegisterPort.hh
ControlFlowEdge::CFLOW_EDGE_FALSE
@ CFLOW_EDGE_FALSE
Definition: ControlFlowEdge.hh:55
MoveNode::setGuardOperationPtr
void setGuardOperationPtr(ProgramOperationPtr po)
Definition: MoveNode.cc:550
TTAProgram::Terminal::copy
virtual Terminal * copy() const =0
InstructionReferenceManager.hh
CopyingDelaySlotFiller::loseCopies
void loseCopies(DataDependenceGraph::NodeSet *keptTempNodes)
Definition: CopyingDelaySlotFiller.cc:1651
MoveNode::sourceOperationPtr
ProgramOperationPtr sourceOperationPtr() const
Definition: MoveNode.cc:458
TTAProgram::Terminal
Definition: Terminal.hh:60
SimpleResourceManager.hh
TTAProgram::Terminal::equals
virtual bool equals(const Terminal &other) const =0
DataDependenceEdge
Definition: DataDependenceEdge.hh:43
MoveNode::isScheduled
bool isScheduled() const
Definition: MoveNode.cc:409
TTAProgram::CodeSnippet::instructionAtIndex
virtual Instruction & instructionAtIndex(int index) const
Definition: CodeSnippet.cc:285
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
SimpleResourceManager
Definition: SimpleResourceManager.hh:58
CopyingDelaySlotFiller::tryToAssignOtherMovesOfDestOps
bool tryToAssignOtherMovesOfDestOps(MoveNode &mn, int firstCycleToFill, ResourceManager &rm, int lastCycle, int nextBBStart, DataDependenceGraph::NodeSet &tempAssigns)
Definition: CopyingDelaySlotFiller.cc:1404
TTAProgram::MoveGuard::copy
MoveGuard * copy() const
Definition: MoveGuard.cc:96
TTAProgram::Terminal::port
virtual const TTAMachine::Port & port() const
Definition: Terminal.cc:378
CopyingDelaySlotFiller::areAllJumpPredsFilled
bool areAllJumpPredsFilled(BasicBlockNode &bbn) const
Definition: CopyingDelaySlotFiller.cc:470
TTAMachine::PortGuard
Definition: Guard.hh:99
TTAMachine::RegisterFile
Definition: RegisterFile.hh:47
TTAProgram::MoveGuard::guard
const TTAMachine::Guard & guard() const
Definition: MoveGuard.cc:86
TTAProgram::ProgramAnnotation
Definition: ProgramAnnotation.hh:49
TTAProgram::Move::isJump
bool isJump() const
Definition: Move.cc:164
TTAProgram::CodeGenerator::createInverseGuard
static TTAProgram::MoveGuard * createInverseGuard(const TTAProgram::MoveGuard &mg, const TTAMachine::Bus *bus=NULL)
Definition: CodeGenerator.cc:837
Move.hh
TTAMachine
Definition: Assembler.hh:48
TTAProgram::Terminal::isImmediate
virtual bool isImmediate() const
Definition: Terminal.cc:63
DataDependenceEdge::DEP_WAR
@ DEP_WAR
Definition: DataDependenceEdge.hh:48
CopyingDelaySlotFiller::areAllJumpPredsScheduled
bool areAllJumpPredsScheduled(BasicBlockNode &bbn) const
Definition: CopyingDelaySlotFiller.cc:498
TTAProgram::Terminal::isRA
virtual bool isRA() const
Definition: Terminal.cc:129
MoveNode.hh
TTAProgram::MoveGuard
Definition: MoveGuard.hh:47
BoostGraph::nodeCount
int nodeCount() const
TTAMachine::RegisterGuard::registerFile
const RegisterFile * registerFile() const
ProgramOperation::outputMove
MoveNode & outputMove(int index) const
Definition: ProgramOperation.cc:632
TTAProgram::InstructionReference
Definition: InstructionReference.hh:49
Operation::affectsCount
virtual int affectsCount() const
Definition: Operation.cc:402
BasicBlockNode::originalStartAddress
InstructionAddress originalStartAddress() const
Definition: BasicBlockNode.cc:162
TTAProgram::Instruction::moveCount
int moveCount() const
Definition: Instruction.cc:176
CopyingDelaySlotFiller::updateFTBBAndCfg
bool updateFTBBAndCfg(BasicBlockNode &jumpingBB, BasicBlockNode &nextBBN, ControlFlowEdge &edge, int slotsFilled)
Definition: CopyingDelaySlotFiller.cc:333
TTAProgram::TerminalRegister
Definition: TerminalRegister.hh:53
CopyingDelaySlotFiller::~CopyingDelaySlotFiller
~CopyingDelaySlotFiller()
Definition: CopyingDelaySlotFiller.cc:1692
ControlFlowGraph
Definition: ControlFlowGraph.hh:100
TTAProgram::Move::setSource
void setSource(Terminal *src)
Definition: Move.cc:312
ProgramOperation::inputMove
MoveNode & inputMove(int index) const
Definition: ProgramOperation.cc:621
CopyingDelaySlotFiller::finishBB
void finishBB(BasicBlockNode &bbn, bool force=false)
Definition: CopyingDelaySlotFiller.cc:1949
TTAMachine::Machine
Definition: Machine.hh:73
TTAProgram::ProgramAnnotation::ANN_CONN_CANDIDATE_UNIT_DST
@ ANN_CONN_CANDIDATE_UNIT_DST
Dst. unit candidate.
Definition: ProgramAnnotation.hh:116
MoveGuard.hh
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50