OpenASIP  2.0
DataDependenceGraphBuilder.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2021 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 DataDependenceGraphBuilder.cc
26  *
27  * Implementation of data dependence graph builder.
28  *
29  * DDG's can be built only from unscheduled code. Registers can
30  * however have been allocated.
31  *
32  * @author Heikki Kultala 2006-2009 (heikki.kultala-no.spam-tut.fi)
33  * @author Pekka Jääskeläinen 2021 (pekka.jaaskelainen tuni fi)
34  * @note rating: red
35  */
36 
37 #include "CompilerWarnings.hh"
38 IGNORE_COMPILER_WARNING("-Wunused-parameter")
39 
40 #include <llvm/CodeGen/MachineInstr.h>
41 #include <llvm/CodeGen/MachineMemOperand.h>
42 
43 #include "AssocTools.hh"
44 #include "ContainerTools.hh"
45 #include "TCEString.hh"
46 #include "SequenceTools.hh"
47 
48 #include "Program.hh"
49 #include "Procedure.hh"
50 #include "Instruction.hh"
51 #include "Operation.hh"
52 #include "SpecialRegisterPort.hh"
53 #include "Move.hh"
54 #include "ProgramOperation.hh"
55 #include "RegisterFile.hh"
56 #include "Machine.hh"
57 #include "UniversalMachine.hh"
58 #include "Exception.hh"
59 #include "UnboundedRegisterFile.hh"
60 #include "MoveGuard.hh"
61 #include "Guard.hh"
62 #include "MoveNodeSet.hh"
63 #include "Operand.hh"
64 #include "POMDisassembler.hh"
65 #include "DisassemblyRegister.hh"
66 #include "Move.hh"
67 #include "ControlFlowGraph.hh"
68 #include "ControlFlowEdge.hh"
69 #include "BasicBlockNode.hh"
70 #include "BasicBlock.hh"
72 #include "DataDependenceEdge.hh"
73 #include "MemoryAliasAnalyzer.hh"
74 #include "PRegionAliasAnalyzer.hh"
75 
76 #include "TerminalRegister.hh"
77 #include "TerminalFUPort.hh"
78 
79 #include "ConstantAliasAnalyzer.hh"
80 #include "FalseAliasAnalyzer.hh"
81 #include "StackAliasAnalyzer.hh"
82 #include "OffsetAliasAnalyzer.hh"
83 #include "GlobalVsStackAA.hh"
84 #include "LLVMAliasAnalyzer.hh"
85 #include "LLVMTCECmdLineOptions.hh"
86 
87 #include "InterPassData.hh"
88 #include "InterPassDatum.hh"
90 
91 #include "MachineInfo.hh"
92 
93 using namespace TTAProgram;
94 using namespace TTAMachine;
95 
96 using std::list;
97 
98 
99 static const int REG_RV_HIGH = -1;
100 static const int REG_SP = 1;
101 static const int REG_RV = 0;
102 static const int REG_IPARAM = 2;
103 
104 static const int REG_VRV = -3;
105 static const int REG_FP = -2;
106 
108 
109 //#define USE_FALSE_AA
110 
111 /**
112  * Constructor of Data Dependence graph builder.
113  *
114  * This constructor does not take special registers from
115  * interpass data, so it must analyze them from the
116  * code annotations. Used with old frontend.
117  */
119  interPassData_(NULL), cfg_(NULL), rvIsParamReg_(false) {
120 
121  /// constant alias AA check aa between global variables.
123 
124 #ifdef USE_FALSE_AA
125  /// defining USE_FALSE_AA results in faster but
126  /// broken code. just for testing theoretical benefits.
128 #endif
130 
131  LLVMTCECmdLineOptions* llvmOptions =
132  dynamic_cast<LLVMTCECmdLineOptions*>(
134  if (llvmOptions != NULL && llvmOptions->disableLLVMAA() == false) {
136  }
137 }
138 
139 /**
140  * Constructor of Data Dependence graph builder.
141  *
142  * This constructor takes special registers from
143  * interpass data.
144  */
146  // TODO: when param reg thing works, rvIsParamReg becomes true here
147  interPassData_(&ipd), cfg_(NULL), rvIsParamReg_(true) {
148 
149  // Need to store data about special registers which have semantics
150  // between function calls and exits. These are stack pointer,
151  // return value register and the secondary "hi bits"
152  // return value register.
153 
154  static const TCEString SP_DATUM = "STACK_POINTER";
155  static const TCEString FP_DATUM = "FRAME_POINTER";
156  static const TCEString RV_DATUM = "RV_REGISTER";
157  // high part of 64-bit return values.
158  static const TCEString RV_HIGH_DATUM = "RV_HIGH_REGISTER";
159 
160  static const TCEString IPARAM_DATUM_PREFIX = "IPARAM";
161  static const TCEString VECTOR_RV_PREFIX="VRV_REGISTER";
162 
164  dynamic_cast<SchedulerCmdLineOptions*>(
166 
167  if (ipd.hasDatum(SP_DATUM)) {
168  RegDatum& sp = dynamic_cast<RegDatum&>(ipd.datum(SP_DATUM));
169  TCEString spName = sp.first + '.' + Conversion::toString(sp.second);
170  specialRegisters_[REG_SP] = spName;
171 
172  // create stack alias analyzer if enabled.
173  if ((options != NULL && options->enableStackAA())) {
175  }
176 
177  if (options != NULL && options->enableOffsetAA()) {
179  }
180 
181  addAliasAnalyzer(new GlobalVsStackAA(spName));
182 
183  } else {
187  << "Warning: Stack pointer datum not found "
188  << "in interpassdata given to ddg builder. "
189  << "May generate invalid code if stack used."
190  << std::endl;
191  }
192  }
193 
194  if (ipd.hasDatum(RV_DATUM)) {
195  RegDatum& rv = dynamic_cast<RegDatum&>(ipd.datum(RV_DATUM));
196  TCEString reg = rv.first + '.' + Conversion::toString(rv.second);
197  specialRegisters_[REG_RV] = reg;
198  if (rvIsParamReg_) {
199  allParamRegs_.insert(reg);
200  }
201 
202  } else {
206  << "Warning: Return value register datum not found "
207  << "in interpassdata given to ddg builder. "
208  << "May generate invalid code if return values used."
209  << std::endl;
210  }
211  }
212 
213  for(int i = 2;;i++) {
214  TCEString datum = IPARAM_DATUM_PREFIX; datum << i;
215  if (ipd.hasDatum(datum)) {
216  RegDatum& p = dynamic_cast<RegDatum&>(ipd.datum(datum));
217  TCEString reg = p.first + '.' + Conversion::toString(p.second);
218  specialRegisters_[REG_IPARAM+i-1] = reg;
219  } else {
220  break;
221  }
222  }
223 
224  for (int i = 0;;i++) {
225  TCEString datum = VECTOR_RV_PREFIX; datum << i;
226  if (ipd.hasDatum(datum)) {
227  RegDatum& p = dynamic_cast<RegDatum&>(ipd.datum(datum));
228  TCEString reg = p.first + '.' + Conversion::toString(p.second);
229  specialRegisters_[REG_VRV-i] = reg;
230  } else {
231  break;
232  }
233 
234  }
235 
236  if (ipd.hasDatum(FP_DATUM)) {
237  RegDatum& fp = dynamic_cast<RegDatum&>(ipd.datum(FP_DATUM));
238  TCEString reg = fp.first + '.' + Conversion::toString(fp.second);
239  specialRegisters_[REG_FP] = reg;
240  } else {
244  << "Warning: Frame Pointer Register datum not found "
245  << "in interpassdata given to ddg builder. "
246  << "May generate invalid code."
247  << std::endl;
248  }
249  }
250 
251  if (ipd.hasDatum(RV_HIGH_DATUM)) {
252  RegDatum& rvh = dynamic_cast<RegDatum&>(ipd.datum(RV_HIGH_DATUM));
254  rvh.first + '.' + Conversion::toString(rvh.second);
255  }
256 
257  // constant alias AA check aa between global variables.
259 
260  LLVMTCECmdLineOptions* llvmOptions =
261  dynamic_cast<LLVMTCECmdLineOptions*>(
263  if (llvmOptions != NULL && llvmOptions->disableLLVMAA() == false) {
265  }
267 
268 #ifdef USE_FALSE_AA
269  /// defining USE_FALSE_AA results in faster but
270  /// broken code. just for testing theoretical benefits.
272 #else
273  if ((options != NULL && options->noaliasFunctions() &&
274  !options->noaliasFunctions()->empty())) {
275  addAliasAnalyzer(new FalseAliasAnalyzer(options->noaliasFunctions()));
276  }
277 #endif
278 }
279 
280 /**
281  * Destructor of DataDependenceGraphBuilder
282  */
285 }
286 
287 /**
288  * Adds a memory alias analyzer to the DDG builder.
289  *
290  * @param analyzer object which will analyze memory accesses.
291  */
292 void
294  aliasAnalyzers_.push_back(analyzer);
295 }
296 
297 /**
298  * Tries to find annotations which tell the static registers
299  * from a program.
300  *
301  * Used only with the old gcc frontend.
302  *
303  * @param cs codesnippet where to search the annotations.
304  */
305 void
308  std::map<int,TCEString>& registers) {
309  for (int i = 0; i < cs.instructionCount(); i++) {
310  Instruction& ins = cs.instructionAtIndex(i);
311  findStaticRegisters(ins, registers);
312  }
313 }
314 
315 /**
316  * Tries to find annotations which tell the static registers
317  * from a program.
318  *
319  * Used only with the old gcc frontend.
320  *
321  * @param cfg cfg where to search the annotations.
322  */
323 void
325  ControlFlowGraph& cfg,
326  std::map<int,TCEString>& registers) {
327  for (int i = 0; i < cfg.nodeCount(); i++) {
328  BasicBlockNode& bbn = cfg.node(i);
329  if (bbn.isNormalBB()) {
330  findStaticRegisters(bbn.basicBlock(), registers);
331  }
332  }
333 }
334 
335 /**
336  * Tries to find annotations which tell the static registers
337  * from a program.
338  *
339  * Used only with the old gcc frontend.
340  *
341  * @param ins instruction where to search the annotations.
342  */
343 void
346  std::map<int,TCEString>& registers) {
347 
348  try {
349  for (int i = 0; i < ins.moveCount(); i++) {
350  Move& move = ins.move(i);
351  for (int j = 0; j < move.annotationCount(); j++) {
352  ProgramAnnotation anno = move.annotation(j);
353  switch (anno.id()) {
354  case ProgramAnnotation::ANN_REGISTER_RV_READ: {
356  move.source());
357  break;
358  }
359  case ProgramAnnotation::ANN_REGISTER_RV_SAVE: {
361  move.destination());
362  break;
363  }
364  case ProgramAnnotation::ANN_REGISTER_SP_READ: {
366  move.source());
367  break;
368  }
369  case ProgramAnnotation::ANN_REGISTER_SP_SAVE: {
371  move.destination());
372  break;
373  }
374  case ProgramAnnotation::ANN_REGISTER_IPARAM_READ: {
375 /* this fixes one unit test silent breakage but another will then happen - unit test
376  tpef's seem to contain a bit broken code
377  Terminal& src = move.source();
378  if (!src.isGPR()) {
379  break;
380  }
381 */
382  TCEString reg =
384  registers[
386  reg;
387  allParamRegs_.insert(reg);
388  break;
389  }
390  case ProgramAnnotation::ANN_REGISTER_IPARAM_SAVE: {
391  TCEString reg =
393  registers[
395  reg;
396  allParamRegs_.insert(reg);
397  break;
398  }
399  default:
400  //TODO: frame pointer, not yet implemented
401  break;
402  }
403  }
404  }
405  } catch (std::bad_cast& e) {
406  throw IllegalProgram(__FILE__,__LINE__, __func__, "Illegal annotation");
407  }
408 }
409 
410 /**
411  * Initializes the static register table from register from
412  * UniversalMachine.
413  *
414  * Needed for analysis of data dependencies of parameter registers,
415  * SP, RV etc.
416  *
417  * @param um UniversalMachine
418  * @param registers map where to store those registers.
419  */
420 void
422  const UniversalMachine& um, std::map<int,TCEString>& registers) {
424 
425  for (int i = 0; i < 6; i++) {
426  TerminalRegister tr(*rf.port(0), i);
428  registers[i] = reg;
429  if (i > REG_SP) {
430  allParamRegs_.insert(reg);
431  }
432  }
433 }
434 
435 ///////////////////////////////////////////////////////////////////////////////
436 // End of initializations
437 ///////////////////////////////////////////////////////////////////////////////
438 
439 ///////////////////////////////////////////////////////////////////////////////
440 // Single-BB DDG construction
441 ///////////////////////////////////////////////////////////////////////////////
442 
443 /**
444  * Creates new Data Dependence Graph for the given basic block.
445  *
446  * Client has to delete the graph when it is not anymore used.
447  *
448  * @param bb BasicBlockNode whose data dependence graph to build.
449  * @param registerAntidependenceLevel which reg antidependencies to create
450  * @param createMemAndFUDeps whether to create also memory and
451  * fu state(side effect) dependencies or only register deps.
452  * @return new DataDependence Graph.
453  *
454  */
457  BasicBlock& bb,
458  DataDependenceGraph::AntidependenceLevel registerAntidependenceLevel,
459  const TTAMachine::Machine& mach,
460  const TCEString& ddgName,
461  const UniversalMachine* um,
462  bool createMemAndFUDeps,
463  llvm::AliasAnalysis* AA) {
464 
465  mach_ = &mach;
466  if (AA) {
467  for (unsigned int i = 0; i < aliasAnalyzers_.size(); i++) {
468  LLVMAliasAnalyzer* llvmaa =
469  dynamic_cast<LLVMAliasAnalyzer*>(aliasAnalyzers_[i]);
470  if (llvmaa != NULL) {
471  llvmaa->setLLVMAA(AA);
472  }
473  }
474  }
475  if (bb.liveRangeData_ == NULL) {
476  bb.liveRangeData_ = new LiveRangeData;
477  }
478 
479  currentBB_ = new BasicBlockNode(bb);
481  allParamRegs_, ddgName, registerAntidependenceLevel, currentBB_,
482  false,true);
483  // GRR, start and end addresses are lost..
484 
486 
487  if (um != NULL) {
489  } else {
491  }
492  try {
493  // first phase. registers , ops and PO's.
496  if (createMemAndFUDeps) {
497  //second phase. mem and fu state deps
500  }
501  } catch (Exception&) {
502  delete currentDDG_; currentDDG_ = NULL;
503  delete currentData_; currentData_ = NULL;
504  delete currentBB_; currentBB_ = NULL;
505  throw;
506  }
507 
508  clearUnneededBookkeeping(bb, false);
509 
510  delete currentData_;
511  currentData_ = NULL;
512  currentDDG_->setMachine(mach);
513  return currentDDG_;
514 }
515 
516 /**
517  * Constructs a Data Dependence Graph for a single basic block.
518  *
519  * Goes thru all moves in the basic block and analyzes their dependencies,
520  * creates their ProgramOperations, MoveNodes and Edges,
521  * and adds the nodes and edges to the graph.
522  * Also used inside implementation of multi-BB-DDG-code.
523  * BB being analyzed has to be already set in member variable currentBB_,
524  * and the graph created and set into member variable currentBB_.
525  *
526  * @param bbd basic block to constructs.
527  * @param phase whether to handle register& operation deps or
528  * memory and side-effect dependencies.
529  */
530 void
532  BBData& bbd, ConstructionPhase phase) {
533 
534  currentData_ = &bbd;
535  currentBB_ = bbd.bblock_;
536 
537  // Parallel inline asm block are already marked as scheduled
538  // TODO: should BBN have isInlineAsm() method?
539  if (currentBB_->isScheduled()) {
541  } else {
542  constructIndividualBB(phase);
543  }
544 }
545 
546 /**
547  * Constructs a Data Dependence Graph for a single basic block.
548  *
549  * Goes thru all moves in the basic block and analyzes their dependencies,
550  * creates their ProgramOperations, MoveNodes and Edges,
551  * and adds the nodes and edges to the graph.
552  * Also used inside implementation of multi-BB-DDG-code.
553  * BB being analyzed has to be already set in member variable currentBB_,
554  * and the graph created and set into member variable currentBB_.
555  *
556  * @param phase whether to handle register& operation deps or
557  * memory and side-effect dependencies.
558  */
559 void
561  ConstructionPhase phase) {
562 
563  for (int ia = 0; ia < currentBB_->basicBlock().instructionCount(); ia++) {
565 
566  for (int i = 0; i < ins.moveCount(); i++) {
567  auto movePtr = ins.movePtr(i);
568  Move& move = *movePtr;
569 
570  MoveNode* moveNode = NULL;
571 
572  // if phase is 0, create the movenode, and handle guard.
573  if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
574  /* In case using the LLVMTCEIRBuilder, the POs have been built already
575  and set to corresponding TerminalFUPorts. Use those MoveNodes and
576  ProgramOperations instead of creating new ones here. NOTE: the
577  ownership of the MoveNodes is transferred to the DDG.
578  */
579  if (move.destination().isFUPort() &&
580  dynamic_cast<TerminalFUPort&>(move.destination()).
581  hasProgramOperation()) {
582  ProgramOperationPtr po =
583  dynamic_cast<TerminalFUPort&>(move.destination()).
584  programOperation();
585  if (po->hasMoveNodeForMove(move)) {
586  moveNode = &po->moveNode(move);
587  } else {
588  // the po might be corrupted and point to an old POM's Moves
589  moveNode = new MoveNode(movePtr);
590  }
591  } else if (move.source().isFUPort() &&
592  dynamic_cast<TerminalFUPort&>(move.source()).
593  hasProgramOperation()) {
594  ProgramOperationPtr po =
595  dynamic_cast<TerminalFUPort&>(move.source()).
596  programOperation();
597  if (po->hasMoveNodeForMove(move)) {
598  moveNode = &po->moveNode(move);
599  } else {
600  // the po might be corrupted and point to an old POM's Moves
601  moveNode = new MoveNode(movePtr);
602  }
603  } else {
604  moveNode = new MoveNode(movePtr);
605  }
606  currentDDG_->addNode(*moveNode, *currentBB_);
607 
608  if (!move.isUnconditional()) {
609  processGuard(*moveNode);
610  }
611 
612  processSource(*moveNode);
613 
614  } else {
615  // on phase 2, just find the already created movenode.
616  moveNode = &currentDDG_->nodeOfMove(move);
617  }
618 
619  // destinaition need to be processed in both phases 0 and 1.
620  processDestination(*moveNode, phase);
621  }
622  }
623 
624  // these are needed no more.
626 
627  // Checks if we have some unready program operations at the end
628  // of a basic block.
629  if (currentData_->destPending_ != NULL ||
630  currentData_->readPending_ != NULL) {
631 
632  TCEString msg = TCEString("Basic block ")
634  + TCEString(" - ")
636  + TCEString(", size : ")
639  + TCEString(" handled but we have unready PO at: ")
640  + currentDDG_->name()
641  + TCEString(", probably an operation without result move?");
642 
643  if (currentData_->readPending_ != NULL) {
644  msg += "\n\tmissing read: " +
645  TCEString(currentData_->readPending_->operation().name());
646  }
647 
648  if (currentData_->destPending_ != NULL) {
649  msg += "\n\tmissing dest: " +
650  TCEString(currentData_->destPending_->operation().name());
651  }
652 
653  if (cfg_ != NULL) {
654  cfg_->writeToDotFile("constructBBbroken_cfg.dot");
655  }
656 
657  throw IllegalProgram(__FILE__,__LINE__,__func__, msg);
658  }
659 }
660 
661 /**
662  * Same as constructIndividualBB() but for already fully scheduled and inline
663  * asm BB.
664  *
665  * @Note: currently, this does not really construct DDG - just creates
666  * dummy MoveNodes.
667  */
668 void
670  ConstructionPhase phase) {
671 
672  if (phase != REGISTERS_AND_PROGRAM_OPERATIONS) {
673  return;
674  }
675  auto& bb = currentBB_->basicBlock();
677  for (int ia = 0; ia < bb.instructionCount(); ia++) {
678  Instruction& ins = bb.instructionAtIndex(ia);
679  for (int i = 0; i < ins.moveCount(); i++) {
680  MoveNode* moveNode = new MoveNode(ins.movePtr(i));
681  currentDDG_->addNode(*moveNode, *currentBB_);
682  }
683  }
684 
685  // Process live range with dummy move nodes.
686  assert(bb.liveRangeData_);
687  LiveRangeData& liveRangeData = *bb.liveRangeData_;
688  std::set<TCEString> actualRegUses;
689  std::set<TCEString> actualRegDefs;
690  for (int i = 0; i < bb.instructionCount(); i++) {
691  auto& ins = bb.instructionAtIndex(i);
692  for (int m = 0; m < ins.moveCount(); m++) {
693  auto& move = ins.move(m);
694 
695  auto rdReg = move.source().isGPR() ? move.source().toString()
696  : TCEString("");
697  if (!rdReg.empty()) actualRegUses.insert(rdReg);
698 
699  if (move.isConditional()) {
700  const Guard& grd = move.guard().guard();
701  const RegisterGuard* grdReg =
702  dynamic_cast<const RegisterGuard*>(&grd);
703  if (grdReg) {
704  TCEString regName = grdReg->registerFile()->name() + '.' +
706  actualRegUses.insert(regName);
707  }
708  }
709 
710  auto wrReg = move.destination().isGPR()
711  ? move.destination().toString()
712  : TCEString("");
713  if (!wrReg.empty()) actualRegDefs.insert(wrReg);
714  }
715  }
716 
717  auto& iaRegUses = liveRangeData.inlineAsmRegUses_;
718  auto effectiveRegUses = SetTools::intersection(iaRegUses, actualRegUses);
719  for (auto reg : effectiveRegUses) {
720  MoveNode* moveNode = new MoveNode();
721  currentDDG_->addNode(*moveNode, *currentBB_);
722  liveRangeData.regFirstUses_[reg].insert(*moveNode);
723  currentDDG_->updateRegUse(*moveNode, reg, bb);
724  }
725 
726  auto& iaRegDefs = liveRangeData.inlineAsmRegDefs_;
727  auto effectiveRegDefs = SetTools::intersection(iaRegDefs, actualRegDefs);
728  for (auto reg : effectiveRegDefs) {
729  MoveNode* moveNode = new MoveNode();
730  currentDDG_->addNode(*moveNode, *currentBB_);
731  liveRangeData.regDefines_[reg].insert(*moveNode);
732  MoveNodeUse mnd(*moveNode);
733  liveRangeData.regKills_[reg] = std::make_pair(mnd, mnd);
734  }
735 
736  for (auto& reg : liveRangeData.inlineAsmClobbers_) {
737  MoveNode* moveNode = new MoveNode();
738  currentDDG_->addNode(*moveNode, *currentBB_);
739  liveRangeData.regDefines_[reg].insert(*moveNode);
740  MoveNodeUse mnd(*moveNode);
741  liveRangeData.regKills_[reg] = std::make_pair(mnd, mnd);
742  }
743 
744  // Not needed anymore.
745  liveRangeData.inlineAsmRegUses_.clear();
746  liveRangeData.inlineAsmRegDefs_.clear();
747  liveRangeData.inlineAsmClobbers_.clear();
748 }
749 
750 /**
751  * Analyzes dependencies related to guard usage.
752  *
753  * Finds the guard register used for the guard and the move
754  * Which writes the guard register, and creates a guard egde
755  * between them.
756  *
757  * @param moveNode MNData of move containing guarded move.
758  */
759 void
761 
762  // new code
763  const Guard& g = moveNode.move().guard().guard();
764  const RegisterGuard* rg = dynamic_cast<const RegisterGuard*>(&g);
765  if (rg != NULL) {
766  TCEString regName = rg->registerFile()->name() + '.' +
768  processRegUse(MoveNodeUse(moveNode, true),regName);
769  } else {
770  throw IllegalProgram(
771  __FILE__,__LINE__,__func__,
772  "Analysis for port guards not supported! used in: "
773  + moveNode.toString());
774  }
775 }
776 
777 /**
778  * Analysis a source of a move and processes it's dependencies,
779  * and if it's a result read then also participates in ProgramOperation
780  * creation.
781  *
782  * @param moveNode Movenode being analyzed.
783  */
784 void
786  Terminal& source = moveNode.move().source();
787 
788  // is this result move of an operation?
789  if (source.isFUPort()) {
790  if (!(dynamic_cast<const SpecialRegisterPort*>(&source.port()))) {
791  processResultRead(moveNode);
792  } else {
793  // handle read from RA.
794  processRegUse(MoveNodeUse(moveNode, false, true), RA_NAME);
795 
796  if (moveNode.move().isReturn()) {
797  processReturn(moveNode);
798  }
799  }
800  } else {
801  if (source.isGPR()) {
802  TerminalRegister& tr = dynamic_cast<TerminalRegister&>(source);
804  processRegUse(MoveNodeUse(moveNode), regName);
805  }
806  }
807 }
808 
809 
811  int destIndex = mn.move().destination().operationIndex();
812  const Operation& op = mn.destinationOperation().operation();
813  int triggerIndex = MachineInfo::triggerIndex(*mach_, op);
814  switch (triggerIndex) {
815  case -1: {
816  TCEString msg = "Trigger index ambiguous for operation: ";
817  msg << op.name() << " in the machine.";
818  throw IllegalMachine(__FILE__,__LINE__,__func__, msg);
819  break;
820  }
821  case 0: {
822  TCEString msg = "Operation: ";
823  msg << op.name() << " Not found from the machine";
824  throw CompileError(__FILE__,__LINE__,__func__, msg);
825  break;
826  }
827  default:
828  return triggerIndex == destIndex;
829  }
830 }
831 
832 /**
833  * Analyzes destination of a move.
834  * Updates bookkeeping and handles WaW and WaR dependencies of the move.
835  *
836  * Checks whether destination is operation or register and calls other
837  * functions to do the actual dependence checks etc.
838  *
839  * @param moveNode MoveNode whose destination is being processed.
840  * @param phase whether to handle register& operation deps or
841  * memory and side-effect dependencies.
842  */
843 void
845  MoveNode& moveNode, ConstructionPhase phase) {
846  Terminal& dest = moveNode.move().destination();
847 
848  // is this a operand to an operation?
849  if (dest.isFUPort()) {
850  if (!(dynamic_cast<const SpecialRegisterPort*>(&dest.port()))) {
851  TerminalFUPort& tfpd = dynamic_cast<TerminalFUPort&>(dest);
852  Operation &dop = tfpd.hintOperation();
853 
854  if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
855  if (tfpd.isOpcodeSetting()) {
857  moveNode, dop);
858  } else {
859  processOperand(moveNode, dop);
860  }
861  } else { // memory and fu state deps
862  if (dop.usesMemory() || dop.hasSideEffects() ||
863  dop.affectsCount() || dop.affectedByCount() ||
864  moveNode.move().isControlFlowMove()) {
865  if (isTriggering(moveNode)) {
866  processTriggerMemoryAndFUStates(moveNode, dop);
867  }
868  }
869  }
870  } else { // RA write
871  if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
872  processRegWrite(MoveNodeUse(moveNode,false,true), RA_NAME);
873  }
874  }
875  } else {
876  if (dest.isGPR()) {
877  // we do not care about register reads in second phase
878  if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
879  TerminalRegister& tr = dynamic_cast<TerminalRegister&>(dest);
881  processRegWrite(MoveNodeUse(moveNode), regName);
882  }
883  } else { // something else
884  throw IllegalProgram(__FILE__,__LINE__,__func__,
885  "Move has illegal destination" +
886  moveNode.toString());
887  }
888  }
889 }
890 
891 /**
892  * Clears bookkeeping which is only needed during ddg construction.
893  *
894  * @param BB containing basic blocks which contain the bookkeeping.
895  * @param interBBInformation needed whether information about inter-bb-
896  * dependencies need to be left intact.
897  */
898 void
900  BasicBlock& bb, bool interBBInformationNeeded) {
901 
902  if (!interBBInformationNeeded) {
903  //used by regcopyadder.
904  bb.liveRangeData_->regFirstDefines_.clear();
905  bb.liveRangeData_->regLastUses_.clear();
906 
907  // used by both
908  bb.liveRangeData_->regDefines_.clear();
909 
910  // these are neede for live range things
911  bb.liveRangeData_->regDefReaches_.clear();
913  bb.liveRangeData_->regFirstUses_.clear();
914  }
915  bb.liveRangeData_->regUseReaches_.clear();
916  bb.liveRangeData_->regLastKills_.clear();
917 
918  bb.liveRangeData_->regDefAfter_.clear();
919  bb.liveRangeData_->regUseAfter_.clear();
920 
921  bb.liveRangeData_->memDefines_.clear();
922  bb.liveRangeData_->memLastUses_.clear();
923 
924  bb.liveRangeData_->memFirstUses_.clear();
925  bb.liveRangeData_->memFirstDefines_.clear();
926 
927  bb.liveRangeData_->memDefReaches_.clear();
928  bb.liveRangeData_->memUseReaches_.clear();
929 
930  bb.liveRangeData_->fuDepReaches_.clear();
931  bb.liveRangeData_->fuDeps_.clear();
932  bb.liveRangeData_->fuDepAfter_.clear();
933 
935 }
936 
937 ///////////////////////////////////////////////////////////////////////////////
938 // ProgramOperation and Operation edges.
939 ///////////////////////////////////////////////////////////////////////////////
940 
941 /**
942  * Handles ProgramOperation creation for a triggering move.
943  *
944  * @param moveNode triggering movenode.
945  * @param dop operation which is being triggered by the movenode.
946  */
947 void
949  MoveNode& moveNode, Operation& dop) {
950  if (currentData_->destPending_ != NULL) {
952 
953  if (&dop != &po->operation()) {
954  std::cerr << "pending po: " << po->toString() << std::endl;
955  std::cerr << "current dop: " << dop.name() << std::endl;
956  currentDDG_->writeToDotFile("build_fail_po.dot");
957  }
958  assert(&dop == &po->operation());
959  if (!po->isComplete()) {
960  po->addInputNode(moveNode);
961  moveNode.addDestinationOperationPtr(po);
962  }
963  if (po->isReady()) {
965  if (dop.numberOfOutputs() > 0) {
966  assert(currentData_->readPending_ == NULL);
969  } else {
971  }
972  } else {
973  throw IllegalProgram(
974  __FILE__, __LINE__, __func__,
975  "Trigger before all operands.");
976  }
977  return;
978  }
979  // only one triggering input?
980  if (dop.numberOfInputs() == 1) {
981  TerminalFUPort& tfpd =
982  dynamic_cast<TerminalFUPort&>(moveNode.move().destination());
984  if (tfpd.hasProgramOperation()) {
985  po = tfpd.programOperation();
986  } else {
987  po = ProgramOperationPtr(new ProgramOperation(dop));
988  moveNode.addDestinationOperationPtr(po);
989  po->addInputNode(moveNode);
990  }
991  if (dop.numberOfOutputs()) {
992  assert(currentData_->readPending_ == NULL);
994  } else {
996  }
997  } else { // trigger came too early
998  const TCEString moveDisasm =
1000  throw IllegalProgram(
1001  __FILE__,__LINE__, __func__,
1002  TCEString("Trigger without operand in ") + moveDisasm);
1003  }
1004 }
1005 
1006 /**
1007  * Analyze write to a trigger of an operation.
1008  *
1009  * Participates in ProgramOperation building. Calls
1010  * createTriggerDependencies(moveNode, dop) to create the register and
1011  * operation dependence egdes of the operation. Checks if operation is
1012  * call and if it is, processes the call-related register dependencies.
1013  *
1014  * @param moveNode mnData related to a move which triggers an operation
1015  * @param dop Operation being triggered
1016  */
1017 void
1019  MoveNode& moveNode, Operation& dop) {
1020 
1021  processTriggerPO(moveNode, dop);
1022 
1023  if (moveNode.move().isFunctionCall()) {
1024  processCall(moveNode);
1025  }
1026 }
1027 
1028 /**
1029  * Analyze write to a trigger of an operation.
1030  *
1031  * Participates in ProgramOperation building. Calls
1032  * createTriggerDependencies(moveNode, dop) to create the memory and
1033  * fu state dependence egdes of the operation. Checks if operation is
1034  * call and if it is, processes the call-related memory dependencies.
1035  *
1036  * @param moveNode mnData related to a move which triggers an operation
1037  * @param dop Operation being triggered
1038  */
1039 void
1041  MoveNode& moveNode, Operation &dop) {
1042 
1043  createTriggerDependencies(moveNode, dop);
1044 
1045  // handle call mem deps
1046  if (moveNode.move().isFunctionCall()) {
1047  // no guard, is not ra, is pseudo.
1048  MoveNodeUse mnd2(moveNode, false, false, true);
1049  processMemWrite(mnd2);
1050  }
1051 }
1052 
1053 /**
1054  * Analyzes operand writes.
1055  *
1056  * Part of ProgramOperation creation.
1057  *
1058  * @param moveNode mnData related to a move which writes a parameter.
1059  * @param dop Operation whose parameter is being written.
1060  */
1061 void
1063  MoveNode& moveNode, Operation &dop) {
1064 
1065  // first operands already analyzed for PO?
1066  // then update existing.
1067  if (currentData_->destPending_ != NULL) {
1069 
1070  assert(&dop == &po->operation());
1071 
1072  if (!po->isComplete()) {
1073  po->addInputNode(moveNode);
1074  moveNode.addDestinationOperationPtr(po);
1075  } else {
1076  // The MoveNode and the PO has been created before entering DDG
1077  // building (in LLVMTCEBuilder.cc).
1078  }
1079  return;
1080  }
1081 
1082  // create a new ProgramOperation
1083  TerminalFUPort& tfpd =
1084  dynamic_cast<TerminalFUPort&>(moveNode.move().destination());
1086  if (tfpd.hasProgramOperation()) {
1087  po = tfpd.programOperation();
1088  } else {
1089  po = ProgramOperationPtr(new ProgramOperation(dop));
1090  moveNode.addDestinationOperationPtr(po);
1091  po->addInputNode(moveNode);
1092  }
1093  currentData_->destPending_ = po;
1094 }
1095 
1096 /**
1097  * Analyzes a source of a result read.
1098  *
1099  * Handles program operation creation and operation dependence creation.
1100  *
1101  * @param moveNode MoveNode of the move being analyzed.
1102  */
1103 void
1105 
1106  // Goes thru all programoperations lacking result read.
1107  // There should be only one if well-behaving
1108  // universalmachine code.
1109  if (currentData_->readPending_ != NULL) {
1112 
1113  if (!po->isComplete()) {
1114  po->addOutputNode(moveNode);
1115  moveNode.setSourceOperationPtr(po);
1116  }
1117 
1118  // if this PO is ready, remove from list of incomplete ones
1119  if (currentData_->poReadsHandled_ >=
1120  po->operation().numberOfOutputs()) {
1125  }
1126  return;
1127  }
1128  throw IllegalProgram(
1129  __FILE__, __LINE__, __func__,
1130  (boost::format("Result move '%s' without operands") %
1131  moveNode.move().toString()).str());
1132 }
1133 
1134 /**
1135  * Creates operand edges between input and output moves of a
1136  * programoperation.
1137  *
1138  * @param po ProgramOperation whose egdes we are creating.
1139  */
1140 void
1142  ProgramOperationPtr po) {
1143 
1144  const Operation& op = po->operation();
1145 
1146  // loop over all input nodes
1147  for (int i = 0; i < po->inputMoveCount(); i++) {
1148  MoveNode& inputNode = po->inputMove(i);
1149  // loop over all output nodes.
1150  for (int j = 0; j < po->outputMoveCount(); j++) {
1151  MoveNode& outputNode = po->outputMove(j);
1152 
1153  // and create operation edges
1154  // from all input nodes to all
1155  // output nodes.
1156  DataDependenceEdge* dde =
1157  new DataDependenceEdge(
1160  op.name());
1161 
1163  inputNode, outputNode, dde);
1164  }
1165  }
1166 }
1167 
1168 ///////////////////////////////////////////////////////////////////////////////
1169 // Register edge creation.
1170 ///////////////////////////////////////////////////////////////////////////////
1171 
1172 /**
1173  * Checks whether there is a previous alive write with same guard than
1174  * given node.
1175  *
1176  * The origin of the guard value is tracked from DDG, not only plain guard
1177  * is done.
1178  *
1179  * @param mnd MoveNode containing the guard.
1180  * @param defines set of earlier writes which to check.
1181  */
1182 bool
1184  MoveNodeUse& mnd, std::set<MoveNodeUse>& defines) {
1185 
1186  // first just check if there is earlier write to this reg with same guard..
1187  for (std::set<MoveNodeUse>::iterator i = defines.begin();
1188  i != defines.end(); i++) {
1189  // if earlier write to this reg with same guard..
1190  if (!mnd.guard() &&
1191  !i->mn()->move().isUnconditional() &&
1192  currentDDG_->sameGuards(*(i->mn()), *(mnd.mn()))) {
1193  return true;
1194  }
1195  }
1196  return false;
1197 }
1198 
1199 std::set<MoveNodeUse>
1201  MoveNodeUse& mnd, std::set<MoveNodeUse>& defines) {
1202 
1203  std::set<MoveNodeUse> results;
1204  // first just check if there is earlier write to this reg with same guard..
1205  for (std::set<MoveNodeUse>::iterator i = defines.begin();
1206  i != defines.end(); i++) {
1207  // if earlier write to this reg with same guard..
1208  if (!mnd.guard() &&
1209  !i->mn()->move().isUnconditional() &&
1210  currentDDG_->sameGuards(*(i->mn()), *(mnd.mn()))) {
1211  results.insert(*i);
1212  }
1213  }
1214  return results;
1215 }
1216 
1217 
1218 /**
1219  * Handles a usage of a register value.
1220  *
1221  * The usage can be either register read or guard usage.
1222  * Creates the incoming edges and handles bookkeping related to the
1223  * register read.
1224  *
1225  * @param mnd Data about the register use
1226  * @param reg Register containing the value being used.
1227  */
1228 void
1230  MoveNodeUse mnd, const TCEString& reg) {
1231 
1232  // We may have multiple definitions to a register alive
1233  // (statically) at same time if some of the writes were guarded,
1234  // so we don't know which of them were actually executed,
1235  // so we have a set instead of single value.
1236  std::set<MoveNodeUse>& defines =
1238 
1239  std::set<MoveNodeUse> sameGuardDefines = earlierWritesWithSameGuard(mnd, defines);
1240  // find if we have a earlier write with same guard. In this case
1241  // no need to draw dependencies over it.
1242  bool guardedKillFound = !sameGuardDefines.empty();
1243 
1244  // then create the edges. if no guarded kill found,
1245  // all non-exclusive. if guarded kill found, not to uncond move.
1246  for (std::set<MoveNodeUse>::iterator i = defines.begin();
1247  i != defines.end(); i++) {
1248  // If we do not have a guarded kill, draw edges from all defines.
1249  // If we have a guarded kill, only draw edges from
1250  // unconditional moves, as the guarded kill overshadows the
1251  // inconditional writes.
1252  if (!guardedKillFound || (!i->mn()->move().isUnconditional() &&
1253  !currentDDG_->hasRegWaw(*i, sameGuardDefines))) {
1254  if (!currentDDG_->exclusingGuards(*(i->mn()), *(mnd.mn()))) {
1255  DataDependenceEdge* dde =
1256  new DataDependenceEdge(
1259  DataDependenceEdge::DEP_RAW, reg, mnd.guard(), false,
1260  i->pseudo(), mnd.pseudo(), i->loop());
1261 
1262  currentDDG_->connectOrDeleteEdge(*i->mn(), *mnd.mn(), dde);
1263  }
1264  }
1265  }
1266 
1267  // writes in previous BB's killed or not?
1268  // if not(this bb has a kill), has to check deps from incoming BB's.
1269  if (currentBB_->basicBlock().liveRangeData_->regKills_.find(reg) ==
1271 
1272  if (!guardedKillFound) {
1273  // process dependencies from previous BB's
1275  insert(mnd);
1276 
1278  }
1279  }
1280  currentBB_->basicBlock().liveRangeData_->regLastUses_[reg].insert(mnd);
1281 
1282  // Two writes to opposite guard may create a combined kill-pair.
1283  // But if this is a read between them, it has to be marked in order
1284  // to save bookkeeping about this move when the another write occurs.
1285  // So mark here that we have a read if we have one guarded write
1286  // in our bookkeeping as potential half of a kill pair.
1287  std::map<TCEString, std::pair<MoveNodeUse, bool> >::iterator iter =
1289  if (iter != currentBB_->basicBlock().liveRangeData_->potentialRegKills_.end()) {
1290  iter->second.second = true;
1291  }
1292 }
1293 
1294 /**
1295  * Creates register antidependencies from set of movenodeuses to one movenode.
1296  *
1297  * @param mnd Movenode which to creat those dependencies
1298  * @param predecessorNodes Nodes where to create dependencies from
1299  * @param depType whether to create WAR or WAW antidependencies
1300  * @param guardedKillFound if there is a write with same guard to the reg.
1301  */
1302 void
1304  const TCEString& reg, MoveNodeUse& mnd,
1305  MoveNodeUseSet& predecessorNodes,
1307  bool guardedKillFound) {
1308 
1309  // create dep to another in own bb
1310  for (std::set<MoveNodeUse>::iterator i = predecessorNodes.begin();
1311  i != predecessorNodes.end();) {
1312 
1313  if (depType == DataDependenceEdge::DEP_WAW) {
1314  // If we do not have a guarded kill, draw edges from all defines.
1315  // If we have a guarded kill, only draw edges from
1316  // unconditional moves, as the guarded kill overshadows the
1317  // inconditional writes.
1318  if (guardedKillFound && i->mn()->move().isUnconditional()) {
1319  i++;
1320  continue;
1321  }
1322  } else {
1323  assert(depType == DataDependenceEdge::DEP_WAR);
1324  // skip if war to itself, ie move foo.1 -> foo.1
1325  if (i->mn() == mnd.mn()) {
1326  i++;
1327  continue;
1328  }
1329  }
1330 
1331  // Do not create antideps if have excluding guards
1332  // But always create antidep if this writes to a reg which is
1333  // used as guard for the previous move.
1334  if (!currentDDG_->exclusingGuards(*(i->mn()), *(mnd.mn())) ||
1335  i->guard()) {
1336 
1337  // create dependency edge
1338  DataDependenceEdge* dde =
1339  new DataDependenceEdge(
1342  depType, reg, i->guard(), false,
1343  i->pseudo(), mnd.pseudo(), i->loop());
1344 
1345  // and connect
1346  currentDDG_->connectOrDeleteEdge(*i->mn(), *mnd.mn(), dde);
1347 
1348  // if have same guards, remove the old from bookkeeping
1349  // this completely overshadows it
1350  if (currentDDG_->sameGuards(*(i->mn()), *(mnd.mn()))) {
1351  predecessorNodes.erase(i++);
1352  continue;
1353  }
1354  }
1355  i++;
1356  }
1357 }
1358 
1359 
1360 /**
1361  * Analyzes a write to a register.
1362  *
1363  * Creates dependence edges and updates bookkeeping.
1364  *
1365  * @param mnd MoveNodeUse containing MoveNode that writes a register
1366  * @param reg register being written by the given movenode.
1367  */
1368 void
1370  MoveNodeUse mnd, const TCEString& reg) {
1371 
1372  // We may have multiple definitions to a register alive
1373  // (statically) at same time if some of the writes were guarded,
1374  // so we don't know which of them were actually executed,
1375  // so we have a set instead of single value.
1376  std::set<MoveNodeUse>& defines =
1378 
1379  // Set of register reads which after last kill.
1380  std::set<MoveNodeUse>& lastUses =
1382 
1383  // find if we have a earlier write with same guard. In this case
1384  // no need to draw dependencies over it.
1385  bool guardedKillFound = hasEarlierWriteWithSameGuard(mnd, defines);
1386 
1387  // if no kills to this reg in this BB, this one kills it.
1388  if (currentBB_->basicBlock().liveRangeData_->regKills_.find(reg) ==
1390 
1391  // is this alone a kill?
1392  if (mnd.mn()->move().isUnconditional()) {
1393  currentBB_->basicBlock().liveRangeData_->regKills_[reg].first = mnd;
1395  } else {
1396  // two guarded moves with opposite guards together may be a kill.
1397  // Check if we have such previous guarded write with opposite
1398  // guard.
1399  std::map<TCEString, std::pair<MoveNodeUse, bool> >::iterator
1400  iter =
1402  if (iter != currentBB_->basicBlock().liveRangeData_->potentialRegKills_.end() &&
1404  *(iter->second.first.mn()), *(mnd.mn()))) {
1406  iter->second.first;
1407  currentBB_->basicBlock().liveRangeData_->regKills_[reg].second = mnd;
1408  }
1409  }
1410  if (!guardedKillFound) {
1411  // may have incoming WaW's / WaRs to this
1412  // insert to bookkeeping for further analysis.
1414 
1415  // do we need to create some inter-bb-antideps?
1417  // deps from other BB.LIVERANGEDATA_->
1419  mnd, reg, currentBB_->basicBlock());
1420  }
1421  }
1422  }
1423 
1424  // Create antideps to defines and uses in this same BB.LIVERANGEDATA_->
1427  reg, mnd, defines, DataDependenceEdge::DEP_WAW, guardedKillFound);
1428 
1430  reg, mnd, lastUses, DataDependenceEdge::DEP_WAR,
1431  guardedKillFound);
1432  }
1433 
1434  // if unconditional, this kills previous deps.
1435  if (mnd.mn()->move().isUnconditional()) {
1436  defines.clear();
1437 
1438  currentBB_->basicBlock().liveRangeData_->regLastKills_[reg].first = mnd;
1440 
1441  // clear reads to given reg.
1442  lastUses.clear();
1444  } else {
1445  // two guarded moves with opposite guards together may be a kill.
1446  // Check if we have such previous guarded write with opposite
1447  // guard.
1448  std::map<TCEString, std::pair<MoveNodeUse, bool> >::iterator iter =
1450  if (iter != currentBB_->basicBlock().liveRangeData_->potentialRegKills_.end() &&
1452  *(iter->second.first.mn()), *(mnd.mn()))) {
1453 
1454  // found earlier write which is exclusive with this one.
1455  // mark that these two together are a kill.
1457  iter->second.first;
1458  currentBB_->basicBlock().liveRangeData_->regLastKills_[reg].second = mnd;
1459 
1460  // If we have no usage of the register between these two
1461  // writes forming the kill pair, we can clear our bookkeeping.
1462 
1463  // only leave the other part of the kill to defines.
1464  defines.clear();
1465  defines.insert(iter->second.first);
1466 
1467  if (!iter->second.second) {
1468  // clear reads to given reg.
1469  lastUses.clear();
1470  }
1471  }
1473  std::pair<MoveNodeUse, bool>(mnd, false);
1474  }
1475  defines.insert(mnd);
1476 }
1477 
1478 /**
1479  * Processes a return from a function.
1480  *
1481  * Creates pseudo-read-deps to SP and RV registers.
1482  *
1483  * @param moveNode moveNode containg the return move.
1484  */
1485 void
1488 
1489  // return is considered as read of sp;
1490  // sp must be correct at the end of the procedure.
1491  if (sp != "") {
1492  processRegUse(MoveNodeUse(moveNode,false,false,true),sp);
1493  }
1494 
1495  // return is considered as read of RV.
1497  if (rv != "") {
1498  processRegUse(MoveNodeUse(moveNode,false,false,true),rv);
1499  }
1500 
1501  // process all vector rv values
1502  for (int i = REG_VRV;;i--) {
1503  auto vrvIt = specialRegisters_.find(i);
1504  if (vrvIt != specialRegisters_.end()) {
1505  processRegUse(
1506  MoveNodeUse(moveNode,false,false,true),vrvIt->second);
1507  } else {
1508  break;
1509  }
1510  }
1511 
1512  // return is also considered as read of RV high(for 64-bit RV's)
1514  if (rvh != "") {
1515  processRegUse(MoveNodeUse(moveNode,false,false,true),rvh);
1516  }
1517 
1519  if (fp != "") {
1520  processRegUse(MoveNodeUse(moveNode,false,false,true),fp);
1521  }
1522 }
1523 
1524 /**
1525  * Processes a call of a function.
1526  *
1527  * Pseudo-reads from parameter registers and SP, writes to RV and RA.
1528  *
1529  * @param mn MoveNode containg the function call move.
1530  */
1531 void
1533 
1534  // calls mess up RA. But immediately, not after delay slots?
1536  MoveNodeUse(mn, false, true, false), RA_NAME);
1537 
1538  // MoveNodeUse for sp and rv(not guard, not ra, is pseudo)
1539  MoveNodeUse mnd2(mn, false,false, true);
1540 
1541  // call is considered read of sp
1543  if (sp != "") {
1544  processRegUse(mnd2,sp);
1545  }
1546 
1547  // call is considered as write of RV
1549  if (rv != "") {
1550  if (rvIsParamReg_) {
1551  processRegUse(mnd2,rv);
1552  }
1553  processRegWrite(mnd2,rv);
1554  }
1555 
1556  // process all vector rv values
1557  for (int i = REG_VRV;;i--) {
1558  auto vrvIt = specialRegisters_.find(i);
1559  if (vrvIt != specialRegisters_.end()) {
1560  processRegWrite(mnd2, vrvIt->second);
1561  } else {
1562  break;
1563  }
1564  }
1565 
1566  // call is considered as write of RV high (64-bit return values)
1568  if (rvh != "") {
1569  processRegWrite(mnd2, rvh);
1570  }
1571 
1572  // params
1573  for (int i = 0; i < 4;i++) {
1574  TCEString paramReg = specialRegisters_[REG_IPARAM+i];
1575  if (paramReg != "") {
1576  processRegUse(mnd2, paramReg);
1577  }
1578  }
1579 }
1580 
1581 ///////////////////////////////////////////////////////////////////////////////
1582 // Side-Effects of triggers.
1583 ///////////////////////////////////////////////////////////////////////////////
1584 
1585 /**
1586  * Analyzes operation of a trigger write.
1587  *
1588  * If memory read, calls processMemRead to manage memory read dependencies.
1589  * Manages FU State dependencies between operations.
1590  *
1591  * @param moveNode mnData related to a move which triggers an operation
1592  * @param dop Operation being triggered
1593  *
1594  */
1595 void
1597  MoveNode& moveNode, Operation& dop) {
1598 
1599  if (dop.readsMemory()) {
1600  processMemUse(MoveNodeUse(moveNode));
1601  } //TODO: avoid drawing antidep to itself
1602 
1603  if (dop.writesMemory()) {
1604  processMemWrite(MoveNodeUse(moveNode));
1605  }
1606 
1609  currentBB_->basicBlock().liveRangeData_->fuDepReaches_, moveNode, dop);
1610 
1611  OperationPool pool;
1612  if (dop.hasSideEffects() || pool.sharesState(dop)) {
1613 
1614  // remove old same op from bookkeeping.
1615  // this should prevent exponential explosion of edge count.
1616  if (dop.hasSideEffects() && moveNode.move().isUnconditional()) {
1617  for (MoveNodeUseSet::iterator iter =
1619  iter != currentBB_->basicBlock().liveRangeData_->fuDeps_.end(); iter++) {
1620 
1621  const Operation& o =
1622  iter->mn()->destinationOperation().operation();
1623  if (&o == &dop) {
1624  currentBB_->basicBlock().liveRangeData_->fuDeps_.erase(iter);
1625  break;
1626  }
1627  }
1628  }
1629  // add the new one to bookkeeping
1630  currentBB_->basicBlock().liveRangeData_->fuDeps_.insert(MoveNodeUse(moveNode));
1631  }
1632 }
1633 
1634 /*
1635  * Creates operation side effect.
1636  *
1637  * Checks the given MoveNode against list of possible side effect
1638  * dependence sources, and creates side effect edges if there is
1639  * a side effect/fu state dependence.
1640  *
1641  * @param prevMoves moves to check side effects against.
1642  * @param mn moveNode that is the destination of the dependencies.
1643  * @param dop Operation that mn triggers.
1644  */
1645 void
1647  MoveNodeUseSet& prevMoves, const MoveNode& mn, Operation& dop) {
1648 
1649  OperationPool pool;
1650  if (pool.sharesState(dop) || dop.hasSideEffects()) {
1651  for (MoveNodeUseSet::iterator i = prevMoves.begin();
1652  i != prevMoves.end(); i++) {
1653  const Operation& o = i->mn()->destinationOperation().operation();
1654 
1655  // mem writes are handled by memory deps so exclude here
1656  if ((&dop == &o && o.hasSideEffects()) ||
1657  dop.dependsOn(o) || o.dependsOn(dop)) {
1658  // if operations are always assigned to differnt FU,
1659  // skip creating dependency edge
1660  if (isAlwaysDifferentFU(&mn, i->mn())) continue;
1661 
1662  if (!currentDDG_->exclusingGuards(*(i->mn()), mn)) {
1663  DataDependenceEdge* dde =
1664  new DataDependenceEdge(
1666  DataDependenceEdge::DEP_UNKNOWN, false,false,false,
1667  false, static_cast<int>(i->loop()));
1669  *(i->mn()), mn, dde);
1670  }
1671  }
1672  }
1673  }
1674 }
1675 
1676 
1677 ///////////////////////////////////////////////////////////////////////////////
1678 // Memory edge creation.
1679 ///////////////////////////////////////////////////////////////////////////////
1680 
1681 /**
1682  * Checks if there is an earlier write to same address or with same guard.
1683  *
1684  * @param mnd the current node dictating guard and mem address to check.
1685  * @param defines set of earlier writes to check for the write.
1686  */
1687 bool
1689  MoveNodeUse& mnd, std::set<MoveNodeUse>& defines) {
1690  // first just check if there is earlier write to this mem address
1691  // with same guard.
1692  for (std::set<MoveNodeUse>::iterator i = defines.begin();
1693  i != defines.end(); i++) {
1694  // if earlier write to this reg with same guard..
1695  if (currentDDG_->sameGuards(*(i->mn()), *(mnd.mn()))) {
1696  ProgramOperation& curPop = mnd.mn()->destinationOperation();
1697  ProgramOperation& prevPop = (i->mn())->destinationOperation();
1698 // MoveNode* currentAddress = addressMove(*mnd.mn());
1699 // MoveNode* prevAddress = addressMove(*(i->mn()));
1700  if (!isAddressTraceable(prevPop) ||
1701  analyzeMemoryAlias(prevPop, curPop, i->bbRelation()) ==
1703  return true;
1704  }
1705  }
1706  }
1707  return false;
1708 }
1709 
1710 /**
1711  * Creates memory dependencies from set of nodes to given nodes.
1712  *
1713  * Does not create if gaurds of aliasing dictate edge not needed.
1714  * If both guard and aliasing indicate fully transitive case for some
1715  * prev nodes, then remove these previous nodes from the bookkeeping.
1716  */
1717 void
1719  MoveNodeUse& mnd, std::set<MoveNodeUse>& prevNodes,
1721  bool traceable) {
1722  // create WaW to another in own bb
1723  for (MoveNodeUseSet::iterator iter =
1724  prevNodes.begin(); iter != prevNodes.end();) {
1725  if ((checkAndCreateMemDep(*iter, mnd, depType) || !traceable) &&
1726  (mnd.mn()->move().isUnconditional() ||
1727  currentDDG_->sameGuards(*(iter->mn()), *(mnd.mn())))) {
1728  // remove current element and update iterator to next.
1729  prevNodes.erase(iter++);
1730  } else { // just take next from the set
1731  iter++;
1732  }
1733  }
1734 }
1735 
1736 /**
1737  * Updates memory operation bookkeeping and creates WaR and WaW
1738  * memory dependencies.
1739  *
1740  * @param moveNode MoveNodeUse related to Move whose memory write to are
1741  * processing.
1742  */
1743 void
1745 
1746  TCEString category = memoryCategory(mnd);
1747 
1748  std::set<MoveNodeUse>& defines =
1750 
1751  std::set<MoveNodeUse>& lastUses =
1753 
1754  // check if no earlier barriers/kills to this one in this bb?
1755  if (currentBB_->basicBlock().liveRangeData_->memKills_[category].mn() == NULL) {
1756 
1757  // is this a kill?
1758  if (mnd.mn()->move().isUnconditional() &&
1760  currentBB_->basicBlock().liveRangeData_->memKills_[category] = mnd;
1761  }
1762 
1763  // check if there is "guarded kill" to this mem address
1764  bool guardedKillFound =
1766 
1767  if (!guardedKillFound) {
1768  // may have incoming WaW's / WaRs to this
1769  currentBB_->basicBlock().liveRangeData_->memFirstDefines_[category].insert(mnd);
1770  updateMemWrite(mnd, category);
1771  }
1772  }
1773 
1774  bool traceable = isAddressTraceable(mnd.mn()->destinationOperation());
1775 
1777  mnd, defines, DataDependenceEdge::DEP_WAW, traceable);
1778 
1780  mnd, lastUses, DataDependenceEdge::DEP_WAR, traceable);
1781 
1782  // does this kill previous deps?
1783  if (mnd.mn()->move().isUnconditional() && !traceable) {
1784  currentBB_->basicBlock().liveRangeData_->memLastKill_[category] = mnd;
1785  defines.clear();
1786  lastUses.clear();
1787  }
1788 
1789  defines.insert(mnd);
1790 }
1791 
1792 /**
1793  * Processes a memory read.
1794  *
1795  * Creates dependence edges and updates bookkeeping.
1796  *
1797  * @param mnd MoveNodeUse of MoveNode being processed.
1798  */
1799 void
1801 
1802  TCEString category = memoryCategory(mnd);
1803 
1804  // can be multiple if some write predicated
1805  std::set<MoveNodeUse>& defines =
1807 
1808  // no kills/barriers to this one in this basic block.
1809  if (currentBB_->basicBlock().liveRangeData_->memKills_[category].mn() == NULL) {
1810 
1811  // check if there is "guarded kill" to this mem address
1812  bool guardedKillFound =
1814 
1815  if (!guardedKillFound) {
1816  currentBB_->basicBlock().liveRangeData_->memFirstUses_[category].insert(mnd);
1817  // so create deps from previous BB's
1818  updateMemUse(mnd, category);
1819  }
1820  }
1821 
1822  // create deps from writes in this BB.LIVERANGEDATA_->
1823  for (MoveNodeUseSet::iterator iter =
1824  defines.begin(); iter != defines.end(); iter++) {
1826  }
1827  // update bookkeeping.
1828  currentBB_->basicBlock().liveRangeData_->memLastUses_[category].insert(mnd);
1829 }
1830 
1831 /**
1832  * Compares a memory op against one previous memory ops and
1833  * creates dependence if may alias.
1834  *
1835  * @param prev Previous Memory write movenode
1836  * @param mn Current memory write movenode
1837  * @param depType dependence type which to create.
1838  * @return true if true alias.
1839  */
1840 bool
1842  MoveNodeUse prev, MoveNodeUse mnd,
1844 
1845  // cannot be dep if opposite guards.
1846  if (currentDDG_->exclusingGuards(*(prev.mn()), *(mnd.mn()))) {
1847  return false;
1848  }
1849 
1852 
1853  // only for true stores and loads; we cannot analyze aliasing
1854  // of pseudo dependencies caused by call/return.
1855  if (!prev.pseudo() && !mnd.pseudo()) {
1856  ProgramOperation& currPop = mnd.mn()->destinationOperation();
1857  ProgramOperation& prevPop = prev.mn()->destinationOperation();
1858 
1859  const llvm::MachineInstr* instr1 = currPop.machineInstr();
1860  const llvm::MachineInstr* instr2 = prevPop.machineInstr();
1861 
1862  // The LLVM MachineInstructions are not connected to
1863  // all memory operands, at least not to those in inline
1864  // assembly blocks (from custom operation calls).
1865  if (instr1 != NULL && instr2 != NULL) {
1866  llvm::MachineInstr::mmo_iterator begin1 =
1867  instr1->memoperands_begin();
1868  // Machine instruction could in theory have several memory operands.
1869  // In practice it is usually just one.
1870  while (begin1 != instr1->memoperands_end()) {
1871  llvm::MachineInstr::mmo_iterator begin2 =
1872  instr2->memoperands_begin();
1873 
1874  while (begin2 != instr2->memoperands_end()) {
1875  // Force program ordering between volatile mem accesses.
1876  if ((*begin1)->isVolatile() && (*begin2)->isVolatile()) {
1877 #if 0
1878  Application::logStream() << "MemDep >> volatile \n";
1879  PRINT_VAR(currPop.toString());
1880  PRINT_VAR(prevPop.toString());
1881  (*begin1)->getValue()->dump();
1882  (*begin2)->getValue()->dump();
1883 #endif
1884  aliasResult = MemoryAliasAnalyzer::ALIAS_PARTIAL;
1885  }
1886  begin2++;
1887  }
1888  begin1++;
1889  }
1890  }
1891  if (aliasResult == MemoryAliasAnalyzer::ALIAS_UNKNOWN)
1892  aliasResult = analyzeMemoryAlias(prevPop, currPop, prev.bbRelation());
1893  }
1894 
1895  if (aliasResult != MemoryAliasAnalyzer::ALIAS_FALSE) {
1896  // if not alias false , have to create mem edge.
1897  bool trueAlias = (aliasResult == MemoryAliasAnalyzer::ALIAS_TRUE);
1898  ProgramOperation& prevPo = prev.mn()->destinationOperation();
1899  for (int i = 0; i < prevPo.inputMoveCount(); i++) {
1900  if (prev.loop() || &prevPo.inputMove(i) != mnd.mn()) {
1901  // if operations are always assigned to differnt FU,
1902  // then skip creating memroy dependency edge
1903  if (isAlwaysDifferentFU(prev.mn(), mnd.mn())) {
1904  continue;
1905  }
1906  DataDependenceEdge* dde2 =
1907  new DataDependenceEdge(
1908  DataDependenceEdge::EDGE_MEMORY, depType, false,
1909  trueAlias, prev.pseudo(), mnd.pseudo(),
1910  static_cast<int>(prev.loop()));
1912  prevPo.inputMove(i), *mnd.mn(), dde2);
1913  }
1914  }
1915  return trueAlias;
1916  }
1917  return false;
1918 }
1919 
1920 ///////////////////////////////////////////////////////////////////////////////
1921 // Alias analysis - related things.
1922 ///////////////////////////////////////////////////////////////////////////////
1923 
1924 /**
1925  * Gets the address-writing move of a move which is a trigger or operand
1926  * to a memory operation.
1927  *
1928  * If none found, return null
1929  *
1930  * @param mn moveNode whose address write move is being searched.
1931  * @return MoveNode which writes address to a mem operation or NULL.
1932 
1933 MoveNode*
1934 DataDependenceGraphBuilder::addressMove(const MoveNode& mn) {
1935  if (mn.isDestinationOperation()) {
1936  return addressOperandMove(mn.destinationOperation());
1937  }
1938  return NULL;
1939 }
1940 */
1941 
1942 /**
1943  * Delegates the call to all registered memory address alias analyzers.
1944  *
1945  * Returns the first non-unknown result.
1946  * If no alias analyzer can analyze these, returns ALIAS_UNKNOWN
1947  *
1948  * @return Whether the memory accesses in the given moves alias.
1949  */
1952  const ProgramOperation& pop1, const ProgramOperation& pop2,
1953  MoveNodeUse::BBRelation bbInfo) {
1954 
1955  for (unsigned int i = 0; i < aliasAnalyzers_.size(); i++) {
1956  MemoryAliasAnalyzer* analyzer = aliasAnalyzers_[i];
1958  analyzer->analyze(*currentDDG_, pop1, pop2, bbInfo);
1960  return res;
1961  }
1962  }
1964 }
1965 
1966 /**
1967  * Can some analyzer say something about this address?
1968  *
1969  * @param mn Movenode containing memory address write.
1970  * @return true if some alias analyzer knows something about the address,
1971  * ie can return something else than ALIAS_UNKNOWN.
1972  */
1973 bool
1975 
1976  for (unsigned int i = 0; i < aliasAnalyzers_.size(); i++) {
1977  if (aliasAnalyzers_.at(i)->isAddressTraceable(*currentDDG_, pop)) {
1978  return true;
1979  }
1980  }
1981  return false;
1982 }
1983 
1984 /**
1985  * Checks into which category this memory address belongs.
1986  *
1987  * Memory accesses in different categories cannot alias, and there is
1988  * separate bookkeeping for every category. Current implementation separates
1989  * spills, different alias spaces, restrict keywords and opencl work items.
1990  *
1991  * @param mnd MoveNodeUse which transfers the address of the memory operation.
1992  * @return string which is then used as key for map.
1993  * unique for different categories, empty for the default category.
1994  *
1995  * @TODO: create some memorycategorizer interface for this analysis?
1996  */
1997 
1998 TCEString
2000 
2001  TCEString category;
2002 
2003 // MoveNode* addressNode = addressMove(*mnd.mn());
2004 // if (addressNode != NULL && addressNode->isMove()) {
2005  const TTAProgram::Move& move = mnd.mn()->move();//addressNode->move();
2006 
2007  // spill annotations are in all operands.
2008  for (int j = 0; j < move.annotationCount(); j++) {
2010  if (anno.id() ==
2012  return "_SPILL";
2013  }
2014  if (anno.id() ==
2016  return "_RA";
2017  }
2018  if (anno.id() ==
2020  return "_FP";
2021  }
2022  if (anno.id() ==
2024  return "_CONSTANT";
2025  }
2026  }
2027  if (!mnd.mn()->isDestinationOperation()) {
2028  PRINT_VAR(mnd.mn()->toString());
2029  abortWithError("Not destination operation!");
2030  }
2031  ProgramOperation& po = mnd.mn()->destinationOperation();
2032 
2033  LLVMTCECmdLineOptions* llvmOptions =
2034  dynamic_cast<LLVMTCECmdLineOptions*>(
2036  if (llvmOptions == NULL || !llvmOptions->disableAddressSpaceAA()) {
2037  // address space
2038  for (int i = 0; i < po.inputMoveCount(); i++) {
2039  MoveNode& mn = po.inputMove(i);
2040  Move& m = mn.move();
2041  if (m.hasAnnotations(
2042  ProgramAnnotation::ANN_POINTER_ADDR_SPACE)) {
2043  if (m.annotation(
2044  0, ProgramAnnotation::ANN_POINTER_ADDR_SPACE).stringValue()
2045  != "0") {
2046  category +=
2047  "_AS:" +
2048  m.annotation(
2049  0, ProgramAnnotation::ANN_POINTER_ADDR_SPACE)
2050  .stringValue();
2051  break;
2052  }
2053  }
2054  }
2055  }
2056  for (int i = 0; i < po.inputMoveCount(); i++) {
2057  MoveNode& mn = po.inputMove(i);
2058  Move& m = mn.move();
2059  TCEString pointerName = "";
2060  // restrict keyword.
2061  if (m.hasAnnotations(
2062  ProgramAnnotation::ANN_POINTER_NAME) &&
2063  m.hasAnnotations(
2064  ProgramAnnotation::ANN_POINTER_NOALIAS)) {
2065  pointerName =
2066  m.annotation(
2067  0, ProgramAnnotation::ANN_POINTER_NAME).stringValue();
2068  category += "_RESTRICT:" + pointerName;
2069  break;
2070  }
2071  }
2072 
2073  /* OpenCL work item variable access.
2074 
2075  OpenCL kernels enforce memory consistency for local and global
2076  memory only at explicit barrier() calls within a work group.
2077  Thus, all memory accesses between work items can be considered
2078  independent in alias analysis in the regions between barrier
2079  calls.
2080  */
2081  for (int i = 0; i < po.inputMoveCount(); i++) {
2082  MoveNode& mn = po.inputMove(i);
2083  Move& m = mn.move();
2084  if (m.hasAnnotations(ProgramAnnotation::ANN_OPENCL_WORK_ITEM_ID)) {
2085  category +=
2086  "_OPENCL_WI:" +
2088  m.annotation(
2089  0, ProgramAnnotation::ANN_OPENCL_WORK_ITEM_ID).
2090  intValue(), 8);
2091  break;
2092  }
2093  }
2094  return category;
2095 }
2096 
2097 ///////////////////////////////////////////////////////////////////////////////
2098 // Multi-BB DDG construction
2099 ///////////////////////////////////////////////////////////////////////////////
2100 
2101 ///////////////////////////////////////////////////////////////////////////////
2102 // High-level Multi-BB DDG construction
2103 ///////////////////////////////////////////////////////////////////////////////
2104 
2105 /**
2106  * Builds a DDG from a CFG.
2107  *
2108  * @param cfg Control flow graph where the ddg is built from.
2109  * @param antidependenceLevel level of register antidependencies to create.
2110  * @param um universalmachine used for the code if registers unallocated.
2111  * if null, assumed that registers allready allocated.
2112  * @param createMemAndFUDeps whether to create also memory and
2113  * fu state(side effect) dependencies or only register deps.
2114  * @param createDeathInformation whether to search the last usage
2115  * of all liveranges. This is needed for things like register renamer
2116  * and threading.
2117  * @return pointer to the ddg which is created.
2118  */
2121  ControlFlowGraph& cfg,
2122  DataDependenceGraph::AntidependenceLevel antidependenceLevel,
2123  const TTAMachine::Machine& mach,
2124  const UniversalMachine* um,
2125  bool createMemAndFUDeps, bool createDeathInformation,
2126  llvm::AliasAnalysis* AA) {
2127 
2128  mach_ = &mach;
2129  if (AA) {
2130  for (unsigned int i = 0; i < aliasAnalyzers_.size(); i++) {
2131  LLVMAliasAnalyzer* llvmaa =
2132  dynamic_cast<LLVMAliasAnalyzer*>(aliasAnalyzers_[i]);
2133  if (llvmaa != NULL) {
2134  llvmaa->setLLVMAA(AA);
2135  }
2136  }
2137  }
2138 
2139  cfg_ = &cfg;
2140 
2141  // @TODO: when CFG subgraphs are in use, 2nd param not always true
2143  allParamRegs_, cfg.name(), antidependenceLevel, NULL, true,
2144  false);
2145  try {
2146  // this is just for old frontend code.
2147  if (um != NULL) {
2149  } else {
2151  }
2152 
2153  currentDDG_ = ddg;
2154 
2155  // do the first phase (register dependencies and operation edges)
2157 
2158  // then do the second phase - mem and fu deps.
2159  if (createMemAndFUDeps) {
2161  }
2162 
2163  // search when registers are used for last time.
2164  // this live range information is used by register renamer and
2165  // threading.
2166  if (createDeathInformation) {
2168  }
2169 
2170  // clear bookkeeping which is not needed anymore.
2172  } catch (const Exception& e) {
2174  << e.fileName() << ": " << e.lineNum() << ": " << e.errorMessageStack()
2175  << std::endl;
2176  delete ddg;
2177  throw;
2178  } catch (...) {
2179  delete ddg;
2180  throw;
2181  }
2182  ddg->setMachine(mach);
2183  return ddg;
2184 }
2185 
2186 /**
2187  * Initializes states of all BB's to unreached
2188  *
2189  */
2190 void
2192 
2193  // initialize state lists
2194  for (int bbi = 0; bbi < cfg_->nodeCount(); bbi++) {
2195  BasicBlockNode& bbn = cfg_->node(bbi);
2196  BasicBlock& bb = bbn.basicBlock();
2197  if (bb.liveRangeData_ == NULL) {
2198  bb.liveRangeData_ = new LiveRangeData;
2199  }
2200  BBData* bbd = new BBData(bbn);
2201  bbData_[&bbn] = bbd;
2202  // in the beginning all are unreached
2203  if (bbn.isNormalBB()) {
2204  blocksByState_[BB_UNREACHED].push_back(bbd);
2205  }
2206  }
2207 }
2208 
2209 /**
2210  * Changes state of a basic block in processing.
2211  * Move BBData into a diffefent list and changes the state data in BBData.
2212  *
2213  * @param bbd BBData of basic block whose state is being changed
2214  * @param newState the new state of the basic block.
2215 */
2216 void
2218  BBData& bbd, BBState newState, bool priorize) {
2219 
2220  BBState oldState = bbd.state_;
2221  if (newState != oldState) {
2223  bbd.state_ = newState;
2224  if (priorize) {
2225  blocksByState_[newState].push_front(&bbd);
2226  } else {
2227  blocksByState_[newState].push_back(&bbd);
2228  }
2229  }
2230 }
2231 
2232 /**
2233  * Queues first basic block to be processed.
2234  *
2235  * @return the first basic block node
2236  */
2239  // get first BB where to start
2241  assert(firstBBs.size() == 1);
2242  BasicBlockNode* firstBB = *firstBBs.begin();
2243  changeState(*(bbData_[firstBB]), BB_QUEUED);
2244  return firstBB;
2245 }
2246 
2247 /**
2248  * Clears bookkeeping which is only needed during ddg construction.
2249  */
2250 void
2252 
2253  for (int i = 0; i < cfg_->nodeCount();i++) {
2254  BasicBlockNode& bbn = cfg_->node(i);
2255  if (bbn.isNormalBB()) {
2256  BasicBlock& bb = bbn.basicBlock();
2257  clearUnneededBookkeeping(bb, true);
2258  }
2259  }
2260 }
2261 
2262 /**
2263  * Does the first phase of ddg construction. handles register deps.
2264  *
2265  * @param cfg control flow graph containing the code.
2266  */
2267 void
2269 
2270  // initializes states of all BB's to unreached.
2272 
2273  // queues first bb for processing
2274  BasicBlockNode* firstBB = queueFirstBB();
2275 
2276  // currentBB need to be set for entry node processing
2277  currentBB_ = firstBB;
2278 
2279  // set entry deps. ( procedure parameter edges )
2280  MoveNode* entryNode = new MoveNode();
2281  currentDDG_->addNode(*entryNode, cfg_->entryNode());
2282 
2283  processEntryNode(*entryNode);
2284 
2285  // iterate over BB's. Loop as long as there are queued BB's.
2286 
2288 
2289  // all should be constructed, but if there are unreachable BB's
2290  // we handle those also
2291  while (!blocksByState_[BB_UNREACHED].empty()) {
2293  Application::logStream() << "Warning: Unreachable Basic Block!"
2294  << std::endl;
2295  Application::logStream() << "In procedure: " << cfg_->name() <<
2296  std::endl;
2297 // cfg.writeToDotFile("unreachable_bb.dot");
2298  }
2301  }
2302  // free bb data
2304 }
2305 
2306 /**
2307  * Does the second phase of ddg construction.
2308  *
2309  * handles mem deps and fu state deps.
2310  */
2311 void
2313 
2314  // initializes states of all BB's to unreached.
2316 
2317  // queues first bb for processing
2318  queueFirstBB();
2319 
2320  // then iterates over all basic blocks.
2322 
2323  // all should be constructed, but if there are unreachable BB's
2324  // we might want to handle those also
2325  while (!blocksByState_[BB_UNREACHED].empty()) {
2328  }
2329  // free bb data
2331 }
2332 
2333 
2334 /**
2335  * Iterates over basic blocks as long as there is some BB to process.
2336  *
2337  * Handles a BB, updates the live value lists of its successors.
2338  * If incoming live values of a BB change, it's scheduled for
2339  * reprocessing.
2340  *
2341  * @param phase whether to handle register& operation deps or
2342  * memory and side-effect dependencies.
2343  */
2344 void
2346  ConstructionPhase phase) {
2347 
2348  while (!blocksByState_[BB_QUEUED].empty()) {
2349  std::list<BBData*>::iterator bbIter =
2350  blocksByState_[BB_QUEUED].begin();
2351  BBData& bbd = **bbIter;
2352 
2353  // construct or update BB
2354  if (bbd.constructed_) {
2355  updateBB(bbd, phase);
2356  } else {
2357  constructIndividualBB(bbd, phase);
2358  }
2359  // mark as ready
2360  changeState(bbd, BB_READY);
2361 
2362  // create deps after and update that to succeeding BBs.
2363  // succeeding BB's are also queued to be scheduled here.
2364  // queue succeeding BB's in case either
2365  // * their input data has changed
2366  // * current BB was processed for the first time
2367  if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
2368  if (updateRegistersAliveAfter(bbd) || !bbd.constructed_) {
2369  setSucceedingPredeps(bbd, !bbd.constructed_, phase);
2370  }
2371  } else {
2372  if (updateMemAndFuAliveAfter(bbd) || !bbd.constructed_) {
2373  setSucceedingPredeps(bbd, !bbd.constructed_, phase);
2374  }
2375  }
2376 
2377  bbd.constructed_ = true;
2378  }
2379 }
2380 
2381 /**
2382  * Updates bookkeeping used for calculating register deaths.
2383  *
2384  * Marks registers used at or after some BB to it's predecessor BB's.
2385  *
2386  * @param bbd basic block to process.
2387  * @param firstTime whether this BB is analyzer for the first time.
2388  */
2389 void
2391  BBData& bbd, bool firstTime) {
2392  BasicBlockNode& bbn = *bbd.bblock_;
2393  BasicBlock& bb = bbn.basicBlock();
2394  BasicBlockNodeSet predecessors = cfg_->predecessors(bbn);
2395  for (BasicBlockNodeSet::iterator predIter = predecessors.begin();
2396  predIter != predecessors.end(); predIter++) {
2397  BasicBlockNode* pred = *predIter;
2398  BasicBlock& predBB = pred->basicBlock();
2399  BBData& predData = *bbData_[pred];
2400  size_t size = predBB.liveRangeData_->registersUsedAfter_.size();
2403 
2404  // if updated, need to be handled again.
2405  if (predBB.liveRangeData_->registersUsedAfter_.size() > size || firstTime) {
2406  if (predData.state_ != BB_QUEUED) {
2407  changeState(predData, BB_QUEUED);
2408  }
2409  }
2410  }
2411 }
2412 
2413 /**
2414  * Sets outgoing data from this BB to incoming data of successors.
2415  *
2416  * Also queues them to be reprocessed if they are changed.
2417  *
2418  * @param bbd BBD whose successors will be updated.
2419  * @param queueAll If true, queues all successors even if they do not change.
2420  * @param phase whether to handle register& operation deps or
2421  * memory and side-effect dependencies.
2422  */
2423 void
2425  BBData& bbd, bool queueAll,
2426  ConstructionPhase phase) {
2427  BasicBlockNode& bbn = *bbd.bblock_;
2428  BasicBlock& bb = bbn.basicBlock();
2429 
2430  BasicBlockNodeSet forwardSuccessors = cfg_->successors(bbn, true);
2431  for (BasicBlockNodeSet::iterator succIter = forwardSuccessors.begin();
2432  succIter != forwardSuccessors.end(); succIter++) {
2434  bb, **succIter, queueAll, false, phase);
2435  }
2436 
2437  // successors over loop edges.
2438  BasicBlockNodeSet backwardSuccessors = cfg_->successors(bbn, false, true);
2439  for (BasicBlockNodeSet::iterator succIter = backwardSuccessors.begin();
2440  succIter != backwardSuccessors.end(); succIter++) {
2442  bb, **succIter, queueAll, true, phase);
2443  }
2444 }
2445 
2446 /**
2447  * Sets outgoing data from this BB to incoming data of one successor.
2448  *
2449  * Also queues them to be reprocessed if they are changed.
2450  *
2451  * @param bb BB whose successor will be updated.
2452  * @param successor successor BB whose incoming data is being updated.
2453  * @param queueAll If true, queues all successors even if they do not change.
2454  * @param loop whether to add loop property to the copied
2455  * bookkeeping, ie create edges with loop property.
2456  * @param phase whether to handle register& operation deps or
2457  * memory and side-effect dependencies.
2458  */
2459 void
2461  BasicBlock& bb, BasicBlockNode& successor, bool queueAll, bool loop,
2462  ConstructionPhase phase) {
2463 
2464  BasicBlock& succBB = successor.basicBlock();
2465  BBData& succData = *bbData_[&successor];
2466  bool changed = false;
2467 
2468  if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
2471  succBB.liveRangeData_->regDefReaches_, loop);
2472 
2474  (&bb == &succBB &&
2478  succBB.liveRangeData_->regUseReaches_, loop);
2479  }
2480  } else {
2481  // mem deps + fu state deps
2482 
2485  succBB.liveRangeData_->memDefReaches_, loop);
2486 
2489  succBB.liveRangeData_->memUseReaches_, loop);
2490 
2491  size_t size = succBB.liveRangeData_->fuDepReaches_.size();
2494  succBB.liveRangeData_->fuDepReaches_, loop);
2495  if (succBB.liveRangeData_->fuDepReaches_.size() > size) {
2496  changed = true;
2497  }
2498  }
2499 
2500  // need to queue successor for update?
2501  if (changed || queueAll) {
2502  changeState(succData, BB_QUEUED, loop);
2503  }
2504 }
2505 
2506 ///////////////////////////////////////////////////////////////////////////////
2507 // Low-level of Multi-BB DDG construction
2508 ///////////////////////////////////////////////////////////////////////////////
2509 
2510 /**
2511  * Updates live register lists after a basic block has been processed.
2512  *
2513  * Copies use and define definitions from the basic block and
2514  * it's prodecessors to the after alive data structures.
2515  *
2516  * @param bbd BBData for bb being processed
2517  * @return true if the after alive data structures have been changed
2518  */
2520  BBData& bbd) {
2521  BasicBlock& bb = bbd.bblock_->basicBlock();
2522  bool changed = false;
2523 
2524  // copy reg definitions that are alive
2525  for (MoveNodeUseMapSet::iterator iter =
2526  bb.liveRangeData_->regDefReaches_.begin();
2527  iter != bb.liveRangeData_->regDefReaches_.end(); iter++) {
2528 
2529  TCEString reg = iter->first;
2530  std::set<MoveNodeUse>& preDefs = iter->second;
2531  // todo: clear or not?
2532  std::set<MoveNodeUse>& defAfter = bb.liveRangeData_->regDefAfter_[reg];
2533  size_t size = defAfter.size();
2534 
2535  // only copy incomin dep if this has no unconditional writes
2536  if (bb.liveRangeData_->regKills_.find(reg) == bb.liveRangeData_->regKills_.end()) {
2537  for (std::set<MoveNodeUse>::iterator i = preDefs.begin();
2538  i != preDefs.end(); i++ ) {
2539  defAfter.insert(*i);
2540  }
2541  }
2542  // if size increased, the data has changed
2543  if (size < defAfter.size()) {
2544  changed = true;
2545  }
2546  }
2547  // own deps. need to do only once but now does after every.
2550  bb.liveRangeData_->regDefAfter_, false);
2551 
2553  // copy uses that are alive
2554  for (MoveNodeUseMapSet::iterator iter =
2555  bb.liveRangeData_->regUseReaches_.begin(); iter != bb.liveRangeData_->regUseReaches_.end();
2556  iter++) {
2557  TCEString reg = iter->first;
2558  std::set<MoveNodeUse>& preUses = iter->second;
2559  std::set<MoveNodeUse>& useAfter = bb.liveRangeData_->regUseAfter_[reg];
2560  size_t size = useAfter.size();
2561  if (bb.liveRangeData_->regKills_.find(reg) == bb.liveRangeData_->regKills_.end()) {
2562  for (std::set<MoveNodeUse>::iterator i = preUses.begin();
2563  i != preUses.end(); i++ ) {
2564  useAfter.insert(*i);
2565  }
2566  }
2567  // if size increased, the data has changed
2568  if (size < useAfter.size()) {
2569  changed = true;
2570  }
2571  }
2572  }
2573 
2574  // own deps. need to do only once but now does after every.
2577  bb.liveRangeData_->regUseAfter_, false);
2578  return changed;
2579 }
2580 
2581 
2582 /**
2583  * Updates live mem access lists and fu state usages after a basic block
2584  * has been processed.
2585  *
2586  * Copies use and write definitions from the basic block and
2587  * it's prodecessors to the after alive data structures.
2588  *
2589  * @param bbd BBData for bb being processed
2590  * @return true if the after alive data structures have been changed
2591  */
2593  BasicBlock& bb = bbd.bblock_->basicBlock();
2594  bool changed = false;
2595 
2596  // copy mem definitions that are alive
2597  for (MoveNodeUseMapSet::iterator iter = bb.liveRangeData_->memDefReaches_.begin();
2598  iter != bb.liveRangeData_->memDefReaches_.end(); iter++) {
2599 
2600  TCEString category = iter->first;
2601  std::set<MoveNodeUse>& preDefs = iter->second;
2602  std::set<MoveNodeUse>& defAfter = bb.liveRangeData_->memDefAfter_[category];
2603  std::set<MoveNodeUse>& ownDefines = bb.liveRangeData_->memDefines_[category];
2604  size_t size = defAfter.size();
2605 
2606  // only copy incomin dep if this has no unconditional writes,
2607  if (bb.liveRangeData_->memKills_.find(category) == bb.liveRangeData_->memKills_.end()) {
2608  for (std::set<MoveNodeUse>::iterator i = preDefs.begin();
2609  i != preDefs.end(); i++ ) {
2610 // MoveNode* preAddress = addressMove(*(i->mn()));
2611  ProgramOperation& prevPop = i->mn()->destinationOperation();
2612 
2613  bool overWritten = false;
2614  for (std::set<MoveNodeUse>::iterator j = ownDefines.begin();
2615  j != ownDefines.end(); j++) {
2616  if (j->mn()->move().isUnconditional()) {
2617 // MoveNode* ownAddress = addressMove(*(j->mn()));
2618  ProgramOperation& ownPop = j->mn()->destinationOperation();
2619  if (analyzeMemoryAlias(prevPop, ownPop, i->bbRelation()) ==
2621  overWritten = true;
2622  break;
2623  }
2624  }
2625  }
2626  if (!overWritten) {
2627  defAfter.insert(*i);
2628  }
2629  }
2630  }
2631  // if size increased, the data has changed
2632  if (size < defAfter.size()) {
2633  changed = true;
2634  }
2635  }
2636  // own deps. need to do only once but now does after every.
2639  bb.liveRangeData_->memDefAfter_, false);
2640 
2641  // copy uses that are alive
2642  for (MoveNodeUseMapSet::iterator iter = bb.liveRangeData_->memUseReaches_.begin();
2643  iter != bb.liveRangeData_->memUseReaches_.end(); iter++) {
2644 
2645  TCEString category = iter->first;
2646  std::set<MoveNodeUse>& preUses = iter->second;
2647  std::set<MoveNodeUse>& useAfter = bb.liveRangeData_->memUseAfter_[category];
2648  std::set<MoveNodeUse>& ownDefines = bb.liveRangeData_->memDefines_[category];
2649 
2650  size_t size = useAfter.size();
2651  if (bb.liveRangeData_->memKills_.find(category) == bb.liveRangeData_->memKills_.end()) {
2652  for (std::set<MoveNodeUse>::iterator i = preUses.begin();
2653  i != preUses.end(); i++ ) {
2654 // MoveNode* preAddress = addressMove(*(i->mn()));
2655  ProgramOperation& prevPop = i->mn()->destinationOperation();
2656  bool overWritten = false;
2657  for (std::set<MoveNodeUse>::iterator j =
2658  ownDefines.begin(); j != ownDefines.end(); j++) {
2659  if (j->mn()->move().isUnconditional()) {
2660  ProgramOperation& ownPop = j->mn()->destinationOperation();
2661  if (analyzeMemoryAlias(prevPop, ownPop, i->bbRelation()) ==
2663  overWritten = true;
2664  break;
2665  }
2666  }
2667  }
2668  if (!overWritten) {
2669  useAfter.insert(*i);
2670  }
2671  }
2672  }
2673  // if size increased, the data has changed
2674  if (size < useAfter.size()) {
2675  changed = true;
2676  }
2677  }
2678 
2679  // fu deps
2680  size_t size = bb.liveRangeData_->fuDepAfter_.size();
2682  if (bb.liveRangeData_->fuDepAfter_.size() > size) {
2683  changed = true;
2684  }
2685  return changed;
2686 }
2687 
2688 /**
2689  * Processes the pseudo deps from entry node.
2690  *
2691  * This procedure must be called when currentBB is the first real
2692  * BB of the procedure.
2693  */
2695 
2696  // initializes RA
2698 
2699  // sp
2700  MoveNodeUse mnd2(mn);
2702  if (sp != "") {
2703  currentBB_->basicBlock().liveRangeData_->regDefReaches_[sp].insert(mnd2);
2704  }
2705 
2706  if (rvIsParamReg_) {
2708  if (rv != "") {
2710  mnd2);
2711  }
2712  }
2713 
2714  // params
2715  // this is for old frontend generated code.
2716  for (int i = 0;;i++) {
2717  TCEString paramReg = specialRegisters_[REG_IPARAM+i];
2718  if(paramReg != "") {
2719  currentBB_->basicBlock().liveRangeData_->regDefReaches_[paramReg].insert(mnd2);
2720  } else {
2721  break;
2722  }
2723  }
2724 
2726  if (fp != "") {
2728  mnd2);
2729  }
2730 }
2731 
2732 /**
2733  * Reprocesses a basic block which has already once been processed.
2734  *
2735  * Checks dependencies to first uses and definitions of registers,
2736  * does not recreate edges inside the basic block.
2737  *
2738  * @param bbd BBData for basic block which is being reprocessed.
2739  * @param phase whether to handle register& operation deps or
2740  * memory and side-effect dependencies.
2741  */
2742 void
2744  BBData& bbd, ConstructionPhase phase) {
2745  currentData_ = &bbd;
2746  currentBB_ = bbd.bblock_;
2747  BasicBlock& bb = bbd.bblock_->basicBlock();
2748 
2749  // register and operation dependencies
2750  if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
2751  //loop all regs having ext deps and create reg edges
2752  for (MoveNodeUseMapSet::iterator firstUseIter =
2753  bb.liveRangeData_->regFirstUses_.begin();
2754  firstUseIter != bb.liveRangeData_->regFirstUses_.end();
2755  firstUseIter++) {
2756  TCEString reg = firstUseIter->first;
2757  std::set<MoveNodeUse>& firstUseSet = firstUseIter->second;
2758  for (std::set<MoveNodeUse>::iterator iter2 = firstUseSet.begin();
2759  iter2 != firstUseSet.end(); iter2++) {
2761  *iter2, reg, currentBB_->basicBlock());
2762  }
2763  }
2764 
2766  // antidependencies to registers
2767  for (MoveNodeUseMapSet::iterator firstDefineIter =
2768  bb.liveRangeData_->regFirstDefines_.begin();
2769  firstDefineIter != bb.liveRangeData_->regFirstDefines_.end();
2770  firstDefineIter++) {
2771  TCEString reg = firstDefineIter->first;
2772  std::set<MoveNodeUse>& firstDefineSet =
2773  firstDefineIter->second;
2774  for (std::set<MoveNodeUse>::iterator iter2=
2775  firstDefineSet.begin();
2776  iter2 != firstDefineSet.end(); iter2++) {
2778  *iter2, reg, currentBB_->basicBlock());
2779  }
2780  }
2781  }
2782  } else {
2783  // phase 1 .. mem deps and fu state/side effect dependencies.
2784 
2785  //loop all first mem uses having ext deps and create mem edges
2786  for (MoveNodeUseMapSet::iterator firstUseIter =
2787  bb.liveRangeData_->memFirstUses_.begin();
2788  firstUseIter != bb.liveRangeData_->memFirstUses_.end();
2789  firstUseIter++) {
2790  TCEString category = firstUseIter->first;
2791  std::set<MoveNodeUse>& firstUseSet = firstUseIter->second;
2792  for (std::set<MoveNodeUse>::iterator iter2 = firstUseSet.begin();
2793  iter2 != firstUseSet.end(); iter2++) {
2794  updateMemUse(*iter2, category);
2795  }
2796  }
2797 
2798  // antidependencies to memory
2799  for (MoveNodeUseMapSet::iterator firstDefineIter =
2800  bb.liveRangeData_->memFirstDefines_.begin();
2801  firstDefineIter != bb.liveRangeData_->memFirstDefines_.end();
2802  firstDefineIter++) {
2803  TCEString category = firstDefineIter->first;
2804  std::set<MoveNodeUse>& firstDefineSet = firstDefineIter->second;
2805  for (std::set<MoveNodeUse>::iterator iter2=firstDefineSet.begin();
2806  iter2 != firstDefineSet.end(); iter2++) {
2807  updateMemWrite(*iter2, category);
2808  }
2809  }
2810 
2811  // and fu state deps
2812  for (MoveNodeUseSet::iterator iter =
2813  bb.liveRangeData_->fuDeps_.begin();
2814  iter != bb.liveRangeData_->fuDeps_.end(); iter++) {
2815  Terminal& dest = iter->mn()->move().destination();
2816  TerminalFUPort& tfpd = dynamic_cast<TerminalFUPort&>(dest);
2817  Operation &dop = tfpd.hintOperation();
2820  *iter->mn(), dop);
2821  }
2822  }
2823 }
2824 
2825 /**
2826  * Checks memory write against uses and defs in incoming basic blocks.
2827  * Creates the needed dependence edges.
2828  *
2829  * @param mnd MoveNodeUse of movenode being processed.
2830  * @param category which memory category this memory write belongs.
2831  */
2832 void
2834  MoveNodeUse mnd, const TCEString& category) {
2835 
2836  // create waw edges from all alive writes to this node.
2837  for (MoveNodeUseSet::iterator iter =
2838  currentBB_->basicBlock().liveRangeData_->memDefReaches_[category].begin();
2839  iter != currentBB_->basicBlock().liveRangeData_->memDefReaches_[category].end();) {
2841  }
2842 
2843  // create war edges from all alive reads to this node.
2844  for (MoveNodeUseSet::iterator iter = currentBB_->basicBlock().liveRangeData_->
2845  memUseReaches_[category].begin();
2846  iter != currentBB_->basicBlock().liveRangeData_->memUseReaches_[category].end();) {
2848  }
2849 }
2850 
2851 
2852 /**
2853  * Checks memory read against uses and defs in incoming basic blocks.
2854  * Creates the needed dependence edges.
2855  *
2856  * @param mnd MoveNodeUse of movenode being processed.
2857  * @param category which memory category this memory write belongs.
2858  */
2860  MoveNodeUse mnd, const TCEString& category) {
2861 
2862  for (MoveNodeUseSet::iterator iter =
2863  currentBB_->basicBlock().liveRangeData_->memDefReaches_[category].begin();
2864  iter != currentBB_->basicBlock().liveRangeData_->memDefReaches_[category].end();
2865  iter++) {
2867  }
2868 }
2869 
2870 
2871 ///////////////////////////////////////////////////////////////////////////////
2872 // Searching of ends of liveranges, ie last uses of values
2873 ///////////////////////////////////////////////////////////////////////////////
2874 
2875 /**
2876  * Searches the last usages a registers.
2877  *
2878  * This information is used for checking whether given register contains
2879  * live value at given cycle.
2880  */
2881 void
2883 
2884  // initializes states of all BB's to unreached.
2886 
2887  // start from end of cfg. (sink nodes), queue them
2889  for (ControlFlowGraph::NodeSet::iterator iter =
2890  lastBBs.begin(); iter != lastBBs.end(); iter++) {
2891  changeState(*(bbData_[*iter]), BB_QUEUED);
2892  }
2893 
2894  // then iterate over all BB's, going from BB to it's
2895  // predecessors.
2897 
2898  // all should have gone thru, but if there are 4ever loop causing
2899  // BB's not reachable from the end.
2900  // we might want to handle those also.
2901  while (!blocksByState_[BB_UNREACHED].empty()) {
2903  Application::logStream() << "Warning: BB in 4ever loop!"
2904  << std::endl;
2905  Application::logStream() << "In procedure: " << cfg_->name() <<
2906  std::endl;
2907 // cfg.writeToDotFile("4everloop_bb.dot");
2908  }
2910 
2912  }
2913 
2914  // free bb data
2916 }
2917 
2918 /**
2919  * Iterates thru all queued BB's and find register deaths from them.
2920  *
2921  * Loops as long as something keeps changing.
2922  */
2923 void
2925 
2926  // loop as long as we have unprocessed/changed BB's
2927  while (!blocksByState_[BB_QUEUED].empty()) {
2928  std::list<BBData*>::iterator bbIter =
2929  blocksByState_[BB_QUEUED].begin();
2930  BBData& bbd = **bbIter;
2931 
2932  // mark as ready
2933  changeState(bbd, BB_READY);
2934 
2935  if (updateRegistersUsedInOrAfter(bbd) || (!bbd.constructed_)) {
2936  // if there asre more registers read after start of this BB,
2937  // have to update this information to preceedign BBs,
2938  // and check if they need to be reprocessed.
2940  }
2941  bbd.constructed_ = true;
2942  }
2943 }
2944 
2945 /**
2946  * Updates bookkeeping about registers used in this or later BBs.
2947  *
2948  * This is a helper function used by searchRegisterDeaths() method.
2949  *
2950  * @param bbd Data about one basicblock.
2951  * @return whether the bookkeeping was changed,
2952  ie the predecessors of this BB need to be reprocessed.
2953  */
2954 bool
2956  BBData& bbd) {
2957  BasicBlock& bb = bbd.bblock_->basicBlock();
2958  size_t size = bb.liveRangeData_->registersUsedInOrAfter_.size();
2959 
2960  // if definition not here, it's earlier - copy.
2961  // if definition here, not alive unless read here.
2962  for (std::set<TCEString>::iterator i = bb.liveRangeData_->registersUsedAfter_.begin();
2963  i != bb.liveRangeData_->registersUsedAfter_.end(); i++) {
2964  // if not written in this, written earlier.
2965  if (bb.liveRangeData_->regKills_.find(*i) == bb.liveRangeData_->regKills_.end()) {
2966  bb.liveRangeData_->registersUsedInOrAfter_.insert(*i);
2967  }
2968  }
2969 
2970  // reads in this BB.liveRangeData_-> Only reads whose defining value comes/can come
2971  // outside this BB.liveRangeData_->
2972  for (MoveNodeUseMapSet::iterator i = bb.liveRangeData_->regFirstUses_.begin();
2973  i != bb.liveRangeData_->regFirstUses_.end(); i++) {
2974  bb.liveRangeData_->registersUsedInOrAfter_.insert(i->first);
2975  }
2976  if (bb.liveRangeData_->registersUsedInOrAfter_.size() > size) {
2977  return true;
2978  }
2979  return false;
2980 }
2981 
2982 /**
2983  * Check if operations are assigned to differnt FU
2984  *
2985  * Operations forced to different FUs are independent since
2986  * the operation state is per FU. Check if the moves have
2987  * forced set of FUs and if the sets overlap.
2988  *
2989  * @param srcMN MoveNode first node for dependency check
2990  * @param dstMN MoveNode for which dependency needs to be checked
2991  * @return Nodes are alawys mapped to different FU
2992  */
2993 bool
2995  const MoveNode* srcMN, const MoveNode* dstMN) {
2996  if (srcMN->move().hasAnnotations(
2998  dstMN->move().hasAnnotations(
3000  bool alwaysDifferentFUs = true;
3001  for (int idx = 0;
3002  idx < srcMN->move().annotationCount(
3004  ++idx) {
3005  if (dstMN->move().hasAnnotation(
3007  srcMN->move()
3008  .annotation(
3010  ANN_ALLOWED_UNIT_DST)
3011  .stringValue())) {
3012  alwaysDifferentFUs = false;
3013  break;
3014  }
3015  }
3016  return alwaysDifferentFUs;
3017  }
3018  return false;
3019 }
3020 
3021 /**
3022  * Internal constant for the name of the return address port
3023  */
3025 
3026 
3027 ///////////////////////////////////////////////////////////////////////////////
3028 // BBData
3029 ///////////////////////////////////////////////////////////////////////////////
3030 
3031 /**
3032  * Constructor
3033  */
3035  poReadsHandled_(0),
3036  state_(BB_UNREACHED), constructed_(false), bblock_(&bb) {
3037 }
3038 
3039 /**
3040  * Destructor.
3041  */
3043 }
DataDependenceGraphBuilder::mach_
const TTAMachine::Machine * mach_
Definition: DataDependenceGraphBuilder.hh:322
DataDependenceGraphBuilder::BBData::state_
BBState state_
State of the BB.
Definition: DataDependenceGraphBuilder.hh:137
TTAMachine::Guard
Definition: Guard.hh:55
UniversalMachine::integerRegisterFile
UnboundedRegisterFile & integerRegisterFile() const
Definition: UniversalMachine.cc:234
ProgramOperation::operation
const Operation & operation() const
Definition: ProgramOperation.cc:590
TTAProgram::Terminal::isFUPort
virtual bool isFUPort() const
Definition: Terminal.cc:118
DataDependenceGraphBuilder::BBData::poReadsHandled_
int poReadsHandled_
Definition: DataDependenceGraphBuilder.hh:135
DataDependenceGraphBuilder::BBData::bblock_
BasicBlockNode * bblock_
Definition: DataDependenceGraphBuilder.hh:140
Operation::affectedByCount
virtual int affectedByCount() const
Definition: Operation.cc:416
DataDependenceGraphBuilder::isTriggering
bool isTriggering(const MoveNode &mn)
Definition: DataDependenceGraphBuilder.cc:810
SimpleInterPassDatum
Definition: InterPassDatum.hh:64
LiveRangeData::regLastKills_
MoveNodeUseMapPair regLastKills_
Definition: LiveRangeData.hh:80
BoostGraph::predecessors
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
TTAProgram
Definition: Estimator.hh:65
MemoryAliasAnalyzer::ALIAS_UNKNOWN
@ ALIAS_UNKNOWN
Definition: MemoryAliasAnalyzer.hh:54
ConstantAliasAnalyzer
Definition: ConstantAliasAnalyzer.hh:42
Operation::writesMemory
virtual bool writesMemory() const
Definition: Operation.cc:252
DataDependenceGraphBuilder::clearUnneededBookkeeping
void clearUnneededBookkeeping()
Definition: DataDependenceGraphBuilder.cc:2251
FalseAliasAnalyzer.hh
MoveNodeUse::BBRelation
BBRelation
Definition: MoveNodeUse.hh:23
DataDependenceGraphBuilder::blocksByState_
BBDataList blocksByState_[BB_STATES]
Definition: DataDependenceGraphBuilder.hh:309
Exception::lineNum
int lineNum() const
DataDependenceGraphBuilder::createMemAndFUstateDeps
void createMemAndFUstateDeps()
Definition: DataDependenceGraphBuilder.cc:2312
MoveNodeUse::mn
const MoveNode * mn() const
Definition: MoveNodeUse.hh:39
StackAliasAnalyzer.hh
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
MoveNode::toString
std::string toString() const
Definition: MoveNode.cc:576
LiveRangeData::inlineAsmRegDefs_
std::set< TCEString > inlineAsmRegDefs_
Definition: LiveRangeData.hh:127
Operation::hasSideEffects
virtual bool hasSideEffects() const
Definition: Operation.cc:272
TTAProgram::Instruction::move
Move & move(int i) const
Definition: Instruction.cc:193
PRINT_VAR
#define PRINT_VAR(VARIABLE__)
Definition: Application.hh:118
DataDependenceGraphBuilder::BBData::constructed_
bool constructed_
Whether the BB has been constructed or not.
Definition: DataDependenceGraphBuilder.hh:139
LLVMAliasAnalyzer.hh
MemoryAliasAnalyzer::analyze
virtual AliasingResult analyze(DataDependenceGraph &ddg, const ProgramOperation &pop1, const ProgramOperation &pop2, MoveNodeUse::BBRelation bbInfo)=0
TTAProgram::Move::isFunctionCall
bool isFunctionCall() const
Definition: Move.cc:219
DataDependenceGraphBuilder::constructIndividualFromInlineAsmBB
void constructIndividualFromInlineAsmBB(ConstructionPhase phase)
Definition: DataDependenceGraphBuilder.cc:669
Exception.hh
DataDependenceGraphBuilder::processResultRead
void processResultRead(MoveNode &moveNode)
Definition: DataDependenceGraphBuilder.cc:1104
BoostGraph::node
Node & node(const int index) const
LiveRangeData::appendMoveNodeUse
static void appendMoveNodeUse(const MoveNodeUseSet &src, MoveNodeUseSet &dst, bool setLoopProperty)
Definition: LiveRangeData.cc:107
TTAMachine::RegisterGuard::registerIndex
int registerIndex() const
LiveRangeData::memFirstUses_
MoveNodeUseMapSet memFirstUses_
Definition: LiveRangeData.hh:104
DataDependenceGraphBuilder::findStaticRegisters
void findStaticRegisters(TTAProgram::CodeSnippet &cs, std::map< int, TCEString > &registers)
find special register data from old frontend code
Definition: DataDependenceGraphBuilder.cc:306
BasicBlockNode::originalEndAddress
InstructionAddress originalEndAddress() const
Definition: BasicBlockNode.cc:174
MoveNode::isDestinationOperation
bool isDestinationOperation() const
DataDependenceGraphBuilder::processCall
void processCall(MoveNode &mn)
Definition: DataDependenceGraphBuilder.cc:1532
TTAProgram::Move::isReturn
bool isReturn() const
Definition: Move.cc:259
MemoryAliasAnalyzer::ALIAS_FALSE
@ ALIAS_FALSE
Definition: MemoryAliasAnalyzer.hh:50
DataDependenceGraph::sameGuards
bool sameGuards(const MoveNode &mn1, const MoveNode &mn2) const
Definition: DataDependenceGraph.cc:4506
LiveRangeData::fuDeps_
MoveNodeUseSet fuDeps_
Definition: LiveRangeData.hh:117
DataDependenceGraphBuilder::DataDependenceGraphBuilder
DataDependenceGraphBuilder()
Definition: DataDependenceGraphBuilder.cc:118
DataDependenceGraphBuilder::processTriggerRegistersAndOperations
void processTriggerRegistersAndOperations(MoveNode &moveNode, Operation &dop)
Definition: DataDependenceGraphBuilder.cc:1018
BoostGraph< BasicBlockNode, ControlFlowEdge >::NodeSet
std::set< BasicBlockNode *, typename BasicBlockNode ::Comparator > NodeSet
Definition: BoostGraph.hh:86
TTAProgram::Instruction
Definition: Instruction.hh:57
TTAProgram::Move::isUnconditional
bool isUnconditional() const
Definition: Move.cc:154
TTAProgram::ProgramAnnotation::stringValue
std::string stringValue() const
Definition: ProgramAnnotation.cc:90
DataDependenceGraphBuilder::initializeBBStates
void initializeBBStates()
Definition: DataDependenceGraphBuilder.cc:2191
MoveNodeUse::pseudo
bool pseudo() const
Definition: MoveNodeUse.hh:42
DataDependenceGraphBuilder::processEntryNode
void processEntryNode(MoveNode &mn)
Definition: DataDependenceGraphBuilder.cc:2694
MoveNodeUse
Definition: MoveNodeUse.hh:20
LiveRangeData::memFirstDefines_
MoveNodeUseMapSet memFirstDefines_
Definition: LiveRangeData.hh:105
DataDependenceGraphBuilder::processMemUse
void processMemUse(MoveNodeUse mnd)
Definition: DataDependenceGraphBuilder.cc:1800
Procedure.hh
LiveRangeData::inlineAsmClobbers_
std::set< TCEString > inlineAsmClobbers_
Definition: LiveRangeData.hh:128
SequenceTools.hh
LiveRangeData::regUseReaches_
MoveNodeUseMapSet regUseReaches_
Definition: LiveRangeData.hh:91
DataDependenceGraph::addProgramOperation
void addProgramOperation(ProgramOperationPtr po)
Definition: DataDependenceGraph.cc:298
DataDependenceGraphBuilder::updateMemUse
void updateMemUse(MoveNodeUse mnd, const TCEString &category)
Definition: DataDependenceGraphBuilder.cc:2859
MemoryAliasAnalyzer::ALIAS_PARTIAL
@ ALIAS_PARTIAL
Definition: MemoryAliasAnalyzer.hh:55
BasicBlockNode.hh
LiveRangeData::memLastUses_
MoveNodeUseMapSet memLastUses_
Definition: LiveRangeData.hh:99
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
LiveRangeData::regDefines_
MoveNodeUseMapSet regDefines_
Definition: LiveRangeData.hh:78
Operation::dependsOn
virtual bool dependsOn(const Operation &op) const
Definition: Operation.cc:458
DataDependenceGraphBuilder::ConstructionPhase
ConstructionPhase
Definition: DataDependenceGraphBuilder.hh:120
Application::VERBOSE_LEVEL_DEFAULT
static const int VERBOSE_LEVEL_DEFAULT
Default verbose level - do not print anything unnecessary.
Definition: Application.hh:222
MachineInfo.hh
DataDependenceGraphBuilder::aliasAnalyzers_
AliasAnalyzerVector aliasAnalyzers_
Definition: DataDependenceGraphBuilder.hh:315
Operation::numberOfInputs
virtual int numberOfInputs() const
Definition: Operation.cc:192
ProgramOperation
Definition: ProgramOperation.hh:70
DataDependenceGraph::setMachine
void setMachine(const TTAMachine::Machine &machine)
Definition: DataDependenceGraph.cc:3116
TTAProgram::Move::toString
std::string toString() const
Definition: Move.cc:436
DataDependenceGraphBuilder::createSideEffectEdges
void createSideEffectEdges(MoveNodeUseSet &prevMoves, const MoveNode &mn, Operation &dop)
Definition: DataDependenceGraphBuilder.cc:1646
MoveNode
Definition: MoveNode.hh:65
DataDependenceGraphBuilder::processMemWrite
void processMemWrite(MoveNodeUse mnd)
Definition: DataDependenceGraphBuilder.cc:1744
ProgramOperation::machineInstr
const llvm::MachineInstr * machineInstr() const
Definition: ProgramOperation.hh:136
LiveRangeData::regKills_
MoveNodeUseMapPair regKills_
Definition: LiveRangeData.hh:85
DataDependenceGraphBuilder::earlierWritesWithSameGuard
std::set< MoveNodeUse > earlierWritesWithSameGuard(MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
Definition: DataDependenceGraphBuilder.cc:1200
CompileError
Definition: Exception.hh:1019
Application::verboseLevel
static int verboseLevel()
Definition: Application.hh:176
DataDependenceGraphBuilder::BB_UNREACHED
@ BB_UNREACHED
Definition: DataDependenceGraphBuilder.hh:115
DataDependenceGraphBuilder::currentBB_
BasicBlockNode * currentBB_
Definition: DataDependenceGraphBuilder.hh:312
LLVMAliasAnalyzer
Definition: LLVMAliasAnalyzer.hh:54
DataDependenceGraphBuilder::BBData::~BBData
virtual ~BBData()
Definition: DataDependenceGraphBuilder.cc:3042
DataDependenceEdge::EDGE_REGISTER
@ EDGE_REGISTER
Definition: DataDependenceEdge.hh:53
Application::logStream
static std::ostream & logStream()
Definition: Application.cc:155
DataDependenceGraphBuilder::processGuard
void processGuard(MoveNode &moveNode)
Definition: DataDependenceGraphBuilder.cc:760
BasicBlockNode::isScheduled
bool isScheduled() const
Definition: BasicBlockNode.hh:93
DataDependenceEdge::DependenceType
DependenceType
Definition: DataDependenceEdge.hh:45
DataDependenceGraphBuilder::queueFirstBB
BasicBlockNode * queueFirstBB()
Definition: DataDependenceGraphBuilder.cc:2238
LLVMTCECmdLineOptions::disableLLVMAA
virtual bool disableLLVMAA() const
Definition: LLVMTCECmdLineOptions.cc:314
ConstantAliasAnalyzer.hh
FalseAliasAnalyzer
Definition: FalseAliasAnalyzer.hh:40
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
LiveRangeData::regDefReaches_
MoveNodeUseMapSet regDefReaches_
Definition: LiveRangeData.hh:90
DataDependenceGraphBuilder::REGISTERS_AND_PROGRAM_OPERATIONS
@ REGISTERS_AND_PROGRAM_OPERATIONS
Definition: DataDependenceGraphBuilder.hh:121
SchedulerCmdLineOptions
Definition: SchedulerCmdLineOptions.hh:45
DataDependenceGraphBuilder::updateRegistersUsedInOrAfter
bool updateRegistersUsedInOrAfter(BBData &bbd)
Definition: DataDependenceGraphBuilder.cc:2955
Conversion::toString
static std::string toString(const T &source)
DataDependenceEdge.hh
LiveRangeData::memLastKill_
MoveNodeUseMap memLastKill_
Definition: LiveRangeData.hh:100
MoveNodeUse::loop
bool loop() const
Definition: MoveNodeUse.hh:43
SchedulerCmdLineOptions.hh
DataDependenceGraphBuilder::memoryCategory
TCEString memoryCategory(const MoveNodeUse &mnd)
Definition: DataDependenceGraphBuilder.cc:1999
REG_IPARAM
static const int REG_IPARAM
Definition: DataDependenceGraphBuilder.cc:102
DataDependenceGraphBuilder::cfg_
ControlFlowGraph * cfg_
Definition: DataDependenceGraphBuilder.hh:320
ProgramOperationPtr
std::shared_ptr< ProgramOperation > ProgramOperationPtr
Definition: MoveNode.hh:52
TerminalRegister.hh
DataDependenceGraphBuilder::iterateBBs
void iterateBBs(ConstructionPhase phase)
Definition: DataDependenceGraphBuilder.cc:2345
POMDisassembler.hh
TCEString.hh
Exception::fileName
std::string fileName() const
LiveRangeData::memDefAfter_
MoveNodeUseMapSet memDefAfter_
Definition: LiveRangeData.hh:112
MoveNode::setSourceOperationPtr
void setSourceOperationPtr(ProgramOperationPtr po)
Definition: MoveNode.cc:541
BasicBlockNode::basicBlock
TTAProgram::BasicBlock & basicBlock()
Definition: BasicBlockNode.cc:126
LiveRangeData::registersUsedInOrAfter_
std::set< TCEString > registersUsedInOrAfter_
Definition: LiveRangeData.hh:122
REG_FP
static const int REG_FP
Definition: DataDependenceGraphBuilder.cc:105
assert
#define assert(condition)
Definition: Application.hh:86
DataDependenceGraphBuilder::BBData::destPending_
ProgramOperationPtr destPending_
ProgramOperations lacking operands.
Definition: DataDependenceGraphBuilder.hh:132
DataDependenceGraphBuilder::BBData::readPending_
ProgramOperationPtr readPending_
ProgramOperations lacking result read.
Definition: DataDependenceGraphBuilder.hh:134
DataDependenceGraphBuilder::processDestination
void processDestination(class MoveNode &moveNode, ConstructionPhase phase)
Definition: DataDependenceGraphBuilder.cc:844
REG_RV_HIGH
static const int REG_RV_HIGH
Definition: DataDependenceGraphBuilder.cc:99
TTAProgram::TerminalFUPort::hintOperation
virtual Operation & hintOperation() const
Definition: TerminalFUPort.cc:262
UniversalMachine.hh
DataDependenceGraphBuilder.hh
MemoryAliasAnalyzer::AliasingResult
AliasingResult
Definition: MemoryAliasAnalyzer.hh:50
DataDependenceEdge::DEP_UNKNOWN
@ DEP_UNKNOWN
Definition: DataDependenceEdge.hh:46
SequenceTools::deleteAllItems
static void deleteAllItems(SequenceType &aSequence)
DataDependenceGraphBuilder::BasicBlockNodeSet
ControlFlowGraph::NodeSet BasicBlockNodeSet
Definition: DataDependenceGraphBuilder.hh:102
TTAProgram::ProgramAnnotation::ANN_CONSTANT_MEM
@ ANN_CONSTANT_MEM
Constant memory access.
Definition: ProgramAnnotation.hh:183
TTAProgram::ProgramAnnotation::id
ProgramAnnotation::Id id() const
Definition: ProgramAnnotation.cc:111
MoveNodeUse::ra
bool ra() const
Definition: MoveNodeUse.hh:41
MemoryAliasAnalyzer::ALIAS_TRUE
@ ALIAS_TRUE
Definition: MemoryAliasAnalyzer.hh:53
TTAProgram::Terminal::operationIndex
virtual int operationIndex() const
Definition: Terminal.cc:364
GlobalVsStackAA
Definition: GlobalVsStackAA.hh:39
DataDependenceGraphBuilder::BB_READY
@ BB_READY
BB which is queued to be processed.
Definition: DataDependenceGraphBuilder.hh:117
LiveRangeData::fuDepReaches_
MoveNodeUseSet fuDepReaches_
Definition: LiveRangeData.hh:116
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
TTAMachine::SpecialRegisterPort
Definition: SpecialRegisterPort.hh:48
TTAProgram::Move::isControlFlowMove
bool isControlFlowMove() const
Definition: Move.cc:233
Instruction.hh
LiveRangeData::memUseAfter_
MoveNodeUseMapSet memUseAfter_
Definition: LiveRangeData.hh:113
REG_VRV
static const int REG_VRV
Definition: DataDependenceGraphBuilder.cc:104
TTAProgram::BasicBlock::liveRangeData_
LiveRangeData * liveRangeData_
Definition: BasicBlock.hh:111
MoveNode::addDestinationOperationPtr
void addDestinationOperationPtr(ProgramOperationPtr po)
Definition: MoveNode.cc:533
TTAProgram::CodeSnippet::instructionCount
virtual int instructionCount() const
Definition: CodeSnippet.cc:205
ControlFlowGraph.hh
DataDependenceGraph::hasSingleBBLoopRegisterAntidependencies
bool hasSingleBBLoopRegisterAntidependencies()
Definition: DataDependenceGraph.hh:383
DataDependenceEdge::DEP_RAW
@ DEP_RAW
Definition: DataDependenceEdge.hh:47
UniversalMachine
Definition: UniversalMachine.hh:56
DataDependenceGraphBuilder::BB_QUEUED
@ BB_QUEUED
Basic block we have not yet encountered.
Definition: DataDependenceGraphBuilder.hh:116
InterPassDatum.hh
DataDependenceGraphBuilder::~DataDependenceGraphBuilder
virtual ~DataDependenceGraphBuilder()
Definition: DataDependenceGraphBuilder.cc:283
ContainerTools::removeValueIfExists
static bool removeValueIfExists(ContainerType &aContainer, const ElementType &aKey)
DataDependenceGraphBuilder::createTriggerDependencies
void createTriggerDependencies(class MoveNode &moveNode, class Operation &dop)
Definition: DataDependenceGraphBuilder.cc:1596
DataDependenceGraphBuilder::updateBB
void updateBB(BBData &bbd, ConstructionPhase phase)
Definition: DataDependenceGraphBuilder.cc:2743
LLVMTCECmdLineOptions.hh
TTAMachine::RegisterGuard
Definition: Guard.hh:137
LLVMTCECmdLineOptions::disableAddressSpaceAA
bool disableAddressSpaceAA() const
Definition: LLVMTCECmdLineOptions.cc:319
DataDependenceGraph::updateRegUse
void updateRegUse(const MoveNodeUse &mnd, const TCEString &reg, TTAProgram::BasicBlock &bb)
Definition: DataDependenceGraph.cc:5367
DataDependenceGraphBuilder::addAliasAnalyzer
void addAliasAnalyzer(MemoryAliasAnalyzer *analyzer)
Definition: DataDependenceGraphBuilder.cc:293
TTAProgram::AnnotatedInstructionElement::hasAnnotation
bool hasAnnotation(ProgramAnnotation::Id id, const TCEString &data) const
Definition: AnnotatedInstructionElement.cc:174
OperationPool::sharesState
bool sharesState(const Operation &op)
Definition: OperationPool.cc:123
DataDependenceGraphBuilder::checkAndCreateMemDep
bool checkAndCreateMemDep(MoveNodeUse prev, MoveNodeUse mnd, DataDependenceEdge::DependenceType depType)
Definition: DataDependenceGraphBuilder.cc:1841
DataDependenceGraphBuilder::processTriggerPO
void processTriggerPO(class MoveNode &moveNode, Operation &dop)
Definition: DataDependenceGraphBuilder.cc:948
LiveRangeData
Definition: LiveRangeData.hh:47
DataDependenceGraphBuilder::rvIsParamReg_
bool rvIsParamReg_
Definition: DataDependenceGraphBuilder.hh:321
DataDependenceEdge::EDGE_FUSTATE
@ EDGE_FUSTATE
Definition: DataDependenceEdge.hh:55
TTAProgram::Move::guard
MoveGuard & guard() const
Definition: Move.cc:345
DataDependenceGraphBuilder::searchRegisterDeaths
void searchRegisterDeaths()
Definition: DataDependenceGraphBuilder.cc:2882
DataDependenceEdge::EDGE_OPERATION
@ EDGE_OPERATION
Definition: DataDependenceEdge.hh:56
Application::cmdLineOptions
static CmdLineOptions * cmdLineOptions()
Definition: Application.cc:397
DataDependenceGraph::nodeOfMove
MoveNode & nodeOfMove(const TTAProgram::Move &move)
Definition: DataDependenceGraph.cc:3600
IllegalProgram
Definition: Exception.hh:895
LiveRangeData::regFirstDefines_
MoveNodeUseMapSet regFirstDefines_
Definition: LiveRangeData.hh:87
UnboundedRegisterFile.hh
DataDependenceGraphBuilder::currentData_
BBData * currentData_
Definition: DataDependenceGraphBuilder.hh:313
DataDependenceGraphBuilder::changeState
void changeState(BBData &bbd, BBState newState, bool priorize=false)
Definition: DataDependenceGraphBuilder.cc:2217
PRegionAliasAnalyzer
Definition: PRegionAliasAnalyzer.hh:41
__func__
#define __func__
Definition: Application.hh:67
LiveRangeData::inlineAsmRegUses_
std::set< TCEString > inlineAsmRegUses_
Definition: LiveRangeData.hh:126
DataDependenceGraphBuilder::checkAndCreateMemAntideps
void checkAndCreateMemAntideps(MoveNodeUse &mnd, std::set< MoveNodeUse > &prevNodes, DataDependenceEdge::DependenceType depType, bool traceable)
Definition: DataDependenceGraphBuilder.cc:1718
DataDependenceGraphBuilder::updateRegistersAliveAfter
bool updateRegistersAliveAfter(BBData &bbd)
Definition: DataDependenceGraphBuilder.cc:2519
BasicBlockNode
Definition: BasicBlockNode.hh:64
LiveRangeData::regLastUses_
MoveNodeUseMapSet regLastUses_
Definition: LiveRangeData.hh:79
MemoryAliasAnalyzer
Definition: MemoryAliasAnalyzer.hh:47
BasicBlockNode::isNormalBB
bool isNormalBB() const
Definition: BasicBlockNode.cc:239
DataDependenceGraphBuilder::BBData::BBData
BBData(BasicBlockNode &bb)
Definition: DataDependenceGraphBuilder.cc:3034
DataDependenceGraphBuilder::createRegisterAntideps
void createRegisterAntideps(const TCEString &reg, MoveNodeUse &mnd, MoveNodeUseSet &predecessorNodes, DataDependenceEdge::DependenceType depType, bool guardedKillFound)
Definition: DataDependenceGraphBuilder.cc:1303
DataDependenceGraphBuilder::createRegisterDeps
void createRegisterDeps()
Definition: DataDependenceGraphBuilder.cc:2268
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
Operation.hh
DataDependenceGraph::connectOrDeleteEdge
bool connectOrDeleteEdge(const MoveNode &tailNode, const MoveNode &headNode, DataDependenceEdge *edge)
Definition: DataDependenceGraph.cc:3355
Operation::readsMemory
virtual bool readsMemory() const
Definition: Operation.cc:242
TerminalFUPort.hh
BoostGraph::sinkNodes
virtual NodeSet sinkNodes() const
DataDependenceGraphBuilder::isAlwaysDifferentFU
bool isAlwaysDifferentFU(const MoveNode *srcMN, const MoveNode *dstMN)
Definition: DataDependenceGraphBuilder.cc:2994
TTAProgram::ProgramAnnotation::ANN_STACKUSE_FP_SAVE
@ ANN_STACKUSE_FP_SAVE
frame ptr save/load
Definition: ProgramAnnotation.hh:91
DataDependenceGraphBuilder::isAddressTraceable
bool isAddressTraceable(const ProgramOperation &pop)
Definition: DataDependenceGraphBuilder.cc:1974
DataDependenceGraphBuilder::iterateRegisterDeaths
void iterateRegisterDeaths()
Definition: DataDependenceGraphBuilder.cc:2924
TTAProgram::Move
Definition: Move.hh:55
DataDependenceGraphBuilder::createOperationEdges
void createOperationEdges(ProgramOperationPtr po)
Definition: DataDependenceGraphBuilder.cc:1141
DataDependenceGraphBuilder::updatePreceedingRegistersUsedAfter
void updatePreceedingRegistersUsedAfter(BBData &bbd, bool firstTime)
Definition: DataDependenceGraphBuilder.cc:2390
Machine.hh
Exception
Definition: Exception.hh:54
GlobalVsStackAA.hh
MoveNodeUse::guard
bool guard() const
Definition: MoveNodeUse.hh:40
InterPassData::hasDatum
bool hasDatum(const std::string &key) const
Definition: InterPassData.cc:75
TTAProgram::ProgramAnnotation::ANN_ALLOWED_UNIT_DST
@ ANN_ALLOWED_UNIT_DST
Dst. unit candidate.
Definition: ProgramAnnotation.hh:113
LLVMTCECmdLineOptions
Definition: LLVMTCECmdLineOptions.hh:48
StackAliasAnalyzer
Definition: StackAliasAnalyzer.hh:46
TTAProgram::TerminalFUPort::isOpcodeSetting
virtual bool isOpcodeSetting() const
Definition: TerminalFUPort.cc:180
ProgramOperation::inputMoveCount
int inputMoveCount() const
Definition: ProgramOperation.cc:600
LiveRangeData::regUseAfter_
MoveNodeUseMapSet regUseAfter_
Definition: LiveRangeData.hh:95
REG_RV
static const int REG_RV
Definition: DataDependenceGraphBuilder.cc:101
LiveRangeData::regDefAfter_
MoveNodeUseMapSet regDefAfter_
Definition: LiveRangeData.hh:94
DataDependenceEdge::DEP_WAW
@ DEP_WAW
Definition: DataDependenceEdge.hh:49
Operation
Definition: Operation.hh:59
TTAProgram::AnnotatedInstructionElement::hasAnnotations
bool hasAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
Definition: AnnotatedInstructionElement.cc:165
DataDependenceGraphBuilder::processRegWrite
void processRegWrite(MoveNodeUse mn, const TCEString &reg)
Definition: DataDependenceGraphBuilder.cc:1369
Conversion::toHexString
static std::string toHexString(T source, std::size_t digits=0, bool include0x=true)
GraphBase::writeToDotFile
virtual void writeToDotFile(const TCEString &fileName) const
PRegionAliasAnalyzer.hh
TTAProgram::CodeSnippet
Definition: CodeSnippet.hh:59
TTAProgram::ProgramAnnotation::ANN_STACKUSE_RA_SAVE
@ ANN_STACKUSE_RA_SAVE
ra, new frontend
Definition: ProgramAnnotation.hh:90
TTAProgram::TerminalFUPort
Definition: TerminalFUPort.hh:56
DataDependenceGraphBuilder::bbData_
BBDataMap bbData_
Definition: DataDependenceGraphBuilder.hh:311
LiveRangeData::potentialRegKills_
std::map< TCEString, std::pair< MoveNodeUse, bool > > potentialRegKills_
Definition: LiveRangeData.hh:82
ProgramOperation.hh
Operand.hh
TTAProgram::TerminalFUPort::hasProgramOperation
bool hasProgramOperation() const
these methods are used to group terminals belonging to a single program operation invocation
Definition: TerminalFUPort.hh:91
options
static MachInfoCmdLineOptions options
Definition: MachInfo.cc:46
DataDependenceGraphBuilder::RA_NAME
static const TCEString RA_NAME
Definition: DataDependenceGraphBuilder.hh:318
DataDependenceGraphBuilder::processSource
void processSource(MoveNode &moveNode)
Definition: DataDependenceGraphBuilder.cc:785
Operation::usesMemory
virtual bool usesMemory() const
Definition: Operation.cc:232
MoveNode::destinationOperation
ProgramOperation & destinationOperation(unsigned int index=0) const
TTAProgram::TerminalFUPort::programOperation
ProgramOperationPtr programOperation() const
Definition: TerminalFUPort.hh:97
DataDependenceGraph::addNode
void addNode(MoveNode &moveNode)
Definition: DataDependenceGraph.cc:144
SetTools::intersection
static void intersection(const std::set< ValueType > &firstContainer, const std::set< ValueType > &secondContainer, std::set< ValueType > &intersection)
TTAProgram::AnnotatedInstructionElement::annotation
ProgramAnnotation annotation(int index, ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
Definition: AnnotatedInstructionElement.cc:100
TTAProgram::BasicBlock
Definition: BasicBlock.hh:85
MoveNode::move
TTAProgram::Move & move()
MoveNodeUse::bbRelation
BBRelation bbRelation() const
Definition: MoveNodeUse.hh:45
TTAMachine::BaseRegisterFile::port
virtual RFPort * port(const std::string &name) const
Definition: BaseRegisterFile.cc:129
ProgramOperation::toString
std::string toString() const
Definition: ProgramOperation.cc:746
DataDependenceGraphBuilder::updateMemAndFuAliveAfter
bool updateMemAndFuAliveAfter(BBData &bbd)
Definition: DataDependenceGraphBuilder.cc:2592
LiveRangeData::registersUsedAfter_
std::set< TCEString > registersUsedAfter_
Definition: LiveRangeData.hh:121
POMDisassembler::disassemble
static std::string disassemble(const TTAProgram::Move &move)
Definition: POMDisassembler.cc:629
DisassemblyRegister.hh
IGNORE_COMPILER_WARNING
#define IGNORE_COMPILER_WARNING(X)
Definition: CompilerWarnings.hh:51
DataDependenceGraphBuilder::currentDDG_
DataDependenceGraph * currentDDG_
Definition: DataDependenceGraphBuilder.hh:314
IllegalMachine
Definition: Exception.hh:878
TTAProgram::ProgramAnnotation::ANN_STACKUSE_SPILL
@ ANN_STACKUSE_SPILL
spilled variable
Definition: ProgramAnnotation.hh:89
Program.hh
DataDependenceGraphBuilder::updateMemWrite
void updateMemWrite(MoveNodeUse mnd, const TCEString &category)
Definition: DataDependenceGraphBuilder.cc:2833
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
DataDependenceEdge::EDGE_MEMORY
@ EDGE_MEMORY
Definition: DataDependenceEdge.hh:54
DataDependenceGraphBuilder::setSucceedingPredepsForBB
void setSucceedingPredepsForBB(TTAProgram::BasicBlock &processedBB, BasicBlockNode &successor, bool queueAll, bool loop, ConstructionPhase phase)
Definition: DataDependenceGraphBuilder.cc:2460
DataDependenceGraphBuilder::allParamRegs_
std::set< TCEString > allParamRegs_
Definition: DataDependenceGraphBuilder.hh:100
AssocTools::append
static void append(const ContainerType &src, ContainerType &dest)
DataDependenceGraph::exclusingGuards
bool exclusingGuards(const MoveNode &mn1, const MoveNode &mn2) const
Definition: DataDependenceGraph.cc:4480
InterPassData.hh
DataDependenceGraphBuilder::BBState
BBState
Definition: DataDependenceGraphBuilder.hh:114
RegisterFile.hh
MoveNodeSet.hh
AssocTools.hh
TCEString
Definition: TCEString.hh:53
BasicBlock.hh
DataDependenceGraphBuilder::processOperand
void processOperand(class MoveNode &moveNode, Operation &dop)
Definition: DataDependenceGraphBuilder.cc:1062
DataDependenceGraph
Definition: DataDependenceGraph.hh:67
POP_COMPILER_DIAGS
#define POP_COMPILER_DIAGS
Definition: CompilerWarnings.hh:68
SpecialRegisterPort.hh
DataDependenceGraphBuilder::build
virtual DataDependenceGraph * build(ControlFlowGraph &cGraph, DataDependenceGraph::AntidependenceLevel antidependenceLevel, const TTAMachine::Machine &mach, const UniversalMachine *um=NULL, bool createMemAndFUDeps=true, bool createDeathInformation=true, llvm::AliasAnalysis *AA=NULL)
Definition: DataDependenceGraphBuilder.cc:2120
ControlFlowGraph::entryNode
BasicBlockNode & entryNode() const
Definition: ControlFlowGraph.cc:1003
DataDependenceGraphBuilder::setSucceedingPredeps
void setSucceedingPredeps(BBData &bbd, bool queueAll, ConstructionPhase phase)
Definition: DataDependenceGraphBuilder.cc:2424
REG_SP
static const int REG_SP
Definition: DataDependenceGraphBuilder.cc:100
DataDependenceGraphBuilder::processReturn
void processReturn(MoveNode &moveNode)
Definition: DataDependenceGraphBuilder.cc:1486
MemoryAliasAnalyzer.hh
DataDependenceGraph::AntidependenceLevel
AntidependenceLevel
Definition: DataDependenceGraph.hh:78
TTAProgram::Terminal
Definition: Terminal.hh:60
DataDependenceEdge
Definition: DataDependenceEdge.hh:43
TTAProgram::CodeSnippet::instructionAtIndex
virtual Instruction & instructionAtIndex(int index) const
Definition: CodeSnippet.cc:285
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
TTAProgram::Terminal::port
virtual const TTAMachine::Port & port() const
Definition: Terminal.cc:378
OffsetAliasAnalyzer.hh
DisassemblyRegister::registerName
static TCEString registerName(const TTAMachine::RegisterFile &rf, int index, char delim='.')
Definition: DisassemblyRegister.cc:95
DataDependenceGraphBuilder::hasEarlierMemWriteToSameAddressWithSameGuard
bool hasEarlierMemWriteToSameAddressWithSameGuard(MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
Definition: DataDependenceGraphBuilder.cc:1688
DataDependenceGraphBuilder::processRegUse
void processRegUse(MoveNodeUse mn, const TCEString &reg)
Definition: DataDependenceGraphBuilder.cc:1229
LLVMAliasAnalyzer::setLLVMAA
virtual void setLLVMAA(llvm::AliasAnalysis *AA)
Definition: LLVMAliasAnalyzer.cc:157
TTAMachine::RegisterFile
Definition: RegisterFile.hh:47
Conversion::toInt
static int toInt(const T &source)
TTAProgram::MoveGuard::guard
const TTAMachine::Guard & guard() const
Definition: MoveGuard.cc:86
DataDependenceGraphBuilder::hasEarlierWriteWithSameGuard
bool hasEarlierWriteWithSameGuard(MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
Definition: DataDependenceGraphBuilder.cc:1183
DataDependenceGraphBuilder::MEMORY_AND_SIDE_EFFECTS
@ MEMORY_AND_SIDE_EFFECTS
Definition: DataDependenceGraphBuilder.hh:122
TTAProgram::ProgramAnnotation
Definition: ProgramAnnotation.hh:49
OperationPool
Definition: OperationPool.hh:52
TTAProgram::Instruction::movePtr
std::shared_ptr< Move > movePtr(int i) const
Definition: Instruction.cc:216
InterPassData::datum
InterPassDatum & datum(const std::string &key)
Definition: InterPassData.cc:62
DataDependenceGraphBuilder::constructIndividualBB
void constructIndividualBB(ConstructionPhase phase)
Definition: DataDependenceGraphBuilder.cc:560
Move.hh
LiveRangeData::memKills_
MoveNodeUseMap memKills_
Definition: LiveRangeData.hh:103
TTAMachine
Definition: Assembler.hh:48
DataDependenceEdge::DEP_WAR
@ DEP_WAR
Definition: DataDependenceEdge.hh:48
OffsetAliasAnalyzer
Definition: OffsetAliasAnalyzer.hh:46
LiveRangeData::fuDepAfter_
MoveNodeUseSet fuDepAfter_
Definition: LiveRangeData.hh:118
LiveRangeData::memDefines_
MoveNodeUseMapSet memDefines_
Definition: LiveRangeData.hh:98
BoostGraph::name
virtual const TCEString & name() const
ControlFlowEdge.hh
LiveRangeData::appendUseMapSets
static bool appendUseMapSets(const MoveNodeUseMapSet &srcMap, MoveNodeUseMapSet &dstMap, bool addLoopProperty)
Definition: LiveRangeData.cc:79
BoostGraph::nodeCount
int nodeCount() const
MachineInfo::triggerIndex
static int triggerIndex(const TTAMachine::Machine &machine, const Operation &op)
Definition: MachineInfo.cc:530
DataDependenceGraph::updateRegWrite
DataDependenceGraph::EdgeSet updateRegWrite(const MoveNodeUse &mnd, const TCEString &reg, TTAProgram::BasicBlock &bb)
Definition: DataDependenceGraph.cc:5401
TTAMachine::RegisterGuard::registerFile
const RegisterFile * registerFile() const
DataDependenceEdge::EDGE_RA
@ EDGE_RA
Definition: DataDependenceEdge.hh:57
BoostGraph::successors
virtual NodeSet successors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
Operation::numberOfOutputs
virtual int numberOfOutputs() const
Definition: Operation.cc:202
DataDependenceGraphBuilder::analyzeMemoryAlias
MemoryAliasAnalyzer::AliasingResult analyzeMemoryAlias(const ProgramOperation &pop1, const ProgramOperation &pop2, MoveNodeUse::BBRelation bbInfo)
Definition: DataDependenceGraphBuilder.cc:1951
AssocTools::deleteAllValues
static void deleteAllValues(ContainerType &aMap)
LiveRangeData::memDefReaches_
MoveNodeUseMapSet memDefReaches_
Definition: LiveRangeData.hh:108
Operation::affectsCount
virtual int affectsCount() const
Definition: Operation.cc:402
DataDependenceGraphBuilder::BBData
Definition: DataDependenceGraphBuilder.hh:127
llvm::AliasAnalysis
AAResults AliasAnalysis
Definition: DataDependenceGraphBuilder.hh:45
DataDependenceGraphBuilder::processTriggerMemoryAndFUStates
void processTriggerMemoryAndFUStates(MoveNode &moveNode, Operation &dop)
Definition: DataDependenceGraphBuilder.cc:1040
DataDependenceGraph::hasAllRegisterAntidependencies
bool hasAllRegisterAntidependencies()
Definition: DataDependenceGraph.hh:379
BasicBlockNode::originalStartAddress
InstructionAddress originalStartAddress() const
Definition: BasicBlockNode.cc:162
TTAProgram::Instruction::moveCount
int moveCount() const
Definition: Instruction.cc:176
DataDependenceGraph::hasRegWaw
bool hasRegWaw(const MoveNodeUse &mnu, std::set< MoveNodeUse > targets) const
Definition: DataDependenceGraph.cc:5518
CompilerWarnings.hh
TTAProgram::TerminalRegister
Definition: TerminalRegister.hh:53
DataDependenceGraphBuilder::MoveNodeUseSet
LiveRangeData::MoveNodeUseSet MoveNodeUseSet
Definition: DataDependenceGraphBuilder.hh:105
LiveRangeData::regFirstUses_
MoveNodeUseMapSet regFirstUses_
Definition: LiveRangeData.hh:86
DataDependenceGraphBuilder::specialRegisters_
SpecialRegisters specialRegisters_
contains stack pointer, RV and parameter registers.
Definition: DataDependenceGraphBuilder.hh:317
ControlFlowGraph
Definition: ControlFlowGraph.hh:100
ProgramOperation::inputMove
MoveNode & inputMove(int index) const
Definition: ProgramOperation.cc:621
TTAMachine::Machine
Definition: Machine.hh:73
TTAProgram::AnnotatedInstructionElement::annotationCount
int annotationCount(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
Definition: AnnotatedInstructionElement.cc:133
ContainerTools.hh
LiveRangeData::memUseReaches_
MoveNodeUseMapSet memUseReaches_
Definition: LiveRangeData.hh:109
DataDependenceGraph::hasIntraBBRegisterAntidependencies
bool hasIntraBBRegisterAntidependencies()
Definition: DataDependenceGraph.hh:387
MoveGuard.hh