OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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.h" | 10 #include "src/compiler/node-properties.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 struct NodeInfo { | 22 struct NodeInfo { |
23 Node* node; | 23 Node* node; |
24 NodeInfo* next; // link in chaining loop members | 24 NodeInfo* next; // link in chaining loop members |
25 }; | 25 }; |
26 | 26 |
27 | 27 |
28 // Temporary loop info needed during traversal and building the loop tree. | 28 // Temporary loop info needed during traversal and building the loop tree. |
29 struct LoopInfo { | 29 struct LoopInfo { |
30 Node* header; | 30 Node* header; |
31 NodeInfo* header_list; | 31 NodeInfo* header_list; |
| 32 NodeInfo* exit_list; |
32 NodeInfo* body_list; | 33 NodeInfo* body_list; |
33 LoopTree::Loop* loop; | 34 LoopTree::Loop* loop; |
34 }; | 35 }; |
35 | 36 |
36 | 37 |
37 // Encapsulation of the loop finding algorithm. | 38 // Encapsulation of the loop finding algorithm. |
38 // ----------------------------------------------------------------------------- | 39 // ----------------------------------------------------------------------------- |
39 // Conceptually, the contents of a loop are those nodes that are "between" the | 40 // Conceptually, the contents of a loop are those nodes that are "between" the |
40 // loop header and the backedges of the loop. Graphs in the soup of nodes can | 41 // loop header and the backedges of the loop. Graphs in the soup of nodes can |
41 // form improper cycles, so standard loop finding algorithms that work on CFGs | 42 // form improper cycles, so standard loop finding algorithms that work on CFGs |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 // Print out the results. | 75 // Print out the results. |
75 for (NodeInfo& ni : info_) { | 76 for (NodeInfo& ni : info_) { |
76 if (ni.node == nullptr) continue; | 77 if (ni.node == nullptr) continue; |
77 for (int i = 1; i <= loops_found_; i++) { | 78 for (int i = 1; i <= loops_found_; i++) { |
78 int index = ni.node->id() * width_ + INDEX(i); | 79 int index = ni.node->id() * width_ + INDEX(i); |
79 bool marked_forward = forward_[index] & BIT(i); | 80 bool marked_forward = forward_[index] & BIT(i); |
80 bool marked_backward = backward_[index] & BIT(i); | 81 bool marked_backward = backward_[index] & BIT(i); |
81 if (marked_forward && marked_backward) { | 82 if (marked_forward && marked_backward) { |
82 PrintF("X"); | 83 PrintF("X"); |
83 } else if (marked_forward) { | 84 } else if (marked_forward) { |
84 PrintF("/"); | 85 PrintF(">"); |
85 } else if (marked_backward) { | 86 } else if (marked_backward) { |
86 PrintF("\\"); | 87 PrintF("<"); |
87 } else { | 88 } else { |
88 PrintF(" "); | 89 PrintF(" "); |
89 } | 90 } |
90 } | 91 } |
91 PrintF(" #%d:%s\n", ni.node->id(), ni.node->op()->mnemonic()); | 92 PrintF(" #%d:%s\n", ni.node->id(), ni.node->op()->mnemonic()); |
92 } | 93 } |
93 | 94 |
94 int i = 0; | 95 int i = 0; |
95 for (LoopInfo& li : loops_) { | 96 for (LoopInfo& li : loops_) { |
96 PrintF("Loop %d headed at #%d\n", i, li.header->id()); | 97 PrintF("Loop %d headed at #%d\n", i, li.header->id()); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 // Setup loop headers first. | 192 // Setup loop headers first. |
192 if (node->opcode() == IrOpcode::kLoop) { | 193 if (node->opcode() == IrOpcode::kLoop) { |
193 // found the loop node first. | 194 // found the loop node first. |
194 loop_num = CreateLoopInfo(node); | 195 loop_num = CreateLoopInfo(node); |
195 } else if (NodeProperties::IsPhi(node)) { | 196 } else if (NodeProperties::IsPhi(node)) { |
196 // found a phi first. | 197 // found a phi first. |
197 Node* merge = node->InputAt(node->InputCount() - 1); | 198 Node* merge = node->InputAt(node->InputCount() - 1); |
198 if (merge->opcode() == IrOpcode::kLoop) { | 199 if (merge->opcode() == IrOpcode::kLoop) { |
199 loop_num = CreateLoopInfo(merge); | 200 loop_num = CreateLoopInfo(merge); |
200 } | 201 } |
| 202 } else if (node->opcode() == IrOpcode::kLoopExit) { |
| 203 // Intentionally ignore return value. Loop exit node marks |
| 204 // are propagated normally. |
| 205 CreateLoopInfo(node->InputAt(1)); |
| 206 } else if (node->opcode() == IrOpcode::kLoopExitValue || |
| 207 node->opcode() == IrOpcode::kLoopExitEffect) { |
| 208 Node* loop_exit = NodeProperties::GetControlInput(node); |
| 209 // Intentionally ignore return value. Loop exit node marks |
| 210 // are propagated normally. |
| 211 CreateLoopInfo(loop_exit->InputAt(1)); |
201 } | 212 } |
202 | 213 |
203 // Propagate marks backwards from this node. | 214 // Propagate marks backwards from this node. |
204 for (int i = 0; i < node->InputCount(); i++) { | 215 for (int i = 0; i < node->InputCount(); i++) { |
205 Node* input = node->InputAt(i); | 216 Node* input = node->InputAt(i); |
206 if (loop_num > 0 && i != kAssumedLoopEntryIndex) { | 217 if (IsBackedge(node, i)) { |
207 // Only propagate the loop mark on backedges. | 218 // Only propagate the loop mark on backedges. |
208 if (SetBackwardMark(input, loop_num)) Queue(input); | 219 if (SetBackwardMark(input, loop_num)) Queue(input); |
209 } else { | 220 } else { |
210 // Entry or normal edge. Propagate all marks except loop_num. | 221 // Entry or normal edge. Propagate all marks except loop_num. |
211 if (PropagateBackwardMarks(node, input, loop_num)) Queue(input); | 222 if (PropagateBackwardMarks(node, input, loop_num)) Queue(input); |
212 } | 223 } |
213 } | 224 } |
214 } | 225 } |
215 } | 226 } |
216 | 227 |
217 // Make a new loop if necessary for the given node. | 228 // Make a new loop if necessary for the given node. |
218 int CreateLoopInfo(Node* node) { | 229 int CreateLoopInfo(Node* node) { |
| 230 DCHECK_EQ(IrOpcode::kLoop, node->opcode()); |
219 int loop_num = LoopNum(node); | 231 int loop_num = LoopNum(node); |
220 if (loop_num > 0) return loop_num; | 232 if (loop_num > 0) return loop_num; |
221 | 233 |
222 loop_num = ++loops_found_; | 234 loop_num = ++loops_found_; |
223 if (INDEX(loop_num) >= width_) ResizeBackwardMarks(); | 235 if (INDEX(loop_num) >= width_) ResizeBackwardMarks(); |
224 | 236 |
225 // Create a new loop. | 237 // Create a new loop. |
226 loops_.push_back({node, nullptr, nullptr, nullptr}); | 238 loops_.push_back({node, nullptr, nullptr, nullptr, nullptr}); |
227 loop_tree_->NewLoop(); | 239 loop_tree_->NewLoop(); |
228 SetBackwardMark(node, loop_num); | 240 SetLoopMarkForLoopHeader(node, loop_num); |
229 loop_tree_->node_to_loop_num_[node->id()] = loop_num; | |
230 | |
231 // Setup loop mark for phis attached to loop header. | |
232 for (Node* use : node->uses()) { | |
233 if (NodeProperties::IsPhi(use)) { | |
234 info(use); // create the NodeInfo | |
235 SetBackwardMark(use, loop_num); | |
236 loop_tree_->node_to_loop_num_[use->id()] = loop_num; | |
237 } | |
238 } | |
239 | |
240 return loop_num; | 241 return loop_num; |
241 } | 242 } |
242 | 243 |
| 244 void SetLoopMark(Node* node, int loop_num) { |
| 245 info(node); // create the NodeInfo |
| 246 SetBackwardMark(node, loop_num); |
| 247 loop_tree_->node_to_loop_num_[node->id()] = loop_num; |
| 248 } |
| 249 |
| 250 void SetLoopMarkForLoopHeader(Node* node, int loop_num) { |
| 251 DCHECK_EQ(IrOpcode::kLoop, node->opcode()); |
| 252 SetLoopMark(node, loop_num); |
| 253 for (Node* use : node->uses()) { |
| 254 if (NodeProperties::IsPhi(use)) { |
| 255 SetLoopMark(use, loop_num); |
| 256 } |
| 257 |
| 258 // Do not keep the loop alive if it does not have any backedges. |
| 259 if (node->InputCount() <= 1) continue; |
| 260 |
| 261 if (use->opcode() == IrOpcode::kLoopExit) { |
| 262 SetLoopMark(use, loop_num); |
| 263 for (Node* exit_use : use->uses()) { |
| 264 if (exit_use->opcode() == IrOpcode::kLoopExitValue || |
| 265 exit_use->opcode() == IrOpcode::kLoopExitEffect) { |
| 266 SetLoopMark(exit_use, loop_num); |
| 267 } |
| 268 } |
| 269 } |
| 270 } |
| 271 } |
| 272 |
243 void ResizeBackwardMarks() { | 273 void ResizeBackwardMarks() { |
244 int new_width = width_ + 1; | 274 int new_width = width_ + 1; |
245 int max = num_nodes(); | 275 int max = num_nodes(); |
246 uint32_t* new_backward = zone_->NewArray<uint32_t>(new_width * max); | 276 uint32_t* new_backward = zone_->NewArray<uint32_t>(new_width * max); |
247 memset(new_backward, 0, new_width * max * sizeof(uint32_t)); | 277 memset(new_backward, 0, new_width * max * sizeof(uint32_t)); |
248 if (width_ > 0) { // copy old matrix data. | 278 if (width_ > 0) { // copy old matrix data. |
249 for (int i = 0; i < max; i++) { | 279 for (int i = 0; i < max; i++) { |
250 uint32_t* np = &new_backward[i * new_width]; | 280 uint32_t* np = &new_backward[i * new_width]; |
251 uint32_t* op = &backward_[i * width_]; | 281 uint32_t* op = &backward_[i * width_]; |
252 for (int j = 0; j < width_; j++) np[j] = op[j]; | 282 for (int j = 0; j < width_; j++) np[j] = op[j]; |
(...skipping 16 matching lines...) Expand all Loading... |
269 SetForwardMark(li.header, LoopNum(li.header)); | 299 SetForwardMark(li.header, LoopNum(li.header)); |
270 Queue(li.header); | 300 Queue(li.header); |
271 } | 301 } |
272 // Propagate forward on paths that were backward reachable from backedges. | 302 // Propagate forward on paths that were backward reachable from backedges. |
273 while (!queue_.empty()) { | 303 while (!queue_.empty()) { |
274 Node* node = queue_.front(); | 304 Node* node = queue_.front(); |
275 queue_.pop_front(); | 305 queue_.pop_front(); |
276 queued_.Set(node, false); | 306 queued_.Set(node, false); |
277 for (Edge edge : node->use_edges()) { | 307 for (Edge edge : node->use_edges()) { |
278 Node* use = edge.from(); | 308 Node* use = edge.from(); |
279 if (!IsBackedge(use, edge)) { | 309 if (!IsBackedge(use, edge.index())) { |
280 if (PropagateForwardMarks(node, use)) Queue(use); | 310 if (PropagateForwardMarks(node, use)) Queue(use); |
281 } | 311 } |
282 } | 312 } |
283 } | 313 } |
284 } | 314 } |
285 | 315 |
286 bool IsBackedge(Node* use, Edge& edge) { | 316 bool IsLoopHeaderNode(Node* node) { |
| 317 return node->opcode() == IrOpcode::kLoop || NodeProperties::IsPhi(node); |
| 318 } |
| 319 |
| 320 bool IsLoopExitNode(Node* node) { |
| 321 return node->opcode() == IrOpcode::kLoopExit || |
| 322 node->opcode() == IrOpcode::kLoopExitValue || |
| 323 node->opcode() == IrOpcode::kLoopExitEffect; |
| 324 } |
| 325 |
| 326 bool IsBackedge(Node* use, int index) { |
287 if (LoopNum(use) <= 0) return false; | 327 if (LoopNum(use) <= 0) return false; |
288 if (edge.index() == kAssumedLoopEntryIndex) return false; | |
289 if (NodeProperties::IsPhi(use)) { | 328 if (NodeProperties::IsPhi(use)) { |
290 return !NodeProperties::IsControlEdge(edge); | 329 return index != NodeProperties::FirstControlIndex(use) && |
| 330 index != kAssumedLoopEntryIndex; |
| 331 } else if (use->opcode() == IrOpcode::kLoop) { |
| 332 return index != kAssumedLoopEntryIndex; |
291 } | 333 } |
292 return true; | 334 DCHECK(IsLoopExitNode(use)); |
| 335 return false; |
293 } | 336 } |
294 | 337 |
295 int LoopNum(Node* node) { return loop_tree_->node_to_loop_num_[node->id()]; } | 338 int LoopNum(Node* node) { return loop_tree_->node_to_loop_num_[node->id()]; } |
296 | 339 |
297 NodeInfo& info(Node* node) { | 340 NodeInfo& info(Node* node) { |
298 NodeInfo& i = info_[node->id()]; | 341 NodeInfo& i = info_[node->id()]; |
299 if (i.node == nullptr) i.node = node; | 342 if (i.node == nullptr) i.node = node; |
300 return i; | 343 return i; |
301 } | 344 } |
302 | 345 |
303 void Queue(Node* node) { | 346 void Queue(Node* node) { |
304 if (!queued_.Get(node)) { | 347 if (!queued_.Get(node)) { |
305 queue_.push_back(node); | 348 queue_.push_back(node); |
306 queued_.Set(node, true); | 349 queued_.Set(node, true); |
307 } | 350 } |
308 } | 351 } |
309 | 352 |
| 353 void AddNodeToLoop(NodeInfo* node_info, LoopInfo* loop, int loop_num) { |
| 354 if (LoopNum(node_info->node) == loop_num) { |
| 355 if (IsLoopHeaderNode(node_info->node)) { |
| 356 node_info->next = loop->header_list; |
| 357 loop->header_list = node_info; |
| 358 } else { |
| 359 DCHECK(IsLoopExitNode(node_info->node)); |
| 360 node_info->next = loop->exit_list; |
| 361 loop->exit_list = node_info; |
| 362 } |
| 363 } else { |
| 364 node_info->next = loop->body_list; |
| 365 loop->body_list = node_info; |
| 366 } |
| 367 } |
| 368 |
310 void FinishLoopTree() { | 369 void FinishLoopTree() { |
311 DCHECK(loops_found_ == static_cast<int>(loops_.size())); | 370 DCHECK(loops_found_ == static_cast<int>(loops_.size())); |
312 DCHECK(loops_found_ == static_cast<int>(loop_tree_->all_loops_.size())); | 371 DCHECK(loops_found_ == static_cast<int>(loop_tree_->all_loops_.size())); |
313 | 372 |
314 // Degenerate cases. | 373 // Degenerate cases. |
315 if (loops_found_ == 0) return; | 374 if (loops_found_ == 0) return; |
316 if (loops_found_ == 1) return FinishSingleLoop(); | 375 if (loops_found_ == 1) return FinishSingleLoop(); |
317 | 376 |
318 for (int i = 1; i <= loops_found_; i++) ConnectLoopTree(i); | 377 for (int i = 1; i <= loops_found_; i++) ConnectLoopTree(i); |
319 | 378 |
(...skipping 15 matching lines...) Expand all Loading... |
335 LoopInfo* loop = &loops_[loop_num - 1]; | 394 LoopInfo* loop = &loops_[loop_num - 1]; |
336 if (innermost == nullptr || | 395 if (innermost == nullptr || |
337 loop->loop->depth_ > innermost->loop->depth_) { | 396 loop->loop->depth_ > innermost->loop->depth_) { |
338 innermost = loop; | 397 innermost = loop; |
339 innermost_index = loop_num; | 398 innermost_index = loop_num; |
340 } | 399 } |
341 } | 400 } |
342 } | 401 } |
343 } | 402 } |
344 if (innermost == nullptr) continue; | 403 if (innermost == nullptr) continue; |
345 if (LoopNum(ni.node) == innermost_index) { | 404 AddNodeToLoop(&ni, innermost, innermost_index); |
346 ni.next = innermost->header_list; | |
347 innermost->header_list = ∋ | |
348 } else { | |
349 ni.next = innermost->body_list; | |
350 innermost->body_list = ∋ | |
351 } | |
352 count++; | 405 count++; |
353 } | 406 } |
354 | 407 |
355 // Serialize the node lists for loops into the loop tree. | 408 // Serialize the node lists for loops into the loop tree. |
356 loop_tree_->loop_nodes_.reserve(count); | 409 loop_tree_->loop_nodes_.reserve(count); |
357 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) { | 410 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) { |
358 SerializeLoop(loop); | 411 SerializeLoop(loop); |
359 } | 412 } |
360 } | 413 } |
361 | 414 |
362 // Handle the simpler case of a single loop (no checks for nesting necessary). | 415 // Handle the simpler case of a single loop (no checks for nesting necessary). |
363 void FinishSingleLoop() { | 416 void FinishSingleLoop() { |
364 // Place nodes into the loop header and body. | 417 // Place nodes into the loop header and body. |
365 LoopInfo* li = &loops_[0]; | 418 LoopInfo* li = &loops_[0]; |
366 li->loop = &loop_tree_->all_loops_[0]; | 419 li->loop = &loop_tree_->all_loops_[0]; |
367 loop_tree_->SetParent(nullptr, li->loop); | 420 loop_tree_->SetParent(nullptr, li->loop); |
368 size_t count = 0; | 421 size_t count = 0; |
369 for (NodeInfo& ni : info_) { | 422 for (NodeInfo& ni : info_) { |
370 if (ni.node == nullptr || !IsInLoop(ni.node, 1)) continue; | 423 if (ni.node == nullptr || !IsInLoop(ni.node, 1)) continue; |
371 if (LoopNum(ni.node) == 1) { | 424 AddNodeToLoop(&ni, li, 1); |
372 ni.next = li->header_list; | |
373 li->header_list = ∋ | |
374 } else { | |
375 ni.next = li->body_list; | |
376 li->body_list = ∋ | |
377 } | |
378 count++; | 425 count++; |
379 } | 426 } |
380 | 427 |
381 // Serialize the node lists for the loop into the loop tree. | 428 // Serialize the node lists for the loop into the loop tree. |
382 loop_tree_->loop_nodes_.reserve(count); | 429 loop_tree_->loop_nodes_.reserve(count); |
383 SerializeLoop(li->loop); | 430 SerializeLoop(li->loop); |
384 } | 431 } |
385 | 432 |
386 // Recursively serialize the list of header nodes and body nodes | 433 // Recursively serialize the list of header nodes and body nodes |
387 // so that nested loops occupy nested intervals. | 434 // so that nested loops occupy nested intervals. |
(...skipping 11 matching lines...) Expand all Loading... |
399 // Serialize the body. | 446 // Serialize the body. |
400 loop->body_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); | 447 loop->body_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); |
401 for (NodeInfo* ni = li.body_list; ni != nullptr; ni = ni->next) { | 448 for (NodeInfo* ni = li.body_list; ni != nullptr; ni = ni->next) { |
402 loop_tree_->loop_nodes_.push_back(ni->node); | 449 loop_tree_->loop_nodes_.push_back(ni->node); |
403 loop_tree_->node_to_loop_num_[ni->node->id()] = loop_num; | 450 loop_tree_->node_to_loop_num_[ni->node->id()] = loop_num; |
404 } | 451 } |
405 | 452 |
406 // Serialize nested loops. | 453 // Serialize nested loops. |
407 for (LoopTree::Loop* child : loop->children_) SerializeLoop(child); | 454 for (LoopTree::Loop* child : loop->children_) SerializeLoop(child); |
408 | 455 |
409 loop->body_end_ = static_cast<int>(loop_tree_->loop_nodes_.size()); | 456 // Serialize the exits. |
| 457 loop->exits_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); |
| 458 for (NodeInfo* ni = li.exit_list; ni != nullptr; ni = ni->next) { |
| 459 loop_tree_->loop_nodes_.push_back(ni->node); |
| 460 loop_tree_->node_to_loop_num_[ni->node->id()] = loop_num; |
| 461 } |
| 462 |
| 463 loop->exits_end_ = static_cast<int>(loop_tree_->loop_nodes_.size()); |
410 } | 464 } |
411 | 465 |
412 // Connect the LoopTree loops to their parents recursively. | 466 // Connect the LoopTree loops to their parents recursively. |
413 LoopTree::Loop* ConnectLoopTree(int loop_num) { | 467 LoopTree::Loop* ConnectLoopTree(int loop_num) { |
414 LoopInfo& li = loops_[loop_num - 1]; | 468 LoopInfo& li = loops_[loop_num - 1]; |
415 if (li.loop != nullptr) return li.loop; | 469 if (li.loop != nullptr) return li.loop; |
416 | 470 |
417 NodeInfo& ni = info(li.header); | 471 NodeInfo& ni = info(li.header); |
418 LoopTree::Loop* parent = nullptr; | 472 LoopTree::Loop* parent = nullptr; |
419 for (int i = 1; i <= loops_found_; i++) { | 473 for (int i = 1; i <= loops_found_; i++) { |
(...skipping 11 matching lines...) Expand all Loading... |
431 return li.loop; | 485 return li.loop; |
432 } | 486 } |
433 | 487 |
434 void PrintLoop(LoopTree::Loop* loop) { | 488 void PrintLoop(LoopTree::Loop* loop) { |
435 for (int i = 0; i < loop->depth_; i++) PrintF(" "); | 489 for (int i = 0; i < loop->depth_; i++) PrintF(" "); |
436 PrintF("Loop depth = %d ", loop->depth_); | 490 PrintF("Loop depth = %d ", loop->depth_); |
437 int i = loop->header_start_; | 491 int i = loop->header_start_; |
438 while (i < loop->body_start_) { | 492 while (i < loop->body_start_) { |
439 PrintF(" H#%d", loop_tree_->loop_nodes_[i++]->id()); | 493 PrintF(" H#%d", loop_tree_->loop_nodes_[i++]->id()); |
440 } | 494 } |
441 while (i < loop->body_end_) { | 495 while (i < loop->exits_start_) { |
442 PrintF(" B#%d", loop_tree_->loop_nodes_[i++]->id()); | 496 PrintF(" B#%d", loop_tree_->loop_nodes_[i++]->id()); |
443 } | 497 } |
| 498 while (i < loop->exits_end_) { |
| 499 PrintF(" E#%d", loop_tree_->loop_nodes_[i++]->id()); |
| 500 } |
444 PrintF("\n"); | 501 PrintF("\n"); |
445 for (LoopTree::Loop* child : loop->children_) PrintLoop(child); | 502 for (LoopTree::Loop* child : loop->children_) PrintLoop(child); |
446 } | 503 } |
447 }; | 504 }; |
448 | 505 |
449 | 506 |
450 LoopTree* LoopFinder::BuildLoopTree(Graph* graph, Zone* zone) { | 507 LoopTree* LoopFinder::BuildLoopTree(Graph* graph, Zone* zone) { |
451 LoopTree* loop_tree = | 508 LoopTree* loop_tree = |
452 new (graph->zone()) LoopTree(graph->NodeCount(), graph->zone()); | 509 new (graph->zone()) LoopTree(graph->NodeCount(), graph->zone()); |
453 LoopFinderImpl finder(graph, loop_tree, zone); | 510 LoopFinderImpl finder(graph, loop_tree, zone); |
(...skipping 10 matching lines...) Expand all Loading... |
464 if (first->opcode() == IrOpcode::kLoop) return first; | 521 if (first->opcode() == IrOpcode::kLoop) return first; |
465 DCHECK(IrOpcode::IsPhiOpcode(first->opcode())); | 522 DCHECK(IrOpcode::IsPhiOpcode(first->opcode())); |
466 Node* header = NodeProperties::GetControlInput(first); | 523 Node* header = NodeProperties::GetControlInput(first); |
467 DCHECK_EQ(IrOpcode::kLoop, header->opcode()); | 524 DCHECK_EQ(IrOpcode::kLoop, header->opcode()); |
468 return header; | 525 return header; |
469 } | 526 } |
470 | 527 |
471 } // namespace compiler | 528 } // namespace compiler |
472 } // namespace internal | 529 } // namespace internal |
473 } // namespace v8 | 530 } // namespace v8 |
OLD | NEW |