OpenASIP 2.2
Loading...
Searching...
No Matches
ProgramDependenceGraph.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file ProgramDependenceGraph.cc
26 *
27 * Implementation of prototype of graph-based program representation:
28 * declaration of the program dependence graph.
29 *
30 * @author Vladimir Guzma 2006 (vladimir.guzma-no.spam-tut.fi)
31 * @note rating: red
32 */
33
34#include <chrono>
35#include <utility>
36
37// include this before boost to avoid deprecation
38// warnings
39#include "hash_set.hh"
40
41#include <boost/graph/depth_first_search.hpp>
42#include <boost/graph/properties.hpp>
43#include <boost/graph/strong_components.hpp>
44#include <boost/graph/graph_utility.hpp>
45#include <boost/graph/topological_sort.hpp>
46#include <boost/graph/exception.hpp>
47#include <boost/format.hpp>
48#include <boost/graph/graphviz.hpp>
49
51#include "UniversalMachine.hh"
52#include "Procedure.hh"
53#include "POMDisassembler.hh"
54#include "MapTools.hh"
55#include "Exception.hh"
56#include "MoveGuard.hh"
57#include "SequenceTools.hh"
61#include "TerminalFUPort.hh"
62#include "ControlUnit.hh"
63#include "HWOperation.hh"
64#include "Machine.hh"
65#include "Guard.hh"
66#include "MoveGuard.hh"
67#include "Move.hh"
68#include "Instruction.hh"
69#include "Program.hh"
71#include "BasicBlock.hh"
72
73#define DEBUG_LEVEL 1
74
76 // Boost destructor will delete nodes from graph
77 for (int i = 0; i < nodeCount(); i++) {
78 Node* n = &node(i);
79 delete n;
80 }
81 for (unsigned int i = 0; i < strongComponents_.size(); i++) {
82 strongComponents_[i].clear();
83 }
84 strongComponents_.clear();
85}
86
87/**
88 * Constructor.
89 * Build Program Dependence Graph from Control and Data Dependence graphs.
90 * @param cdg Control Dependence Graph of procedure
91 * @param ddg Data Dependence Graph of procedure
92 */
97 cdg_(&cdg),
98 ddg_(&ddg),
99 entryNode_(NULL),
100 ddgEntryNode_(NULL),
101 insCount_(0),
102 wrongCounter_(0) {
103
104 ControlToProgram cNodePNode;
105 BBToCD BBNodeCDNode;
106 MoveNodeToPDGNode movePD;
107 MovesInCD moveToCD;
108 program_ = cdg.program();
109
110 // Creates PDG node for each region node of CDG
111 for (int i = 0; i < cdg.nodeCount(); i++) {
112 ControlDependenceNode& cnode = cdg.node(i);
113 if (cnode.isRegionNode()
114 || cnode.isEntryNode()
115 || cnode.isLoopEntryNode()
116 || cnode.isLoopCloseNode()) {
117
120 if (cnode.isLoopCloseNode()) {
122 }
123 if (cnode.isLoopEntryNode()) {
125 }
126
127 ProgramDependenceNode* newNode = new
128 ProgramDependenceNode(cnode, type);
129 if (cnode.isLastNode()) {
130 newNode->setLastNode();
131 }
132 addNode(*newNode);
133 cNodePNode.insert(
134 std::pair<ControlDependenceNode*, ProgramDependenceNode*>(
135 &cnode, newNode));
136 if (cnode.isEntryNode()) {
137 BBNodeCDNode.insert(
138 std::pair<BasicBlockNode*, ControlDependenceNode*>(
139 cnode.basicBlockNode(), &cnode));
140 entryNode_ = newNode;
141 }
142 } else {
143 BBNodeCDNode.insert(
144 std::pair<BasicBlockNode*, ControlDependenceNode*>(
145 cnode.basicBlockNode(), &cnode));
146 }
147 }
148 assert(entryNode_ != NULL && "Entry node of the graph was not defined!");
149 // Copies edges between region nodes of CDG into the PDG
150 for (int i = 0; i < cdg.edgeCount(); i++) {
154 headNode = &cdg.headNode(edge);
155 tailNode = &cdg.tailNode(edge);
156 // CDG predicate node is special type of BB node with 2 outgoing
157 // edges
158 // Entry node is special kind of BB, which we are also interested in
159 // here
160 if (!headNode->isBBNode()
161 && !headNode->isPredicateNode()
162 && (!tailNode->isBBNode() || tailNode->isEntryNode())
163 && !tailNode->isPredicateNode()) {
164 // headNode is one with arrow in boost graphs
165 ProgramDependenceNode* sourceNode;
166 ProgramDependenceNode* targetNode;
167 try {
169 cNodePNode, tailNode);
171 cNodePNode, headNode);
172 } catch (const Exception& e) {
173 throw InvalidData(
174 __FILE__, __LINE__, __func__, e.errorMessageStack());
175 }
177 pEdge = new ProgramDependenceEdge(edge);
178 connectNodes(*sourceNode, *targetNode, *pEdge);
179 }
180 }
181
182 // Add each MoveNode of DDG also to PDG
183 for (int i = 0; i < ddg.nodeCount(); i++) {
184 Node* newNode = NULL;
186 // Guarded jumps and calls becomes predicates
187 MoveNode& node = ddg.node(i);
188 if (node.isMove() &&
189 node.move().isControlFlowMove() &&
190 !node.move().isUnconditional()) {
191 typeOfNode = Node::PDG_NODE_PREDICATE;
192 } else if (node.isMove() &&
193 node.move().isControlFlowMove() &&
194 node.move().isJump() &&
195 !node.move().isReturn()){
196 /// Ignore unconditional jumps
197 continue;
198 }
199 newNode = new ProgramDependenceNode(node, typeOfNode);
200 addNode(*newNode);
201 if(!node.isMove()) {
202 ddgEntryNode_ = newNode;
203 }
204 movePD.insert(std::pair<MoveNode*, ProgramDependenceNode*>(
205 &node, newNode));
206 }
207
208 // Add the edges between MoveNodes in DDG
209 for (int j = 0; j < ddg.edgeCount(); j++) {
210 ProgramDependenceNode* pSource = NULL;
211 ProgramDependenceNode* pTarget = NULL;
212 DataDependenceEdge& edge = ddg.edge(j);
213 if (!MapTools::containsKey(movePD, &ddg.tailNode(edge))) {
214 continue;
215 }
217 movePD, &ddg.tailNode(edge));
218 if (!MapTools::containsKey(movePD, &ddg.headNode(edge))) {
219 continue;
220 }
222 movePD, &ddg.headNode(edge));
224 pEdge = new ProgramDependenceEdge(edge);
225 connectNodes(*pSource, *pTarget, *pEdge);
226 }
227
228 // edges between region nodes and move nodes
229 for (int i = 0; i < ddg.nodeCount(); i++) {
230 // Some jumps were not copied so we skip them when adding edges
231 MoveNode& node = ddg.node(i);
232 if (!MapTools::containsKey(movePD, &node)) {
233 continue;
234 }
235
236 BasicBlockNode* b = NULL;
237 b = &ddg.getBasicBlockNode(node);
238 ControlDependenceNode* cNode = NULL;
239 if (!MapTools::containsKey(BBNodeCDNode, b)) {
240 throw InvalidData(
241 __FILE__, __LINE__, __func__,
242 "No Control Dependence Node for Basic Block Node!");
243 }
244 try {
246 BBNodeCDNode, b);
247 } catch (const Exception& e) {
248 throw InvalidData(
249 __FILE__, __LINE__, __func__, e.errorMessageStack());
250 }
251
252 ProgramDependenceNode* pNode = NULL;
253 try {
255 movePD, &node);
256 } catch (const Exception& e) {
257 throw InvalidData(
258 __FILE__, __LINE__, __func__, e.errorMessageStack());
259 }
260 if (pNode->isMoveNode() && pNode->moveNode().isMove() == false) {
261 /// Found dummy entry node of ddg, connect it to entry node of
262 /// pdg as well.
264 ProgramDependenceEdge* pEdge = new ProgramDependenceEdge(*cdgEdge);
265 connectNodes(entryNode(), *pNode, *pEdge);
266 continue;
267 }
268 if (!MapTools::containsKey(moveToCD, cNode)) {
269 std::vector<Node*> tmp;
270 tmp.push_back(pNode);
271 moveToCD[cNode] = tmp;
272 } else {
273 std::vector<Node*> tmp = moveToCD[cNode];
274 tmp.push_back(pNode);
275 moveToCD[cNode] = tmp;
276 }
277 // For each MoveNode, find in which Basic Block it was
278 // and all input edges that went into CDG for given Basic Block
279 // are also added to the MoveNode
280 for (int j = 0; j < cdg.inDegree(*cNode); j++) {
281 ControlDependenceNode* source;
282 source = &cdg.tailNode(cdg.inEdge(*cNode, j));
283 if (source->isRegionNode()
284 || source->isEntryNode()
285 || source->isLoopEntryNode()
286 || source->isLoopCloseNode()) {
288 pEdge = new
289 ProgramDependenceEdge(cdg.inEdge(*cNode, j));
290 ProgramDependenceNode* pSource = NULL;
291 try {
293 cNodePNode, source);
294 } catch (const Exception& e) {
295 throw InvalidData(
296 __FILE__, __LINE__, __func__, e.errorMessageStack());
297 }
298 connectNodes(*pSource, *pNode, *pEdge);
299 } else {
300 abortWithError("The source of control dependence is not\
301 region node!");
302 }
303 }
304 if (pNode->isPredicateMoveNode() &&
305 pNode->moveNode().move().isJump()){
306 removeGuardedJump(cNodePNode, *pNode, *cNode);
307 removeNode(*pNode);
308 }
309 }
310 /// If CDG already has analysis of Region and EEC done, just copy
311 /// results
312 if (cdg.analyzed()) {
313 copyRegionEECComponent(cNodePNode, BBNodeCDNode, movePD, moveToCD);
314 }
315}
316
317/**
318 * Remove guarded jumps from the graph, makes guard generating operation
319 * a predicated node and fixes the true and false edges in case the jump
320 * had inverted guard.
321 * @param cToP mapping between Control Dependence nodes of original CDG and
322 * newly created Program Dependence nodes in PDG.
323 * @param pNode Program Dependence Node containing guarded jump
324 * @param cNode Control Dependence node which included guarded jump in CDG
325 */
326void
328 ControlToProgram& cToP,
330 ControlDependenceNode& cNode) {
331
332 ProgramDependenceNode* guardSource = NULL;
333 bool isInverted = pNode.moveNode().move().guard().isInverted();
334 if (inDegree(pNode) != 2) {
335 /// This used to be error, but now it possible
336 if(Application::verboseLevel() > 0) {
337 Application::logStream() << (boost::format(
338 "Guarded jump (%s) has inDegree different from 2! Degree =%d.\n")
339 % pNode.toString() % inDegree(pNode)).str();
340 EdgeSet e = inEdges(pNode);
341 for (EdgeSet::iterator ei = e.begin(); ei != e.end(); ei++) {
342 Node* n = & tailNode(**ei);
343 Application::logStream() << n->toString() << " "
344 << (*ei)->toString() << " ";
345 }
346 }
347 }
348 for (int i = 0; i < inDegree(pNode); i++) {
349 if (inEdge(pNode,i).isDataDependence()) {
350 guardSource = &tailNode(inEdge(pNode,i));
351 break;
352 }
353 }
354 if (guardSource == NULL) {
355 throw InvalidData(
356 __FILE__, __LINE__, __func__,
357 "Guarded jump did not have source of guard defined!");
358 }
359 guardSource->setPredicateMoveNode();
360 /// All incoming control dependence edges into the predicate node
361 /// are also incoming edges to the guard, since they were in same
362 /// block in CDG
363 for (int j = 0; j < cdg_->outDegree(cNode); j++) {
364 ControlDependenceNode* target;
365 target = &cdg_->headNode(cdg_->outEdge(cNode, j));
366 if (target->isRegionNode()
367 || target->isLoopEntryNode()
368 || target->isLoopCloseNode()) {
370 ControlDependenceEdge* newEdge = &cdg_->outEdge(cNode, j);;
371 if (isInverted) {
372 newEdge->invertEdgePredicate();
373 }
374 pEdge = new ProgramDependenceEdge(*newEdge);
375 ProgramDependenceNode* pTarget;
376 try {
378 cToP, target);
379 } catch (const Exception& e) {
380 throw InvalidData(
381 __FILE__, __LINE__, __func__, e.errorMessageStack());
382 }
383
384 connectNodes(*guardSource, *pTarget, *pEdge);
385 } else {
386 throw InvalidData(
387 __FILE__, __LINE__, __func__,
388 "Basic block with guarded jump does not have"
389 " Region nodes as control dependent!");
390 }
391 }
392}
393/**
394 * Performs serialization of ProgramDependenceGraph, turning it into
395 * Control Flow Graph.
396 *
397 * @return ControlFlowGraph representation of PDG
398 * @throw InvalidData in case serialization of graph is not possible
399 */
400bool
402
404 Application::logStream() << (boost::format(
405 "\tStarting PDG serialization for %s with %d nodes and %d edges.\n")
406 % name() % nodeCount() % edgeCount()).str();
407 }
408
409 /// Created filtered PDG graph containing only control dependence edges
410 CDGFilter<Graph> filter(graph_);
411 FilteredCDG filteredCDG = FilteredCDG(graph_, filter);
412 auto timer = std::chrono::steady_clock::now();
413 long elapsed = 0;
414 /// Detect strong components if they were not detected in CDG and transferred
415 if (!cdg_->analyzed()) {
416 PDGOrderMap componentMap;
417 DescriptorMap rootMap;
418 /// Modifies graph_ with added close nodes and close edges
419 int componentCount = detectStrongComponents(
420 componentMap, rootMap, filteredCDG);
421 elapsed = std::chrono::duration_cast<std::chrono::seconds>(
422 std::chrono::steady_clock::now() - timer)
423 .count();
425 Application::logStream() << (boost::format(
426 "\t\tStrong components:%d components, %d minutes and %d seconds.\n")
427 % componentCount % (elapsed/60) % (elapsed%60)).str();
428 }
429 }
430
431 /// map to store post order information for all the nodes of a graph
432 PDGOrderMap lastMap;
433 PDGOrder lastOrder(lastMap);
434 /// map to store color information during dfs
435 ColorMap colorMap;
436 Color colorsDFS(colorMap);
437 int fStamp(-1);
438 /// boost::on_finish_vertex will give us post order numbering
439 boost::time_stamper<PDGOrder, int, boost::on_finish_vertex>
440 lastOrderStamper(lastOrder, fStamp);
441 timer = std::chrono::steady_clock::now(); // restart
442 /// Computes post order of all the nodes in PDG
443 boost::depth_first_visit(
444 filteredCDG, descriptor(entryNode()),
445 boost::make_dfs_visitor(lastOrderStamper), colorsDFS);
446 elapsed = std::chrono::duration_cast<std::chrono::seconds>(
447 std::chrono::steady_clock::now() - timer)
448 .count();
450 Application::logStream() << (boost::format(
451 "\t\tPost order: %d minutes and %d seconds.\n")
452 % (elapsed/60) % (elapsed%60)).str();
453 }
454 /// If not computed on CDG and copied, computes 'region' information for
455 /// all nodes of a graph
456 if (!cdg_->analyzed()) {
457 timer = std::chrono::steady_clock::now(); // restart
458 computeRegionInfo(lastMap, filteredCDG);
459 elapsed = std::chrono::duration_cast<std::chrono::seconds>(
460 std::chrono::steady_clock::now() - timer)
461 .count();
463 Application::logStream() << (boost::format(
464 "\t\tRegion: %d minutes and %d seconds.\n")
465 % (elapsed/60) % (elapsed%60)).str();
466 }
467 /// If not computed on CDG and copied, computes 'eec' information for
468 /// all nodes of a graph
469 timer = std::chrono::steady_clock::now(); // restart
470 computeEECInfo(lastMap, filteredCDG);
471 elapsed = std::chrono::duration_cast<std::chrono::seconds>(
472 std::chrono::steady_clock::now() - timer)
473 .count();
475 Application::logStream() << (boost::format(
476 "\t\tEEC: %d minutes and %d seconds.\n")
477 % (elapsed/60) % (elapsed%60)).str();
478 }
479 }
480
481 timer = std::chrono::steady_clock::now(); // restart
482 /// If CDG comes analyzed we need to add region and eec info for
483 /// dummy ENTRYNODE of DDG. By it's definition, ENTRYNODE is leaf
484 /// in terms of control dependence, region == eec
485 if(cdg_->analyzed() && ddgEntryNode_ != NULL) {
486 Node::NodesInfo finalNodesInfo;
487 regionHelper(ddgEntryNode_, filteredCDG, finalNodesInfo);
488 for (Node::NodesInfo::iterator k = finalNodesInfo.begin();
489 k != finalNodesInfo.end(); k++) {
490 ddgEntryNode_->addToRegion(**k);
491 ddgEntryNode_->addToEEC(**k);
492 }
493 }
494 return true;
495#if 0
496 /// Compute actual relations between sibling nodes. Move Data Dependence
497 /// edges to root's of subgraph if they connect subgraph with outside
498 /// nodes
499 ///computeRelations(lastMap, filteredCDG);
500 elapsed = static_cast<long>(timer.elapsed());
502 Application::logStream() << (boost::format(
503 "\t\tRelations: %d minutes and %d seconds.\n")
504 % (elapsed/60) % (elapsed%60)).str();
505 }
507 Application::logStream() << (boost::format(
508 "Procedure %s has %d nodes and %d edges.\n")
509 % name() % nodeCount() % edgeCount()).str();
510 }
511 //writeToDotFile(name() + "_pdgSerialized.dot");
512 //disassemble();
513 return true;
514#endif
515}
516
517/**
518 * Detects all strong components of a PDG graph (loops). Strong components are
519 * maximal sets of nodes that are reachable from each other. Each node is member
520 * of some component. If it is not in loop then node is components of it's own.
521 * Augments graph with loop entry and close nodes.
522 * Works iteratively, first detects maximal component, then proceeds to ones
523 * that are "embedded".
524 *
525 * @param components After return contains for each node number of component
526 * to which node belongs
527 * @param roots After return contains for each node a node that is root of
528 * component to which node belongs
529 * @return returns number of components in a graph
530 */
531int
533 PDGOrderMap& components,
534 DescriptorMap& roots,
535 FilteredCDG& cdg) {
536
537 std::vector<std::pair<Node*, Node*> > backEdges;
538 int componentCount = 0;
539 int currentComponents = 0;
540 int numberOfNodes = 0;
541
542 /// Will repeat until all the strong components will be found
543 /// Including weirdly nested :-)
544 do {
545 PDGOrder componentOrder(components);
546 Descriptors componentRoots(roots);
547 currentComponents = 0;
548 /// Node count will change with addition of close nodes
549 numberOfNodes = boost::num_vertices(cdg);
550 currentComponents = boost::strong_components(
551 cdg, componentOrder, boost::root_map(componentRoots));
552
553 // for each component add vector of nodes that belongs to it
554 std::vector<std::set<Node*> > componentVector;
555 componentVector.resize(componentCount + currentComponents);
556
557 /// If the number of components is identical to number of nodes
558 /// there are no loops in graph
559 if (currentComponents == numberOfNodes) {
560 componentCount = strongComponents_.size();
561 break;
562 }
563
564 /// Add to strong components only those which are loops
565 /// Store them as Node*, use of descriptors is not possible
566 /// due to later addition of Nodes which will invalidate
567 /// descriptors
568 for (PDGOrderMap::iterator iterA = components.begin();
569 iterA != components.end(); iterA ++) {
570 Node* cNode = cdg[(*iterA).first];
571 componentVector[(*iterA).second].insert(cNode);
572 }
573 for (unsigned int i = componentCount; i < componentVector.size(); i++){
574 if (componentVector[i].size() > 1) {
575 std::set<Node*>& vector = componentVector[i];
576 std::set<Node*> ref;
577 int componentsSize = strongComponents_.size();
578 for (std::set<Node*>::iterator iterB = vector.begin();
579 iterB != vector.end();
580 iterB++) {
581 ref.insert(*iterB);
582 // Set component number
583 if ((*iterB)->component() == -1){
584 (*iterB)->setComponent(componentsSize);
585 }
586 }
587 strongComponents_.push_back(ref);
588 }
589 }
590
591 /// Detects all loop entry nodes
592 /// Stores Nodes which are identified as loop entry nodes
593 /// together with number to which loop they belong
594 std::vector<std::pair<Node*,int> > newEntry;
595 /// for each entry node, collect edges that points to it from outside
596 /// the loop, deals only with newly added components
597 std::map<Node*, std::vector<Node*> > incomingToEntry;
598 for (unsigned int i = componentCount;
599 i < strongComponents_.size();
600 i++) {
601 std::set<Node*>& nodes = strongComponents_[i];
602 for (std::set<Node*>::iterator iterD = nodes.begin();
603 iterD != nodes.end();
604 iterD++) {
605
607 vec = descriptor(**iterD);
608 FilteredInEdgePair edges = boost::in_edges(vec, cdg);
609 for (FilteredInEdgeIter ei = edges.first;
610 ei != edges.second;
611 ++ei) {
612
613 Node* testedNode = cdg[boost::source(*ei, cdg)];
614 if (nodes.find(testedNode) == nodes.end()) {
615 /// tail of the edge is not inside component
616 /// it is external edge making this node loop entry
617 if (!(*iterD)->isLoopEntryNode(i)) {
618 (*iterD)->setLoopEntryNode(i);
619 newEntry.push_back(
620 std::pair<Node*,int>(*iterD,i));
621 incomingToEntry[*iterD].push_back(testedNode);
622 } else {
623 /// Several nodes points to loop entry node
624 /// we create dummy region node to collect those
625 /// edges
626 incomingToEntry[*iterD].push_back(testedNode);
627 }
628 }
629 }
630 }
631 }
632
633 /// Adds close nodes for each loop entry node
634 /// Node and Edge descriptors are invalidated here!
635 for (unsigned int j = 0; j < newEntry.size(); j++) {
636 Node* loopNode = newEntry[j].first;
637 std::set<Node*>& nodes =
638 strongComponents_[newEntry[j].second];
639 /// Create one "close" node for each loop entry
640 Node* close = new Node(Node::PDG_NODE_LOOPCLOSE);
641 close->setComponent(newEntry[j].second);
642 addNode(*close);
643
644 /// Close node is also part of component
645 strongComponents_[newEntry[j].second].insert(close);
646
648 vec = descriptor(*loopNode);
649 FilteredInEdgePair edges = boost::in_edges(vec, cdg);
650 std::vector<Edge*> storeEdges;
651 /// Redirect edges to loop entry from inside the loop
652 /// to loop close node. Collect edges that needs redirecting
653 for (FilteredInEdgeIter ei = edges.first;
654 ei != edges.second;
655 ++ei) {
656 Node* sourceNode = cdg[boost::source(*ei, cdg)];
657 if (nodes.find(sourceNode) != nodes.end()){
658 /// store edges that will have to be moved
659 Edge* edge = cdg[*ei];
660 storeEdges.push_back(edge);
661 }
662 }
663 /// Actually redirect edges
664 for (unsigned int counter = 0;
665 counter < storeEdges.size();
666 counter++) {
667 moveInEdge(*loopNode, *close, *storeEdges[counter]);
668 }
669 /// Back edge will be added later, after all loops are found
670 backEdges.push_back(
671 std::pair<Node*, Node*>(close, loopNode));
672
673 /// Close node is also added to unfiltered pdg, as well as edges
674 /// so we can test it directly there and not on filtered graph
675 if (inDegree(*close) == 0) {
676 TCEString msg = "Close node for loop entry node ";
677 msg += loopNode->toString() + " was not connected!";
678 throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
679 }
680 /// In case loop entry has multiple incoming edges
681 /// outside loop, we add new region to group them together
682 /// This can be also on original pdg, no need to use filtered
683 /// version
684 std::vector<Node*> tmp =
686 incomingToEntry, loopNode);
687 if (tmp.size() > 1) {
688 /// Creates new artificial region node without equivalent
689 /// one in CDG
690 Node* collect = new Node();
691 addNode(*collect);
692 for (unsigned int i = 0; i < tmp.size(); i++) {
693 Node* input = tmp[i];
694 EdgeDescriptor ed = connectingEdge(*input, *loopNode);
695 Edge* e = graph_[ed];
696 moveInEdge(*loopNode, *collect, *e);
697 }
698 ProgramDependenceEdge* pdgEdge =
700 connectNodes(*collect, *loopNode, *pdgEdge);
701 }
702 }
703 newEntry.clear();
704 componentCount = strongComponents_.size();
705 } while (true);
706
707 /// Add edges from close nodes to their respective loop entries
708 for (unsigned int i = 0; i < backEdges.size(); i++) {
709 ProgramDependenceEdge* pdgEdge =
712 connectNodes(*backEdges[i].first, *backEdges[i].second, *pdgEdge);
713 }
714
715#if 0
716 for (unsigned int i = 0; i < strongComponents_.size() ; i++) {
717 std::cerr << "\tComponent: " << i << std::endl;
718 for (std::set<Node*>::iterator iter = strongComponents_[i].begin();
719 iter != strongComponents_[i].end(); iter++) {
720 std::cerr << "\t\t" << (*iter)->toString() << std::endl;
721 }
722 std::cerr << std::endl;
723 }
724#endif
725 return componentCount;
726}
727
728/**
729 * Compute the "region" information for each node of graph. Region is used to
730 * compute "eec" to determine order in which sibling subgraphs will be in
731 * resulting cfg.
732 *
733 * "Region" of node X is set of nodes that will be executed in case is X
734 * executed.
735 *
736 * @param orderMap post order map of PDG graph, nodes will be augmented with
737 * "region" information.
738 * @param cdg Program Dependence Graph filtered to us only control dependence
739 * edges.
740 */
741void
743 const PDGOrderMap& orderMap,
744 FilteredCDG& cdg){
745
746 int mapSize = orderMap.size();
747 if (mapSize == 0) {
748 throw ModuleRunTimeError(__FILE__, __LINE__, __func__,
749 "No nodes in CDG graph for " + name() + "!");
750 }
751 /// Compute "region" information using reverse post-order processing
752 /// Node descriptors in filtered graph are identical to original graph
753 /// we only care about edge filtering here
754 for (int i = mapSize -1 ; i >= 0 ; i--) {
755 NodeDescriptor des =
757 Node* node = graph_[des];
758 if (!node->isLoopEntryNode()) {
759 /// For non loop entry nodes, simply compute region info
760 /// and store it in the node
761 Node::NodesInfo finalNodesInfo;
762 regionHelper(node, cdg, finalNodesInfo);
763 for (Node::NodesInfo::iterator k = finalNodesInfo.begin();
764 k != finalNodesInfo.end(); k++) {
765 node->addToRegion(**k);
766 }
767
768 } else if (node->region().size() == 0) {
769 /// for loop entry node, find all other entry nodes
770 /// of the same loop (component)
771 /// final region info will be intersection of region info from
772 /// all the entry nodes in the same loop
773 /// it will be same for all the nodes too (they are reachable)
774 std::vector<Node*> entries;
775 std::set<Node*> component = strongComponents_[node->component()];
776 for (std::set<Node*>::iterator si = component.begin();
777 si != component.end(); si++) {
778 /// Check if node is loop entry node of tested component
779 if ((*si)->isLoopEntryNode(node->component())) {
780 entries.push_back(*si);
781 }
782 }
783 Node::NodesInfo finalNodesInfo;
784 for (unsigned int i = 0; i < entries.size(); i++) {
785 /// for every entry node of the loop compute region info
786 Node* entryNode = entries[i];
787 regionHelper(entryNode, cdg, finalNodesInfo);
788 }
789 for (unsigned j = 0; j < entries.size(); j++) {
790 Node* result = entries[j];
791 for (Node::NodesInfo::iterator k = finalNodesInfo.begin();
792 k != finalNodesInfo.end();
793 k++) {
794 result->addToRegion(**k);
795 }
796 }
797 }
798 }
799}
800
801/**
802 * Compute the "eec" information for each node of graph. EEC is used to
803 * determine order in which sibling subgraphs needs to be scheduled in
804 * resulting cfg.
805 *
806 * "eec" of node X is set of nodes that will be executed in case any of the
807nodes
808 * in subgraph of X will be executed.
809 *
810 * @param orderMap post order map of PDG graph, nodes augmented with
811 * "region" information, "eec" information will be added.
812 */
813void
815 const PDGOrderMap& orderMap,
816 FilteredCDG& filteredCDG) {
817
818 int mapSize = orderMap.size();
819
820 for (int i = 0; i < mapSize; i++) {
821 NodeDescriptor des =
823 orderMap, i);
824 Node* node = graph_[des];
825 /// eec already exists, skip
826 if (node->eec().size() > 0) {
827 continue;
828 }
829 /// Found close node, eec(node) == intersection of all close
830 /// nodes of same loop region(node) (close node is as leaf node)
831 if (node->isLoopCloseNode() && node->eec().size() == 0) {
832 std::vector<Node*> closeNodes;
833 std::set<Node*> component = strongComponents_[node->component()];
834 // collect all loop close nodes of same loop
835 for (std::set<Node*>::iterator si = component.begin();
836 si != component.end(); si++) {
837 if ((*si)->isLoopCloseNode()) {
838 closeNodes.push_back(*si);
839 } else if ((*si)->isRegionNode()
840 || (*si)->isPredicateMoveNode()) {
841 (*si)->setLastNode();
842 }
843 }
844 Node::NodesInfo finalInfo;
845 Node::NodesInfo storeResult;
846 finalInfo.insert(node->region().begin(),node->region().end());
847 for (unsigned int i = 0; i < closeNodes.size(); i++) {
849 finalInfo, closeNodes[i]->region(), storeResult);
850 finalInfo.swap(storeResult);
851 storeResult.clear();
852 }
853 // add intersection of all region info to each close node in loop
854 for (unsigned j = 0; j < closeNodes.size(); j++) {
855 Node* result = closeNodes[j];
856 /// Close nodes eec must be empty before we get here
857 if(result->eec().size() != 0) {
858 TCEString msg = (boost::format(
859 "Close node %s in %s already has eec!\n")
860 % result->toString() % node->toString()).str();
861 throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
862 }
863 for (Node::NodesInfo::iterator k = finalInfo.begin();
864 k != finalInfo.end(); k++) {
865 result->addToEEC(**k);
866 }
867 }
868
869 } else if (boost::out_degree(descriptor(*node), filteredCDG) == 0) {
870 /// Found leaf node, eec(node) == region(node)
871 Node::NodesInfo regionX = node->region();
872 for (Node::NodesInfo::iterator t = regionX.begin();
873 t != regionX.end(); t++) {
874 node->addToEEC( **t);
875 }
876 } else {
877 /// Not a leaf node,
878 /// eec(x) = intersection(eec(children(x)) \ children(x)
879 Node::NodesInfo childNodes;
880 FilteredOutEdgePair edges =
881 boost::out_edges(descriptor(*node), filteredCDG);
882 for (FilteredOutEdgeIter ei = edges.first;
883 ei != edges.second;
884 ++ei) {
885 Node* testedNode = filteredCDG[boost::target(*ei, filteredCDG)];
886 childNodes.insert(testedNode);
887 }
888 Node::NodesInfo finalEEC;
889
890 // Fill in candidate set with data from first successor
891 finalEEC.insert(
892 (*(childNodes.begin()))->eec().begin(),
893 (*(childNodes.begin()))->eec().end());
894 // compute intersection of successors eec
895 for(Node::NodesInfo::iterator j = childNodes.begin();
896 j != childNodes.end(); j++ ) {
897 Node::NodesInfo storeResult;
898 SetTools::intersection(finalEEC, (*j)->eec(), storeResult);
899 finalEEC.swap(storeResult);
900 storeResult.clear();
901 }
902 std::vector<Node*> result(finalEEC.size(), NULL);
903 // compute set difference, returns iterator pointing to
904 // .end() of the result
905 std::vector<Node*>::iterator resultEnd =
906 std::set_difference(finalEEC.begin(), finalEEC.end(),
907 childNodes.begin(), childNodes.end(), result.begin());
908 // push resulting eec into the node eec info
909 for (std::vector<Node*>::iterator t = result.begin();
910 t != resultEnd; t++) {
911 node->addToEEC(**t);
912 }
913 }
914 }
915}
916
917/**
918 * Compare sibling nodes and determines their ordering relation
919 * based on eec information. In addition, nodes marked as lastNode
920 * are always ordered later in case ANY_ORDER is available.
921 *
922 * @param a First node to compare
923 * @param b Second node to compare
924 * @return value determining relation
925 */
928 bool AinA = false;
929 bool BinB = false;
930 bool BinA = false;
931 bool AinB = false;
932
933#ifdef AVOID_COMPILER_WARNINGS_REMOVE_THESE_LINES
934 bool extra = false;
935 if (a->isPredicateMoveNode() || b->isPredicateMoveNode()) {
936 extra = true;
937 }
938#endif
939 /// Both a and b are simple statements, order is given by data dependencies
940 /// no need to test eec info
941 if (a->isMoveNode() && b->isMoveNode()
942 && !a->isPredicateMoveNode() && !b->isPredicateMoveNode()) {
943 return ANY_ORDER;
944 }
945 /// Find nodes relations in eec
946 if (AssocTools::containsKey(a->eec(), a)) {
947 AinA = true;
948 }
949 if (AssocTools::containsKey(b->eec(), b)) {
950 BinB = true;
951 }
952 if (AssocTools::containsKey(a->eec(), b)) {
953 BinA = true;
954 }
955 if (AssocTools::containsKey(b->eec(), a)) {
956 AinB = true;
957 }
958 //std::cerr << "AinA=" << AinA << ", BinB=" << BinB <<", AinB=" << AinB
959 // << ", BinA=" << BinA << std::endl;
960 if ((a->isLoopEntryNode() || a->isPredicateMoveNode())
961 && (b->isMoveNode() && !b->isPredicateMoveNode())
962 && AinA == true) {
963 if (a->isLastNode()) {
964 return B_BEFORE_A;
965 }
966 return ANY_ORDER;
967 }
968 if ((b->isLoopEntryNode() || b->isPredicateMoveNode())
969 && (a->isMoveNode() && !a->isPredicateMoveNode())
970 && BinB == true) {
971 if (b->isLastNode()) {
972 return A_BEFORE_B;
973 }
974 return ANY_ORDER;
975 }
976 if ((a->isLoopEntryNode() || a->isPredicateMoveNode())
977 && (b->isLoopEntryNode() || b->isPredicateMoveNode())
978 && AinA == true && BinB == true) {
979 if (a->isLastNode()) {
980 return B_BEFORE_A;
981 }
982 if (b->isLastNode()) {
983 return A_BEFORE_B;
984 }
985 return ANY_ORDER;
986 }
987 if ((a->isLoopEntryNode() || a->isPredicateMoveNode())
988 && (b->isMoveNode() && !b->isPredicateMoveNode())
989 && AinA == false) {
990 return B_BEFORE_A;
991 }
992 if ((b->isLoopEntryNode() || b->isPredicateMoveNode())
993 && (a->isMoveNode() && !a->isPredicateMoveNode())
994 && BinB == false) {
995 return A_BEFORE_B;
996 }
997 if ((a->isLoopEntryNode() || a->isPredicateMoveNode())
998 && (b->isLoopEntryNode() || b->isPredicateMoveNode())
999 && AinA == false && BinB == true) {
1000 return B_BEFORE_A;
1001 }
1002 if ((b->isLoopEntryNode() || b->isPredicateMoveNode())
1003 && (a->isLoopEntryNode() || a->isPredicateMoveNode())
1004 && AinA == true && BinB == false) {
1005 return A_BEFORE_B;
1006 }
1007 if ((a->isLoopEntryNode() || a->isPredicateMoveNode())
1008 && (b->isLoopEntryNode() || b->isPredicateMoveNode())
1009 && AinA == false && BinB == false) {
1010 //std::cerr << "\tUnorderable 1" << std::endl;
1011 return UNORDERABLE;
1012 }
1013 if ((a->isRegionNode() && AinB == true)
1014 && (b->isMoveNode() ||
1015 b->isLoopEntryNode() ||
1016 b->isPredicateMoveNode())){
1017 return B_BEFORE_A;
1018 }
1019 if ((b->isRegionNode() && BinA == true)
1020 && (a->isMoveNode() ||
1021 a->isLoopEntryNode() ||
1022 a->isPredicateMoveNode())){
1023 return A_BEFORE_B;
1024 }
1025 if ((a->isRegionNode() && AinB == false)
1026 && (b->isLoopEntryNode() || b->isPredicateMoveNode())
1027 && AinB == false) {
1028 //std::cerr << "\tUnorderable 2" << std::endl;
1029 return UNORDERABLE;
1030 }
1031 if ((b->isRegionNode() && BinA == false)
1032 && (a->isLoopEntryNode() || a->isPredicateMoveNode())
1033 && BinA == false) {
1034 //std::cerr << "\tUnorderable 3" << std::endl;
1035 return UNORDERABLE;
1036 }
1037 if ((a->isRegionNode() && AinB == false)
1038 && (b->isRegionNode() && BinA == true)) {
1039 return B_BEFORE_A;
1040 }
1041 if ((b->isRegionNode() && BinA == false)
1042 && (a->isRegionNode() && AinB == true)) {
1043 return A_BEFORE_B;
1044 }
1045 if ((a->isRegionNode() && AinB == false)
1046 && (b->isRegionNode() && BinA == false)) {
1047 return UNORDERABLE;
1048 }
1049 if ((a->isLoopCloseNode() && AinB == true)
1050 && (b->isMoveNode() || b->isPredicateMoveNode() || b->isLoopEntryNode()
1051 || b->isRegionNode())) {
1052 return B_BEFORE_A;
1053 }
1054 if ((b->isLoopCloseNode() && BinA == true)
1055 && (a->isMoveNode() || a->isPredicateMoveNode() || a->isLoopEntryNode()
1056 || a->isRegionNode())) {
1057 return A_BEFORE_B;
1058 }
1059 if ((a->isLoopCloseNode() && AinB == false)
1060 && (b->isPredicateMoveNode() || b->isLoopEntryNode()
1061 || b->isRegionNode())) {
1062 //std::cerr << "\tUnorderable 5" << std::endl;
1063 return UNORDERABLE;
1064 }
1065 if ((b->isLoopCloseNode() && BinA == false)
1066 && (a->isPredicateMoveNode() || a->isLoopEntryNode()
1067 || a->isRegionNode())) {
1068 //std::cerr << "\tUnorderable 6" << std::endl;
1069 return UNORDERABLE;
1070 }
1071 /// FIXME:
1072 /// Unique region node rule is broken when creating loop
1073 /// entry nodes (removing loop back edge) and creating new region for
1074 /// incoming edges into loop entry - there can be another region
1075 /// which already has same set of dependencies and loop entry was
1076 /// supposed to be child of that, but was not. Problem with detection
1077 /// of subsets of dependencies when creating region nodes!
1078 if ((a->isRegionNode() && AinB == true)
1079 && (b->isRegionNode() && BinA == true)) {
1080 Application::logStream() << (boost::format(
1081 "Found two regions with identical control dependencies. "
1082 "Known issue with CDG detection not reusing regions.\n")).str();
1083 if (a->isLastNode()) {
1084 return B_BEFORE_A;
1085 }
1086 if (b->isLastNode()) {
1087 return A_BEFORE_B;
1088 }
1089 return ANY_ORDER;
1090 }
1091 return ERROR;
1092}
1093
1094/**
1095 * Returns entry node of the graph.
1096 * @return Entry node
1097 */
1100 if (entryNode_ == NULL ) {
1101 throw ModuleRunTimeError(
1102 __FILE__, __LINE__, __func__,
1103 "Trying to get entry node before it was defined!");
1104 }
1105 return *entryNode_;
1106}
1107
1108/**
1109 * Helper function to compute actual region information for a node.
1110 * Called several times for a case when there are loop entry nodes
1111 * detected.
1112 *
1113 * @param node Node for which to compute region info
1114 * @param cdg Filtered PDG graph with only control dependence edges
1115 * @param finalNodesInfo stores actual computed region info
1116 */
1117void
1119 Node* node,
1120 FilteredCDG& cdg,
1121 Node::NodesInfo& finalNodesInfo){
1122
1124 std::vector<Node::NodesInfo> tmpResult;
1125 /// Find all incoming control dependence edges
1126 FilteredInEdgePair edges = boost::in_edges(des, cdg);
1127 for (FilteredInEdgeIter ei = edges.first;
1128 ei != edges.second;
1129 ++ei) {
1130 Node* previous = cdg[boost::source(*ei, cdg)];
1131 /// There is no Region info for Entry node
1132 if (previous->isRegionNode()
1133 || previous->isLoopEntryNode()) {
1134 if (previous->region().size() == 0 &&
1135 ! (previous == entryNode_)) {
1136 /// If parent's region is not yet computed (should be btw)
1137 /// compute it before continuing.
1138 Node::NodesInfo addedNodesInfo;
1139 regionHelper(previous, cdg, addedNodesInfo);
1140 for (Node::NodesInfo::iterator k = addedNodesInfo.begin();
1141 k != addedNodesInfo.end();
1142 k++) {
1143 previous->addToRegion(**k);
1144 }
1145
1146/* writeToDotFile(name() + "_broken.dot");
1147 TCEString msg = "Parent " + previous->toString();
1148 msg += " of node " + (*iter)->toString();
1149 msg += " has empty region information!";
1150 msg += " Procedure has " + Conversion::toString(nodeCount());
1151 msg += " nodes.";
1152 throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);*/
1153 }
1154 /// region(node,parent) == region(parent) U children(parent)
1155 Node::NodesInfo tmp = previous->region();
1156 FilteredOutEdgePair edges =
1157 boost::out_edges(descriptor(*previous), cdg);
1158 for (FilteredOutEdgeIter ei = edges.first;
1159 ei != edges.second;
1160 ++ei) {
1161 Node* testedNode = cdg[boost::target(*ei, cdg)];
1162 tmp.insert(testedNode);
1163 }
1164 tmpResult.push_back(tmp);
1165 } else if (previous->isPredicateMoveNode()){
1166 /// region(node,parent) == region(parent)
1167 Node::NodesInfo tmp = previous->region();
1168 tmpResult.push_back(tmp);
1169 } else {
1170 assert(previous->isLoopCloseNode());
1171 }
1172 }
1173 /// fill in final region info with info from first of parents
1174 if (tmpResult.size() > 0) {
1175 finalNodesInfo.insert(
1176 tmpResult[0].begin(), tmpResult[0].end());
1177 }
1178 /// region(node) = intersection(region(node,parent(node)))
1179 /// for all parents. finalNodesInfo is already initialized from
1180 /// counter 0
1181 for (unsigned int l = 1; l < tmpResult.size(); l++) {
1182 Node::NodesInfo storeResult;
1184 finalNodesInfo, tmpResult[l], storeResult);
1185 finalNodesInfo.swap(storeResult);
1186 storeResult.clear();
1187 }
1188}
1189
1190/**
1191 * "Sorts" all the child nodes of a region in topological order based on
1192 * their control and data dependencies.
1193 *
1194 * @param regionNode Region/Predicate node who's child nodes to process
1195 * @param filteredCDG Control Dependence subraph
1196 */
1197void
1199 Node* regionNode,
1200 FilteredCDG& filteredCDG) {
1201
1202 /// Get all child nodes of region node
1203 NodeDescriptor nodeDes = descriptor(*regionNode);
1204 FilteredOutEdgePair edges = boost::out_edges(nodeDes, filteredCDG);
1205 /// Store all child nodes, we will need to collect all edges
1206 /// to and from subgraph rooted by region
1207 NodeSet subgraphNodes;
1208 subgraphNodes.insert(regionNode);
1209 std::vector<std::pair<Node*, Node*> > newEdges;
1210 std::vector<std::pair<Node*, Node*> > unorderable;
1211 for (FilteredOutEdgeIter ei1 = edges.first;
1212 ei1 != edges.second;
1213 ++ei1) {
1214 NodeDescriptor des = boost::target(*ei1, filteredCDG);
1215 Node* node1 = graph_[des];
1216 subgraphNodes.insert(node1);
1217
1218 /// node1 will be compared against all the other previously untested
1219 /// nodes
1220 FilteredOutEdgeIter ei2 = ei1;
1221 ei2++;
1222 for (; ei2 != edges.second; ++ei2) {
1223 Node* node2 = graph_[boost::target(*ei2, filteredCDG)];
1224 /// Test relation between siblings, should never return ERROR!
1225 CompareResult result = compareSiblings(node1, node2);
1226 switch(result) {
1227 case ERROR:
1228 if(Application::verboseLevel() > 0) {
1229 writeToDotFile(name() + "_pdg_broken.dot");
1230 node1->printRelations();
1231 node2->printRelations();
1232 }
1233 throw ModuleRunTimeError(
1234 __FILE__, __LINE__, __func__,
1235 (boost::format(
1236 "Ordering error for A='%s' and B='%s'")
1237 % node1->toString() % node2->toString()).str());
1238 case A_BEFORE_B:
1239 newEdges.push_back(std::pair<Node*, Node*>(node1, node2));
1240 break;
1241 case B_BEFORE_A:
1242 newEdges.push_back(std::pair<Node*, Node*>(node2, node1));
1243 break;
1244 case UNORDERABLE:
1245 if(Application::verboseLevel() >= 0) {
1246 Application::logStream() << (boost::format(
1247 "Nodes (%s) and (%s) can not "
1248 "be put into any order.\n")
1249 % node1->toString()% node2->toString()).str();
1250 }
1251 unorderable.push_back(
1252 std::pair<Node*, Node*>(node1, node2));
1253 break;
1254 case ANY_ORDER:
1255 break;
1256 }
1257
1258 }
1259 }
1260 /// Move/copy edges between nodes "inside" subgraph and nodes outside the
1261 /// subgraph
1262 moveDDGedges(*regionNode, subgraphNodes, filteredCDG);
1263 /// Add actual control dependence edges for serialization
1264 for (unsigned int i = 0; i < newEdges.size(); i++) {
1266 connectNodes(*newEdges[i].first, *newEdges[i].second, *direction);
1267 }
1268 newEdges.clear();
1269 //return;
1270 /// Nodes of subgraph without it's root
1272 regionNode, subgraphNodes, graph_);
1273 /// No loop close edges or DDG loop edges
1274 BackFilter<Graph> backFilter(graph_);
1275 /// Create filtered graph
1276 Subgraph sub = Subgraph(graph_, backFilter, subgraph);
1277 /// Sort nodes of subgraph topologically
1278 std::vector<NodeDescriptor> sorted;
1279 try {
1280 boost::topological_sort(sub, std::back_inserter(sorted));
1281 } catch (boost::not_a_dag & x) {
1282 /// In case topological sort fails with graph not being DAG
1283 /// Write it out
1285 TCEString outName =
1286 name() + Conversion::toString(wrongCounter_) + "_notDAG.dot";
1287 wrongCounter_++;
1288 std::ofstream output(outName.c_str());
1289 boost::write_graphviz(output, sub,lb,lb);
1290
1291 Application::logStream() << (boost::format(
1292 "Topological sort of %s(%s) failed.\n"
1293 "Most likely loop is present.\n")
1294 % name() % regionNode->toString()).str();
1295 return;
1296 } catch (...) {
1297 Application::logStream() << (boost::format(
1298 "Topological sort of %s(%s) failed.\n"
1299 "Most likely loop is present.\n")
1300 % name() % regionNode->toString()).str();
1301 return;
1302 }
1303
1304 BasicBlockNode* lastBB = NULL;
1305 std::vector<BasicBlockNode*> leafBlocks;
1306 bool changeBB = false;
1307
1308 for (std::vector<NodeDescriptor>::reverse_iterator iter = sorted.rbegin();
1309 iter != sorted.rend(); iter++) {
1310 Node* accessedNode = graph_[*iter];
1311 BasicBlockNode* bb = NULL;
1312
1313 if(accessedNode->newFirstBB() != NULL) {
1314 // Child node is region or predicate and already has BBs
1315 // we will just link them
1316 bb = accessedNode->newFirstBB();
1317 if (regionNode->newFirstBB() == NULL) {
1318 assert(leafBlocks.size() == 0 && lastBB == NULL);
1319 /// It is first block so we add it as new first also to parent
1320 regionNode->setNewFirstBB(bb);
1321 }
1322 /// There was some previous node tested, we have to add edges
1323 if (lastBB != NULL) {
1324 assert(leafBlocks.size() == 0);
1325 /// Previously, statements created single basic block
1326 /// so we add edge from that to this one
1327 ControlFlowEdge* edge = NULL;
1328 /// If previous block ended with call we add CALL type of edge
1329 if (changeBB == true) {
1330 changeBB = false;
1331 edge = new
1334 } else {
1335 edge = new ControlFlowEdge();
1336 }
1337/* Application::logStream() << (boost::format(
1338 "Adding edge from lastBB %s to %s in %s\n")
1339 % lastBB->toString() % bb->toString() % name()).str();*/
1340 newCFG_->connectNodes(*lastBB, *bb, *edge);
1341 std::cerr << "Adding for lastBB != NULL" << std::endl;
1342 createJump(lastBB, bb);
1343 /// clear lastBB, the edge was already added
1344/* Application::logStream() << (boost::format(
1345 "\tChanged lastbb from %s to NULL\n")
1346 % lastBB->toString()).str();*/
1347 lastBB = NULL;
1348 leafBlocks.clear();
1349 }
1350/* Application::logStream() << (boost::format(
1351 "\tStart adding leaf blocks for %s in region %s with bb %s\n")
1352 % accessedNode->toString() % regionNode->toString()
1353 % bb->toString()).str();*/
1354 addLeafEdges(leafBlocks, bb);
1355 /// leafs were processed, this node should have some leafs as well
1356 leafBlocks.clear();
1357 leafBlocks = accessedNode->leafBlocks();
1358 /// if we got this far, lastBB should be NULL
1359 assert(lastBB == NULL);
1360 /// Accessed node is loop entry, we add edge from corresponding
1361 /// loop close node to it.
1362 if (accessedNode->isLoopEntryNode()) {
1363 processLoopEntry(accessedNode, bb);
1364 }
1365 } else {
1366 /// We found single statement, time to add it to basic block
1367 if (lastBB == NULL || changeBB == true) {
1368 /// Time to create new BB
1369 TTAProgram::BasicBlock* block =
1371 insCount_++;
1372 bb = new BasicBlockNode(*block);
1373/* Application::logStream() << (boost::format(
1374 "Create new BB %s in %s for %s\n")
1375 % bb->toString() % regionNode->toString() %
1376 accessedNode->toString()).str();*/
1377 newCFG_->addNode(*bb);
1378 if (regionNode->newFirstBB() == NULL) {
1379 /// We just created first BB for children of region
1380 /// so we set it as first BB
1381 regionNode->setNewFirstBB(bb);
1382 }
1383 /// Previous BB ended with CALL, so we link it to new one
1384 /// with call edge
1385 if (changeBB == true && lastBB != NULL) {
1386 changeBB = false;
1390 newCFG_->connectNodes(*lastBB, *bb, *edge);
1391 assert(leafBlocks.size() == 0);
1392 }
1393 /// Block just created is current lastBB
1394/* Application::logStream() << (boost::format(
1395 "\tChanged lastbb to %s\n")
1396 %bb->toString()).str();*/
1397 lastBB = bb;
1398 }
1399 }
1400 if(accessedNode->isMoveNode()
1401 && accessedNode->moveNode().isMove()) {
1402 TTAProgram::Instruction* newIns =
1404 newIns->addMove(accessedNode->moveNode().movePtr());
1405 lastBB->basicBlock().add(newIns);
1406 insCount_++;
1407 if (accessedNode->moveNode().move().isCall()) {
1408 changeBB = true;
1409 }
1410 if (leafBlocks.size() > 0) {
1411/* Application::logStream() << (boost::format(
1412 "\tStart adding leaf blocks: %s in region %s with bb %s\n")
1413 % accessedNode->toString() % regionNode->toString()
1414 % bb->toString()).str();*/
1415 addLeafEdges(leafBlocks, bb);
1416 /// Leaf blocks were added, we can clear them
1417 leafBlocks.clear();
1418 } else {
1419 if (Application::verboseLevel() > 2) {
1421 (boost::format(" Undetected case! %s inside %s\n")
1422 % accessedNode->toString() % regionNode->toString()
1423 ).str();
1424 }
1425 }
1426 }
1427 }
1428 if (leafBlocks.size() > 0) {
1429 regionNode->addLeafBlocks(leafBlocks);
1430 leafBlocks.clear();
1431 }
1432 if (lastBB != NULL) {
1433/* Application::logStream() << (boost::format(
1434 "Add last bb %s as a leaf to %s\n")
1435 % lastBB->toString() % regionNode->toString()).str();*/
1436 regionNode->addLeafBlock(lastBB);
1437 }
1438 if(regionNode == entryNode_) {
1439 processEntry(regionNode->newFirstBB());
1440 }
1441 unorderable.clear();
1442}
1443
1444/**
1445 * Computes relation between every pair of nodes in a graph that has
1446 * common parent.
1447 *
1448 * @param orderMap Post order map of a graph
1449 * @parem filteredCDG Filtered PDG with only control dependence edges
1450 */
1451void
1453 const PDGOrderMap& orderMap,
1454 FilteredCDG& filteredCDG) {
1455
1456 /// Process nodes in post order, guarantees child region/loopEntry/predicate
1457 /// nodes will be processed before their parent
1458 int mapSize = orderMap.size();
1459
1460 cdg_->writeToDotFile(name() + "_originalCDG.dot");
1461
1463 for (int i = 0; i < mapSize; i++) {
1464 NodeDescriptor des =
1466 orderMap, i);
1467 Node* node = graph_[des];
1468 /// MoveNodes are skipped here, they are always children of region
1469 if (node->isRegionNode()
1470 || node->isLoopEntryNode()) {
1471 processRegion(node, filteredCDG);
1472 continue;
1473 }
1474 if (node->isPredicateMoveNode()){
1475 processPredicate(node, filteredCDG);
1476 continue;
1477 }
1478 if (node->isLoopCloseNode()) {
1480 continue;
1481 }
1482 }
1483 newCFG_->writeToDotFile(name() + "_newCFG.dot");
1484 writeToDotFile(name() + "_newPDG.dot");
1485
1486}
1487
1488/**
1489 * Helper method to move/copy DDG edges that connected subraph nodes with rest
1490 * of the graph to the root node of subgraph
1491 *
1492 * @param rootNode Root node of subgraph
1493 * @param subgraphNodes Nodes of the subgraph to test
1494 * @param filteredCDG Filtered cdg graph, containing only control dependence
1495nodes
1496 */
1497void
1499 Node& root,
1500 NodeSet& subgraphNodes,
1501 FilteredCDG& filteredCDG) {
1502
1503 for (NodeSet::iterator iter = subgraphNodes.begin();
1504 iter != subgraphNodes.end();
1505 iter++) {
1506 /// Do not process root of a subtree, it is child of other node
1507 /// and will be processed later
1508 if ((*iter) == &root) {
1509 continue;
1510 }
1511 /// Test if target is region, predicate or loop node,
1512 /// those prefer copies
1513 bool copyInsteadOfMove = false;
1514 if (!(*iter)->isMoveNode()) {
1515 /// gets incoming control dependence edges of node
1516 /// more then one edge means node is reachable from several places
1517 int parentCount = boost::in_degree(descriptor(**iter), filteredCDG);
1518 if (parentCount > 1) {
1519 copyInsteadOfMove = true;
1520 }
1521 }
1522 /// Deal with incoming edges
1523 EdgeSet inputs = inEdges(**iter);
1524 for (EdgeSet::iterator ein = inputs.begin();
1525 ein != inputs.end();
1526 ein++) {
1527 /// No need to deal with control dependence edges or data dependence
1528 /// that had been "fixed" - meaning they are between nodes of same
1529 /// subtree (including edges between root of subtree and child node)
1530 if (!(*ein)->isDataDependence() || (*ein)->fixed()) {
1531 continue;
1532 }
1533 Node* tail = &tailNode(**ein);
1534 if (!AssocTools::containsKey(subgraphNodes, tail)) {
1535 Edge* testedEdge = *ein;
1536 EdgeSet inputEdges = connectingEdges(*tail, root);
1537 bool duplicateEdge = false;
1538 for (EdgeSet::iterator testIter = inputEdges.begin();
1539 testIter != inputEdges.end();
1540 testIter ++) {
1541 if (!(*testIter)->isDataDependence()) {
1542 continue;
1543 }
1544 if ((testedEdge->dataDependenceEdge().dependenceType() ==
1545 (*testIter)->dataDependenceEdge().dependenceType())
1546 &&
1547 (testedEdge->dataDependenceEdge().edgeReason() ==
1548 (*testIter)->dataDependenceEdge().edgeReason())) {
1549 /// Edges with identical properties already exists
1550 /// no need to copy or move, just remove edge
1551 duplicateEdge = true;
1552 }
1553 }
1554 if (copyInsteadOfMove && !duplicateEdge) {
1555 /// Creates copy of edge from outside subgraph
1556 /// to root of the graph
1557 copyInEdge(root, **ein, tail);
1558 } else if (duplicateEdge) {
1559 /// Edge is duplicate of already existing dependence
1560 removeEdge(**ein);
1561 } else {
1562 /// Moves edge from outside the subgraph to target root
1563 moveInEdge(**iter, root, **ein);
1564 }
1565 } else {
1566 /// Edge between nodes in subtree
1567 (*ein)->setFixed();
1568 }
1569 }
1570 /// Deal with outgoing edges
1571 EdgeSet outputs = outEdges(**iter);
1572 for (EdgeSet::iterator eout = outputs.begin();
1573 eout != outputs.end();
1574 eout++) {
1575 /// No need to deal with control dependence edges or data dependence
1576 /// that had been "fixed" - meaning they are between nodes of same
1577 /// subtree (including edges between root of subtree and child node)
1578 if (!(*eout)->isDataDependence() || (*eout)->fixed()) {
1579 continue;
1580 }
1581 Node* head = &headNode(**eout);
1582 if (!AssocTools::containsKey(subgraphNodes, head)) {
1583 Edge* testedEdge = *eout;
1584 EdgeSet outputEdges = connectingEdges(root, *head);
1585 bool duplicateEdge = false;
1586 for (EdgeSet::iterator testIter = outputEdges.begin();
1587 testIter != outputEdges.end();
1588 testIter ++) {
1589 if (!(*testIter)->isDataDependence()) {
1590 continue;
1591 }
1592 if ((testedEdge->dataDependenceEdge().dependenceType() ==
1593 (*testIter)->dataDependenceEdge().dependenceType())
1594 &&
1595 (testedEdge->dataDependenceEdge().edgeReason() ==
1596 (*testIter)->dataDependenceEdge().edgeReason())) {
1597 /// Edges with identical properties already exists
1598 /// no need to copy or move, just remove edge
1599 duplicateEdge = true;
1600 }
1601 }
1602 if (copyInsteadOfMove && !duplicateEdge) {
1603 /// Creates copy of edge from outside subgraph
1604 /// to root of the graph if such edge does not exists
1605 copyOutEdge(root, **eout, head);
1606 } else if (duplicateEdge) {
1607 /// Edge is duplicate of already existing dependence
1608 removeEdge(**eout);
1609 } else {
1610 /// Moves edge from outside the subgraph to target root
1611 moveOutEdge(**iter, root, **eout);
1612 }
1613 } else {
1614 /// Edge between nodes in subtree
1615 (*eout)->setFixed();
1616 }
1617 }
1618 }
1619}
1620
1621/**
1622 * Copies Region and EEC information from CDG nodes to PDG. Only used if
1623 * "preprocessing" is done via CDG analysis. Copies also component members.
1624 *
1625 * @param cDNodeToPNode Map between CDG nodes and PDG nodes
1626 * @param bBlockToCDNode Map between basic blocks and CDG nodes
1627 * @param moveToPNode Map between move nodes and their PDG equivalents
1628 * @param moveToCD Map between CDG node and all PDG equivalents of it's content
1629 */
1630void
1632 ControlToProgram& cDNodeToPNode,
1633 BBToCD& bBlockToCDNode,
1634 MoveNodeToPDGNode& /*moveToPNode*/,
1635 MovesInCD& moveToCD) {
1636
1637 int componentCount = cdg_->componentCount();
1638 strongComponents_.resize(componentCount);
1639
1640 for (int i = 0; i < nodeCount(); i++) {
1642 ControlDependenceNode* cNode = NULL;
1643
1644 /// Find source of region and eec. In case node is move or predicate
1645 /// have to find parent CDG node
1646 if (node == entryNode_) {
1647 /// No region or eec info in entry
1648 continue;
1649 }
1650 if (node->isRegionNode()
1651 || node->isLoopEntryNode()
1652 || node->isLoopCloseNode()) {
1653 /// For non basic block/predicate nodes, we copied them so
1654 /// they will also be in 'region' and 'eec'.
1655 /// Set component info for nodes that are part of loop as well
1656 cNode = &node->cdgNode();
1657 if (cNode->component() != -1) {
1658 node->setComponent(cNode->component());
1659 strongComponents_[node->component()].insert(node);
1660 }
1661 } else {
1662 const BasicBlockNode* BB =
1663 &ddg_->getBasicBlockNode(node->moveNode());
1664 if (MapTools::containsKey(bBlockToCDNode, BB)) {
1665 cNode =
1667 bBlockToCDNode, BB);
1668 } else {
1669 throw InvalidData(__FILE__, __LINE__, __func__,
1670 "No CD node for basic block!" + BB->toString());
1671 }
1672 /// If cdg node is basic block or predicate, all moves inside
1673 /// will be part of same component
1674 if (cNode->component() != -1) {
1675 std::vector<Node*> nodesInBB = moveToCD[cNode];
1676 int currentComponent = cNode->component();
1677 for (unsigned int i = 0; i < nodesInBB.size(); i++) {
1678 strongComponents_[currentComponent].insert(
1679 nodesInBB[i]);
1680 nodesInBB[i]->setComponent(currentComponent);
1681 }
1682 }
1683 }
1684
1686 for (ControlDependenceNode::NodesInfo::iterator iter = rInfo.begin();
1687 iter != rInfo.end();
1688 iter++) {
1689 /// If destination in 'region' is CDG node, add it
1690 if ((*iter)->isRegionNode()
1691 || (*iter)->isLoopCloseNode()
1692 || (*iter)->isLoopEntryNode()) {
1693 Node* target = cDNodeToPNode[*iter];
1694 node->addToRegion(*target);
1695 } else {
1696 /// If destination in 'region' is BB, add all the moves in it
1697 std::vector<Node*> nodesInBB = moveToCD[*iter];
1698 for (unsigned int i = 0; i < nodesInBB.size(); i++) {
1699 node->addToRegion(*nodesInBB[i]);
1700 }
1701 }
1702 }
1704 if (cNode->isPredicateNode() && !node->isPredicateMoveNode()) {
1705 /// We have node which was in predicate basic block but is not
1706 /// the actual predicate move node.
1707 /// We have to copy "shadow" eec information
1708 eecInfo = cNode->pseudoPredicateEEC();
1709 } else {
1710 /// any other type of node should have same eec information as it's
1711 /// CDG counterpart or basic block it belonged to
1712 eecInfo = cNode->eec();
1713 /// If node was in predicate basic block and is predicate we also
1714 /// test if it is lastNode and set info
1715 if (cNode->isPredicateNode()
1716 && node->isPredicateMoveNode()
1717 && cNode->isLastNode()) {
1718 node->setLastNode();
1719 }
1720 }
1721 for (ControlDependenceNode::NodesInfo::iterator iter =
1722 eecInfo.begin(); iter != eecInfo.end(); iter++) {
1723 if ((*iter)->isRegionNode()
1724 || (*iter)->isLoopCloseNode()
1725 || (*iter)->isLoopEntryNode()) {
1726 Node* target = cDNodeToPNode[*iter];
1727 node->addToEEC(*target);
1728 } else {
1729 std::vector<Node*> nodesInBB = moveToCD[*iter];
1730 for (unsigned int i = 0; i < nodesInBB.size(); i++) {
1731 node->addToEEC(*nodesInBB[i]);
1732 }
1733 }
1734 }
1735 }
1736}
1737
1738/**
1739 * When entry node is found during serialization, the artificial Entry and Exit
1740 * nodes are added to CFG. There is added edge from Entry to first BB and
1741 * All leaf nodes will have edge to the exit.
1742 */
1743void
1745 BasicBlockNode* newEntry = new BasicBlockNode(0, 0, true, false);
1746 newCFG_->addNode(*newEntry);
1748 newCFG_->connectNodes(*newEntry, *firstBB, *edge);
1749 newCFG_->addExit();
1750// Application::logStream() << (boost::format(
1751// "Create new Entry %s for %s\n")
1752// % newEntry->toString() % firstBB->toString()).str();
1753}
1754
1755/**
1756 * Process predicate node of the graph.
1757 *
1758 * Add edges from predicate to one or two child region nodes and fill in
1759 * next basic block with last BB of first child region and fall through
1760 * BB with last BB of second child (if exists), otherwise predicate BB
1761 * itself. Also moves DDG edges between child nodes and out of subtree
1762 * to point to predicate for topological sorting of region where predicate
1763 * itself belongs.
1764 * @param predicate Predicate node to process
1765 * @param filteredCDG Filtered graph from where we get child nodes of predicate
1766 */
1767void
1769 Node* predicate,
1770 FilteredCDG& filteredCDG) {
1771
1772 /// Get all child nodes of predicate node
1773 NodeDescriptor nodeDes = descriptor(*predicate);
1774 FilteredOutEdgePair edges = boost::out_edges(nodeDes, filteredCDG);
1775 /// Store all child nodes, we will need to collect all edges
1776 /// to and from subgraph rooted by predicate
1777 NodeSet subgraphNodes;
1778 subgraphNodes.insert(predicate);
1779 /// Create basic block with predicate, it will be also first to
1780 /// execute
1782 BasicBlockNode* bb = new BasicBlockNode(*block);
1783// Application::logStream() << (boost::format(
1784// "Create new Predicate BB %s for %s\n")
1785// % bb->toString() % predicate->toString()).str();
1786
1787 newCFG_->addNode(*bb);
1789 newIns->addMove(predicate->moveNode().movePtr());
1790 TTAProgram::Terminal& guardReg =
1791 predicate->moveNode().move().destination();
1792
1793 bb->basicBlock().add(newIns);
1794 insCount_++;
1795 predicate->setNewFirstBB(bb);
1796
1797 bool hasTrue = false;
1798 bool hasFalse = false;
1799 for (FilteredOutEdgeIter ei1 = edges.first;
1800 ei1 != edges.second;
1801 ++ei1) {
1802 Edge* edge = graph_[*ei1];
1803 if (edge->isArtificialControlDependence()) {
1804 continue;
1805 }
1806 NodeDescriptor des = boost::target(*ei1, filteredCDG);
1807 Node* node = graph_[des];
1808 subgraphNodes.insert(node);
1809
1810 /// In case one of branches had only single
1811 /// absolute jump to "exit" of procedure, there
1812 /// is no child basic block
1813 if(node->newFirstBB() != NULL) {
1814 ControlFlowEdge::CFGEdgePredicate predicateValue =
1816 if (edge->controlDependenceEdge().isTrueEdge()) {
1817 predicateValue = ControlFlowEdge::CFLOW_EDGE_TRUE;
1818 hasTrue = true;
1819 } else {
1820 predicateValue = ControlFlowEdge::CFLOW_EDGE_FALSE;
1821 hasFalse = true;
1822 }
1823 ControlFlowEdge *newEdge = new ControlFlowEdge(predicateValue);
1824/* Application::logStream() << (boost::format(
1825 "Adding edge for predicate %s to %s in %s\n")
1826 % bb->toString() % node->newFirstBB()->toString() % name()).str();*/
1828 *bb, *node->newFirstBB(), *newEdge);
1829 std::cerr << "Adding for predicate" << std::endl;
1830 createJump(bb, node->newFirstBB(), &guardReg, predicateValue);
1831 //predicate->addLeafBlocks(node->leafBlocks());
1832 } else {
1833 if(boost::out_degree(des, filteredCDG) != 0) {
1834 TCEString msg = (boost::format(
1835 "Found a node without first BB set. %s for predicate %s"
1836 " in procedure %s\n")
1837 % node->toString() % predicate->toString() % name()).str();
1838 throw InvalidData(__FILE__, __LINE__, __func__, msg);
1839 }
1840 }
1841 if (node->isLoopCloseNode()) {
1842 assert(node->newFirstBB() != NULL);
1843 //predicate->setLastNode();
1844 }
1845 if (node->isLoopEntryNode()) {
1846 processLoopEntry(node, node->newFirstBB());
1847 }
1848 }
1849 /// One of the outgoing edges is missing, we will have to add edge
1850 /// from predicate itself to next BB
1851 if (!(hasTrue && hasFalse)) {
1852 predicate->addLeafBlock(bb);
1853 }
1854 /// Move/copy edges between nodes "inside" subgraph and nodes outside the
1855 /// subgraph
1856 moveDDGedges(*predicate, subgraphNodes, filteredCDG);
1857}
1858
1859/**
1860 * Add edges from 'leaf' blocks of a subgraph to the basic block
1861 *
1862 * @param leafBlocks vector of basic blocks to add
1863 * @param bb Basic block to which the edges will point to
1864 */
1865void
1867 std::vector<BasicBlockNode*> leafBlocks,
1868 BasicBlockNode* bb) {
1869 for (unsigned int i = 0; i < leafBlocks.size(); i++) {
1870 /// One previously tested was predicate or region
1871 /// we have to add edges from all of their leafs to this block
1873 newCFG_->outEdges(*leafBlocks[i]);
1876 /// Predicate had only one outgoing edge, we add second with
1877 /// inverse value
1878 for(ControlFlowGraph::EdgeSet::iterator cfe = edges.begin();
1879 cfe != edges.end(); cfe++) {
1880 if ((*cfe)->isTrueEdge()) {
1882 break;
1883 }
1884 if ((*cfe)->isFalseEdge()) {
1886 break;
1887 }
1888 }
1889 if (newCFG_->connectingEdges(*leafBlocks[i], *bb).size() == 0) {
1890 ControlFlowEdge* edge = new ControlFlowEdge(predicate);
1891 Application::logStream() << (boost::format(
1892 "Adding leaf edge from %s to %s in %s\n")
1893 % leafBlocks[i]->toString() % bb->toString() % name()).str();
1894 newCFG_->connectNodes(*leafBlocks[i], *bb, *edge);
1895 std::cerr << "Adding for leaf edges" << std::endl;
1896 createJump(leafBlocks[i], bb);
1897 }
1898 }
1899 leafBlocks.clear();
1900}
1901
1902void
1905 BasicBlockNode* bb = new BasicBlockNode(*block);
1906 newCFG_->addNode(*bb);
1908 /// Add empty instruction, actual jump move will be created when
1909 /// we process corresponding loop entry
1910 bb->basicBlock().add(newIns);
1911 insCount_++;
1912 node->setNewFirstBB(bb);
1913 /*NodeSet predecessorsNodes = predecessors(*node);
1914 for (NodeSet::iterator iter = predecessorsNodes.begin();
1915 iter != predecessorsNodes.end(); iter++) {
1916 (*iter)->setLastNode();
1917 }*/
1918/* Application::logStream() << (boost::format(
1919 "Creating BB %s for loop close %s")
1920 % bb->toString() % node->toString()).str();*/
1921}
1922
1923void
1925 /// Add edge from loop close node to corresponding loop entry
1926 if (bb == NULL) {
1927 return;
1928 }
1929 NodeSet inputs = predecessors(*node);
1930 for(NodeSet::iterator ni = inputs.begin(); ni != inputs.end();
1931 ni++) {
1932 if((*ni)->isLoopCloseNode()
1933 && (*ni)->newFirstBB() != NULL
1934 && (*ni)->component() == node->component()) {
1935/* Application::logStream() << "Adding loop edge "
1936 << (*ni)->newFirstBB()->toString() << " to "
1937 << bb->toString() << std::endl;*/
1939 edge->setBackEdge();
1940 newCFG_->connectNodes(*(*ni)->newFirstBB(), *bb, *edge);
1941 std::cerr << "Adding for loop entry" << std::endl;
1942 createJump((*ni)->newFirstBB(), bb);
1943 }
1944 }
1945}
1946
1947void
1949#if 0
1951 /// Create filtered graph
1952 CFGSubgraph sub = CFGSubgraph(*newCFG_, backCFGFilter);
1953 /// Sort nodes of subgraph topologically
1954 std::vector<ControlFlowGraph::NodeDescriptor> sorted;
1955 try {
1956 boost::topological_sort(*newCFG_, std::back_inserter(sorted));
1957 } catch (...) {
1958 Application::logStream() << (boost::format(
1959 "CFG %s can not be topologically sorted\n")
1960 % name()).str();
1961 }
1962 for (std::vector<ControlFlowGraph::NodeDescriptor>::reverse_iterator iter =
1963 sorted.rbegin();
1964 iter != sorted.rend(); iter++) {
1965 BasicBlockNode* node = newCFG_[*iter];
1966 if (node->isNormalBB()) {
1968 POMDIsassembler::disassemble(node->basicBlock());
1969 }
1970 }
1971
1972 Application::logStream() << (boost::format(
1973 "Trying out %s with node count %d\n")
1974 % name() % newCFG_->nodeCount()).str();
1977 TTAProgram::Procedure newProc(name(), space, 0);
1978 Application::logStream() << "Is in program " << newProc.isInProgram() <<
1979 std::endl;
1980 cdg_->program()->addProcedure(&newProc);
1981 newCFG_->copyToProcedure(newProc);
1982 //newCFG_->updateReferencesFromProcToCfg();
1983 Application::logStream() << "Procedure copied" <<
1984 std::endl;
1985 Application::logStream() << " start " << newProc.startAddress().location()
1986 << " end " << newProc.endAddress().location() << std::endl;
1987 //Application::logStream() <<
1988 // POMDisassembler::disassemble(newProc);
1989 cdg_->program()->removeProcedure(newProc);
1990 int count = newProc.instructionCount();
1991 for (int i = 0; i < count; i++) {
1992 Application::logStream() << (boost::format(
1993 "%s\n")
1994 % POMDisassembler::disassemble(newProc.instructionAtIndex(i),1)).str();
1995 }
1996 //ControlFlowGraph testCFG(newProc);
1997 //testCFG.writeToDotFile(name() + "_testCFG.dot");
1998 //delete newCFG_;
1999#endif
2000}
2001
2002void
2004 BasicBlockNode* from,
2005 BasicBlockNode* to,
2006 TTAProgram::Terminal* guardReg,
2008 return;
2009 if (from->isNormalBB() && to->isNormalBB()
2010 //&& !from->basicBlock().lastInstruction().hasControlFlowMove()
2011 ) {
2013 Application::logStream() << "\tMove already has CF " <<
2014 from->basicBlock().lastInstruction().toString() << std::endl;
2015 }
2016 Application::logStream() << (boost::format(
2017 "Creating jump from %s to %s\n")
2018 % from->toString() % to->toString()).str();
2021 /// If reference already exists, just return it
2024
2027
2028 TTAProgram::TerminalFUPort* jump1Terminal =
2029 new TTAProgram::TerminalFUPort(*hwOp, 1);
2030
2031 TTAProgram::Terminal* jump0Terminal =
2033
2034 auto jumpMove = std::make_shared<TTAProgram::Move>(
2035 jump0Terminal, jump1Terminal,
2037
2038 if (predicate == ControlFlowEdge::CFLOW_EDGE_TRUE) {
2041 for (int i = 0; i < busNav.count(); i++) {
2042 TTAMachine::Bus* bus = busNav.item(i);
2043 for (int i = 0; i < bus->guardCount(); i++) {
2044 TTAMachine::RegisterGuard* regGuard =
2045 dynamic_cast<TTAMachine::RegisterGuard*>(bus->guard(i));
2046 if (regGuard != NULL &&
2047 regGuard->registerFile() == &guardReg->registerFile() &&
2048 regGuard->registerIndex() == (int)guardReg->index()) {
2049 jumpMove->setGuard(
2050 new TTAProgram::MoveGuard(*regGuard));
2051 break;
2052 }
2053 }
2054 }
2055 } else if (predicate == ControlFlowEdge::CFLOW_EDGE_FALSE) {
2058 for (int i = 0; i < busNav.count(); i++) {
2059 TTAMachine::Bus* bus = busNav.item(i);
2060 for (int i = 0; i < bus->guardCount(); i++) {
2061 TTAMachine::RegisterGuard* regGuard =
2062 dynamic_cast<TTAMachine::RegisterGuard*>(bus->guard(i));
2063 if (regGuard != NULL &&
2064 regGuard->registerFile() == &guardReg->registerFile() &&
2065 regGuard->registerIndex() == (int)guardReg->index() &&
2066 regGuard->isInverted() == true) {
2067 jumpMove->setGuard(
2068 new TTAProgram::MoveGuard(*regGuard));
2069 break;
2070 }
2071 }
2072 }
2073 }
2074
2076 if (inst->moveCount() > 0) {
2077 inst = new TTAProgram::Instruction();
2078 from->basicBlock().add(inst);
2079 }
2080 std::cerr << " before result " << inst->toString() << std::endl;
2081 inst->addMove(jumpMove);
2082 std::cerr << " after result " << inst->toString() << std::endl;
2083 } else {
2084 Application::logStream() << (boost::format(
2085 "Failed to add jump for %s %s, %s, %s\n")
2086 % from->toString() % to->toString() %
2087 from->basicBlock().lastInstruction().toString() %
2088 to->basicBlock().firstInstruction().toString()).str();
2089 }
2090}
#define __func__
#define abortWithError(message)
#define assert(condition)
#define sub
#define DEBUG_LEVEL
static int verboseLevel()
static std::ostream & logStream()
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
TTAProgram::BasicBlock & basicBlock()
bool isNormalBB() const
std::string toString() const
GraphTraits::vertex_descriptor NodeDescriptor
Type with which nodes of the graph are seen internally.
virtual Node & headNode(const Edge &edge) const
int edgeCount() const
virtual void copyOutEdge(const Node &destination, Edge &edge, const Node *head=NULL)
std::set< ProgramDependenceEdge *, typename GraphEdge::Comparator > EdgeSet
Definition BoostGraph.hh:87
virtual Edge & outEdge(const Node &node, const int index) const
virtual Edge & inEdge(const Node &node, const int index) const
virtual void copyInEdge(const Node &destination, Edge &edge, const Node *tail=NULL)
virtual void moveOutEdge(const Node &source, const Node &destination, Edge &edge, const Node *head=NULL, bool childs=false)
EdgeDescriptor connectingEdge(const Node &nTail, const Node &nHead) const
GraphTraits::edge_descriptor EdgeDescriptor
Type with which edges of the graph are seen internally.
virtual int inDegree(const Node &node) const
std::set< ProgramDependenceNode *, typename GraphNode::Comparator > NodeSet
Definition BoostGraph.hh:86
virtual void moveInEdge(const Node &source, const Node &destination, Edge &edge, const Node *tail=NULL, bool childs=false)
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
virtual int outDegree(const Node &node) const
ProgramDependenceNode Node
The (base) node type managed by this graph.
Definition BoostGraph.hh:90
EdgeSet connectingEdges(const Node &nTail, const Node &nHead) const
virtual EdgeSet outEdges(const Node &node) const
virtual Node & tailNode(const Edge &edge) const
virtual EdgeSet inEdges(const Node &node) const
virtual void connectNodes(const Node &nTail, const Node &nHead, Edge &e)
TTAProgram::Program * program() const
const NodesInfo & pseudoPredicateEEC()
std::set< ControlDependenceNode * > NodesInfo
Storage type for other nodes of same graph needed to define some non graph relations....
BasicBlockNode * basicBlockNode() const
void copyToProcedure(TTAProgram::Procedure &proc, TTAProgram::InstructionReferenceManager *irm=NULL)
void addExit(NodeSet &retSourceNodes)
static std::string toString(const T &source)
DependenceType dependenceType() const
EdgeReason edgeReason() const
const BasicBlockNode & getBasicBlockNode(const MoveNode &mn) const
std::string errorMessageStack(bool messagesOnly=false) const
Definition Exception.cc:138
virtual void writeToDotFile(const TCEString &fileName) const
std::set< GraphEdge *, typename GraphEdge::Comparator > EdgeSet
Definition Graph.hh:54
virtual std::string toString() const
Definition GraphNode.cc:61
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
bool isMove() const
std::shared_ptr< TTAProgram::Move > movePtr()
TTAProgram::Move & move()
static std::string disassemble(const TTAProgram::Move &move)
DataDependenceEdge & dataDependenceEdge()
@ PDG_EDGE_LOOP_CLOSE
Indicates Data Dependence Edge from DDG.
void moveDDGedges(Node &root, NodeSet &subgraphNodes, FilteredCDG &filteredCDG)
boost::graph_traits< FilteredCDG >::in_edge_iterator FilteredInEdgeIter
Few types to work with filtered graph.
Node * ddgEntryNode_
Stored reference to PDG equivalent of DDG ENTRYNODE.
void removeGuardedJump(ControlToProgram &, ProgramDependenceNode &, ControlDependenceNode &)
void computeEECInfo(const PDGOrderMap &orderMap, FilteredCDG &filteredCDG)
Node * entryNode_
Stores pointer to entry node of the PDG graph.
int detectStrongComponents(PDGOrderMap &components, DescriptorMap &roots, FilteredCDG &filteredCDG)
ProgramDependenceGraph(ControlDependenceGraph &cdg, DataDependenceGraph &ddg)
std::vector< std::set< Node * > > strongComponents_
stores nodes present in each of the found components
boost::graph_traits< FilteredCDG >::vertex_descriptor FilteredVertexDescriptor
void computeRegionInfo(const PDGOrderMap &orderMap, FilteredCDG &filteredCDG)
void processEntry(BasicBlockNode *firstBB)
void addLeafEdges(std::vector< BasicBlockNode * > leafs, BasicBlockNode *bb)
int insCount_
Counts new instructions when creating basic blocks.
void copyRegionEECComponent(ControlToProgram &, BBToCD &, MoveNodeToPDGNode &, MovesInCD &)
void processRegion(Node *region, FilteredCDG &filteredCDG)
std::map< const MoveNode *, ProgramDependenceNode *, MoveNode::Comparator > MoveNodeToPDGNode
std::map< const BasicBlockNode *, ControlDependenceNode *, BasicBlockNode::Comparator > BBToCD
std::map< NodeDescriptor, int > PDGOrderMap
Stores data to compute post order relation on CDG and strong components.
std::map< const ControlDependenceNode *, std::vector< Node * > > MovesInCD
void computeRelations(const PDGOrderMap &orderMap, FilteredCDG &filteredCDG)
std::map< NodeDescriptor, NodeDescriptor > DescriptorMap
Storage for relations between nodes.
boost::associative_property_map< ColorMap > Color
ControlFlowGraph * newCFG_
Newly created control flow graph.
std::pair< FilteredInEdgeIter, FilteredInEdgeIter > FilteredInEdgePair
const ControlDependenceGraph * cdg_
Stores original control dependence graph.
boost::filtered_graph< Graph, BackCFGFilter< Graph > > CFGSubgraph
TTAProgram::Program * program_
Original Program object, to get instruction reference manager.
boost::filtered_graph< Graph, CDGFilter< Graph > > FilteredCDG
Type of filtered graph with CD edges only.
boost::graph_traits< FilteredCDG >::out_edge_iterator FilteredOutEdgeIter
std::pair< FilteredOutEdgeIter, FilteredOutEdgeIter > FilteredOutEdgePair
ProgramDependenceNode & entryNode() const
const DataDependenceGraph * ddg_
Stores original data dependence graph.
CompareResult compareSiblings(Node *a, Node *b)
void processLoopEntry(Node *node, BasicBlockNode *bb)
boost::associative_property_map< PDGOrderMap > PDGOrder
void regionHelper(Node *node, FilteredCDG &filteredCDG, Node::NodesInfo &finalNodesInfo)
std::map< const ControlDependenceNode *, ProgramDependenceNode *, ControlDependenceNode::Comparator > ControlToProgram
void processPredicate(Node *predicate, FilteredCDG &filteredCDG)
void createJump(BasicBlockNode *from, BasicBlockNode *to, TTAProgram::Terminal *guardReg=NULL, ControlFlowEdge::CFGEdgePredicate predicate=ControlFlowEdge::CFLOW_EDGE_NORMAL)
boost::filtered_graph< Graph, BackFilter< Graph >, SubgraphTypeTest< NodeSet, Graph > > Subgraph
std::map< NodeDescriptor, boost::default_color_type > ColorMap
Storage for color property used by dfs.
boost::associative_property_map< DescriptorMap > Descriptors
void setNewFirstBB(BasicBlockNode *newBB)
void addLeafBlock(BasicBlockNode *newLeaf)
void addToEEC(ProgramDependenceNode &node)
void setComponent(int component)
BasicBlockNode * newFirstBB()
void addToRegion(ProgramDependenceNode &node)
void addLeafBlocks(std::vector< BasicBlockNode * > newLeafs)
std::vector< BasicBlockNode * > leafBlocks()
std::set< ProgramDependenceNode * > NodesInfo
void setLoopEntryNode(int component)
std::string toString() const
static void intersection(const std::set< ValueType > &firstContainer, const std::set< ValueType > &secondContainer, std::set< ValueType > &intersection)
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual HWOperation * operation(const std::string &name) const
virtual bool isInverted() const
ComponentType * item(int index) const
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
const RegisterFile * registerFile() const
InstructionAddress location() const
virtual Address endAddress() const
virtual Instruction & firstInstruction() const
virtual bool isInProgram() const
virtual void add(Instruction *ins)
virtual int instructionCount() const
virtual Address startAddress() const
virtual Instruction & lastInstruction() const
virtual Instruction & instructionAtIndex(int index) const
InstructionReference createReference(Instruction &ins)
std::string toString() const
bool hasControlFlowMove() const
void addMove(std::shared_ptr< Move > move)
bool isInverted() const
Definition MoveGuard.cc:76
MoveGuard & guard() const
Definition Move.cc:345
bool isJump() const
Definition Move.cc:164
bool isCall() const
Definition Move.cc:190
Terminal & destination() const
Definition Move.cc:323
void removeProcedure(Procedure &proc)
Definition Program.cc:901
void addProcedure(Procedure *proc)
Definition Program.cc:524
InstructionReferenceManager & instructionReferenceManager() const
Definition Program.cc:688
UniversalMachine & universalMachine() const
Definition Program.cc:104
virtual int index() const
Definition Terminal.cc:274
virtual const TTAMachine::RegisterFile & registerFile() const
Definition Terminal.cc:225
TTAMachine::AddressSpace & instructionAddressSpace() const
TTAMachine::Bus & universalBus() const
Filter control dependence edges only.