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 |