| OLD | NEW |
| (Empty) | |
| 1 //===- subzero/src/IceLoopAnalyzer.cpp - Loop Analysis --------------------===// |
| 2 // |
| 3 // The Subzero Code Generator |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 /// |
| 10 /// \file |
| 11 /// This file implements the loop analysis on the CFG. |
| 12 /// |
| 13 //===----------------------------------------------------------------------===// |
| 14 #include "IceLoopAnalyzer.h" |
| 15 |
| 16 #include "IceCfg.h" |
| 17 #include "IceCfgNode.h" |
| 18 |
| 19 namespace Ice { |
| 20 |
| 21 void LoopAnalyzer::LoopNode::reset() { |
| 22 if (Deleted) |
| 23 return; |
| 24 Succ = BB->getOutEdges().begin(); |
| 25 Index = LowLink = UndefinedIndex; |
| 26 OnStack = false; |
| 27 } |
| 28 |
| 29 NodeList::const_iterator LoopAnalyzer::LoopNode::successorsEnd() const { |
| 30 return BB->getOutEdges().end(); |
| 31 } |
| 32 |
| 33 void LoopAnalyzer::LoopNode::incrementLoopNestDepth() { |
| 34 BB->incrementLoopNestDepth(); |
| 35 } |
| 36 |
| 37 LoopAnalyzer::LoopAnalyzer(Cfg *Func) : Func(Func) { |
| 38 const NodeList &Nodes = Func->getNodes(); |
| 39 |
| 40 // Allocate memory ahead of time. This is why a vector is used instead of a |
| 41 // stack which doesn't support reserving (or bulk erasure used below). |
| 42 AllNodes.reserve(Nodes.size()); |
| 43 WorkStack.reserve(Nodes.size()); |
| 44 LoopStack.reserve(Nodes.size()); |
| 45 |
| 46 // Create the LoopNodes from the function's CFG |
| 47 for (CfgNode *Node : Nodes) |
| 48 AllNodes.emplace_back(Node); |
| 49 } |
| 50 |
| 51 void LoopAnalyzer::computeLoopNestDepth() { |
| 52 assert(AllNodes.size() == Func->getNodes().size()); |
| 53 assert(NextIndex == FirstDefinedIndex); |
| 54 assert(NumDeletedNodes == 0); |
| 55 |
| 56 while (NumDeletedNodes < AllNodes.size()) { |
| 57 // Prepare to run Tarjan's |
| 58 for (LoopNode &Node : AllNodes) |
| 59 Node.reset(); |
| 60 |
| 61 assert(WorkStack.empty()); |
| 62 assert(LoopStack.empty()); |
| 63 |
| 64 for (LoopNode &Node : AllNodes) { |
| 65 if (Node.isDeleted() || Node.isVisited()) |
| 66 continue; |
| 67 |
| 68 WorkStack.push_back(&Node); |
| 69 |
| 70 while (!WorkStack.empty()) { |
| 71 LoopNode &WorkNode = *WorkStack.back(); |
| 72 if (LoopNode *Succ = processNode(WorkNode)) |
| 73 WorkStack.push_back(Succ); |
| 74 else |
| 75 WorkStack.pop_back(); |
| 76 } |
| 77 } |
| 78 } |
| 79 } |
| 80 |
| 81 LoopAnalyzer::LoopNode * |
| 82 LoopAnalyzer::processNode(LoopAnalyzer::LoopNode &Node) { |
| 83 if (!Node.isVisited()) { |
| 84 Node.visit(NextIndex++); |
| 85 LoopStack.push_back(&Node); |
| 86 Node.setOnStack(); |
| 87 } else { |
| 88 // Returning to a node after having recursed into Succ so continue |
| 89 // iterating through successors after using the Succ.LowLink value that was |
| 90 // computed in the recursion. |
| 91 LoopNode &Succ = AllNodes[(*Node.currentSuccessor())->getIndex()]; |
| 92 Node.tryLink(Succ.getLowLink()); |
| 93 Node.nextSuccessor(); |
| 94 } |
| 95 |
| 96 // Visit the successors and recurse into unvisited nodes. The recursion could |
| 97 // cause the iteration to be suspended but it will resume as the stack is |
| 98 // unwound. |
| 99 auto SuccEnd = Node.successorsEnd(); |
| 100 for (; Node.currentSuccessor() != SuccEnd; Node.nextSuccessor()) { |
| 101 LoopNode &Succ = AllNodes[(*Node.currentSuccessor())->getIndex()]; |
| 102 |
| 103 if (Succ.isDeleted()) |
| 104 continue; |
| 105 |
| 106 if (!Succ.isVisited()) |
| 107 return &Succ; |
| 108 else if (Succ.isOnStack()) |
| 109 Node.tryLink(Succ.getIndex()); |
| 110 } |
| 111 |
| 112 if (Node.getLowLink() != Node.getIndex()) |
| 113 return nullptr; |
| 114 |
| 115 // Single node means no loop in the CFG |
| 116 if (LoopStack.back() == &Node) { |
| 117 LoopStack.back()->setOnStack(false); |
| 118 LoopStack.back()->setDeleted(); |
| 119 ++NumDeletedNodes; |
| 120 LoopStack.pop_back(); |
| 121 return nullptr; |
| 122 } |
| 123 |
| 124 // Reaching here means a loop has been found! It consists of the nodes on |
| 125 // the top of the stack, down until the current node being processed, Node, |
| 126 // is found. |
| 127 for (auto It = LoopStack.rbegin(); It != LoopStack.rend(); ++It) { |
| 128 (*It)->setOnStack(false); |
| 129 (*It)->incrementLoopNestDepth(); |
| 130 // Remove the loop from the stack and delete the head node |
| 131 if (*It == &Node) { |
| 132 (*It)->setDeleted(); |
| 133 ++NumDeletedNodes; |
| 134 LoopStack.erase(It.base() - 1, LoopStack.end()); |
| 135 break; |
| 136 } |
| 137 } |
| 138 |
| 139 return nullptr; |
| 140 } |
| 141 |
| 142 } // end of namespace Ice |
| OLD | NEW |