Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Side by Side Diff: src/IceLoopAnalyzer.cpp

Issue 2149803005: Subzero: Improve LoopAnalyzer Interface (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: More Refactoring Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/IceLoopAnalyzer.h ('K') | « src/IceLoopAnalyzer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceLoopAnalyzer.cpp - Loop Analysis --------------------===// 1 //===- subzero/src/IceLoopAnalyzer.cpp - Loop Analysis --------------------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
11 /// \brief Implements the loop analysis on the CFG. 11 /// \brief Implements the loop analysis on the CFG.
12 /// 12 ///
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 #include "IceLoopAnalyzer.h" 14 #include "IceLoopAnalyzer.h"
15 15
16 #include "IceCfg.h" 16 #include "IceCfg.h"
17 #include "IceCfgNode.h" 17 #include "IceCfgNode.h"
18 18
19 #include <algorithm>
20
19 namespace Ice { 21 namespace Ice {
22 class LoopAnalyzer {
23 public:
24 LoopAnalyzer() = default;
Jim Stichnoth 2016/07/19 20:22:56 Also delete or "default" the default copy ctor and
25 explicit LoopAnalyzer(Cfg *Func);
20 26
27 /// Use Tarjan's strongly connected components algorithm to identify outermost
28 /// to innermost loops. By deleting the head of the loop from the graph, inner
29 /// loops can be found. This assumes that the head node is not shared between
30 /// loops but instead all paths to the head come from 'continue' constructs.
31 ///
32 /// This only computes the loop nest depth within the function and does not
33 /// take into account whether the function was called from within a loop.
34 // TODO(ascull): this currently uses a extension of Tarjan's algorithm with
35 // is bounded linear. ncbray suggests another algorithm which is linear in
36 // practice but not bounded linear. I think it also finds dominators.
37 // http://lenx.100871.net/papers/loop-SAS.pdf
38
39 CfgVector<CfgUnorderedSet<SizeT>> getLoopBodies() { return Loops; }
40
41 private:
42 void computeLoopNestDepth();
43
44 using IndexT = uint32_t;
45 static constexpr IndexT UndefinedIndex = 0;
46 static constexpr IndexT FirstDefinedIndex = 1;
47
48 // TODO(ascull): classify the other fields
49 class LoopNode {
50 LoopNode() = delete;
51 LoopNode operator=(const LoopNode &) = delete;
52
53 public:
54 explicit LoopNode(CfgNode *BB) : BB(BB) { reset(); }
55 LoopNode(const LoopNode &) = default;
56
57 void reset();
58
59 NodeList::const_iterator successorsEnd() const;
60 NodeList::const_iterator currentSuccessor() const { return Succ; }
61 void nextSuccessor() { ++Succ; }
62
63 void visit(IndexT VisitIndex) { Index = LowLink = VisitIndex; }
64 bool isVisited() const { return Index != UndefinedIndex; }
65 IndexT getIndex() const { return Index; }
66
67 void tryLink(IndexT NewLink) {
68 if (NewLink < LowLink)
69 LowLink = NewLink;
70 }
71 IndexT getLowLink() const { return LowLink; }
72
73 void setOnStack(bool NewValue = true) { OnStack = NewValue; }
74 bool isOnStack() const { return OnStack; }
75
76 void setDeleted() { Deleted = true; }
77 bool isDeleted() const { return Deleted; }
78
79 void incrementLoopNestDepth();
80 bool hasSelfEdge() const;
81
82 CfgNode *getNode() { return BB; }
83
84 private:
85 CfgNode *BB;
86 NodeList::const_iterator Succ;
87 IndexT Index;
88 IndexT LowLink;
89 bool OnStack;
90 bool Deleted = false;
91 };
92
93 using LoopNodeList = CfgVector<LoopNode>;
94 using LoopNodePtrList = CfgVector<LoopNode *>;
95
96 /// Process the node as part as part of Tarjan's algorithm and return either a
97 /// node to recurse into or nullptr when the node has been fully processed.
98 LoopNode *processNode(LoopNode &Node);
99
100 /// The function to analyze for loops.
101 Cfg *const Func;
102 /// A list of decorated nodes in the same order as Func->getNodes() which
103 /// means the node's index will also be valid in this list.
104 LoopNodeList AllNodes;
105 /// This is used as a replacement for the call stack.
106 LoopNodePtrList WorkStack;
107 /// Track which loop a node belongs to.
108 LoopNodePtrList LoopStack;
109 /// The index to assign to the next visited node.
110 IndexT NextIndex = FirstDefinedIndex;
111 /// The number of nodes which have been marked deleted. This is used to track
112 /// when the iteration should end.
113 LoopNodePtrList::size_type NumDeletedNodes = 0;
114
115 /// All the Loops, in descending order of size
116 CfgVector<CfgUnorderedSet<SizeT>> Loops;
117 };
21 void LoopAnalyzer::LoopNode::reset() { 118 void LoopAnalyzer::LoopNode::reset() {
22 if (Deleted) 119 if (Deleted)
23 return; 120 return;
24 Succ = BB->getOutEdges().begin(); 121 Succ = BB->getOutEdges().begin();
25 Index = LowLink = UndefinedIndex; 122 Index = LowLink = UndefinedIndex;
26 OnStack = false; 123 OnStack = false;
27 } 124 }
28 125
29 NodeList::const_iterator LoopAnalyzer::LoopNode::successorsEnd() const { 126 NodeList::const_iterator LoopAnalyzer::LoopNode::successorsEnd() const {
30 return BB->getOutEdges().end(); 127 return BB->getOutEdges().end();
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 // Reaching here means a loop has been found! It consists of the nodes on the 232 // Reaching here means a loop has been found! It consists of the nodes on the
136 // top of the stack, down until the current node being processed, Node, is 233 // top of the stack, down until the current node being processed, Node, is
137 // found. 234 // found.
138 for (auto It = LoopStack.rbegin(); It != LoopStack.rend(); ++It) { 235 for (auto It = LoopStack.rbegin(); It != LoopStack.rend(); ++It) {
139 (*It)->setOnStack(false); 236 (*It)->setOnStack(false);
140 (*It)->incrementLoopNestDepth(); 237 (*It)->incrementLoopNestDepth();
141 // Remove the loop from the stack and delete the head node 238 // Remove the loop from the stack and delete the head node
142 if (*It == &Node) { 239 if (*It == &Node) {
143 (*It)->setDeleted(); 240 (*It)->setDeleted();
144 ++NumDeletedNodes; 241 ++NumDeletedNodes;
145 CfgVector<SizeT> LoopNodes; 242 CfgUnorderedSet<SizeT> LoopNodes;
146 for (auto LoopIter = It.base() - 1; LoopIter != LoopStack.end(); 243 for (auto LoopIter = It.base() - 1; LoopIter != LoopStack.end();
147 ++LoopIter) { 244 ++LoopIter) {
148 LoopNodes.push_back((*LoopIter)->getNode()->getIndex()); 245 LoopNodes.insert((*LoopIter)->getNode()->getIndex());
149 } 246 }
150 Loops[(*It)->getNode()->getIndex()] = LoopNodes; 247 Loops.push_back(LoopNodes);
151 LoopStack.erase(It.base() - 1, LoopStack.end()); 248 LoopStack.erase(It.base() - 1, LoopStack.end());
152 break; 249 break;
153 } 250 }
154 } 251 }
155 252
156 return nullptr; 253 return nullptr;
157 } 254 }
255 CfgVector<Loop> ComputeLoopInfo(Cfg *Func) {
256 auto LoopBodies = LoopAnalyzer(Func).getLoopBodies();
257
258 CfgVector<Loop> Loops;
259 Loops.reserve(LoopBodies.size());
260 std::sort(
261 LoopBodies.begin(), LoopBodies.end(),
262 [](const CfgUnorderedSet<SizeT> &A, const CfgUnorderedSet<SizeT> &B) {
263 return A.size() > B.size();
264 });
265 for (auto &LoopBody : LoopBodies) {
266 CfgNode *Header = nullptr;
267 bool IsSimpleLoop = true;
268 for (auto NodeIndex : LoopBody) {
269 CfgNode *Cur = Func->getNodes()[NodeIndex];
270 for (auto *Prev : Cur->getInEdges()) {
271 if (LoopBody.find(Prev->getIndex()) ==
272 LoopBody.end()) { // coming from outside
273 if (Header == nullptr) {
274 Header = Cur;
275 } else {
276 Header = nullptr;
277 IsSimpleLoop = false;
278 break;
279 }
280 }
281 }
282 if (!IsSimpleLoop) {
283 break;
284 }
285 }
286 if (!IsSimpleLoop)
287 continue; // To next potential loop
288
289 CfgNode *PreHeader = nullptr;
290 for (auto *Prev : Header->getInEdges()) {
291 if (LoopBody.find(Prev->getIndex()) == LoopBody.end()) {
292 if (PreHeader == nullptr) {
293 PreHeader = Prev;
294 } else {
295 PreHeader = nullptr;
296 break;
297 }
298 }
299 }
300
301 Loops.emplace_back(Header, PreHeader, LoopBody);
302 }
303 return Loops;
304 }
158 305
159 } // end of namespace Ice 306 } // end of namespace Ice
OLDNEW
« src/IceLoopAnalyzer.h ('K') | « src/IceLoopAnalyzer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698