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

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

Issue 655833005: Switch schedule early phase to use forward propagation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments by Jaro. Created 6 years, 1 month 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 | « no previous file | 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 scheduler.ScheduleLate(); 57 scheduler.ScheduleLate();
58 58
59 had_floating_control = scheduler.ConnectFloatingControl(); 59 had_floating_control = scheduler.ConnectFloatingControl();
60 } while (had_floating_control); 60 } while (had_floating_control);
61 61
62 return schedule; 62 return schedule;
63 } 63 }
64 64
65 65
66 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { 66 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() {
67 SchedulerData def = {NULL, 0, false, false, kUnknown}; 67 SchedulerData def = {schedule_->start(), 0, false, false, kUnknown};
68 return def; 68 return def;
69 } 69 }
70 70
71 71
72 Scheduler::SchedulerData* Scheduler::GetData(Node* node) { 72 Scheduler::SchedulerData* Scheduler::GetData(Node* node) {
73 DCHECK(node->id() < static_cast<int>(node_data_.size())); 73 DCHECK(node->id() < static_cast<int>(node_data_.size()));
74 return &node_data_[node->id()]; 74 return &node_data_[node->id()];
75 } 75 }
76 76
77 77
(...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 // node's uses are scheduled before the node itself. 945 // node's uses are scheduled before the node itself.
946 PrepareUsesVisitor prepare_uses(this); 946 PrepareUsesVisitor prepare_uses(this);
947 graph_->VisitNodeInputsFromEnd(&prepare_uses); 947 graph_->VisitNodeInputsFromEnd(&prepare_uses);
948 } 948 }
949 949
950 950
951 // ----------------------------------------------------------------------------- 951 // -----------------------------------------------------------------------------
952 // Phase 4: Schedule nodes early. 952 // Phase 4: Schedule nodes early.
953 953
954 954
955 class ScheduleEarlyNodeVisitor : public NullNodeVisitor { 955 class ScheduleEarlyNodeVisitor {
956 public: 956 public:
957 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) 957 ScheduleEarlyNodeVisitor(Zone* zone, Scheduler* scheduler)
958 : scheduler_(scheduler), schedule_(scheduler->schedule_) {} 958 : scheduler_(scheduler), schedule_(scheduler->schedule_), queue_(zone) {}
959 959
960 GenericGraphVisit::Control Pre(Node* node) { 960 // Run the schedule early algorithm on a set of fixed root nodes.
961 Scheduler::SchedulerData* data = scheduler_->GetData(node); 961 void Run(NodeVector* roots) {
962 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { 962 for (NodeVectorIter i = roots->begin(); i != roots->end(); ++i) {
963 // Fixed nodes already know their schedule early position. 963 queue_.push(*i);
964 if (data->minimum_block_ == NULL) { 964 while (!queue_.empty()) {
965 data->minimum_block_ = schedule_->block(node); 965 VisitNode(queue_.front());
966 Trace("Preschedule #%d:%s minimum_rpo = %d (fixed)\n", node->id(), 966 queue_.pop();
967 node->op()->mnemonic(), data->minimum_block_->rpo_number());
968 }
969 } else {
970 // For unfixed nodes the minimum RPO is the max of all of the inputs.
971 if (data->minimum_block_ == NULL) {
972 data->minimum_block_ = ComputeMaximumInputRPO(node);
973 if (data->minimum_block_ == NULL) return GenericGraphVisit::REENTER;
974 Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(),
975 node->op()->mnemonic(), data->minimum_block_->rpo_number());
976 } 967 }
977 } 968 }
978 DCHECK_NE(data->minimum_block_, NULL);
979 return GenericGraphVisit::CONTINUE;
980 }
981
982 GenericGraphVisit::Control Post(Node* node) {
983 Scheduler::SchedulerData* data = scheduler_->GetData(node);
984 if (scheduler_->GetPlacement(node) != Scheduler::kFixed) {
985 // For unfixed nodes the minimum RPO is the max of all of the inputs.
986 if (data->minimum_block_ == NULL) {
987 data->minimum_block_ = ComputeMaximumInputRPO(node);
988 Trace("Postschedule #%d:%s minimum_rpo = %d\n", node->id(),
989 node->op()->mnemonic(), data->minimum_block_->rpo_number());
990 }
991 }
992 DCHECK_NE(data->minimum_block_, NULL);
993 return GenericGraphVisit::CONTINUE;
994 }
995
996 // Computes the maximum of the minimum RPOs for all inputs. If the maximum
997 // cannot be determined (i.e. minimum RPO for at least one input is {NULL}),
998 // then {NULL} is returned.
999 BasicBlock* ComputeMaximumInputRPO(Node* node) {
1000 BasicBlock* max_block = schedule_->start();
1001 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
1002 DCHECK_NE(node, *i); // Loops only exist for fixed nodes.
1003 BasicBlock* block = scheduler_->GetData(*i)->minimum_block_;
1004 if (block == NULL) return NULL;
1005 if (block->rpo_number() > max_block->rpo_number()) {
1006 max_block = block;
1007 }
1008 }
1009 return max_block;
1010 } 969 }
1011 970
1012 private: 971 private:
972 // Visits one node from the queue and propagates its current schedule early
973 // position to all uses. This in turn might push more nodes onto the queue.
974 void VisitNode(Node* node) {
975 Scheduler::SchedulerData* data = scheduler_->GetData(node);
976
977 // Fixed nodes already know their schedule early position.
978 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) {
979 DCHECK_EQ(schedule_->start(), data->minimum_block_);
980 data->minimum_block_ = schedule_->block(node);
981 Trace("Fixing #%d:%s minimum_rpo = %d\n", node->id(),
982 node->op()->mnemonic(), data->minimum_block_->rpo_number());
983 }
984
985 // No need to propagate unconstrained schedule early positions.
986 if (data->minimum_block_ == schedule_->start()) return;
987
988 // Propagate schedule early position.
989 DCHECK(data->minimum_block_ != NULL);
990 Node::Uses uses = node->uses();
991 for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) {
992 PropagateMinimumRPOToNode(data->minimum_block_, *i);
993 }
994 }
995
996 // Propagates {block} as another minimum RPO placement into the given {node}.
997 // This has the net effect of computing the maximum of the minimum RPOs for
998 // all inputs to {node} when the queue has been fully processed.
999 void PropagateMinimumRPOToNode(BasicBlock* block, Node* node) {
1000 Scheduler::SchedulerData* data = scheduler_->GetData(node);
1001
1002 // No need to propagate to fixed node, it's guaranteed to be a root.
1003 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) return;
1004
1005 // Propagate new position if it is larger than the current.
1006 if (block->rpo_number() > data->minimum_block_->rpo_number()) {
1007 data->minimum_block_ = block;
1008 queue_.push(node);
1009 Trace("Propagating #%d:%s minimum_rpo = %d\n", node->id(),
1010 node->op()->mnemonic(), data->minimum_block_->rpo_number());
1011 }
1012 }
1013
1013 Scheduler* scheduler_; 1014 Scheduler* scheduler_;
1014 Schedule* schedule_; 1015 Schedule* schedule_;
1016 ZoneQueue<Node*> queue_;
1015 }; 1017 };
1016 1018
1017 1019
1018 void Scheduler::ScheduleEarly() { 1020 void Scheduler::ScheduleEarly() {
1019 Trace("--- SCHEDULE EARLY -----------------------------------------\n"); 1021 Trace("--- SCHEDULE EARLY -----------------------------------------\n");
1022 if (FLAG_trace_turbo_scheduler) {
1023 Trace("roots: ");
1024 for (NodeVectorIter i = schedule_root_nodes_.begin();
1025 i != schedule_root_nodes_.end(); ++i) {
1026 Trace("#%d:%s ", (*i)->id(), (*i)->op()->mnemonic());
1027 }
1028 Trace("\n");
1029 }
1020 1030
1021 // Compute the minimum RPO for each node thereby determining the earliest 1031 // Compute the minimum RPO for each node thereby determining the earliest
1022 // position each node could be placed within a valid schedule. 1032 // position each node could be placed within a valid schedule.
1023 ScheduleEarlyNodeVisitor visitor(this); 1033 ScheduleEarlyNodeVisitor schedule_early_visitor(zone_, this);
1024 graph_->VisitNodeInputsFromEnd(&visitor); 1034 schedule_early_visitor.Run(&schedule_root_nodes_);
1025 } 1035 }
1026 1036
1027 1037
1028 // ----------------------------------------------------------------------------- 1038 // -----------------------------------------------------------------------------
1029 // Phase 5: Schedule nodes late. 1039 // Phase 5: Schedule nodes late.
1030 1040
1031 1041
1032 class ScheduleLateNodeVisitor { 1042 class ScheduleLateNodeVisitor {
1033 public: 1043 public:
1034 ScheduleLateNodeVisitor(Zone* zone, Scheduler* scheduler) 1044 ScheduleLateNodeVisitor(Zone* zone, Scheduler* scheduler)
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1091 Trace(" hoisting #%d:%s to block %d\n", node->id(), 1101 Trace(" hoisting #%d:%s to block %d\n", node->id(),
1092 node->op()->mnemonic(), hoist_block->id().ToInt()); 1102 node->op()->mnemonic(), hoist_block->id().ToInt());
1093 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth()); 1103 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth());
1094 block = hoist_block; 1104 block = hoist_block;
1095 hoist_block = GetPreHeader(hoist_block); 1105 hoist_block = GetPreHeader(hoist_block);
1096 } 1106 }
1097 1107
1098 ScheduleNode(block, node); 1108 ScheduleNode(block, node);
1099 } 1109 }
1100 1110
1101 private:
1102 BasicBlock* GetPreHeader(BasicBlock* block) { 1111 BasicBlock* GetPreHeader(BasicBlock* block) {
1103 if (block->IsLoopHeader()) { 1112 if (block->IsLoopHeader()) {
1104 return block->dominator(); 1113 return block->dominator();
1105 } else if (block->loop_header() != NULL) { 1114 } else if (block->loop_header() != NULL) {
1106 return block->loop_header()->dominator(); 1115 return block->loop_header()->dominator();
1107 } else { 1116 } else {
1108 return NULL; 1117 return NULL;
1109 } 1118 }
1110 } 1119 }
1111 1120
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1288 start->ReplaceInput(NodeProperties::FirstControlIndex(start), block_start); 1297 start->ReplaceInput(NodeProperties::FirstControlIndex(start), block_start);
1289 1298
1290 Trace(" Connecting floating control start %d:%s to %d:%s\n", start->id(), 1299 Trace(" Connecting floating control start %d:%s to %d:%s\n", start->id(),
1291 start->op()->mnemonic(), block_start->id(), 1300 start->op()->mnemonic(), block_start->id(),
1292 block_start->op()->mnemonic()); 1301 block_start->op()->mnemonic());
1293 } 1302 }
1294 1303
1295 } // namespace compiler 1304 } // namespace compiler
1296 } // namespace internal 1305 } // namespace internal
1297 } // namespace v8 1306 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698