| 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 |