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

Side by Side Diff: src/compiler/scheduler.cc

Issue 654583004: Revert "Make sure floating phi nodes are coupled to their control." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler/scheduler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 return schedule; 63 return schedule;
64 } 64 }
65 65
66 66
67 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { 67 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() {
68 SchedulerData def = {NULL, 0, false, false, kUnknown}; 68 SchedulerData def = {NULL, 0, false, false, kUnknown};
69 return def; 69 return def;
70 } 70 }
71 71
72 72
73 Scheduler::SchedulerData* Scheduler::GetData(Node* node) {
74 DCHECK(node->id() < static_cast<int>(node_data_.size()));
75 return &node_data_[node->id()];
76 }
77
78
79 Scheduler::Placement Scheduler::GetPlacement(Node* node) { 73 Scheduler::Placement Scheduler::GetPlacement(Node* node) {
80 SchedulerData* data = GetData(node); 74 SchedulerData* data = GetData(node);
81 if (data->placement_ == kUnknown) { // Compute placement, once, on demand. 75 if (data->placement_ == kUnknown) { // Compute placement, once, on demand.
82 switch (node->opcode()) { 76 switch (node->opcode()) {
83 case IrOpcode::kParameter: 77 case IrOpcode::kParameter:
84 // Parameters are always fixed to the start node. 78 // Parameters are always fixed to the start node.
85 data->placement_ = kFixed; 79 data->placement_ = kFixed;
86 break; 80 break;
87 case IrOpcode::kPhi: 81 case IrOpcode::kPhi:
88 case IrOpcode::kEffectPhi: { 82 case IrOpcode::kEffectPhi: {
89 // Phis and effect phis are fixed if their control inputs are, whereas 83 // Phis and effect phis are fixed if their control inputs are.
90 // otherwise they are coupled to a floating control node. 84 data->placement_ = GetPlacement(NodeProperties::GetControlInput(node));
91 Placement p = GetPlacement(NodeProperties::GetControlInput(node));
92 data->placement_ = (p == kFixed ? kFixed : kCoupled);
93 break; 85 break;
94 } 86 }
95 #define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V: 87 #define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V:
96 CONTROL_OP_LIST(DEFINE_FLOATING_CONTROL_CASE) 88 CONTROL_OP_LIST(DEFINE_FLOATING_CONTROL_CASE)
97 #undef DEFINE_FLOATING_CONTROL_CASE 89 #undef DEFINE_FLOATING_CONTROL_CASE
98 { 90 {
99 // Control nodes that were not control-reachable from end may float. 91 // Control nodes that were not control-reachable from end may float.
100 data->placement_ = kSchedulable; 92 data->placement_ = kSchedulable;
101 if (!data->is_connected_control_) { 93 if (!data->is_connected_control_) {
102 data->is_floating_control_ = true; 94 data->is_floating_control_ = true;
103 has_floating_control_ = true; 95 has_floating_control_ = true;
104 // TODO(mstarzinger): Workaround to fix visitation order.
105 schedule_root_nodes_.push_back(node);
106 Trace("Floating control found: #%d:%s\n", node->id(), 96 Trace("Floating control found: #%d:%s\n", node->id(),
107 node->op()->mnemonic()); 97 node->op()->mnemonic());
108 } 98 }
109 break; 99 break;
110 } 100 }
111 default: 101 default:
112 data->placement_ = kSchedulable; 102 data->placement_ = kSchedulable;
113 break; 103 break;
114 } 104 }
115 } 105 }
116 return data->placement_; 106 return data->placement_;
117 } 107 }
118 108
119 109
120 void Scheduler::IncrementUnscheduledUseCount(Node* node, Node* from) {
121 if (GetPlacement(node) == kCoupled) {
122 // Use count for coupled nodes is summed up on their control.
123 Node* control = NodeProperties::GetControlInput(node);
124 return IncrementUnscheduledUseCount(control, from);
125 }
126 ++(GetData(node)->unscheduled_count_);
127 if (FLAG_trace_turbo_scheduler) {
128 Trace(" Use count of #%d:%s (used by #%d:%s)++ = %d\n", node->id(),
129 node->op()->mnemonic(), from->id(), from->op()->mnemonic(),
130 GetData(node)->unscheduled_count_);
131 }
132 }
133
134
135 void Scheduler::DecrementUnscheduledUseCount(Node* node, Node* from) {
136 if (GetPlacement(node) == kCoupled) {
137 // Use count for coupled nodes is summed up on their control.
138 Node* control = NodeProperties::GetControlInput(node);
139 return DecrementUnscheduledUseCount(control, from);
140 }
141 DCHECK(GetData(node)->unscheduled_count_ > 0);
142 --(GetData(node)->unscheduled_count_);
143 if (FLAG_trace_turbo_scheduler) {
144 Trace(" Use count of #%d:%s (used by #%d:%s)-- = %d\n", node->id(),
145 node->op()->mnemonic(), from->id(), from->op()->mnemonic(),
146 GetData(node)->unscheduled_count_);
147 if (GetData(node)->unscheduled_count_ == 0) {
148 Trace(" newly eligible #%d:%s\n", node->id(), node->op()->mnemonic());
149 }
150 }
151 }
152
153
154 int Scheduler::GetRPONumber(BasicBlock* block) {
155 DCHECK(block->rpo_number() >= 0 &&
156 block->rpo_number() < static_cast<int>(schedule_->rpo_order_.size()));
157 DCHECK(schedule_->rpo_order_[block->rpo_number()] == block);
158 return block->rpo_number();
159 }
160
161
162 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) { 110 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
163 while (b1 != b2) { 111 while (b1 != b2) {
164 int b1_rpo = GetRPONumber(b1); 112 int b1_rpo = GetRPONumber(b1);
165 int b2_rpo = GetRPONumber(b2); 113 int b2_rpo = GetRPONumber(b2);
166 DCHECK(b1_rpo != b2_rpo); 114 DCHECK(b1_rpo != b2_rpo);
167 if (b1_rpo < b2_rpo) { 115 if (b1_rpo < b2_rpo) {
168 b2 = b2->dominator(); 116 b2 = b2->dominator();
169 } else { 117 } else {
170 b1 = b1->dominator(); 118 b1 = b1->dominator();
171 } 119 }
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 392
445 return GenericGraphVisit::CONTINUE; 393 return GenericGraphVisit::CONTINUE;
446 } 394 }
447 395
448 void PostEdge(Node* from, int index, Node* to) { 396 void PostEdge(Node* from, int index, Node* to) {
449 // If the edge is from an unscheduled node, then tally it in the use count 397 // If the edge is from an unscheduled node, then tally it in the use count
450 // for all of its inputs. The same criterion will be used in ScheduleLate 398 // for all of its inputs. The same criterion will be used in ScheduleLate
451 // for decrementing use counts. 399 // for decrementing use counts.
452 if (!schedule_->IsScheduled(from)) { 400 if (!schedule_->IsScheduled(from)) {
453 DCHECK_NE(Scheduler::kFixed, scheduler_->GetPlacement(from)); 401 DCHECK_NE(Scheduler::kFixed, scheduler_->GetPlacement(from));
454 scheduler_->IncrementUnscheduledUseCount(to, from); 402 ++(scheduler_->GetData(to)->unscheduled_count_);
403 Trace(" Use count of #%d:%s (used by #%d:%s)++ = %d\n", to->id(),
404 to->op()->mnemonic(), from->id(), from->op()->mnemonic(),
405 scheduler_->GetData(to)->unscheduled_count_);
406 if (OperatorProperties::IsBasicBlockBegin(to->op()) &&
407 (from->opcode() == IrOpcode::kEffectPhi ||
408 from->opcode() == IrOpcode::kPhi) &&
409 scheduler_->GetData(to)->is_floating_control_ &&
410 !scheduler_->GetData(to)->is_connected_control_) {
411 for (InputIter i = from->inputs().begin(); i != from->inputs().end();
412 ++i) {
413 if (!NodeProperties::IsControlEdge(i.edge())) {
414 ++(scheduler_->GetData(*i)->unscheduled_count_);
415 Trace(
416 " Use count of #%d:%s (additional dependency of #%d:%s)++ = "
417 "%d\n",
418 (*i)->id(), (*i)->op()->mnemonic(), to->id(),
419 to->op()->mnemonic(),
420 scheduler_->GetData(*i)->unscheduled_count_);
421 }
422 }
423 }
455 } 424 }
456 } 425 }
457 426
458 private: 427 private:
459 Scheduler* scheduler_; 428 Scheduler* scheduler_;
460 Schedule* schedule_; 429 Schedule* schedule_;
461 }; 430 };
462 431
463 432
464 void Scheduler::PrepareUses() { 433 void Scheduler::PrepareUses() {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 public: 525 public:
557 explicit ScheduleLateNodeVisitor(Scheduler* scheduler) 526 explicit ScheduleLateNodeVisitor(Scheduler* scheduler)
558 : scheduler_(scheduler), schedule_(scheduler_->schedule_) {} 527 : scheduler_(scheduler), schedule_(scheduler_->schedule_) {}
559 528
560 GenericGraphVisit::Control Pre(Node* node) { 529 GenericGraphVisit::Control Pre(Node* node) {
561 // Don't schedule nodes that are already scheduled. 530 // Don't schedule nodes that are already scheduled.
562 if (schedule_->IsScheduled(node)) { 531 if (schedule_->IsScheduled(node)) {
563 return GenericGraphVisit::CONTINUE; 532 return GenericGraphVisit::CONTINUE;
564 } 533 }
565 534
566 // Don't schedule coupled nodes on their own.
567 if (scheduler_->GetPlacement(node) == Scheduler::kCoupled) {
568 Node* control = NodeProperties::GetControlInput(node);
569 scheduler_->DecrementUnscheduledUseCount(control, node);
570 return GenericGraphVisit::CONTINUE;
571 }
572
573 Scheduler::SchedulerData* data = scheduler_->GetData(node); 535 Scheduler::SchedulerData* data = scheduler_->GetData(node);
574 DCHECK_EQ(Scheduler::kSchedulable, scheduler_->GetPlacement(node)); 536 DCHECK_EQ(Scheduler::kSchedulable, data->placement_);
575 537
576 // If all the uses of a node have been scheduled, then the node itself can 538 // If all the uses of a node have been scheduled, then the node itself can
577 // be scheduled. 539 // be scheduled.
578 bool eligible = data->unscheduled_count_ == 0; 540 bool eligible = data->unscheduled_count_ == 0;
579 Trace("Testing for schedule eligibility for #%d:%s = %s\n", node->id(), 541 Trace("Testing for schedule eligibility for #%d:%s = %s\n", node->id(),
580 node->op()->mnemonic(), eligible ? "true" : "false"); 542 node->op()->mnemonic(), eligible ? "true" : "false");
581 if (!eligible) return GenericGraphVisit::DEFER; 543 if (!eligible) return GenericGraphVisit::DEFER;
582 544
583 // Determine the dominating block for all of the uses of this node. It is 545 // Determine the dominating block for all of the uses of this node. It is
584 // the latest block that this node can be scheduled in. 546 // the latest block that this node can be scheduled in.
585 BasicBlock* block = GetCommonDominatorOfUses(node); 547 BasicBlock* block = NULL;
586 DCHECK_NE(NULL, block); 548 for (Node::Uses::iterator i = node->uses().begin(); i != node->uses().end();
549 ++i) {
550 BasicBlock* use_block = GetBlockForUse(i.edge());
551 block = block == NULL ? use_block : use_block == NULL
552 ? block
553 : scheduler_->GetCommonDominator(
554 block, use_block);
555 }
556 DCHECK(block != NULL);
587 557
588 int min_rpo = data->minimum_block_->rpo_number(); 558 int min_rpo = data->minimum_block_->rpo_number();
589 Trace("Schedule late of #%d:%s is B%d at loop depth %d, minimum_rpo = %d\n", 559 Trace(
590 node->id(), node->op()->mnemonic(), block->id().ToInt(), 560 "Schedule late conservative for #%d:%s is B%d at loop depth %d, "
591 block->loop_depth(), min_rpo); 561 "minimum_rpo = %d\n",
592 562 node->id(), node->op()->mnemonic(), block->id().ToInt(),
563 block->loop_depth(), min_rpo);
593 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively 564 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively
594 // into enclosing loop pre-headers until they would preceed their 565 // into enclosing loop pre-headers until they would preceed their
595 // ScheduleEarly position. 566 // ScheduleEarly position.
596 BasicBlock* hoist_block = block; 567 BasicBlock* hoist_block = block;
597 while (hoist_block != NULL && hoist_block->rpo_number() >= min_rpo) { 568 while (hoist_block != NULL && hoist_block->rpo_number() >= min_rpo) {
598 if (hoist_block->loop_depth() < block->loop_depth()) { 569 if (hoist_block->loop_depth() < block->loop_depth()) {
599 block = hoist_block; 570 block = hoist_block;
600 Trace(" hoisting #%d:%s to block %d\n", node->id(), 571 Trace(" hoisting #%d:%s to block %d\n", node->id(),
601 node->op()->mnemonic(), block->id().ToInt()); 572 node->op()->mnemonic(), block->id().ToInt());
602 } 573 }
(...skipping 10 matching lines...) Expand all
613 hoist_block = pre_header; 584 hoist_block = pre_header;
614 } 585 }
615 } 586 }
616 587
617 ScheduleNode(block, node); 588 ScheduleNode(block, node);
618 589
619 return GenericGraphVisit::CONTINUE; 590 return GenericGraphVisit::CONTINUE;
620 } 591 }
621 592
622 private: 593 private:
623 BasicBlock* GetCommonDominatorOfUses(Node* node) {
624 BasicBlock* block = NULL;
625 Node::Uses uses = node->uses();
626 for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) {
627 BasicBlock* use_block = GetBlockForUse(i.edge());
628 block = block == NULL ? use_block : use_block == NULL
629 ? block
630 : scheduler_->GetCommonDominator(
631 block, use_block);
632 }
633 return block;
634 }
635
636 BasicBlock* GetBlockForUse(Node::Edge edge) { 594 BasicBlock* GetBlockForUse(Node::Edge edge) {
637 Node* use = edge.from(); 595 Node* use = edge.from();
638 IrOpcode::Value opcode = use->opcode(); 596 IrOpcode::Value opcode = use->opcode();
639 if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) { 597 if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) {
640 // If the use is from a coupled (i.e. floating) phi, compute the common
641 // dominator of its uses. This will not recurse more than one level.
642 if (scheduler_->GetPlacement(use) == Scheduler::kCoupled) {
643 Trace(" inspecting uses of coupled phi #%d:%s\n", use->id(),
644 use->op()->mnemonic());
645 DCHECK_EQ(edge.to(), NodeProperties::GetControlInput(use));
646 return GetCommonDominatorOfUses(use);
647 }
648 // If the use is from a fixed (i.e. non-floating) phi, use the block 598 // If the use is from a fixed (i.e. non-floating) phi, use the block
649 // of the corresponding control input to the merge. 599 // of the corresponding control input to the merge.
600 int index = edge.index();
650 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { 601 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) {
651 Trace(" input@%d into a fixed phi #%d:%s\n", edge.index(), use->id(), 602 Trace(" input@%d into a fixed phi #%d:%s\n", index, use->id(),
652 use->op()->mnemonic()); 603 use->op()->mnemonic());
653 Node* merge = NodeProperties::GetControlInput(use, 0); 604 Node* merge = NodeProperties::GetControlInput(use, 0);
654 opcode = merge->opcode(); 605 opcode = merge->opcode();
655 DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop); 606 DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop);
656 use = NodeProperties::GetControlInput(merge, edge.index()); 607 use = NodeProperties::GetControlInput(merge, index);
657 } 608 }
658 } 609 }
659 BasicBlock* result = schedule_->block(use); 610 BasicBlock* result = schedule_->block(use);
660 if (result == NULL) return NULL; 611 if (result == NULL) return NULL;
661 Trace(" must dominate use #%d:%s in B%d\n", use->id(), 612 Trace(" must dominate use #%d:%s in B%d\n", use->id(),
662 use->op()->mnemonic(), result->id().ToInt()); 613 use->op()->mnemonic(), result->id().ToInt());
663 return result; 614 return result;
664 } 615 }
665 616
666 void ScheduleNode(BasicBlock* block, Node* node) { 617 void ScheduleNode(BasicBlock* block, Node* node) {
667 schedule_->PlanNode(block, node); 618 schedule_->PlanNode(block, node);
668 scheduler_->scheduled_nodes_[block->id().ToSize()].push_back(node); 619 scheduler_->scheduled_nodes_[block->id().ToSize()].push_back(node);
669 620
670 // Reduce the use count of the node's inputs to potentially make them 621 // Reduce the use count of the node's inputs to potentially make them
671 // schedulable. 622 // schedulable.
672 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { 623 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
673 scheduler_->DecrementUnscheduledUseCount(*i, i.edge().from()); 624 Scheduler::SchedulerData* data = scheduler_->GetData(*i);
625 DCHECK(data->unscheduled_count_ > 0);
626 --data->unscheduled_count_;
627 if (FLAG_trace_turbo_scheduler) {
628 Trace(" Use count for #%d:%s (used by #%d:%s)-- = %d\n", (*i)->id(),
629 (*i)->op()->mnemonic(), i.edge().from()->id(),
630 i.edge().from()->op()->mnemonic(), data->unscheduled_count_);
631 if (data->unscheduled_count_ == 0) {
632 Trace(" newly eligible #%d:%s\n", (*i)->id(),
633 (*i)->op()->mnemonic());
634 }
635 }
636 }
637
638 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
639 Node* use = *i;
640 if (use->opcode() == IrOpcode::kPhi ||
641 use->opcode() == IrOpcode::kEffectPhi) {
642 Node* control = NodeProperties::GetControlInput(use);
643 Scheduler::SchedulerData* data = scheduler_->GetData(control);
644 if (data->is_floating_control_ && !data->is_connected_control_) {
645 --data->unscheduled_count_;
646 if (FLAG_trace_turbo_scheduler) {
647 Trace(
648 " Use count for #%d:%s (additional dependency of #%d:%s)-- = "
649 "%d\n",
650 (*i)->id(), (*i)->op()->mnemonic(), node->id(),
651 node->op()->mnemonic(), data->unscheduled_count_);
652 if (data->unscheduled_count_ == 0) {
653 Trace(" newly eligible #%d:%s\n", (*i)->id(),
654 (*i)->op()->mnemonic());
655 }
656 }
657 }
658 }
674 } 659 }
675 } 660 }
676 661
677 Scheduler* scheduler_; 662 Scheduler* scheduler_;
678 Schedule* schedule_; 663 Schedule* schedule_;
679 }; 664 };
680 665
681 666
682 void Scheduler::ScheduleLate() { 667 void Scheduler::ScheduleLate() {
683 Trace("--- SCHEDULE LATE ------------------------------------------\n"); 668 Trace("--- SCHEDULE LATE ------------------------------------------\n");
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 #if DEBUG 1198 #if DEBUG
1214 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); 1199 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order);
1215 VerifySpecialRPO(num_loops, loops, final_order); 1200 VerifySpecialRPO(num_loops, loops, final_order);
1216 #endif 1201 #endif
1217 return final_order; 1202 return final_order;
1218 } 1203 }
1219 1204
1220 } // namespace compiler 1205 } // namespace compiler
1221 } // namespace internal 1206 } // namespace internal
1222 } // namespace v8 1207 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/scheduler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698