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/bit-vector.h" | 10 #include "src/bit-vector.h" |
| 11 #include "src/compiler/control-equivalence.h" |
11 #include "src/compiler/graph.h" | 12 #include "src/compiler/graph.h" |
12 #include "src/compiler/graph-inl.h" | 13 #include "src/compiler/graph-inl.h" |
13 #include "src/compiler/node.h" | 14 #include "src/compiler/node.h" |
14 #include "src/compiler/node-properties.h" | 15 #include "src/compiler/node-properties.h" |
15 #include "src/compiler/node-properties-inl.h" | 16 #include "src/compiler/node-properties-inl.h" |
16 | 17 |
17 namespace v8 { | 18 namespace v8 { |
18 namespace internal { | 19 namespace internal { |
19 namespace compiler { | 20 namespace compiler { |
20 | 21 |
(...skipping 30 matching lines...) Expand all Loading... |
51 scheduler.ScheduleEarly(); | 52 scheduler.ScheduleEarly(); |
52 scheduler.ScheduleLate(); | 53 scheduler.ScheduleLate(); |
53 | 54 |
54 scheduler.SealFinalSchedule(); | 55 scheduler.SealFinalSchedule(); |
55 | 56 |
56 return schedule; | 57 return schedule; |
57 } | 58 } |
58 | 59 |
59 | 60 |
60 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { | 61 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { |
61 SchedulerData def = {schedule_->start(), 0, false, false, kUnknown}; | 62 SchedulerData def = {schedule_->start(), 0, false, kUnknown}; |
62 return def; | 63 return def; |
63 } | 64 } |
64 | 65 |
65 | 66 |
66 Scheduler::SchedulerData* Scheduler::GetData(Node* node) { | 67 Scheduler::SchedulerData* Scheduler::GetData(Node* node) { |
67 DCHECK(node->id() < static_cast<int>(node_data_.size())); | 68 DCHECK(node->id() < static_cast<int>(node_data_.size())); |
68 return &node_data_[node->id()]; | 69 return &node_data_[node->id()]; |
69 } | 70 } |
70 | 71 |
71 | 72 |
72 Scheduler::Placement Scheduler::GetPlacement(Node* node) { | 73 Scheduler::Placement Scheduler::GetPlacement(Node* node) { |
73 SchedulerData* data = GetData(node); | 74 SchedulerData* data = GetData(node); |
74 if (data->placement_ == kUnknown) { // Compute placement, once, on demand. | 75 if (data->placement_ == kUnknown) { // Compute placement, once, on demand. |
75 switch (node->opcode()) { | 76 switch (node->opcode()) { |
76 case IrOpcode::kParameter: | 77 case IrOpcode::kParameter: |
77 // Parameters are always fixed to the start node. | 78 // Parameters are always fixed to the start node. |
78 data->placement_ = kFixed; | 79 data->placement_ = kFixed; |
79 break; | 80 break; |
80 case IrOpcode::kPhi: | 81 case IrOpcode::kPhi: |
81 case IrOpcode::kEffectPhi: { | 82 case IrOpcode::kEffectPhi: { |
82 // Phis and effect phis are fixed if their control inputs are, whereas | 83 // Phis and effect phis are fixed if their control inputs are, whereas |
83 // otherwise they are coupled to a floating control node. | 84 // otherwise they are coupled to a floating control node. |
84 Placement p = GetPlacement(NodeProperties::GetControlInput(node)); | 85 Placement p = GetPlacement(NodeProperties::GetControlInput(node)); |
85 data->placement_ = (p == kFixed ? kFixed : kCoupled); | 86 data->placement_ = (p == kFixed ? kFixed : kCoupled); |
86 break; | 87 break; |
87 } | 88 } |
88 #define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V: | 89 #define DEFINE_CONTROL_CASE(V) case IrOpcode::k##V: |
89 CONTROL_OP_LIST(DEFINE_FLOATING_CONTROL_CASE) | 90 CONTROL_OP_LIST(DEFINE_CONTROL_CASE) |
90 #undef DEFINE_FLOATING_CONTROL_CASE | 91 #undef DEFINE_CONTROL_CASE |
91 { | 92 { |
92 // Control nodes that were not control-reachable from end may float. | 93 // Control nodes that were not control-reachable from end may float. |
93 data->placement_ = kSchedulable; | 94 data->placement_ = kSchedulable; |
94 if (!data->is_connected_control_) { | |
95 data->is_floating_control_ = true; | |
96 Trace("Floating control found: #%d:%s\n", node->id(), | |
97 node->op()->mnemonic()); | |
98 } | |
99 break; | 95 break; |
100 } | 96 } |
101 default: | 97 default: |
102 data->placement_ = kSchedulable; | 98 data->placement_ = kSchedulable; |
103 break; | 99 break; |
104 } | 100 } |
105 } | 101 } |
106 return data->placement_; | 102 return data->placement_; |
107 } | 103 } |
108 | 104 |
109 | 105 |
110 void Scheduler::UpdatePlacement(Node* node, Placement placement) { | 106 void Scheduler::UpdatePlacement(Node* node, Placement placement) { |
111 SchedulerData* data = GetData(node); | 107 SchedulerData* data = GetData(node); |
112 if (data->placement_ != kUnknown) { // Trap on mutation, not initialization. | 108 if (data->placement_ != kUnknown) { // Trap on mutation, not initialization. |
113 switch (node->opcode()) { | 109 switch (node->opcode()) { |
114 case IrOpcode::kParameter: | 110 case IrOpcode::kParameter: |
115 // Parameters are fixed once and for all. | 111 // Parameters are fixed once and for all. |
116 UNREACHABLE(); | 112 UNREACHABLE(); |
117 break; | 113 break; |
118 case IrOpcode::kPhi: | 114 case IrOpcode::kPhi: |
119 case IrOpcode::kEffectPhi: { | 115 case IrOpcode::kEffectPhi: { |
120 // Phis and effect phis are coupled to their respective blocks. | 116 // Phis and effect phis are coupled to their respective blocks. |
121 DCHECK_EQ(Scheduler::kCoupled, data->placement_); | 117 DCHECK_EQ(Scheduler::kCoupled, data->placement_); |
122 DCHECK_EQ(Scheduler::kFixed, placement); | 118 DCHECK_EQ(Scheduler::kFixed, placement); |
123 Node* control = NodeProperties::GetControlInput(node); | 119 Node* control = NodeProperties::GetControlInput(node); |
124 BasicBlock* block = schedule_->block(control); | 120 BasicBlock* block = schedule_->block(control); |
125 schedule_->AddNode(block, node); | 121 schedule_->AddNode(block, node); |
126 break; | 122 break; |
127 } | 123 } |
128 #define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V: | 124 #define DEFINE_CONTROL_CASE(V) case IrOpcode::k##V: |
129 CONTROL_OP_LIST(DEFINE_FLOATING_CONTROL_CASE) | 125 CONTROL_OP_LIST(DEFINE_CONTROL_CASE) |
130 #undef DEFINE_FLOATING_CONTROL_CASE | 126 #undef DEFINE_CONTROL_CASE |
131 { | 127 { |
132 // Control nodes force coupled uses to be placed. | 128 // Control nodes force coupled uses to be placed. |
133 Node::Uses uses = node->uses(); | 129 Node::Uses uses = node->uses(); |
134 for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) { | 130 for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) { |
135 if (GetPlacement(*i) == Scheduler::kCoupled) { | 131 if (GetPlacement(*i) == Scheduler::kCoupled) { |
136 DCHECK_EQ(node, NodeProperties::GetControlInput(*i)); | 132 DCHECK_EQ(node, NodeProperties::GetControlInput(*i)); |
137 UpdatePlacement(*i, placement); | 133 UpdatePlacement(*i, placement); |
138 } | 134 } |
139 } | 135 } |
140 break; | 136 break; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 // between them within a Schedule) from the node graph. Visits control edges of | 230 // between them within a Schedule) from the node graph. Visits control edges of |
235 // the graph backwards from an end node in order to find the connected control | 231 // the graph backwards from an end node in order to find the connected control |
236 // subgraph, needed for scheduling. | 232 // subgraph, needed for scheduling. |
237 class CFGBuilder { | 233 class CFGBuilder { |
238 public: | 234 public: |
239 CFGBuilder(Zone* zone, Scheduler* scheduler) | 235 CFGBuilder(Zone* zone, Scheduler* scheduler) |
240 : scheduler_(scheduler), | 236 : scheduler_(scheduler), |
241 schedule_(scheduler->schedule_), | 237 schedule_(scheduler->schedule_), |
242 queue_(zone), | 238 queue_(zone), |
243 control_(zone), | 239 control_(zone), |
244 component_head_(NULL), | 240 component_entry_(NULL), |
245 component_start_(NULL), | 241 component_start_(NULL), |
246 component_end_(NULL) {} | 242 component_end_(NULL) {} |
247 | 243 |
248 // Run the control flow graph construction algorithm by walking the graph | 244 // Run the control flow graph construction algorithm by walking the graph |
249 // backwards from end through control edges, building and connecting the | 245 // backwards from end through control edges, building and connecting the |
250 // basic blocks for control nodes. | 246 // basic blocks for control nodes. |
251 void Run() { | 247 void Run() { |
252 Queue(scheduler_->graph_->end()); | 248 Queue(scheduler_->graph_->end()); |
253 | 249 |
| 250 // TODO(mstarzinger): This is just for testing, remove again. |
| 251 scheduler_->equivalence_->Run(scheduler_->graph_->end()); |
| 252 |
254 while (!queue_.empty()) { // Breadth-first backwards traversal. | 253 while (!queue_.empty()) { // Breadth-first backwards traversal. |
255 Node* node = queue_.front(); | 254 Node* node = queue_.front(); |
256 queue_.pop(); | 255 queue_.pop(); |
257 int max = NodeProperties::PastControlIndex(node); | 256 int max = NodeProperties::PastControlIndex(node); |
258 for (int i = NodeProperties::FirstControlIndex(node); i < max; i++) { | 257 for (int i = NodeProperties::FirstControlIndex(node); i < max; i++) { |
259 Queue(node->InputAt(i)); | 258 Queue(node->InputAt(i)); |
260 } | 259 } |
261 } | 260 } |
262 | 261 |
263 for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) { | 262 for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) { |
264 ConnectBlocks(*i); // Connect block to its predecessor/successors. | 263 ConnectBlocks(*i); // Connect block to its predecessor/successors. |
265 } | 264 } |
266 } | 265 } |
267 | 266 |
268 // Run the control flow graph construction for a minimal control-connected | 267 // Run the control flow graph construction for a minimal control-connected |
269 // component ending in {node} and merge that component into an existing | 268 // component ending in {exit} and merge that component into an existing |
270 // control flow graph at the bottom of {block}. | 269 // control flow graph at the bottom of {block}. |
271 void Run(BasicBlock* block, Node* node) { | 270 void Run(BasicBlock* block, Node* exit) { |
272 Queue(node); | 271 Queue(exit); |
273 | 272 |
274 component_start_ = block; | 273 component_start_ = block; |
275 component_end_ = schedule_->block(node); | 274 component_end_ = schedule_->block(exit); |
| 275 scheduler_->equivalence_->Run(exit); |
276 while (!queue_.empty()) { // Breadth-first backwards traversal. | 276 while (!queue_.empty()) { // Breadth-first backwards traversal. |
277 Node* node = queue_.front(); | 277 Node* node = queue_.front(); |
278 queue_.pop(); | 278 queue_.pop(); |
279 bool is_dom = true; | 279 |
| 280 // Use control dependence equivalence to find a canonical single-entry |
| 281 // single-exit region that makes up a minimal component to be scheduled. |
| 282 if (IsSingleEntrySingleExitRegion(node, exit)) { |
| 283 Trace("Found SESE at #%d:%s\n", node->id(), node->op()->mnemonic()); |
| 284 DCHECK_EQ(NULL, component_entry_); |
| 285 component_entry_ = node; |
| 286 continue; |
| 287 } |
| 288 |
280 int max = NodeProperties::PastControlIndex(node); | 289 int max = NodeProperties::PastControlIndex(node); |
281 for (int i = NodeProperties::FirstControlIndex(node); i < max; i++) { | 290 for (int i = NodeProperties::FirstControlIndex(node); i < max; i++) { |
282 is_dom = is_dom && | |
283 !scheduler_->GetData(node->InputAt(i))->is_floating_control_; | |
284 Queue(node->InputAt(i)); | 291 Queue(node->InputAt(i)); |
285 } | 292 } |
286 // TODO(mstarzinger): This is a hacky way to find component dominator. | |
287 if (is_dom) component_head_ = node; | |
288 } | 293 } |
289 DCHECK_NOT_NULL(component_head_); | 294 DCHECK_NE(NULL, component_entry_); |
290 | 295 |
291 for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) { | 296 for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) { |
292 scheduler_->GetData(*i)->is_floating_control_ = false; | |
293 ConnectBlocks(*i); // Connect block to its predecessor/successors. | 297 ConnectBlocks(*i); // Connect block to its predecessor/successors. |
294 } | 298 } |
295 } | 299 } |
296 | 300 |
297 private: | 301 private: |
298 // TODO(mstarzinger): Only for Scheduler::FuseFloatingControl. | 302 // TODO(mstarzinger): Only for Scheduler::FuseFloatingControl. |
299 friend class Scheduler; | 303 friend class Scheduler; |
300 | 304 |
301 void FixNode(BasicBlock* block, Node* node) { | 305 void FixNode(BasicBlock* block, Node* node) { |
302 schedule_->AddNode(block, node); | 306 schedule_->AddNode(block, node); |
303 scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 307 scheduler_->UpdatePlacement(node, Scheduler::kFixed); |
304 } | 308 } |
305 | 309 |
306 void Queue(Node* node) { | 310 void Queue(Node* node) { |
307 // Mark the connected control nodes as they are queued. | 311 // Mark the connected control nodes as they are queued. |
308 Scheduler::SchedulerData* data = scheduler_->GetData(node); | 312 Scheduler::SchedulerData* data = scheduler_->GetData(node); |
309 if (!data->is_connected_control_) { | 313 if (!data->is_connected_control_) { |
310 data->is_connected_control_ = true; | 314 data->is_connected_control_ = true; |
311 BuildBlocks(node); | 315 BuildBlocks(node); |
312 queue_.push(node); | 316 queue_.push(node); |
313 control_.push_back(node); | 317 control_.push_back(node); |
314 } | 318 } |
315 } | 319 } |
316 | 320 |
317 | |
318 void BuildBlocks(Node* node) { | 321 void BuildBlocks(Node* node) { |
319 switch (node->opcode()) { | 322 switch (node->opcode()) { |
320 case IrOpcode::kEnd: | 323 case IrOpcode::kEnd: |
321 FixNode(schedule_->end(), node); | 324 FixNode(schedule_->end(), node); |
322 break; | 325 break; |
323 case IrOpcode::kStart: | 326 case IrOpcode::kStart: |
324 FixNode(schedule_->start(), node); | 327 FixNode(schedule_->start(), node); |
325 break; | 328 break; |
326 case IrOpcode::kLoop: | 329 case IrOpcode::kLoop: |
327 case IrOpcode::kMerge: | 330 case IrOpcode::kMerge: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 } | 384 } |
382 | 385 |
383 // Collect the branch-related projections from a node, such as IfTrue, | 386 // Collect the branch-related projections from a node, such as IfTrue, |
384 // IfFalse. | 387 // IfFalse. |
385 // TODO(titzer): consider moving this to node.h | 388 // TODO(titzer): consider moving this to node.h |
386 void CollectSuccessorProjections(Node* node, Node** buffer, | 389 void CollectSuccessorProjections(Node* node, Node** buffer, |
387 IrOpcode::Value true_opcode, | 390 IrOpcode::Value true_opcode, |
388 IrOpcode::Value false_opcode) { | 391 IrOpcode::Value false_opcode) { |
389 buffer[0] = NULL; | 392 buffer[0] = NULL; |
390 buffer[1] = NULL; | 393 buffer[1] = NULL; |
391 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) { | 394 for (Node* use : node->uses()) { |
392 if ((*i)->opcode() == true_opcode) { | 395 if (use->opcode() == true_opcode) { |
393 DCHECK_EQ(NULL, buffer[0]); | 396 DCHECK_EQ(NULL, buffer[0]); |
394 buffer[0] = *i; | 397 buffer[0] = use; |
395 } | 398 } |
396 if ((*i)->opcode() == false_opcode) { | 399 if (use->opcode() == false_opcode) { |
397 DCHECK_EQ(NULL, buffer[1]); | 400 DCHECK_EQ(NULL, buffer[1]); |
398 buffer[1] = *i; | 401 buffer[1] = use; |
399 } | 402 } |
400 } | 403 } |
401 DCHECK_NE(NULL, buffer[0]); | 404 DCHECK_NE(NULL, buffer[0]); |
402 DCHECK_NE(NULL, buffer[1]); | 405 DCHECK_NE(NULL, buffer[1]); |
403 } | 406 } |
404 | 407 |
405 void CollectSuccessorBlocks(Node* node, BasicBlock** buffer, | 408 void CollectSuccessorBlocks(Node* node, BasicBlock** buffer, |
406 IrOpcode::Value true_opcode, | 409 IrOpcode::Value true_opcode, |
407 IrOpcode::Value false_opcode) { | 410 IrOpcode::Value false_opcode) { |
408 Node* successors[2]; | 411 Node* successors[2]; |
(...skipping 12 matching lines...) Expand all Loading... |
421 case BranchHint::kNone: | 424 case BranchHint::kNone: |
422 break; | 425 break; |
423 case BranchHint::kTrue: | 426 case BranchHint::kTrue: |
424 successor_blocks[1]->set_deferred(true); | 427 successor_blocks[1]->set_deferred(true); |
425 break; | 428 break; |
426 case BranchHint::kFalse: | 429 case BranchHint::kFalse: |
427 successor_blocks[0]->set_deferred(true); | 430 successor_blocks[0]->set_deferred(true); |
428 break; | 431 break; |
429 } | 432 } |
430 | 433 |
431 if (branch == component_head_) { | 434 if (branch == component_entry_) { |
432 TraceConnect(branch, component_start_, successor_blocks[0]); | 435 TraceConnect(branch, component_start_, successor_blocks[0]); |
433 TraceConnect(branch, component_start_, successor_blocks[1]); | 436 TraceConnect(branch, component_start_, successor_blocks[1]); |
434 schedule_->InsertBranch(component_start_, component_end_, branch, | 437 schedule_->InsertBranch(component_start_, component_end_, branch, |
435 successor_blocks[0], successor_blocks[1]); | 438 successor_blocks[0], successor_blocks[1]); |
436 } else { | 439 } else { |
437 Node* branch_block_node = NodeProperties::GetControlInput(branch); | 440 Node* branch_block_node = NodeProperties::GetControlInput(branch); |
438 BasicBlock* branch_block = schedule_->block(branch_block_node); | 441 BasicBlock* branch_block = schedule_->block(branch_block_node); |
439 DCHECK(branch_block != NULL); | 442 DCHECK(branch_block != NULL); |
440 | 443 |
441 TraceConnect(branch, branch_block, successor_blocks[0]); | 444 TraceConnect(branch, branch_block, successor_blocks[0]); |
442 TraceConnect(branch, branch_block, successor_blocks[1]); | 445 TraceConnect(branch, branch_block, successor_blocks[1]); |
443 schedule_->AddBranch(branch_block, branch, successor_blocks[0], | 446 schedule_->AddBranch(branch_block, branch, successor_blocks[0], |
444 successor_blocks[1]); | 447 successor_blocks[1]); |
445 } | 448 } |
446 } | 449 } |
447 | 450 |
448 void ConnectMerge(Node* merge) { | 451 void ConnectMerge(Node* merge) { |
449 // Don't connect the special merge at the end to its predecessors. | 452 // Don't connect the special merge at the end to its predecessors. |
450 if (IsFinalMerge(merge)) return; | 453 if (IsFinalMerge(merge)) return; |
451 | 454 |
452 BasicBlock* block = schedule_->block(merge); | 455 BasicBlock* block = schedule_->block(merge); |
453 DCHECK(block != NULL); | 456 DCHECK(block != NULL); |
454 // For all of the merge's control inputs, add a goto at the end to the | 457 // For all of the merge's control inputs, add a goto at the end to the |
455 // merge's basic block. | 458 // merge's basic block. |
456 for (InputIter j = merge->inputs().begin(); j != merge->inputs().end(); | 459 for (Node* input : merge->inputs()) { |
457 ++j) { | 460 BasicBlock* predecessor_block = schedule_->block(input); |
458 BasicBlock* predecessor_block = schedule_->block(*j); | |
459 TraceConnect(merge, predecessor_block, block); | 461 TraceConnect(merge, predecessor_block, block); |
460 schedule_->AddGoto(predecessor_block, block); | 462 schedule_->AddGoto(predecessor_block, block); |
461 } | 463 } |
462 } | 464 } |
463 | 465 |
464 void ConnectReturn(Node* ret) { | 466 void ConnectReturn(Node* ret) { |
465 Node* return_block_node = NodeProperties::GetControlInput(ret); | 467 Node* return_block_node = NodeProperties::GetControlInput(ret); |
466 BasicBlock* return_block = schedule_->block(return_block_node); | 468 BasicBlock* return_block = schedule_->block(return_block_node); |
467 TraceConnect(ret, return_block, NULL); | 469 TraceConnect(ret, return_block, NULL); |
468 schedule_->AddReturn(return_block, ret); | 470 schedule_->AddReturn(return_block, ret); |
469 } | 471 } |
470 | 472 |
471 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { | 473 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { |
472 DCHECK_NE(NULL, block); | 474 DCHECK_NE(NULL, block); |
473 if (succ == NULL) { | 475 if (succ == NULL) { |
474 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), | 476 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), |
475 block->id().ToInt()); | 477 block->id().ToInt()); |
476 } else { | 478 } else { |
477 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), | 479 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), |
478 block->id().ToInt(), succ->id().ToInt()); | 480 block->id().ToInt(), succ->id().ToInt()); |
479 } | 481 } |
480 } | 482 } |
481 | 483 |
482 bool IsFinalMerge(Node* node) { | 484 bool IsFinalMerge(Node* node) { |
483 return (node->opcode() == IrOpcode::kMerge && | 485 return (node->opcode() == IrOpcode::kMerge && |
484 node == scheduler_->graph_->end()->InputAt(0)); | 486 node == scheduler_->graph_->end()->InputAt(0)); |
485 } | 487 } |
486 | 488 |
| 489 bool IsSingleEntrySingleExitRegion(Node* entry, Node* exit) const { |
| 490 size_t entry_class = scheduler_->equivalence_->ClassOf(entry); |
| 491 size_t exit_class = scheduler_->equivalence_->ClassOf(exit); |
| 492 return entry != exit && entry_class == exit_class; |
| 493 } |
| 494 |
487 Scheduler* scheduler_; | 495 Scheduler* scheduler_; |
488 Schedule* schedule_; | 496 Schedule* schedule_; |
489 ZoneQueue<Node*> queue_; | 497 ZoneQueue<Node*> queue_; |
490 NodeVector control_; | 498 NodeVector control_; |
491 Node* component_head_; | 499 Node* component_entry_; |
492 BasicBlock* component_start_; | 500 BasicBlock* component_start_; |
493 BasicBlock* component_end_; | 501 BasicBlock* component_end_; |
494 }; | 502 }; |
495 | 503 |
496 | 504 |
497 void Scheduler::BuildCFG() { | 505 void Scheduler::BuildCFG() { |
498 Trace("--- CREATING CFG -------------------------------------------\n"); | 506 Trace("--- CREATING CFG -------------------------------------------\n"); |
499 | 507 |
| 508 // Instantiate a new control equivalence algorithm for the graph. |
| 509 equivalence_ = new (zone_) ControlEquivalence(zone_, graph_); |
| 510 |
500 // Build a control-flow graph for the main control-connected component that | 511 // Build a control-flow graph for the main control-connected component that |
501 // is being spanned by the graph's start and end nodes. | 512 // is being spanned by the graph's start and end nodes. |
502 CFGBuilder cfg_builder(zone_, this); | 513 CFGBuilder cfg_builder(zone_, this); |
503 cfg_builder.Run(); | 514 cfg_builder.Run(); |
504 | 515 |
505 // Initialize per-block data. | 516 // Initialize per-block data. |
506 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_)); | 517 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_)); |
507 } | 518 } |
508 | 519 |
509 | 520 |
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1376 } | 1387 } |
1377 } | 1388 } |
1378 BasicBlock* result = schedule_->block(use); | 1389 BasicBlock* result = schedule_->block(use); |
1379 if (result == NULL) return NULL; | 1390 if (result == NULL) return NULL; |
1380 Trace(" must dominate use #%d:%s in B%d\n", use->id(), | 1391 Trace(" must dominate use #%d:%s in B%d\n", use->id(), |
1381 use->op()->mnemonic(), result->id().ToInt()); | 1392 use->op()->mnemonic(), result->id().ToInt()); |
1382 return result; | 1393 return result; |
1383 } | 1394 } |
1384 | 1395 |
1385 void ScheduleFloatingControl(BasicBlock* block, Node* node) { | 1396 void ScheduleFloatingControl(BasicBlock* block, Node* node) { |
1386 DCHECK(scheduler_->GetData(node)->is_floating_control_); | |
1387 scheduler_->FuseFloatingControl(block, node); | 1397 scheduler_->FuseFloatingControl(block, node); |
1388 } | 1398 } |
1389 | 1399 |
1390 void ScheduleNode(BasicBlock* block, Node* node) { | 1400 void ScheduleNode(BasicBlock* block, Node* node) { |
1391 schedule_->PlanNode(block, node); | 1401 schedule_->PlanNode(block, node); |
1392 scheduler_->scheduled_nodes_[block->id().ToSize()].push_back(node); | 1402 scheduler_->scheduled_nodes_[block->id().ToSize()].push_back(node); |
1393 scheduler_->UpdatePlacement(node, Scheduler::kScheduled); | 1403 scheduler_->UpdatePlacement(node, Scheduler::kScheduled); |
1394 } | 1404 } |
1395 | 1405 |
1396 Scheduler* scheduler_; | 1406 Scheduler* scheduler_; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1503 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { | 1513 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { |
1504 schedule_->SetBlockForNode(to, *i); | 1514 schedule_->SetBlockForNode(to, *i); |
1505 scheduled_nodes_[to->id().ToSize()].push_back(*i); | 1515 scheduled_nodes_[to->id().ToSize()].push_back(*i); |
1506 } | 1516 } |
1507 nodes->clear(); | 1517 nodes->clear(); |
1508 } | 1518 } |
1509 | 1519 |
1510 } // namespace compiler | 1520 } // namespace compiler |
1511 } // namespace internal | 1521 } // namespace internal |
1512 } // namespace v8 | 1522 } // namespace v8 |
OLD | NEW |