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

Side by Side Diff: src/compiler/loop-analysis.cc

Issue 855653002: [turbofan] Improve loop analysis to handle more than 32 loops. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 11 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
« no previous file with comments | « src/compiler/loop-analysis.h ('k') | test/cctest/compiler/test-loop-analysis.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/loop-analysis.h" 5 #include "src/compiler/loop-analysis.h"
6 6
7 #include "src/compiler/graph.h" 7 #include "src/compiler/graph.h"
8 #include "src/compiler/node.h" 8 #include "src/compiler/node.h"
9 #include "src/compiler/node-marker.h" 9 #include "src/compiler/node-marker.h"
10 #include "src/compiler/node-properties-inl.h" 10 #include "src/compiler/node-properties-inl.h"
11 #include "src/zone.h" 11 #include "src/zone.h"
12 12
13 namespace v8 { 13 namespace v8 {
14 namespace internal { 14 namespace internal {
15 namespace compiler { 15 namespace compiler {
16 16
17 typedef uint32_t LoopMarks; 17 #define OFFSET(x) ((x)&0x1f)
18 18 #define BIT(x) (1u << OFFSET(x))
19 #define INDEX(x) ((x) >> 5)
19 20
20 // TODO(titzer): don't assume entry edges have a particular index. 21 // TODO(titzer): don't assume entry edges have a particular index.
21 // TODO(titzer): use a BitMatrix to generalize this algorithm.
22 static const size_t kMaxLoops = 31;
23 static const int kAssumedLoopEntryIndex = 0; // assume loops are entered here. 22 static const int kAssumedLoopEntryIndex = 0; // assume loops are entered here.
24 static const LoopMarks kVisited = 1; // loop #0 is reserved.
25 23
26 24
27 // Temporary information for each node during marking. 25 // Temporary information for each node during marking.
28 struct NodeInfo { 26 struct NodeInfo {
29 Node* node; 27 Node* node;
30 NodeInfo* next; // link in chaining loop members 28 NodeInfo* next; // link in chaining loop members
31 LoopMarks forward; // accumulated marks in the forward direction
32 LoopMarks backward; // accumulated marks in the backward direction
33 LoopMarks loop_mark; // loop mark for header nodes; encodes loop_num
34
35 bool MarkBackward(LoopMarks bw) {
36 LoopMarks prev = backward;
37 LoopMarks next = backward | bw;
38 backward = next;
39 return prev != next;
40 }
41
42 bool MarkForward(LoopMarks fw) {
43 LoopMarks prev = forward;
44 LoopMarks next = forward | fw;
45 forward = next;
46 return prev != next;
47 }
48
49 bool IsInLoop(size_t loop_num) {
50 DCHECK(loop_num > 0 && loop_num <= 31);
51 return forward & backward & (1 << loop_num);
52 }
53
54 bool IsLoopHeader() { return loop_mark != 0; }
55 bool IsInAnyLoop() { return (forward & backward) > kVisited; }
56
57 bool IsInHeaderForLoop(size_t loop_num) {
58 DCHECK(loop_num > 0);
59 return loop_mark == (kVisited | (1 << loop_num));
60 }
61 }; 29 };
62 30
63 31
64 // Temporary loop info needed during traversal and building the loop tree. 32 // Temporary loop info needed during traversal and building the loop tree.
65 struct LoopInfo { 33 struct LoopInfo {
66 Node* header; 34 Node* header;
67 NodeInfo* header_list; 35 NodeInfo* header_list;
68 NodeInfo* body_list; 36 NodeInfo* body_list;
69 LoopTree::Loop* loop; 37 LoopTree::Loop* loop;
70 }; 38 };
71 39
72 40
73 static const NodeInfo kEmptyNodeInfo = {nullptr, nullptr, 0, 0, 0};
74
75
76 // Encapsulation of the loop finding algorithm. 41 // Encapsulation of the loop finding algorithm.
77 // ----------------------------------------------------------------------------- 42 // -----------------------------------------------------------------------------
78 // Conceptually, the contents of a loop are those nodes that are "between" the 43 // Conceptually, the contents of a loop are those nodes that are "between" the
79 // loop header and the backedges of the loop. Graphs in the soup of nodes can 44 // loop header and the backedges of the loop. Graphs in the soup of nodes can
80 // form improper cycles, so standard loop finding algorithms that work on CFGs 45 // form improper cycles, so standard loop finding algorithms that work on CFGs
81 // aren't sufficient. However, in valid TurboFan graphs, all cycles involve 46 // aren't sufficient. However, in valid TurboFan graphs, all cycles involve
82 // either a {Loop} node or a phi. The {Loop} node itself and its accompanying 47 // either a {Loop} node or a phi. The {Loop} node itself and its accompanying
83 // phis are treated together as a set referred to here as the loop header. 48 // phis are treated together as a set referred to here as the loop header.
84 // This loop finding algorithm works by traversing the graph in two directions, 49 // This loop finding algorithm works by traversing the graph in two directions,
85 // first from nodes to their inputs, starting at {end}, then in the reverse 50 // first from nodes to their inputs, starting at {end}, then in the reverse
86 // direction, from nodes to their uses, starting at loop headers. 51 // direction, from nodes to their uses, starting at loop headers.
87 // 1 bit per loop per node per direction are required during the marking phase. 52 // 1 bit per loop per node per direction are required during the marking phase.
88 // To handle nested loops correctly, the algorithm must filter some reachability 53 // To handle nested loops correctly, the algorithm must filter some reachability
89 // marks on edges into/out-of the loop header nodes. 54 // marks on edges into/out-of the loop header nodes.
90 class LoopFinderImpl { 55 class LoopFinderImpl {
91 public: 56 public:
92 LoopFinderImpl(Graph* graph, LoopTree* loop_tree, Zone* zone) 57 LoopFinderImpl(Graph* graph, LoopTree* loop_tree, Zone* zone)
93 : end_(graph->end()), 58 : zone_(zone),
59 end_(graph->end()),
94 queue_(zone), 60 queue_(zone),
95 queued_(graph, 2), 61 queued_(graph, 2),
96 info_(graph->NodeCount(), kEmptyNodeInfo, zone), 62 info_(graph->NodeCount(), {nullptr, nullptr}, zone),
97 loops_(zone), 63 loops_(zone),
64 loop_num_(graph->NodeCount(), -1, zone),
98 loop_tree_(loop_tree), 65 loop_tree_(loop_tree),
99 loops_found_(0) {} 66 loops_found_(0),
67 width_(0),
68 backward_(nullptr),
69 forward_(nullptr) {}
100 70
101 void Run() { 71 void Run() {
102 PropagateBackward(); 72 PropagateBackward();
103 PropagateForward(); 73 PropagateForward();
104 FinishLoopTree(); 74 FinishLoopTree();
105 } 75 }
106 76
107 void Print() { 77 void Print() {
108 // Print out the results. 78 // Print out the results.
109 for (NodeInfo& ni : info_) { 79 for (NodeInfo& ni : info_) {
110 if (ni.node == nullptr) continue; 80 if (ni.node == nullptr) continue;
111 for (size_t i = 1; i <= loops_.size(); i++) { 81 for (int i = 1; i <= loops_found_; i++) {
112 if (ni.IsInLoop(i)) { 82 int index = ni.node->id() * width_ + INDEX(i);
83 bool marked_forward = forward_[index] & BIT(i);
84 bool marked_backward = backward_[index] & BIT(i);
85 if (marked_forward && marked_backward) {
113 PrintF("X"); 86 PrintF("X");
114 } else if (ni.forward & (1 << i)) { 87 } else if (marked_forward) {
115 PrintF("/"); 88 PrintF("/");
116 } else if (ni.backward & (1 << i)) { 89 } else if (marked_backward) {
117 PrintF("\\"); 90 PrintF("\\");
118 } else { 91 } else {
119 PrintF(" "); 92 PrintF(" ");
120 } 93 }
121 } 94 }
122 PrintF(" #%d:%s\n", ni.node->id(), ni.node->op()->mnemonic()); 95 PrintF(" #%d:%s\n", ni.node->id(), ni.node->op()->mnemonic());
123 } 96 }
124 97
125 int i = 0; 98 int i = 0;
126 for (LoopInfo& li : loops_) { 99 for (LoopInfo& li : loops_) {
127 PrintF("Loop %d headed at #%d\n", i, li.header->id()); 100 PrintF("Loop %d headed at #%d\n", i, li.header->id());
128 i++; 101 i++;
129 } 102 }
130 103
131 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) { 104 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) {
132 PrintLoop(loop); 105 PrintLoop(loop);
133 } 106 }
134 } 107 }
135 108
136 private: 109 private:
110 Zone* zone_;
137 Node* end_; 111 Node* end_;
138 NodeDeque queue_; 112 NodeDeque queue_;
139 NodeMarker<bool> queued_; 113 NodeMarker<bool> queued_;
140 ZoneVector<NodeInfo> info_; 114 ZoneVector<NodeInfo> info_;
141 ZoneVector<LoopInfo> loops_; 115 ZoneVector<LoopInfo> loops_;
116 ZoneVector<int> loop_num_;
142 LoopTree* loop_tree_; 117 LoopTree* loop_tree_;
143 size_t loops_found_; 118 int loops_found_;
119 int width_;
120 uint32_t* backward_;
121 uint32_t* forward_;
122
123 int num_nodes() {
124 return static_cast<int>(loop_tree_->node_to_loop_num_.size());
125 }
126
127 // Tb = Tb | (Fb - loop_filter)
128 bool PropagateBackwardMarks(Node* from, Node* to, int loop_filter) {
129 if (from == to) return false;
130 uint32_t* fp = &backward_[from->id() * width_];
131 uint32_t* tp = &backward_[to->id() * width_];
132 bool change = false;
133 for (int i = 0; i < width_; i++) {
134 uint32_t mask = i == INDEX(loop_filter) ? ~BIT(loop_filter) : 0xFFFFFFFF;
135 uint32_t prev = tp[i];
136 uint32_t next = prev | (fp[i] & mask);
137 tp[i] = next;
138 if (!change && (prev != next)) change = true;
139 }
140 return change;
141 }
142
143 // Tb = Tb | B
144 bool SetBackwardMark(Node* to, int loop_num) {
145 uint32_t* tp = &backward_[to->id() * width_ + INDEX(loop_num)];
146 uint32_t prev = tp[0];
147 uint32_t next = prev | BIT(loop_num);
148 tp[0] = next;
149 return next != prev;
150 }
151
152 // Tf = Tf | B
153 bool SetForwardMark(Node* to, int loop_num) {
154 uint32_t* tp = &forward_[to->id() * width_ + INDEX(loop_num)];
155 uint32_t prev = tp[0];
156 uint32_t next = prev | BIT(loop_num);
157 tp[0] = next;
158 return next != prev;
159 }
160
161 // Tf = Tf | (Ff & Tb)
162 bool PropagateForwardMarks(Node* from, Node* to) {
163 if (from == to) return false;
164 bool change = false;
165 int findex = from->id() * width_;
166 int tindex = to->id() * width_;
167 for (int i = 0; i < width_; i++) {
168 uint32_t marks = backward_[tindex + i] & forward_[findex + i];
169 uint32_t prev = forward_[tindex + i];
170 uint32_t next = prev | marks;
171 forward_[tindex + i] = next;
172 if (!change && (prev != next)) change = true;
173 }
174 return change;
175 }
176
177 bool IsInLoop(Node* node, int loop_num) {
178 int offset = node->id() * width_ + INDEX(loop_num);
179 return backward_[offset] & forward_[offset] & BIT(loop_num);
180 }
144 181
145 // Propagate marks backward from loop headers. 182 // Propagate marks backward from loop headers.
146 void PropagateBackward() { 183 void PropagateBackward() {
147 PropagateBackward(end_, kVisited); 184 ResizeBackwardMarks();
185 SetBackwardMark(end_, 0);
186 Queue(end_);
148 187
149 while (!queue_.empty()) { 188 while (!queue_.empty()) {
150 Node* node = queue_.front(); 189 Node* node = queue_.front();
190 info(node);
151 queue_.pop_front(); 191 queue_.pop_front();
152 queued_.Set(node, false); 192 queued_.Set(node, false);
153 193
194 int loop_num = -1;
154 // Setup loop headers first. 195 // Setup loop headers first.
155 NodeInfo& ni = info(node);
156 if (node->opcode() == IrOpcode::kLoop) { 196 if (node->opcode() == IrOpcode::kLoop) {
157 // found the loop node first. 197 // found the loop node first.
158 CreateLoopInfo(node, ni); 198 loop_num = CreateLoopInfo(node);
159 } else if (node->opcode() == IrOpcode::kPhi || 199 } else if (node->opcode() == IrOpcode::kPhi ||
160 node->opcode() == IrOpcode::kEffectPhi) { 200 node->opcode() == IrOpcode::kEffectPhi) {
161 // found a phi first. 201 // found a phi first.
162 Node* merge = node->InputAt(node->InputCount() - 1); 202 Node* merge = node->InputAt(node->InputCount() - 1);
163 if (merge->opcode() == IrOpcode::kLoop) { 203 if (merge->opcode() == IrOpcode::kLoop) {
164 NodeInfo& mi = info(merge); 204 loop_num = CreateLoopInfo(merge);
165 CreateLoopInfo(merge, mi);
166 ni.MarkBackward(mi.loop_mark);
167 } 205 }
168 } 206 }
169 207
170 // Propagate reachability marks backwards from this node. 208 // Propagate marks backwards from this node.
171 if (ni.IsLoopHeader()) { 209 for (int i = 0; i < node->InputCount(); i++) {
172 // Handle edges from loop header nodes specially. 210 Node* input = node->InputAt(i);
173 for (int i = 0; i < node->InputCount(); i++) { 211 if (loop_num > 0 && i != kAssumedLoopEntryIndex) {
174 if (i == kAssumedLoopEntryIndex) { 212 // Only propagate the loop mark on backedges.
175 // Don't propagate the loop mark backwards on the entry edge. 213 if (SetBackwardMark(input, loop_num)) Queue(input);
176 PropagateBackward(node->InputAt(0), 214 } else {
177 kVisited | (ni.backward & ~ni.loop_mark)); 215 // Entry or normal edge. Propagate all marks except loop_num.
178 } else { 216 if (PropagateBackwardMarks(node, input, loop_num)) Queue(input);
179 // Only propagate the loop mark on backedges.
180 PropagateBackward(node->InputAt(i), ni.loop_mark);
181 }
182 }
183 } else {
184 // Propagate all loop marks backwards for a normal node.
185 for (Node* const input : node->inputs()) {
186 PropagateBackward(input, ni.backward);
187 } 217 }
188 } 218 }
189 } 219 }
190 } 220 }
191 221
192 // Make a new loop header for the given node. 222 // Make a new loop if necessary for the given node.
193 void CreateLoopInfo(Node* node, NodeInfo& ni) { 223 int CreateLoopInfo(Node* node) {
194 if (ni.IsLoopHeader()) return; // loop already set up. 224 int loop_num = LoopNum(node);
225 if (loop_num > 0) return loop_num;
195 226
196 loops_found_++; 227 loop_num = ++loops_found_;
197 size_t loop_num = loops_.size() + 1; 228 if (INDEX(loop_num) >= width_) ResizeBackwardMarks();
198 CHECK(loops_found_ <= kMaxLoops); // TODO(titzer): don't crash. 229
199 // Create a new loop. 230 // Create a new loop.
200 loops_.push_back({node, nullptr, nullptr, nullptr}); 231 loops_.push_back({node, nullptr, nullptr, nullptr});
201 loop_tree_->NewLoop(); 232 loop_tree_->NewLoop();
202 LoopMarks loop_mark = kVisited | (1 << loop_num); 233 SetBackwardMark(node, loop_num);
203 ni.loop_mark = loop_mark; 234 loop_tree_->node_to_loop_num_[node->id()] = loop_num;
204 235
205 // Setup loop mark for phis attached to loop header. 236 // Setup loop mark for phis attached to loop header.
206 for (Node* use : node->uses()) { 237 for (Node* use : node->uses()) {
207 if (use->opcode() == IrOpcode::kPhi || 238 if (use->opcode() == IrOpcode::kPhi ||
208 use->opcode() == IrOpcode::kEffectPhi) { 239 use->opcode() == IrOpcode::kEffectPhi) {
209 info(use).loop_mark = loop_mark; 240 SetBackwardMark(use, loop_num);
241 loop_tree_->node_to_loop_num_[use->id()] = loop_num;
210 } 242 }
211 } 243 }
244
245 return loop_num;
246 }
247
248 void ResizeBackwardMarks() {
249 int new_width = width_ + 1;
250 int max = num_nodes();
251 uint32_t* new_backward = zone_->NewArray<uint32_t>(new_width * max);
252 memset(new_backward, 0, new_width * max * sizeof(uint32_t));
253 if (width_ > 0) { // copy old matrix data.
254 for (int i = 0; i < max; i++) {
255 uint32_t* np = &new_backward[i * new_width];
256 uint32_t* op = &backward_[i * width_];
257 for (int j = 0; j < width_; j++) np[j] = op[j];
258 }
259 }
260 width_ = new_width;
261 backward_ = new_backward;
262 }
263
264 void ResizeForwardMarks() {
265 int max = num_nodes();
266 forward_ = zone_->NewArray<uint32_t>(width_ * max);
267 memset(forward_, 0, width_ * max * sizeof(uint32_t));
212 } 268 }
213 269
214 // Propagate marks forward from loops. 270 // Propagate marks forward from loops.
215 void PropagateForward() { 271 void PropagateForward() {
272 ResizeForwardMarks();
216 for (LoopInfo& li : loops_) { 273 for (LoopInfo& li : loops_) {
217 queued_.Set(li.header, true); 274 SetForwardMark(li.header, LoopNum(li.header));
218 queue_.push_back(li.header); 275 Queue(li.header);
219 NodeInfo& ni = info(li.header);
220 ni.forward = ni.loop_mark;
221 } 276 }
222 // Propagate forward on paths that were backward reachable from backedges. 277 // Propagate forward on paths that were backward reachable from backedges.
223 while (!queue_.empty()) { 278 while (!queue_.empty()) {
224 Node* node = queue_.front(); 279 Node* node = queue_.front();
225 queue_.pop_front(); 280 queue_.pop_front();
226 queued_.Set(node, false); 281 queued_.Set(node, false);
227 NodeInfo& ni = info(node);
228 for (Edge edge : node->use_edges()) { 282 for (Edge edge : node->use_edges()) {
229 Node* use = edge.from(); 283 Node* use = edge.from();
230 NodeInfo& ui = info(use); 284 if (!IsBackedge(use, edge)) {
231 if (IsBackedge(use, ui, edge)) continue; // skip backedges. 285 if (PropagateForwardMarks(node, use)) Queue(use);
232 LoopMarks both = ni.forward & ui.backward;
233 if (ui.MarkForward(both) && !queued_.Get(use)) {
234 queued_.Set(use, true);
235 queue_.push_back(use);
236 } 286 }
237 } 287 }
238 } 288 }
239 } 289 }
240 290
241 bool IsBackedge(Node* use, NodeInfo& ui, Edge& edge) { 291 bool IsBackedge(Node* use, Edge& edge) {
242 // TODO(titzer): checking for backedges here is ugly. 292 if (LoopNum(use) <= 0) return false;
243 if (!ui.IsLoopHeader()) return false;
244 if (edge.index() == kAssumedLoopEntryIndex) return false; 293 if (edge.index() == kAssumedLoopEntryIndex) return false;
245 if (use->opcode() == IrOpcode::kPhi || 294 if (use->opcode() == IrOpcode::kPhi ||
246 use->opcode() == IrOpcode::kEffectPhi) { 295 use->opcode() == IrOpcode::kEffectPhi) {
247 return !NodeProperties::IsControlEdge(edge); 296 return !NodeProperties::IsControlEdge(edge);
248 } 297 }
249 return true; 298 return true;
250 } 299 }
251 300
301 int LoopNum(Node* node) { return loop_tree_->node_to_loop_num_[node->id()]; }
302
252 NodeInfo& info(Node* node) { 303 NodeInfo& info(Node* node) {
253 NodeInfo& i = info_[node->id()]; 304 NodeInfo& i = info_[node->id()];
254 if (i.node == nullptr) i.node = node; 305 if (i.node == nullptr) i.node = node;
255 return i; 306 return i;
256 } 307 }
257 308
258 void PropagateBackward(Node* node, LoopMarks marks) { 309 void Queue(Node* node) {
259 if (info(node).MarkBackward(marks) && !queued_.Get(node)) { 310 if (!queued_.Get(node)) {
260 queue_.push_back(node); 311 queue_.push_back(node);
261 queued_.Set(node, true); 312 queued_.Set(node, true);
262 } 313 }
263 } 314 }
264 315
265 void FinishLoopTree() { 316 void FinishLoopTree() {
317 DCHECK(loops_found_ == static_cast<int>(loops_.size()));
318 DCHECK(loops_found_ == static_cast<int>(loop_tree_->all_loops_.size()));
319
266 // Degenerate cases. 320 // Degenerate cases.
267 if (loops_.size() == 0) return; 321 if (loops_found_ == 0) return;
268 if (loops_.size() == 1) return FinishSingleLoop(); 322 if (loops_found_ == 1) return FinishSingleLoop();
269 323
270 for (size_t i = 1; i <= loops_.size(); i++) ConnectLoopTree(i); 324 for (int i = 1; i <= loops_found_; i++) ConnectLoopTree(i);
271 325
272 size_t count = 0; 326 size_t count = 0;
273 // Place the node into the innermost nested loop of which it is a member. 327 // Place the node into the innermost nested loop of which it is a member.
274 for (NodeInfo& ni : info_) { 328 for (NodeInfo& ni : info_) {
275 if (ni.node == nullptr || !ni.IsInAnyLoop()) continue; 329 if (ni.node == nullptr) continue;
276 330
277 LoopInfo* innermost = nullptr; 331 LoopInfo* innermost = nullptr;
278 size_t index = 0; 332 int innermost_index = 0;
279 for (size_t i = 1; i <= loops_.size(); i++) { 333 int pos = ni.node->id() * width_;
280 if (ni.IsInLoop(i)) { 334 // Search the marks word by word.
281 LoopInfo* loop = &loops_[i - 1]; 335 for (int i = 0; i < width_; i++) {
282 if (innermost == nullptr || 336 uint32_t marks = backward_[pos + i] & forward_[pos + i];
283 loop->loop->depth_ > innermost->loop->depth_) { 337 for (int j = 0; j < 32; j++) {
284 innermost = loop; 338 if (marks & (1u << j)) {
285 index = i; 339 int loop_num = i * 32 + j;
340 if (loop_num == 0) continue;
341 LoopInfo* loop = &loops_[loop_num - 1];
342 if (innermost == nullptr ||
343 loop->loop->depth_ > innermost->loop->depth_) {
344 innermost = loop;
345 innermost_index = loop_num;
346 }
286 } 347 }
287 } 348 }
288 } 349 }
289 if (ni.IsInHeaderForLoop(index)) { 350 if (innermost == nullptr) continue;
351 if (LoopNum(ni.node) == innermost_index) {
290 ni.next = innermost->header_list; 352 ni.next = innermost->header_list;
291 innermost->header_list = &ni; 353 innermost->header_list = &ni;
292 } else { 354 } else {
293 ni.next = innermost->body_list; 355 ni.next = innermost->body_list;
294 innermost->body_list = &ni; 356 innermost->body_list = &ni;
295 } 357 }
296 count++; 358 count++;
297 } 359 }
298 360
299 // Serialize the node lists for loops into the loop tree. 361 // Serialize the node lists for loops into the loop tree.
300 loop_tree_->loop_nodes_.reserve(count); 362 loop_tree_->loop_nodes_.reserve(count);
301 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) { 363 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) {
302 SerializeLoop(loop); 364 SerializeLoop(loop);
303 } 365 }
304 } 366 }
305 367
306 // Handle the simpler case of a single loop (no checks for nesting necessary). 368 // Handle the simpler case of a single loop (no checks for nesting necessary).
307 void FinishSingleLoop() { 369 void FinishSingleLoop() {
308 DCHECK(loops_.size() == 1);
309 DCHECK(loop_tree_->all_loops_.size() == 1);
310
311 // Place nodes into the loop header and body. 370 // Place nodes into the loop header and body.
312 LoopInfo* li = &loops_[0]; 371 LoopInfo* li = &loops_[0];
313 li->loop = &loop_tree_->all_loops_[0]; 372 li->loop = &loop_tree_->all_loops_[0];
314 loop_tree_->SetParent(nullptr, li->loop); 373 loop_tree_->SetParent(nullptr, li->loop);
315 size_t count = 0; 374 size_t count = 0;
316 for (NodeInfo& ni : info_) { 375 for (NodeInfo& ni : info_) {
317 if (ni.node == nullptr || !ni.IsInAnyLoop()) continue; 376 if (ni.node == nullptr || !IsInLoop(ni.node, 1)) continue;
318 DCHECK(ni.IsInLoop(1)); 377 if (LoopNum(ni.node) == 1) {
319 if (ni.IsInHeaderForLoop(1)) {
320 ni.next = li->header_list; 378 ni.next = li->header_list;
321 li->header_list = &ni; 379 li->header_list = &ni;
322 } else { 380 } else {
323 ni.next = li->body_list; 381 ni.next = li->body_list;
324 li->body_list = &ni; 382 li->body_list = &ni;
325 } 383 }
326 count++; 384 count++;
327 } 385 }
328 386
329 // Serialize the node lists for the loop into the loop tree. 387 // Serialize the node lists for the loop into the loop tree.
330 loop_tree_->loop_nodes_.reserve(count); 388 loop_tree_->loop_nodes_.reserve(count);
331 SerializeLoop(li->loop); 389 SerializeLoop(li->loop);
332 } 390 }
333 391
334 // Recursively serialize the list of header nodes and body nodes 392 // Recursively serialize the list of header nodes and body nodes
335 // so that nested loops occupy nested intervals. 393 // so that nested loops occupy nested intervals.
336 void SerializeLoop(LoopTree::Loop* loop) { 394 void SerializeLoop(LoopTree::Loop* loop) {
337 size_t loop_num = loop_tree_->LoopNum(loop); 395 int loop_num = loop_tree_->LoopNum(loop);
338 LoopInfo& li = loops_[loop_num - 1]; 396 LoopInfo& li = loops_[loop_num - 1];
339 397
340 // Serialize the header. 398 // Serialize the header.
341 loop->header_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); 399 loop->header_start_ = static_cast<int>(loop_tree_->loop_nodes_.size());
342 for (NodeInfo* ni = li.header_list; ni != nullptr; ni = ni->next) { 400 for (NodeInfo* ni = li.header_list; ni != nullptr; ni = ni->next) {
343 loop_tree_->loop_nodes_.push_back(ni->node); 401 loop_tree_->loop_nodes_.push_back(ni->node);
344 // TODO(titzer): lift loop count restriction. 402 loop_tree_->node_to_loop_num_[ni->node->id()] = loop_num;
345 loop_tree_->node_to_loop_num_[ni->node->id()] =
346 static_cast<uint8_t>(loop_num);
347 } 403 }
348 404
349 // Serialize the body. 405 // Serialize the body.
350 loop->body_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); 406 loop->body_start_ = static_cast<int>(loop_tree_->loop_nodes_.size());
351 for (NodeInfo* ni = li.body_list; ni != nullptr; ni = ni->next) { 407 for (NodeInfo* ni = li.body_list; ni != nullptr; ni = ni->next) {
352 loop_tree_->loop_nodes_.push_back(ni->node); 408 loop_tree_->loop_nodes_.push_back(ni->node);
353 // TODO(titzer): lift loop count restriction. 409 loop_tree_->node_to_loop_num_[ni->node->id()] = loop_num;
354 loop_tree_->node_to_loop_num_[ni->node->id()] =
355 static_cast<uint8_t>(loop_num);
356 } 410 }
357 411
358 // Serialize nested loops. 412 // Serialize nested loops.
359 for (LoopTree::Loop* child : loop->children_) SerializeLoop(child); 413 for (LoopTree::Loop* child : loop->children_) SerializeLoop(child);
360 414
361 loop->body_end_ = static_cast<int>(loop_tree_->loop_nodes_.size()); 415 loop->body_end_ = static_cast<int>(loop_tree_->loop_nodes_.size());
362 } 416 }
363 417
364 // Connect the LoopTree loops to their parents recursively. 418 // Connect the LoopTree loops to their parents recursively.
365 LoopTree::Loop* ConnectLoopTree(size_t loop_num) { 419 LoopTree::Loop* ConnectLoopTree(int loop_num) {
366 LoopInfo& li = loops_[loop_num - 1]; 420 LoopInfo& li = loops_[loop_num - 1];
367 if (li.loop != nullptr) return li.loop; 421 if (li.loop != nullptr) return li.loop;
368 422
369 NodeInfo& ni = info(li.header); 423 NodeInfo& ni = info(li.header);
370 LoopTree::Loop* parent = nullptr; 424 LoopTree::Loop* parent = nullptr;
371 for (size_t i = 1; i <= loops_.size(); i++) { 425 for (int i = 1; i <= loops_found_; i++) {
372 if (i == loop_num) continue; 426 if (i == loop_num) continue;
373 if (ni.IsInLoop(i)) { 427 if (IsInLoop(ni.node, i)) {
374 // recursively create potential parent loops first. 428 // recursively create potential parent loops first.
375 LoopTree::Loop* upper = ConnectLoopTree(i); 429 LoopTree::Loop* upper = ConnectLoopTree(i);
376 if (parent == nullptr || upper->depth_ > parent->depth_) { 430 if (parent == nullptr || upper->depth_ > parent->depth_) {
377 parent = upper; 431 parent = upper;
378 } 432 }
379 } 433 }
380 } 434 }
381 li.loop = &loop_tree_->all_loops_[loop_num - 1]; 435 li.loop = &loop_tree_->all_loops_[loop_num - 1];
382 loop_tree_->SetParent(parent, li.loop); 436 loop_tree_->SetParent(parent, li.loop);
383 return li.loop; 437 return li.loop;
(...skipping 22 matching lines...) Expand all
406 finder.Run(); 460 finder.Run();
407 if (FLAG_trace_turbo_graph) { 461 if (FLAG_trace_turbo_graph) {
408 finder.Print(); 462 finder.Print();
409 } 463 }
410 return loop_tree; 464 return loop_tree;
411 } 465 }
412 466
413 } // namespace compiler 467 } // namespace compiler
414 } // namespace internal 468 } // namespace internal
415 } // namespace v8 469 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/loop-analysis.h ('k') | test/cctest/compiler/test-loop-analysis.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698