| OLD | NEW |
| 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 <deque> | 5 #include <deque> |
| 6 #include <queue> | 6 #include <queue> |
| 7 | 7 |
| 8 #include "src/compiler/scheduler.h" | 8 #include "src/compiler/scheduler.h" |
| 9 | 9 |
| 10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 ConnectReturn(node); | 115 ConnectReturn(node); |
| 116 break; | 116 break; |
| 117 default: | 117 default: |
| 118 break; | 118 break; |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 | 121 |
| 122 void BuildBlockForNode(Node* node) { | 122 void BuildBlockForNode(Node* node) { |
| 123 if (schedule_->block(node) == NULL) { | 123 if (schedule_->block(node) == NULL) { |
| 124 BasicBlock* block = schedule_->NewBasicBlock(); | 124 BasicBlock* block = schedule_->NewBasicBlock(); |
| 125 Trace("Create block B%d for #%d:%s\n", block->id(), node->id(), | 125 Trace("Create block B%d for #%d:%s\n", block->id().ToInt(), node->id(), |
| 126 node->op()->mnemonic()); | 126 node->op()->mnemonic()); |
| 127 FixNode(block, node); | 127 FixNode(block, node); |
| 128 } | 128 } |
| 129 } | 129 } |
| 130 | 130 |
| 131 void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a, | 131 void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a, |
| 132 IrOpcode::Value b) { | 132 IrOpcode::Value b) { |
| 133 Node* successors[2]; | 133 Node* successors[2]; |
| 134 CollectSuccessorProjections(node, successors, a, b); | 134 CollectSuccessorProjections(node, successors, a, b); |
| 135 BuildBlockForNode(successors[0]); | 135 BuildBlockForNode(successors[0]); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 Node* return_block_node = NodeProperties::GetControlInput(ret); | 202 Node* return_block_node = NodeProperties::GetControlInput(ret); |
| 203 BasicBlock* return_block = schedule_->block(return_block_node); | 203 BasicBlock* return_block = schedule_->block(return_block_node); |
| 204 TraceConnect(ret, return_block, NULL); | 204 TraceConnect(ret, return_block, NULL); |
| 205 schedule_->AddReturn(return_block, ret); | 205 schedule_->AddReturn(return_block, ret); |
| 206 } | 206 } |
| 207 | 207 |
| 208 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { | 208 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { |
| 209 DCHECK_NE(NULL, block); | 209 DCHECK_NE(NULL, block); |
| 210 if (succ == NULL) { | 210 if (succ == NULL) { |
| 211 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), | 211 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), |
| 212 block->id()); | 212 block->id().ToInt()); |
| 213 } else { | 213 } else { |
| 214 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), | 214 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), |
| 215 block->id(), succ->id()); | 215 block->id().ToInt(), succ->id().ToInt()); |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 }; | 218 }; |
| 219 | 219 |
| 220 | 220 |
| 221 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { | 221 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { |
| 222 SchedulerData def = {0, 0, false, false, kUnknown}; | 222 SchedulerData def = {0, 0, false, false, kUnknown}; |
| 223 return def; | 223 return def; |
| 224 } | 224 } |
| 225 | 225 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_)); | 304 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_)); |
| 305 } | 305 } |
| 306 | 306 |
| 307 | 307 |
| 308 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) { | 308 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) { |
| 309 while (b1 != b2) { | 309 while (b1 != b2) { |
| 310 int b1_rpo = GetRPONumber(b1); | 310 int b1_rpo = GetRPONumber(b1); |
| 311 int b2_rpo = GetRPONumber(b2); | 311 int b2_rpo = GetRPONumber(b2); |
| 312 DCHECK(b1_rpo != b2_rpo); | 312 DCHECK(b1_rpo != b2_rpo); |
| 313 if (b1_rpo < b2_rpo) { | 313 if (b1_rpo < b2_rpo) { |
| 314 b2 = b2->dominator_; | 314 b2 = b2->dominator(); |
| 315 } else { | 315 } else { |
| 316 b1 = b1->dominator_; | 316 b1 = b1->dominator(); |
| 317 } | 317 } |
| 318 } | 318 } |
| 319 return b1; | 319 return b1; |
| 320 } | 320 } |
| 321 | 321 |
| 322 | 322 |
| 323 void Scheduler::GenerateImmediateDominatorTree() { | 323 void Scheduler::GenerateImmediateDominatorTree() { |
| 324 // Build the dominator graph. TODO(danno): consider using Lengauer & Tarjan's | 324 // Build the dominator graph. TODO(danno): consider using Lengauer & Tarjan's |
| 325 // if this becomes really slow. | 325 // if this becomes really slow. |
| 326 Trace("------------ IMMEDIATE BLOCK DOMINATORS -----------\n"); | 326 Trace("------------ IMMEDIATE BLOCK DOMINATORS -----------\n"); |
| 327 for (size_t i = 0; i < schedule_->rpo_order_.size(); i++) { | 327 for (size_t i = 0; i < schedule_->rpo_order_.size(); i++) { |
| 328 BasicBlock* current_rpo = schedule_->rpo_order_[i]; | 328 BasicBlock* current_rpo = schedule_->rpo_order_[i]; |
| 329 if (current_rpo != schedule_->start()) { | 329 if (current_rpo != schedule_->start()) { |
| 330 BasicBlock::Predecessors::iterator current_pred = | 330 BasicBlock::Predecessors::iterator current_pred = |
| 331 current_rpo->predecessors().begin(); | 331 current_rpo->predecessors_begin(); |
| 332 BasicBlock::Predecessors::iterator end = | 332 BasicBlock::Predecessors::iterator end = current_rpo->predecessors_end(); |
| 333 current_rpo->predecessors().end(); | |
| 334 DCHECK(current_pred != end); | 333 DCHECK(current_pred != end); |
| 335 BasicBlock* dominator = *current_pred; | 334 BasicBlock* dominator = *current_pred; |
| 336 ++current_pred; | 335 ++current_pred; |
| 337 // For multiple predecessors, walk up the rpo ordering until a common | 336 // For multiple predecessors, walk up the rpo ordering until a common |
| 338 // dominator is found. | 337 // dominator is found. |
| 339 int current_rpo_pos = GetRPONumber(current_rpo); | 338 int current_rpo_pos = GetRPONumber(current_rpo); |
| 340 while (current_pred != end) { | 339 while (current_pred != end) { |
| 341 // Don't examine backwards edges | 340 // Don't examine backwards edges |
| 342 BasicBlock* pred = *current_pred; | 341 BasicBlock* pred = *current_pred; |
| 343 if (GetRPONumber(pred) < current_rpo_pos) { | 342 if (GetRPONumber(pred) < current_rpo_pos) { |
| 344 dominator = GetCommonDominator(dominator, *current_pred); | 343 dominator = GetCommonDominator(dominator, *current_pred); |
| 345 } | 344 } |
| 346 ++current_pred; | 345 ++current_pred; |
| 347 } | 346 } |
| 348 current_rpo->dominator_ = dominator; | 347 current_rpo->set_dominator(dominator); |
| 349 Trace("Block %d's idom is %d\n", current_rpo->id(), dominator->id()); | 348 Trace("Block %d's idom is %d\n", current_rpo->id(), |
| 349 dominator->id().ToInt()); |
| 350 } | 350 } |
| 351 } | 351 } |
| 352 } | 352 } |
| 353 | 353 |
| 354 | 354 |
| 355 class ScheduleEarlyNodeVisitor : public NullNodeVisitor { | 355 class ScheduleEarlyNodeVisitor : public NullNodeVisitor { |
| 356 public: | 356 public: |
| 357 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) | 357 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) |
| 358 : has_changed_rpo_constraints_(true), | 358 : has_changed_rpo_constraints_(true), |
| 359 scheduler_(scheduler), | 359 scheduler_(scheduler), |
| 360 schedule_(scheduler->schedule_) {} | 360 schedule_(scheduler->schedule_) {} |
| 361 | 361 |
| 362 GenericGraphVisit::Control Pre(Node* node) { | 362 GenericGraphVisit::Control Pre(Node* node) { |
| 363 int max_rpo = 0; | 363 int max_rpo = 0; |
| 364 // Fixed nodes already know their schedule early position. | 364 // Fixed nodes already know their schedule early position. |
| 365 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { | 365 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { |
| 366 BasicBlock* block = schedule_->block(node); | 366 BasicBlock* block = schedule_->block(node); |
| 367 DCHECK(block != NULL); | 367 DCHECK(block != NULL); |
| 368 max_rpo = block->rpo_number_; | 368 max_rpo = block->rpo_number(); |
| 369 if (scheduler_->GetData(node)->minimum_rpo_ != max_rpo) { | 369 if (scheduler_->GetData(node)->minimum_rpo_ != max_rpo) { |
| 370 has_changed_rpo_constraints_ = true; | 370 has_changed_rpo_constraints_ = true; |
| 371 } | 371 } |
| 372 scheduler_->GetData(node)->minimum_rpo_ = max_rpo; | 372 scheduler_->GetData(node)->minimum_rpo_ = max_rpo; |
| 373 Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(), | 373 Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(), |
| 374 node->op()->mnemonic(), max_rpo); | 374 node->op()->mnemonic(), max_rpo); |
| 375 } | 375 } |
| 376 return GenericGraphVisit::CONTINUE; | 376 return GenericGraphVisit::CONTINUE; |
| 377 } | 377 } |
| 378 | 378 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 ? block | 506 ? block |
| 507 : scheduler_->GetCommonDominator( | 507 : scheduler_->GetCommonDominator( |
| 508 block, use_block); | 508 block, use_block); |
| 509 } | 509 } |
| 510 DCHECK(block != NULL); | 510 DCHECK(block != NULL); |
| 511 | 511 |
| 512 int min_rpo = data->minimum_rpo_; | 512 int min_rpo = data->minimum_rpo_; |
| 513 Trace( | 513 Trace( |
| 514 "Schedule late conservative for #%d:%s is B%d at loop depth %d, " | 514 "Schedule late conservative for #%d:%s is B%d at loop depth %d, " |
| 515 "minimum_rpo = %d\n", | 515 "minimum_rpo = %d\n", |
| 516 node->id(), node->op()->mnemonic(), block->id(), block->loop_depth_, | 516 node->id(), node->op()->mnemonic(), block->id().ToInt(), |
| 517 min_rpo); | 517 block->loop_depth(), min_rpo); |
| 518 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively | 518 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively |
| 519 // into enclosing loop pre-headers until they would preceed their | 519 // into enclosing loop pre-headers until they would preceed their |
| 520 // ScheduleEarly position. | 520 // ScheduleEarly position. |
| 521 BasicBlock* hoist_block = block; | 521 BasicBlock* hoist_block = block; |
| 522 while (hoist_block != NULL && hoist_block->rpo_number_ >= min_rpo) { | 522 while (hoist_block != NULL && hoist_block->rpo_number() >= min_rpo) { |
| 523 if (hoist_block->loop_depth_ < block->loop_depth_) { | 523 if (hoist_block->loop_depth() < block->loop_depth()) { |
| 524 block = hoist_block; | 524 block = hoist_block; |
| 525 Trace(" hoisting #%d:%s to block %d\n", node->id(), | 525 Trace(" hoisting #%d:%s to block %d\n", node->id(), |
| 526 node->op()->mnemonic(), block->id()); | 526 node->op()->mnemonic(), block->id().ToInt()); |
| 527 } | 527 } |
| 528 // Try to hoist to the pre-header of the loop header. | 528 // Try to hoist to the pre-header of the loop header. |
| 529 hoist_block = hoist_block->loop_header(); | 529 hoist_block = hoist_block->loop_header(); |
| 530 if (hoist_block != NULL) { | 530 if (hoist_block != NULL) { |
| 531 BasicBlock* pre_header = hoist_block->dominator_; | 531 BasicBlock* pre_header = hoist_block->dominator(); |
| 532 DCHECK(pre_header == NULL || | 532 DCHECK(pre_header == NULL || |
| 533 *hoist_block->predecessors().begin() == pre_header); | 533 *hoist_block->predecessors_begin() == pre_header); |
| 534 Trace( | 534 Trace( |
| 535 " hoist to pre-header B%d of loop header B%d, depth would be %d\n", | 535 " hoist to pre-header B%d of loop header B%d, depth would be %d\n", |
| 536 pre_header->id(), hoist_block->id(), pre_header->loop_depth_); | 536 pre_header->id().ToInt(), hoist_block->id().ToInt(), |
| 537 pre_header->loop_depth()); |
| 537 hoist_block = pre_header; | 538 hoist_block = pre_header; |
| 538 } | 539 } |
| 539 } | 540 } |
| 540 | 541 |
| 541 ScheduleNode(block, node); | 542 ScheduleNode(block, node); |
| 542 | 543 |
| 543 return GenericGraphVisit::CONTINUE; | 544 return GenericGraphVisit::CONTINUE; |
| 544 } | 545 } |
| 545 | 546 |
| 546 private: | 547 private: |
| 547 BasicBlock* GetBlockForUse(Node::Edge edge) { | 548 BasicBlock* GetBlockForUse(Node::Edge edge) { |
| 548 Node* use = edge.from(); | 549 Node* use = edge.from(); |
| 549 IrOpcode::Value opcode = use->opcode(); | 550 IrOpcode::Value opcode = use->opcode(); |
| 550 if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) { | 551 if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) { |
| 551 // If the use is from a fixed (i.e. non-floating) phi, use the block | 552 // If the use is from a fixed (i.e. non-floating) phi, use the block |
| 552 // of the corresponding control input to the merge. | 553 // of the corresponding control input to the merge. |
| 553 int index = edge.index(); | 554 int index = edge.index(); |
| 554 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { | 555 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { |
| 555 Trace(" input@%d into a fixed phi #%d:%s\n", index, use->id(), | 556 Trace(" input@%d into a fixed phi #%d:%s\n", index, use->id(), |
| 556 use->op()->mnemonic()); | 557 use->op()->mnemonic()); |
| 557 Node* merge = NodeProperties::GetControlInput(use, 0); | 558 Node* merge = NodeProperties::GetControlInput(use, 0); |
| 558 opcode = merge->opcode(); | 559 opcode = merge->opcode(); |
| 559 DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop); | 560 DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop); |
| 560 use = NodeProperties::GetControlInput(merge, index); | 561 use = NodeProperties::GetControlInput(merge, index); |
| 561 } | 562 } |
| 562 } | 563 } |
| 563 BasicBlock* result = schedule_->block(use); | 564 BasicBlock* result = schedule_->block(use); |
| 564 if (result == NULL) return NULL; | 565 if (result == NULL) return NULL; |
| 565 Trace(" must dominate use #%d:%s in B%d\n", use->id(), | 566 Trace(" must dominate use #%d:%s in B%d\n", use->id(), |
| 566 use->op()->mnemonic(), result->id()); | 567 use->op()->mnemonic(), result->id().ToInt()); |
| 567 return result; | 568 return result; |
| 568 } | 569 } |
| 569 | 570 |
| 570 void ScheduleNode(BasicBlock* block, Node* node) { | 571 void ScheduleNode(BasicBlock* block, Node* node) { |
| 571 schedule_->PlanNode(block, node); | 572 schedule_->PlanNode(block, node); |
| 572 scheduler_->scheduled_nodes_[block->id()].push_back(node); | 573 scheduler_->scheduled_nodes_[block->id().ToSize()].push_back(node); |
| 573 | 574 |
| 574 // Reduce the use count of the node's inputs to potentially make them | 575 // Reduce the use count of the node's inputs to potentially make them |
| 575 // schedulable. | 576 // schedulable. |
| 576 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { | 577 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { |
| 577 Scheduler::SchedulerData* data = scheduler_->GetData(*i); | 578 Scheduler::SchedulerData* data = scheduler_->GetData(*i); |
| 578 DCHECK(data->unscheduled_count_ > 0); | 579 DCHECK(data->unscheduled_count_ > 0); |
| 579 --data->unscheduled_count_; | 580 --data->unscheduled_count_; |
| 580 if (FLAG_trace_turbo_scheduler) { | 581 if (FLAG_trace_turbo_scheduler) { |
| 581 Trace(" Use count for #%d:%s (used by #%d:%s)-- = %d\n", (*i)->id(), | 582 Trace(" Use count for #%d:%s (used by #%d:%s)-- = %d\n", (*i)->id(), |
| 582 (*i)->op()->mnemonic(), i.edge().from()->id(), | 583 (*i)->op()->mnemonic(), i.edge().from()->id(), |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 // Process blocks and instructions backwards to find and connect floating | 637 // Process blocks and instructions backwards to find and connect floating |
| 637 // control nodes into the control graph according to the block they were | 638 // control nodes into the control graph according to the block they were |
| 638 // scheduled into. | 639 // scheduled into. |
| 639 int max = static_cast<int>(schedule_->rpo_order()->size()); | 640 int max = static_cast<int>(schedule_->rpo_order()->size()); |
| 640 for (int i = max - 1; i >= 0; i--) { | 641 for (int i = max - 1; i >= 0; i--) { |
| 641 BasicBlock* block = schedule_->rpo_order()->at(i); | 642 BasicBlock* block = schedule_->rpo_order()->at(i); |
| 642 // TODO(titzer): we place at most one floating control structure per | 643 // TODO(titzer): we place at most one floating control structure per |
| 643 // basic block because scheduling currently can interleave phis from | 644 // basic block because scheduling currently can interleave phis from |
| 644 // one subgraph with the merges from another subgraph. | 645 // one subgraph with the merges from another subgraph. |
| 645 bool one_placed = false; | 646 bool one_placed = false; |
| 646 for (int j = static_cast<int>(block->nodes_.size()) - 1; j >= 0; j--) { | 647 for (size_t j = 0; j < block->NodeCount(); j++) { |
| 647 Node* node = block->nodes_[j]; | 648 Node* node = block->NodeAt(block->NodeCount() - 1 - j); |
| 648 SchedulerData* data = GetData(node); | 649 SchedulerData* data = GetData(node); |
| 649 if (data->is_floating_control_ && !data->is_connected_control_ && | 650 if (data->is_floating_control_ && !data->is_connected_control_ && |
| 650 !one_placed) { | 651 !one_placed) { |
| 651 Trace(" Floating control #%d:%s was scheduled in B%d\n", node->id(), | 652 Trace(" Floating control #%d:%s was scheduled in B%d\n", node->id(), |
| 652 node->op()->mnemonic(), block->id()); | 653 node->op()->mnemonic(), block->id().ToInt()); |
| 653 ConnectFloatingControlSubgraph(block, node); | 654 ConnectFloatingControlSubgraph(block, node); |
| 654 one_placed = true; | 655 one_placed = true; |
| 655 } | 656 } |
| 656 } | 657 } |
| 657 } | 658 } |
| 658 | 659 |
| 659 return true; | 660 return true; |
| 660 } | 661 } |
| 661 | 662 |
| 662 | 663 |
| 663 void Scheduler::ConnectFloatingControlSubgraph(BasicBlock* block, Node* end) { | 664 void Scheduler::ConnectFloatingControlSubgraph(BasicBlock* block, Node* end) { |
| 664 Node* block_start = block->nodes_[0]; | 665 Node* block_start = block->NodeAt(0); |
| 665 DCHECK(IrOpcode::IsControlOpcode(block_start->opcode())); | 666 DCHECK(IrOpcode::IsControlOpcode(block_start->opcode())); |
| 666 // Find the current "control successor" of the node that starts the block | 667 // Find the current "control successor" of the node that starts the block |
| 667 // by searching the control uses for a control input edge from a connected | 668 // by searching the control uses for a control input edge from a connected |
| 668 // control node. | 669 // control node. |
| 669 Node* control_succ = NULL; | 670 Node* control_succ = NULL; |
| 670 for (UseIter i = block_start->uses().begin(); i != block_start->uses().end(); | 671 for (UseIter i = block_start->uses().begin(); i != block_start->uses().end(); |
| 671 ++i) { | 672 ++i) { |
| 672 Node::Edge edge = i.edge(); | 673 Node::Edge edge = i.edge(); |
| 673 if (NodeProperties::IsControlEdge(edge) && | 674 if (NodeProperties::IsControlEdge(edge) && |
| 674 GetData(edge.from())->is_connected_control_) { | 675 GetData(edge.from())->is_connected_control_) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 | 727 |
| 727 // Numbering for BasicBlockData.rpo_number_ for this block traversal: | 728 // Numbering for BasicBlockData.rpo_number_ for this block traversal: |
| 728 static const int kBlockOnStack = -2; | 729 static const int kBlockOnStack = -2; |
| 729 static const int kBlockVisited1 = -3; | 730 static const int kBlockVisited1 = -3; |
| 730 static const int kBlockVisited2 = -4; | 731 static const int kBlockVisited2 = -4; |
| 731 static const int kBlockUnvisited1 = -1; | 732 static const int kBlockUnvisited1 = -1; |
| 732 static const int kBlockUnvisited2 = kBlockVisited1; | 733 static const int kBlockUnvisited2 = kBlockVisited1; |
| 733 | 734 |
| 734 struct SpecialRPOStackFrame { | 735 struct SpecialRPOStackFrame { |
| 735 BasicBlock* block; | 736 BasicBlock* block; |
| 736 int index; | 737 size_t index; |
| 737 }; | 738 }; |
| 738 | 739 |
| 739 struct BlockList { | 740 struct BlockList { |
| 740 BasicBlock* block; | 741 BasicBlock* block; |
| 741 BlockList* next; | 742 BlockList* next; |
| 742 | 743 |
| 743 BlockList* Add(Zone* zone, BasicBlock* b) { | 744 BlockList* Add(Zone* zone, BasicBlock* b) { |
| 744 BlockList* list = static_cast<BlockList*>(zone->New(sizeof(BlockList))); | 745 BlockList* list = static_cast<BlockList*>(zone->New(sizeof(BlockList))); |
| 745 list->block = b; | 746 list->block = b; |
| 746 list->next = this; | 747 list->next = this; |
| 747 return list; | 748 return list; |
| 748 } | 749 } |
| 749 | 750 |
| 750 void Serialize(BasicBlockVector* final_order) { | 751 void Serialize(BasicBlockVector* final_order) { |
| 751 for (BlockList* l = this; l != NULL; l = l->next) { | 752 for (BlockList* l = this; l != NULL; l = l->next) { |
| 752 l->block->rpo_number_ = static_cast<int>(final_order->size()); | 753 l->block->set_rpo_number(static_cast<int>(final_order->size())); |
| 753 final_order->push_back(l->block); | 754 final_order->push_back(l->block); |
| 754 } | 755 } |
| 755 } | 756 } |
| 756 }; | 757 }; |
| 757 | 758 |
| 758 struct LoopInfo { | 759 struct LoopInfo { |
| 759 BasicBlock* header; | 760 BasicBlock* header; |
| 760 ZoneList<BasicBlock*>* outgoing; | 761 ZoneList<BasicBlock*>* outgoing; |
| 761 BitVector* members; | 762 BitVector* members; |
| 762 LoopInfo* prev; | 763 LoopInfo* prev; |
| 763 BlockList* end; | 764 BlockList* end; |
| 764 BlockList* start; | 765 BlockList* start; |
| 765 | 766 |
| 766 void AddOutgoing(Zone* zone, BasicBlock* block) { | 767 void AddOutgoing(Zone* zone, BasicBlock* block) { |
| 767 if (outgoing == NULL) outgoing = new (zone) ZoneList<BasicBlock*>(2, zone); | 768 if (outgoing == NULL) outgoing = new (zone) ZoneList<BasicBlock*>(2, zone); |
| 768 outgoing->Add(block, zone); | 769 outgoing->Add(block, zone); |
| 769 } | 770 } |
| 770 }; | 771 }; |
| 771 | 772 |
| 772 | 773 |
| 773 static int Push(SpecialRPOStackFrame* stack, int depth, BasicBlock* child, | 774 static int Push(SpecialRPOStackFrame* stack, int depth, BasicBlock* child, |
| 774 int unvisited) { | 775 int unvisited) { |
| 775 if (child->rpo_number_ == unvisited) { | 776 if (child->rpo_number() == unvisited) { |
| 776 stack[depth].block = child; | 777 stack[depth].block = child; |
| 777 stack[depth].index = 0; | 778 stack[depth].index = 0; |
| 778 child->rpo_number_ = kBlockOnStack; | 779 child->set_rpo_number(kBlockOnStack); |
| 779 return depth + 1; | 780 return depth + 1; |
| 780 } | 781 } |
| 781 return depth; | 782 return depth; |
| 782 } | 783 } |
| 783 | 784 |
| 784 | 785 |
| 785 // Computes loop membership from the backedges of the control flow graph. | 786 // Computes loop membership from the backedges of the control flow graph. |
| 786 static LoopInfo* ComputeLoopInfo( | 787 static LoopInfo* ComputeLoopInfo( |
| 787 Zone* zone, SpecialRPOStackFrame* queue, int num_loops, int num_blocks, | 788 Zone* zone, SpecialRPOStackFrame* queue, int num_loops, size_t num_blocks, |
| 788 ZoneList<std::pair<BasicBlock*, int> >* backedges) { | 789 ZoneList<std::pair<BasicBlock*, size_t> >* backedges) { |
| 789 LoopInfo* loops = zone->NewArray<LoopInfo>(num_loops); | 790 LoopInfo* loops = zone->NewArray<LoopInfo>(num_loops); |
| 790 memset(loops, 0, num_loops * sizeof(LoopInfo)); | 791 memset(loops, 0, num_loops * sizeof(LoopInfo)); |
| 791 | 792 |
| 792 // Compute loop membership starting from backedges. | 793 // Compute loop membership starting from backedges. |
| 793 // O(max(loop_depth) * max(|loop|) | 794 // O(max(loop_depth) * max(|loop|) |
| 794 for (int i = 0; i < backedges->length(); i++) { | 795 for (int i = 0; i < backedges->length(); i++) { |
| 795 BasicBlock* member = backedges->at(i).first; | 796 BasicBlock* member = backedges->at(i).first; |
| 796 BasicBlock* header = member->SuccessorAt(backedges->at(i).second); | 797 BasicBlock* header = member->SuccessorAt(backedges->at(i).second); |
| 797 int loop_num = header->loop_end_; | 798 int loop_num = header->loop_end(); |
| 798 if (loops[loop_num].header == NULL) { | 799 if (loops[loop_num].header == NULL) { |
| 799 loops[loop_num].header = header; | 800 loops[loop_num].header = header; |
| 800 loops[loop_num].members = new (zone) BitVector(num_blocks, zone); | 801 loops[loop_num].members = |
| 802 new (zone) BitVector(static_cast<int>(num_blocks), zone); |
| 801 } | 803 } |
| 802 | 804 |
| 803 int queue_length = 0; | 805 int queue_length = 0; |
| 804 if (member != header) { | 806 if (member != header) { |
| 805 // As long as the header doesn't have a backedge to itself, | 807 // As long as the header doesn't have a backedge to itself, |
| 806 // Push the member onto the queue and process its predecessors. | 808 // Push the member onto the queue and process its predecessors. |
| 807 if (!loops[loop_num].members->Contains(member->id())) { | 809 if (!loops[loop_num].members->Contains(member->id().ToInt())) { |
| 808 loops[loop_num].members->Add(member->id()); | 810 loops[loop_num].members->Add(member->id().ToInt()); |
| 809 } | 811 } |
| 810 queue[queue_length++].block = member; | 812 queue[queue_length++].block = member; |
| 811 } | 813 } |
| 812 | 814 |
| 813 // Propagate loop membership backwards. All predecessors of M up to the | 815 // Propagate loop membership backwards. All predecessors of M up to the |
| 814 // loop header H are members of the loop too. O(|blocks between M and H|). | 816 // loop header H are members of the loop too. O(|blocks between M and H|). |
| 815 while (queue_length > 0) { | 817 while (queue_length > 0) { |
| 816 BasicBlock* block = queue[--queue_length].block; | 818 BasicBlock* block = queue[--queue_length].block; |
| 817 for (int i = 0; i < block->PredecessorCount(); i++) { | 819 for (size_t i = 0; i < block->PredecessorCount(); i++) { |
| 818 BasicBlock* pred = block->PredecessorAt(i); | 820 BasicBlock* pred = block->PredecessorAt(i); |
| 819 if (pred != header) { | 821 if (pred != header) { |
| 820 if (!loops[loop_num].members->Contains(pred->id())) { | 822 if (!loops[loop_num].members->Contains(pred->id().ToInt())) { |
| 821 loops[loop_num].members->Add(pred->id()); | 823 loops[loop_num].members->Add(pred->id().ToInt()); |
| 822 queue[queue_length++].block = pred; | 824 queue[queue_length++].block = pred; |
| 823 } | 825 } |
| 824 } | 826 } |
| 825 } | 827 } |
| 826 } | 828 } |
| 827 } | 829 } |
| 828 return loops; | 830 return loops; |
| 829 } | 831 } |
| 830 | 832 |
| 831 | 833 |
| 832 #if DEBUG | 834 #if DEBUG |
| 833 static void PrintRPO(int num_loops, LoopInfo* loops, BasicBlockVector* order) { | 835 static void PrintRPO(int num_loops, LoopInfo* loops, BasicBlockVector* order) { |
| 834 PrintF("-- RPO with %d loops ", num_loops); | 836 OFStream os(stdout); |
| 837 os << "-- RPO with " << num_loops << " loops "; |
| 835 if (num_loops > 0) { | 838 if (num_loops > 0) { |
| 836 PrintF("("); | 839 os << "("; |
| 837 for (int i = 0; i < num_loops; i++) { | 840 for (int i = 0; i < num_loops; i++) { |
| 838 if (i > 0) PrintF(" "); | 841 if (i > 0) os << " "; |
| 839 PrintF("B%d", loops[i].header->id()); | 842 os << "B" << loops[i].header->id(); |
| 840 } | 843 } |
| 841 PrintF(") "); | 844 os << ") "; |
| 842 } | 845 } |
| 843 PrintF("-- \n"); | 846 os << "-- \n"; |
| 844 | 847 |
| 845 for (int i = 0; i < static_cast<int>(order->size()); i++) { | 848 for (size_t i = 0; i < order->size(); i++) { |
| 846 BasicBlock* block = (*order)[i]; | 849 BasicBlock* block = (*order)[i]; |
| 847 int bid = block->id(); | 850 BasicBlock::Id bid = block->id(); |
| 848 PrintF("%5d:", i); | 851 // TODO(jarin,svenpanne): Add formatting here once we have support for that |
| 849 for (int i = 0; i < num_loops; i++) { | 852 // in streams (we want an equivalent of PrintF("%5d:", i) here). |
| 850 bool membership = loops[i].members->Contains(bid); | 853 os << i << ":"; |
| 851 bool range = loops[i].header->LoopContains(block); | 854 for (int j = 0; j < num_loops; j++) { |
| 852 PrintF(membership ? " |" : " "); | 855 bool membership = loops[j].members->Contains(bid.ToInt()); |
| 853 PrintF(range ? "x" : " "); | 856 bool range = loops[j].header->LoopContains(block); |
| 857 os << (membership ? " |" : " "); |
| 858 os << (range ? "x" : " "); |
| 854 } | 859 } |
| 855 PrintF(" B%d: ", bid); | 860 os << " B" << bid << ": "; |
| 856 if (block->loop_end_ >= 0) { | 861 if (block->loop_end() >= 0) { |
| 857 PrintF(" range: [%d, %d)", block->rpo_number_, block->loop_end_); | 862 os << " range: [" << block->rpo_number() << ", " << block->loop_end() |
| 863 << ")"; |
| 858 } | 864 } |
| 859 PrintF("\n"); | 865 os << "\n"; |
| 860 } | 866 } |
| 861 } | 867 } |
| 862 | 868 |
| 863 | 869 |
| 864 static void VerifySpecialRPO(int num_loops, LoopInfo* loops, | 870 static void VerifySpecialRPO(int num_loops, LoopInfo* loops, |
| 865 BasicBlockVector* order) { | 871 BasicBlockVector* order) { |
| 866 DCHECK(order->size() > 0); | 872 DCHECK(order->size() > 0); |
| 867 DCHECK((*order)[0]->id() == 0); // entry should be first. | 873 DCHECK((*order)[0]->id().ToInt() == 0); // entry should be first. |
| 868 | 874 |
| 869 for (int i = 0; i < num_loops; i++) { | 875 for (int i = 0; i < num_loops; i++) { |
| 870 LoopInfo* loop = &loops[i]; | 876 LoopInfo* loop = &loops[i]; |
| 871 BasicBlock* header = loop->header; | 877 BasicBlock* header = loop->header; |
| 872 | 878 |
| 873 DCHECK(header != NULL); | 879 DCHECK(header != NULL); |
| 874 DCHECK(header->rpo_number_ >= 0); | 880 DCHECK(header->rpo_number() >= 0); |
| 875 DCHECK(header->rpo_number_ < static_cast<int>(order->size())); | 881 DCHECK(header->rpo_number() < static_cast<int>(order->size())); |
| 876 DCHECK(header->loop_end_ >= 0); | 882 DCHECK(header->loop_end() >= 0); |
| 877 DCHECK(header->loop_end_ <= static_cast<int>(order->size())); | 883 DCHECK(header->loop_end() <= static_cast<int>(order->size())); |
| 878 DCHECK(header->loop_end_ > header->rpo_number_); | 884 DCHECK(header->loop_end() > header->rpo_number()); |
| 879 | 885 |
| 880 // Verify the start ... end list relationship. | 886 // Verify the start ... end list relationship. |
| 881 int links = 0; | 887 int links = 0; |
| 882 BlockList* l = loop->start; | 888 BlockList* l = loop->start; |
| 883 DCHECK(l != NULL && l->block == header); | 889 DCHECK(l != NULL && l->block == header); |
| 884 bool end_found; | 890 bool end_found; |
| 885 while (true) { | 891 while (true) { |
| 886 if (l == NULL || l == loop->end) { | 892 if (l == NULL || l == loop->end) { |
| 887 end_found = (loop->end == l); | 893 end_found = (loop->end == l); |
| 888 break; | 894 break; |
| 889 } | 895 } |
| 890 // The list should be in same order as the final result. | 896 // The list should be in same order as the final result. |
| 891 DCHECK(l->block->rpo_number_ == links + loop->header->rpo_number_); | 897 DCHECK(l->block->rpo_number() == links + loop->header->rpo_number()); |
| 892 links++; | 898 links++; |
| 893 l = l->next; | 899 l = l->next; |
| 894 DCHECK(links < static_cast<int>(2 * order->size())); // cycle? | 900 DCHECK(links < static_cast<int>(2 * order->size())); // cycle? |
| 895 } | 901 } |
| 896 DCHECK(links > 0); | 902 DCHECK(links > 0); |
| 897 DCHECK(links == (header->loop_end_ - header->rpo_number_)); | 903 DCHECK(links == (header->loop_end() - header->rpo_number())); |
| 898 DCHECK(end_found); | 904 DCHECK(end_found); |
| 899 | 905 |
| 900 // Check the contiguousness of loops. | 906 // Check the contiguousness of loops. |
| 901 int count = 0; | 907 int count = 0; |
| 902 for (int j = 0; j < static_cast<int>(order->size()); j++) { | 908 for (int j = 0; j < static_cast<int>(order->size()); j++) { |
| 903 BasicBlock* block = order->at(j); | 909 BasicBlock* block = order->at(j); |
| 904 DCHECK(block->rpo_number_ == j); | 910 DCHECK(block->rpo_number() == j); |
| 905 if (j < header->rpo_number_ || j >= header->loop_end_) { | 911 if (j < header->rpo_number() || j >= header->loop_end()) { |
| 906 DCHECK(!loop->members->Contains(block->id())); | 912 DCHECK(!loop->members->Contains(block->id().ToInt())); |
| 907 } else { | 913 } else { |
| 908 if (block == header) { | 914 if (block == header) { |
| 909 DCHECK(!loop->members->Contains(block->id())); | 915 DCHECK(!loop->members->Contains(block->id().ToInt())); |
| 910 } else { | 916 } else { |
| 911 DCHECK(loop->members->Contains(block->id())); | 917 DCHECK(loop->members->Contains(block->id().ToInt())); |
| 912 } | 918 } |
| 913 count++; | 919 count++; |
| 914 } | 920 } |
| 915 } | 921 } |
| 916 DCHECK(links == count); | 922 DCHECK(links == count); |
| 917 } | 923 } |
| 918 } | 924 } |
| 919 #endif // DEBUG | 925 #endif // DEBUG |
| 920 | 926 |
| 921 | 927 |
| 922 // Compute the special reverse-post-order block ordering, which is essentially | 928 // Compute the special reverse-post-order block ordering, which is essentially |
| 923 // a RPO of the graph where loop bodies are contiguous. Properties: | 929 // a RPO of the graph where loop bodies are contiguous. Properties: |
| 924 // 1. If block A is a predecessor of B, then A appears before B in the order, | 930 // 1. If block A is a predecessor of B, then A appears before B in the order, |
| 925 // unless B is a loop header and A is in the loop headed at B | 931 // unless B is a loop header and A is in the loop headed at B |
| 926 // (i.e. A -> B is a backedge). | 932 // (i.e. A -> B is a backedge). |
| 927 // => If block A dominates block B, then A appears before B in the order. | 933 // => If block A dominates block B, then A appears before B in the order. |
| 928 // => If block A is a loop header, A appears before all blocks in the loop | 934 // => If block A is a loop header, A appears before all blocks in the loop |
| 929 // headed at A. | 935 // headed at A. |
| 930 // 2. All loops are contiguous in the order (i.e. no intervening blocks that | 936 // 2. All loops are contiguous in the order (i.e. no intervening blocks that |
| 931 // do not belong to the loop.) | 937 // do not belong to the loop.) |
| 932 // Note a simple RPO traversal satisfies (1) but not (3). | 938 // Note a simple RPO traversal satisfies (1) but not (3). |
| 933 BasicBlockVector* Scheduler::ComputeSpecialRPO(Schedule* schedule) { | 939 BasicBlockVector* Scheduler::ComputeSpecialRPO(Schedule* schedule) { |
| 934 Zone tmp_zone(schedule->zone()->isolate()); | 940 Zone tmp_zone(schedule->zone()->isolate()); |
| 935 Zone* zone = &tmp_zone; | 941 Zone* zone = &tmp_zone; |
| 936 Trace("------------- COMPUTING SPECIAL RPO ---------------\n"); | 942 Trace("------------- COMPUTING SPECIAL RPO ---------------\n"); |
| 937 // RPO should not have been computed for this schedule yet. | 943 // RPO should not have been computed for this schedule yet. |
| 938 CHECK_EQ(kBlockUnvisited1, schedule->start()->rpo_number_); | 944 CHECK_EQ(kBlockUnvisited1, schedule->start()->rpo_number()); |
| 939 CHECK_EQ(0, static_cast<int>(schedule->rpo_order_.size())); | 945 CHECK_EQ(0, static_cast<int>(schedule->rpo_order_.size())); |
| 940 | 946 |
| 941 // Perform an iterative RPO traversal using an explicit stack, | 947 // Perform an iterative RPO traversal using an explicit stack, |
| 942 // recording backedges that form cycles. O(|B|). | 948 // recording backedges that form cycles. O(|B|). |
| 943 ZoneList<std::pair<BasicBlock*, int> > backedges(1, zone); | 949 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone); |
| 944 SpecialRPOStackFrame* stack = | 950 SpecialRPOStackFrame* stack = zone->NewArray<SpecialRPOStackFrame>( |
| 945 zone->NewArray<SpecialRPOStackFrame>(schedule->BasicBlockCount()); | 951 static_cast<int>(schedule->BasicBlockCount())); |
| 946 BasicBlock* entry = schedule->start(); | 952 BasicBlock* entry = schedule->start(); |
| 947 BlockList* order = NULL; | 953 BlockList* order = NULL; |
| 948 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); | 954 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); |
| 949 int num_loops = 0; | 955 int num_loops = 0; |
| 950 | 956 |
| 951 while (stack_depth > 0) { | 957 while (stack_depth > 0) { |
| 952 int current = stack_depth - 1; | 958 int current = stack_depth - 1; |
| 953 SpecialRPOStackFrame* frame = stack + current; | 959 SpecialRPOStackFrame* frame = stack + current; |
| 954 | 960 |
| 955 if (frame->index < frame->block->SuccessorCount()) { | 961 if (frame->index < frame->block->SuccessorCount()) { |
| 956 // Process the next successor. | 962 // Process the next successor. |
| 957 BasicBlock* succ = frame->block->SuccessorAt(frame->index++); | 963 BasicBlock* succ = frame->block->SuccessorAt(frame->index++); |
| 958 if (succ->rpo_number_ == kBlockVisited1) continue; | 964 if (succ->rpo_number() == kBlockVisited1) continue; |
| 959 if (succ->rpo_number_ == kBlockOnStack) { | 965 if (succ->rpo_number() == kBlockOnStack) { |
| 960 // The successor is on the stack, so this is a backedge (cycle). | 966 // The successor is on the stack, so this is a backedge (cycle). |
| 961 backedges.Add( | 967 backedges.Add( |
| 962 std::pair<BasicBlock*, int>(frame->block, frame->index - 1), zone); | 968 std::pair<BasicBlock*, size_t>(frame->block, frame->index - 1), |
| 963 if (succ->loop_end_ < 0) { | 969 zone); |
| 970 if (succ->loop_end() < 0) { |
| 964 // Assign a new loop number to the header if it doesn't have one. | 971 // Assign a new loop number to the header if it doesn't have one. |
| 965 succ->loop_end_ = num_loops++; | 972 succ->set_loop_end(num_loops++); |
| 966 } | 973 } |
| 967 } else { | 974 } else { |
| 968 // Push the successor onto the stack. | 975 // Push the successor onto the stack. |
| 969 DCHECK(succ->rpo_number_ == kBlockUnvisited1); | 976 DCHECK(succ->rpo_number() == kBlockUnvisited1); |
| 970 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); | 977 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); |
| 971 } | 978 } |
| 972 } else { | 979 } else { |
| 973 // Finished with all successors; pop the stack and add the block. | 980 // Finished with all successors; pop the stack and add the block. |
| 974 order = order->Add(zone, frame->block); | 981 order = order->Add(zone, frame->block); |
| 975 frame->block->rpo_number_ = kBlockVisited1; | 982 frame->block->set_rpo_number(kBlockVisited1); |
| 976 stack_depth--; | 983 stack_depth--; |
| 977 } | 984 } |
| 978 } | 985 } |
| 979 | 986 |
| 980 // If no loops were encountered, then the order we computed was correct. | 987 // If no loops were encountered, then the order we computed was correct. |
| 981 LoopInfo* loops = NULL; | 988 LoopInfo* loops = NULL; |
| 982 if (num_loops != 0) { | 989 if (num_loops != 0) { |
| 983 // Otherwise, compute the loop information from the backedges in order | 990 // Otherwise, compute the loop information from the backedges in order |
| 984 // to perform a traversal that groups loop bodies together. | 991 // to perform a traversal that groups loop bodies together. |
| 985 loops = ComputeLoopInfo(zone, stack, num_loops, schedule->BasicBlockCount(), | 992 loops = ComputeLoopInfo(zone, stack, num_loops, schedule->BasicBlockCount(), |
| 986 &backedges); | 993 &backedges); |
| 987 | 994 |
| 988 // Initialize the "loop stack". Note the entry could be a loop header. | 995 // Initialize the "loop stack". Note the entry could be a loop header. |
| 989 LoopInfo* loop = entry->IsLoopHeader() ? &loops[entry->loop_end_] : NULL; | 996 LoopInfo* loop = entry->IsLoopHeader() ? &loops[entry->loop_end()] : NULL; |
| 990 order = NULL; | 997 order = NULL; |
| 991 | 998 |
| 992 // Perform an iterative post-order traversal, visiting loop bodies before | 999 // Perform an iterative post-order traversal, visiting loop bodies before |
| 993 // edges that lead out of loops. Visits each block once, but linking loop | 1000 // edges that lead out of loops. Visits each block once, but linking loop |
| 994 // sections together is linear in the loop size, so overall is | 1001 // sections together is linear in the loop size, so overall is |
| 995 // O(|B| + max(loop_depth) * max(|loop|)) | 1002 // O(|B| + max(loop_depth) * max(|loop|)) |
| 996 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); | 1003 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); |
| 997 while (stack_depth > 0) { | 1004 while (stack_depth > 0) { |
| 998 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); | 1005 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); |
| 999 BasicBlock* block = frame->block; | 1006 BasicBlock* block = frame->block; |
| 1000 BasicBlock* succ = NULL; | 1007 BasicBlock* succ = NULL; |
| 1001 | 1008 |
| 1002 if (frame->index < block->SuccessorCount()) { | 1009 if (frame->index < block->SuccessorCount()) { |
| 1003 // Process the next normal successor. | 1010 // Process the next normal successor. |
| 1004 succ = block->SuccessorAt(frame->index++); | 1011 succ = block->SuccessorAt(frame->index++); |
| 1005 } else if (block->IsLoopHeader()) { | 1012 } else if (block->IsLoopHeader()) { |
| 1006 // Process additional outgoing edges from the loop header. | 1013 // Process additional outgoing edges from the loop header. |
| 1007 if (block->rpo_number_ == kBlockOnStack) { | 1014 if (block->rpo_number() == kBlockOnStack) { |
| 1008 // Finish the loop body the first time the header is left on the | 1015 // Finish the loop body the first time the header is left on the |
| 1009 // stack. | 1016 // stack. |
| 1010 DCHECK(loop != NULL && loop->header == block); | 1017 DCHECK(loop != NULL && loop->header == block); |
| 1011 loop->start = order->Add(zone, block); | 1018 loop->start = order->Add(zone, block); |
| 1012 order = loop->end; | 1019 order = loop->end; |
| 1013 block->rpo_number_ = kBlockVisited2; | 1020 block->set_rpo_number(kBlockVisited2); |
| 1014 // Pop the loop stack and continue visiting outgoing edges within the | 1021 // Pop the loop stack and continue visiting outgoing edges within the |
| 1015 // the context of the outer loop, if any. | 1022 // the context of the outer loop, if any. |
| 1016 loop = loop->prev; | 1023 loop = loop->prev; |
| 1017 // We leave the loop header on the stack; the rest of this iteration | 1024 // We leave the loop header on the stack; the rest of this iteration |
| 1018 // and later iterations will go through its outgoing edges list. | 1025 // and later iterations will go through its outgoing edges list. |
| 1019 } | 1026 } |
| 1020 | 1027 |
| 1021 // Use the next outgoing edge if there are any. | 1028 // Use the next outgoing edge if there are any. |
| 1022 int outgoing_index = frame->index - block->SuccessorCount(); | 1029 int outgoing_index = |
| 1023 LoopInfo* info = &loops[block->loop_end_]; | 1030 static_cast<int>(frame->index - block->SuccessorCount()); |
| 1031 LoopInfo* info = &loops[block->loop_end()]; |
| 1024 DCHECK(loop != info); | 1032 DCHECK(loop != info); |
| 1025 if (info->outgoing != NULL && | 1033 if (info->outgoing != NULL && |
| 1026 outgoing_index < info->outgoing->length()) { | 1034 outgoing_index < info->outgoing->length()) { |
| 1027 succ = info->outgoing->at(outgoing_index); | 1035 succ = info->outgoing->at(outgoing_index); |
| 1028 frame->index++; | 1036 frame->index++; |
| 1029 } | 1037 } |
| 1030 } | 1038 } |
| 1031 | 1039 |
| 1032 if (succ != NULL) { | 1040 if (succ != NULL) { |
| 1033 // Process the next successor. | 1041 // Process the next successor. |
| 1034 if (succ->rpo_number_ == kBlockOnStack) continue; | 1042 if (succ->rpo_number() == kBlockOnStack) continue; |
| 1035 if (succ->rpo_number_ == kBlockVisited2) continue; | 1043 if (succ->rpo_number() == kBlockVisited2) continue; |
| 1036 DCHECK(succ->rpo_number_ == kBlockUnvisited2); | 1044 DCHECK(succ->rpo_number() == kBlockUnvisited2); |
| 1037 if (loop != NULL && !loop->members->Contains(succ->id())) { | 1045 if (loop != NULL && !loop->members->Contains(succ->id().ToInt())) { |
| 1038 // The successor is not in the current loop or any nested loop. | 1046 // The successor is not in the current loop or any nested loop. |
| 1039 // Add it to the outgoing edges of this loop and visit it later. | 1047 // Add it to the outgoing edges of this loop and visit it later. |
| 1040 loop->AddOutgoing(zone, succ); | 1048 loop->AddOutgoing(zone, succ); |
| 1041 } else { | 1049 } else { |
| 1042 // Push the successor onto the stack. | 1050 // Push the successor onto the stack. |
| 1043 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); | 1051 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); |
| 1044 if (succ->IsLoopHeader()) { | 1052 if (succ->IsLoopHeader()) { |
| 1045 // Push the inner loop onto the loop stack. | 1053 // Push the inner loop onto the loop stack. |
| 1046 DCHECK(succ->loop_end_ >= 0 && succ->loop_end_ < num_loops); | 1054 DCHECK(succ->loop_end() >= 0 && succ->loop_end() < num_loops); |
| 1047 LoopInfo* next = &loops[succ->loop_end_]; | 1055 LoopInfo* next = &loops[succ->loop_end()]; |
| 1048 next->end = order; | 1056 next->end = order; |
| 1049 next->prev = loop; | 1057 next->prev = loop; |
| 1050 loop = next; | 1058 loop = next; |
| 1051 } | 1059 } |
| 1052 } | 1060 } |
| 1053 } else { | 1061 } else { |
| 1054 // Finished with all successors of the current block. | 1062 // Finished with all successors of the current block. |
| 1055 if (block->IsLoopHeader()) { | 1063 if (block->IsLoopHeader()) { |
| 1056 // If we are going to pop a loop header, then add its entire body. | 1064 // If we are going to pop a loop header, then add its entire body. |
| 1057 LoopInfo* info = &loops[block->loop_end_]; | 1065 LoopInfo* info = &loops[block->loop_end()]; |
| 1058 for (BlockList* l = info->start; true; l = l->next) { | 1066 for (BlockList* l = info->start; true; l = l->next) { |
| 1059 if (l->next == info->end) { | 1067 if (l->next == info->end) { |
| 1060 l->next = order; | 1068 l->next = order; |
| 1061 info->end = order; | 1069 info->end = order; |
| 1062 break; | 1070 break; |
| 1063 } | 1071 } |
| 1064 } | 1072 } |
| 1065 order = info->start; | 1073 order = info->start; |
| 1066 } else { | 1074 } else { |
| 1067 // Pop a single node off the stack and add it to the order. | 1075 // Pop a single node off the stack and add it to the order. |
| 1068 order = order->Add(zone, block); | 1076 order = order->Add(zone, block); |
| 1069 block->rpo_number_ = kBlockVisited2; | 1077 block->set_rpo_number(kBlockVisited2); |
| 1070 } | 1078 } |
| 1071 stack_depth--; | 1079 stack_depth--; |
| 1072 } | 1080 } |
| 1073 } | 1081 } |
| 1074 } | 1082 } |
| 1075 | 1083 |
| 1076 // Construct the final order from the list. | 1084 // Construct the final order from the list. |
| 1077 BasicBlockVector* final_order = &schedule->rpo_order_; | 1085 BasicBlockVector* final_order = &schedule->rpo_order_; |
| 1078 order->Serialize(final_order); | 1086 order->Serialize(final_order); |
| 1079 | 1087 |
| 1080 // Compute the correct loop header for every block and set the correct loop | 1088 // Compute the correct loop header for every block and set the correct loop |
| 1081 // ends. | 1089 // ends. |
| 1082 LoopInfo* current_loop = NULL; | 1090 LoopInfo* current_loop = NULL; |
| 1083 BasicBlock* current_header = NULL; | 1091 BasicBlock* current_header = NULL; |
| 1084 int loop_depth = 0; | 1092 int loop_depth = 0; |
| 1085 for (BasicBlockVectorIter i = final_order->begin(); i != final_order->end(); | 1093 for (BasicBlockVectorIter i = final_order->begin(); i != final_order->end(); |
| 1086 ++i) { | 1094 ++i) { |
| 1087 BasicBlock* current = *i; | 1095 BasicBlock* current = *i; |
| 1088 current->loop_header_ = current_header; | 1096 current->set_loop_header(current_header); |
| 1089 if (current->IsLoopHeader()) { | 1097 if (current->IsLoopHeader()) { |
| 1090 loop_depth++; | 1098 loop_depth++; |
| 1091 current_loop = &loops[current->loop_end_]; | 1099 current_loop = &loops[current->loop_end()]; |
| 1092 BlockList* end = current_loop->end; | 1100 BlockList* end = current_loop->end; |
| 1093 current->loop_end_ = end == NULL ? static_cast<int>(final_order->size()) | 1101 current->set_loop_end(end == NULL ? static_cast<int>(final_order->size()) |
| 1094 : end->block->rpo_number_; | 1102 : end->block->rpo_number()); |
| 1095 current_header = current_loop->header; | 1103 current_header = current_loop->header; |
| 1096 Trace("B%d is a loop header, increment loop depth to %d\n", current->id(), | 1104 Trace("B%d is a loop header, increment loop depth to %d\n", |
| 1097 loop_depth); | 1105 current->id().ToInt(), loop_depth); |
| 1098 } else { | 1106 } else { |
| 1099 while (current_header != NULL && | 1107 while (current_header != NULL && |
| 1100 current->rpo_number_ >= current_header->loop_end_) { | 1108 current->rpo_number() >= current_header->loop_end()) { |
| 1101 DCHECK(current_header->IsLoopHeader()); | 1109 DCHECK(current_header->IsLoopHeader()); |
| 1102 DCHECK(current_loop != NULL); | 1110 DCHECK(current_loop != NULL); |
| 1103 current_loop = current_loop->prev; | 1111 current_loop = current_loop->prev; |
| 1104 current_header = current_loop == NULL ? NULL : current_loop->header; | 1112 current_header = current_loop == NULL ? NULL : current_loop->header; |
| 1105 --loop_depth; | 1113 --loop_depth; |
| 1106 } | 1114 } |
| 1107 } | 1115 } |
| 1108 current->loop_depth_ = loop_depth; | 1116 current->set_loop_depth(loop_depth); |
| 1109 if (current->loop_header_ == NULL) { | 1117 if (current->loop_header() == NULL) { |
| 1110 Trace("B%d is not in a loop (depth == %d)\n", current->id(), | 1118 Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(), |
| 1111 current->loop_depth_); | 1119 current->loop_depth()); |
| 1112 } else { | 1120 } else { |
| 1113 Trace("B%d has loop header B%d, (depth == %d)\n", current->id(), | 1121 Trace("B%d has loop header B%d, (depth == %d)\n", current->id().ToInt(), |
| 1114 current->loop_header_->id(), current->loop_depth_); | 1122 current->loop_header()->id().ToInt(), current->loop_depth()); |
| 1115 } | 1123 } |
| 1116 } | 1124 } |
| 1117 | 1125 |
| 1118 #if DEBUG | 1126 #if DEBUG |
| 1119 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); | 1127 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); |
| 1120 VerifySpecialRPO(num_loops, loops, final_order); | 1128 VerifySpecialRPO(num_loops, loops, final_order); |
| 1121 #endif | 1129 #endif |
| 1122 return final_order; | 1130 return final_order; |
| 1123 } | 1131 } |
| 1124 } | 1132 } |
| 1125 } | 1133 } |
| 1126 } // namespace v8::internal::compiler | 1134 } // namespace v8::internal::compiler |
| OLD | NEW |