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

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

Issue 649203002: Switch schedule early phase to basic blocks. (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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 scheduler.ScheduleLate(); 56 scheduler.ScheduleLate();
57 57
58 had_floating_control = scheduler.ConnectFloatingControl(); 58 had_floating_control = scheduler.ConnectFloatingControl();
59 } while (had_floating_control); 59 } while (had_floating_control);
60 60
61 return schedule; 61 return schedule;
62 } 62 }
63 63
64 64
65 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { 65 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() {
66 SchedulerData def = {0, -1, false, false, kUnknown}; 66 SchedulerData def = {NULL, 0, false, false, kUnknown};
67 return def; 67 return def;
68 } 68 }
69 69
70 70
71 Scheduler::Placement Scheduler::GetPlacement(Node* node) { 71 Scheduler::Placement Scheduler::GetPlacement(Node* node) {
72 SchedulerData* data = GetData(node); 72 SchedulerData* data = GetData(node);
73 if (data->placement_ == kUnknown) { // Compute placement, once, on demand. 73 if (data->placement_ == kUnknown) { // Compute placement, once, on demand.
74 switch (node->opcode()) { 74 switch (node->opcode()) {
75 case IrOpcode::kParameter: 75 case IrOpcode::kParameter:
76 // Parameters are always fixed to the start node. 76 // Parameters are always fixed to the start node.
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 block->id().ToInt()); 308 block->id().ToInt());
309 } else { 309 } else {
310 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), 310 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(),
311 block->id().ToInt(), succ->id().ToInt()); 311 block->id().ToInt(), succ->id().ToInt());
312 } 312 }
313 } 313 }
314 }; 314 };
315 315
316 316
317 void Scheduler::BuildCFG() { 317 void Scheduler::BuildCFG() {
318 Trace("---------------- CREATING CFG ------------------\n"); 318 Trace("--- CREATING CFG -------------------------------------------\n");
319 CFGBuilder cfg_builder(zone_, this); 319 CFGBuilder cfg_builder(zone_, this);
320 cfg_builder.Run(); 320 cfg_builder.Run();
321 // Initialize per-block data. 321 // Initialize per-block data.
322 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_)); 322 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_));
323 } 323 }
324 324
325 325
326 void Scheduler::GenerateImmediateDominatorTree() { 326 void Scheduler::GenerateImmediateDominatorTree() {
327 // Build the dominator graph. TODO(danno): consider using Lengauer & Tarjan's 327 // Build the dominator graph. TODO(danno): consider using Lengauer & Tarjan's
328 // if this becomes really slow. 328 // if this becomes really slow.
329 Trace("------------ IMMEDIATE BLOCK DOMINATORS -----------\n"); 329 Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n");
330 for (size_t i = 0; i < schedule_->rpo_order_.size(); i++) { 330 for (size_t i = 0; i < schedule_->rpo_order_.size(); i++) {
331 BasicBlock* current_rpo = schedule_->rpo_order_[i]; 331 BasicBlock* current_rpo = schedule_->rpo_order_[i];
332 if (current_rpo != schedule_->start()) { 332 if (current_rpo != schedule_->start()) {
333 BasicBlock::Predecessors::iterator current_pred = 333 BasicBlock::Predecessors::iterator current_pred =
334 current_rpo->predecessors_begin(); 334 current_rpo->predecessors_begin();
335 BasicBlock::Predecessors::iterator end = current_rpo->predecessors_end(); 335 BasicBlock::Predecessors::iterator end = current_rpo->predecessors_end();
336 DCHECK(current_pred != end); 336 DCHECK(current_pred != end);
337 BasicBlock* dominator = *current_pred; 337 BasicBlock* dominator = *current_pred;
338 ++current_pred; 338 ++current_pred;
339 // For multiple predecessors, walk up the rpo ordering until a common 339 // For multiple predecessors, walk up the rpo ordering until a common
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 } 398 }
399 } 399 }
400 400
401 private: 401 private:
402 Scheduler* scheduler_; 402 Scheduler* scheduler_;
403 Schedule* schedule_; 403 Schedule* schedule_;
404 }; 404 };
405 405
406 406
407 void Scheduler::PrepareUses() { 407 void Scheduler::PrepareUses() {
408 Trace("------------------- PREPARE USES ------------------\n"); 408 Trace("--- PREPARE USES -------------------------------------------\n");
409 409
410 // Count the uses of every node, it will be used to ensure that all of a 410 // Count the uses of every node, it will be used to ensure that all of a
411 // node's uses are scheduled before the node itself. 411 // node's uses are scheduled before the node itself.
412 PrepareUsesVisitor prepare_uses(this); 412 PrepareUsesVisitor prepare_uses(this);
413 graph_->VisitNodeInputsFromEnd(&prepare_uses); 413 graph_->VisitNodeInputsFromEnd(&prepare_uses);
414 } 414 }
415 415
416 416
417 // ----------------------------------------------------------------------------- 417 // -----------------------------------------------------------------------------
418 // Phase 3: Schedule nodes early. 418 // Phase 3: Schedule nodes early.
419 419
420 420
421 class ScheduleEarlyNodeVisitor : public NullNodeVisitor { 421 class ScheduleEarlyNodeVisitor : public NullNodeVisitor {
422 public: 422 public:
423 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) 423 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler)
424 : scheduler_(scheduler), schedule_(scheduler->schedule_) {} 424 : scheduler_(scheduler), schedule_(scheduler->schedule_) {}
425 425
426 GenericGraphVisit::Control Pre(Node* node) { 426 GenericGraphVisit::Control Pre(Node* node) {
427 Scheduler::SchedulerData* data = scheduler_->GetData(node);
427 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { 428 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) {
428 // Fixed nodes already know their schedule early position. 429 // Fixed nodes already know their schedule early position.
429 Scheduler::SchedulerData* data = scheduler_->GetData(node); 430 if (data->minimum_block_ == NULL) {
430 BasicBlock* block = schedule_->block(node); 431 data->minimum_block_ = schedule_->block(node);
431 DCHECK(block != NULL);
432 if (data->minimum_rpo_ < 0) {
433 data->minimum_rpo_ = block->rpo_number();
434 Trace("Preschedule #%d:%s minimum_rpo = %d (fixed)\n", node->id(), 432 Trace("Preschedule #%d:%s minimum_rpo = %d (fixed)\n", node->id(),
435 node->op()->mnemonic(), data->minimum_rpo_); 433 node->op()->mnemonic(), data->minimum_block_->rpo_number());
436 } 434 }
437 } else { 435 } else {
438 // For unfixed nodes the minimum RPO is the max of all of the inputs. 436 // For unfixed nodes the minimum RPO is the max of all of the inputs.
439 Scheduler::SchedulerData* data = scheduler_->GetData(node); 437 if (data->minimum_block_ == NULL) {
440 if (data->minimum_rpo_ < 0) { 438 data->minimum_block_ = ComputeMaximumInputRPO(node);
441 data->minimum_rpo_ = ComputeMaximumInputRPO(node); 439 if (data->minimum_block_ == NULL) return GenericGraphVisit::REENTER;
442 if (data->minimum_rpo_ < 0) return GenericGraphVisit::REENTER;
443 Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(), 440 Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(),
444 node->op()->mnemonic(), data->minimum_rpo_); 441 node->op()->mnemonic(), data->minimum_block_->rpo_number());
445 } 442 }
446 DCHECK_GE(data->minimum_rpo_, 0);
447 } 443 }
444 DCHECK_NE(data->minimum_block_, NULL);
448 return GenericGraphVisit::CONTINUE; 445 return GenericGraphVisit::CONTINUE;
449 } 446 }
450 447
451 GenericGraphVisit::Control Post(Node* node) { 448 GenericGraphVisit::Control Post(Node* node) {
449 Scheduler::SchedulerData* data = scheduler_->GetData(node);
452 if (scheduler_->GetPlacement(node) != Scheduler::kFixed) { 450 if (scheduler_->GetPlacement(node) != Scheduler::kFixed) {
453 Scheduler::SchedulerData* data = scheduler_->GetData(node);
454 // For unfixed nodes the minimum RPO is the max of all of the inputs. 451 // For unfixed nodes the minimum RPO is the max of all of the inputs.
455 if (data->minimum_rpo_ < 0) { 452 if (data->minimum_block_ == NULL) {
456 data->minimum_rpo_ = ComputeMaximumInputRPO(node); 453 data->minimum_block_ = ComputeMaximumInputRPO(node);
457 Trace("Postschedule #%d:%s minimum_rpo = %d\n", node->id(), 454 Trace("Postschedule #%d:%s minimum_rpo = %d\n", node->id(),
458 node->op()->mnemonic(), data->minimum_rpo_); 455 node->op()->mnemonic(), data->minimum_block_->rpo_number());
459 } 456 }
460 DCHECK_GE(data->minimum_rpo_, 0);
461 } 457 }
458 DCHECK_NE(data->minimum_block_, NULL);
462 return GenericGraphVisit::CONTINUE; 459 return GenericGraphVisit::CONTINUE;
463 } 460 }
464 461
465 // Computes the maximum of the minimum RPOs for all inputs. If the maximum 462 // Computes the maximum of the minimum RPOs for all inputs. If the maximum
466 // cannot be determined (i.e. minimum RPO for at least one input not known), 463 // cannot be determined (i.e. minimum RPO for at least one input is {NULL}),
467 // then a negative number is returned. 464 // then {NULL} is returned.
468 int ComputeMaximumInputRPO(Node* node) { 465 BasicBlock* ComputeMaximumInputRPO(Node* node) {
469 int max_rpo = 0; 466 BasicBlock* max_block = schedule_->start();
470 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { 467 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
471 DCHECK_NE(node, *i); // Loops only exist for fixed nodes. 468 DCHECK_NE(node, *i); // Loops only exist for fixed nodes.
472 int control_rpo = scheduler_->GetData(*i)->minimum_rpo_; 469 BasicBlock* block = scheduler_->GetData(*i)->minimum_block_;
473 if (control_rpo > max_rpo) { 470 if (block == NULL) return NULL;
474 max_rpo = control_rpo; 471 if (block->rpo_number() > max_block->rpo_number()) {
475 } else if (control_rpo < 0) { 472 max_block = block;
476 return control_rpo;
477 } 473 }
478 } 474 }
479 return max_rpo; 475 return max_block;
480 } 476 }
481 477
482 private: 478 private:
483 Scheduler* scheduler_; 479 Scheduler* scheduler_;
484 Schedule* schedule_; 480 Schedule* schedule_;
485 }; 481 };
486 482
487 483
488 void Scheduler::ScheduleEarly() { 484 void Scheduler::ScheduleEarly() {
489 Trace("------------------- SCHEDULE EARLY ----------------\n"); 485 Trace("--- SCHEDULE EARLY -----------------------------------------\n");
490 486
491 // Compute the minimum RPO for each node thereby determining the earliest 487 // Compute the minimum RPO for each node thereby determining the earliest
492 // position each node could be placed within a valid schedule. 488 // position each node could be placed within a valid schedule.
493 ScheduleEarlyNodeVisitor visitor(this); 489 ScheduleEarlyNodeVisitor visitor(this);
494 graph_->VisitNodeInputsFromEnd(&visitor); 490 graph_->VisitNodeInputsFromEnd(&visitor);
495 } 491 }
496 492
497 493
498 // ----------------------------------------------------------------------------- 494 // -----------------------------------------------------------------------------
499 // Phase 4: Schedule nodes late. 495 // Phase 4: Schedule nodes late.
(...skipping 25 matching lines...) Expand all
525 for (Node::Uses::iterator i = node->uses().begin(); i != node->uses().end(); 521 for (Node::Uses::iterator i = node->uses().begin(); i != node->uses().end();
526 ++i) { 522 ++i) {
527 BasicBlock* use_block = GetBlockForUse(i.edge()); 523 BasicBlock* use_block = GetBlockForUse(i.edge());
528 block = block == NULL ? use_block : use_block == NULL 524 block = block == NULL ? use_block : use_block == NULL
529 ? block 525 ? block
530 : scheduler_->GetCommonDominator( 526 : scheduler_->GetCommonDominator(
531 block, use_block); 527 block, use_block);
532 } 528 }
533 DCHECK(block != NULL); 529 DCHECK(block != NULL);
534 530
535 int min_rpo = data->minimum_rpo_; 531 int min_rpo = data->minimum_block_->rpo_number();
536 Trace( 532 Trace(
537 "Schedule late conservative for #%d:%s is B%d at loop depth %d, " 533 "Schedule late conservative for #%d:%s is B%d at loop depth %d, "
538 "minimum_rpo = %d\n", 534 "minimum_rpo = %d\n",
539 node->id(), node->op()->mnemonic(), block->id().ToInt(), 535 node->id(), node->op()->mnemonic(), block->id().ToInt(),
540 block->loop_depth(), min_rpo); 536 block->loop_depth(), min_rpo);
541 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively 537 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively
542 // into enclosing loop pre-headers until they would preceed their 538 // into enclosing loop pre-headers until they would preceed their
543 // ScheduleEarly position. 539 // ScheduleEarly position.
544 BasicBlock* hoist_block = block; 540 BasicBlock* hoist_block = block;
545 while (hoist_block != NULL && hoist_block->rpo_number() >= min_rpo) { 541 while (hoist_block != NULL && hoist_block->rpo_number() >= min_rpo) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 } 608 }
613 } 609 }
614 } 610 }
615 611
616 Scheduler* scheduler_; 612 Scheduler* scheduler_;
617 Schedule* schedule_; 613 Schedule* schedule_;
618 }; 614 };
619 615
620 616
621 void Scheduler::ScheduleLate() { 617 void Scheduler::ScheduleLate() {
622 Trace("------------------- SCHEDULE LATE -----------------\n"); 618 Trace("--- SCHEDULE LATE ------------------------------------------\n");
623 if (FLAG_trace_turbo_scheduler) { 619 if (FLAG_trace_turbo_scheduler) {
624 Trace("roots: "); 620 Trace("roots: ");
625 for (NodeVectorIter i = schedule_root_nodes_.begin(); 621 for (NodeVectorIter i = schedule_root_nodes_.begin();
626 i != schedule_root_nodes_.end(); ++i) { 622 i != schedule_root_nodes_.end(); ++i) {
627 Trace("#%d:%s ", (*i)->id(), (*i)->op()->mnemonic()); 623 Trace("#%d:%s ", (*i)->id(), (*i)->op()->mnemonic());
628 } 624 }
629 Trace("\n"); 625 Trace("\n");
630 } 626 }
631 627
632 // Schedule: Places nodes in dominator block of all their uses. 628 // Schedule: Places nodes in dominator block of all their uses.
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 // (i.e. A -> B is a backedge). 954 // (i.e. A -> B is a backedge).
959 // => If block A dominates block B, then A appears before B in the order. 955 // => If block A dominates block B, then A appears before B in the order.
960 // => If block A is a loop header, A appears before all blocks in the loop 956 // => If block A is a loop header, A appears before all blocks in the loop
961 // headed at A. 957 // headed at A.
962 // 2. All loops are contiguous in the order (i.e. no intervening blocks that 958 // 2. All loops are contiguous in the order (i.e. no intervening blocks that
963 // do not belong to the loop.) 959 // do not belong to the loop.)
964 // Note a simple RPO traversal satisfies (1) but not (3). 960 // Note a simple RPO traversal satisfies (1) but not (3).
965 BasicBlockVector* Scheduler::ComputeSpecialRPO(Schedule* schedule) { 961 BasicBlockVector* Scheduler::ComputeSpecialRPO(Schedule* schedule) {
966 Zone tmp_zone(schedule->zone()->isolate()); 962 Zone tmp_zone(schedule->zone()->isolate());
967 Zone* zone = &tmp_zone; 963 Zone* zone = &tmp_zone;
968 Trace("------------- COMPUTING SPECIAL RPO ---------------\n"); 964 Trace("--- COMPUTING SPECIAL RPO ----------------------------------\n");
969 // RPO should not have been computed for this schedule yet. 965 // RPO should not have been computed for this schedule yet.
970 CHECK_EQ(kBlockUnvisited1, schedule->start()->rpo_number()); 966 CHECK_EQ(kBlockUnvisited1, schedule->start()->rpo_number());
971 CHECK_EQ(0, static_cast<int>(schedule->rpo_order_.size())); 967 CHECK_EQ(0, static_cast<int>(schedule->rpo_order_.size()));
972 968
973 // Perform an iterative RPO traversal using an explicit stack, 969 // Perform an iterative RPO traversal using an explicit stack,
974 // recording backedges that form cycles. O(|B|). 970 // recording backedges that form cycles. O(|B|).
975 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone); 971 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone);
976 SpecialRPOStackFrame* stack = zone->NewArray<SpecialRPOStackFrame>( 972 SpecialRPOStackFrame* stack = zone->NewArray<SpecialRPOStackFrame>(
977 static_cast<int>(schedule->BasicBlockCount())); 973 static_cast<int>(schedule->BasicBlockCount()));
978 BasicBlock* entry = schedule->start(); 974 BasicBlock* entry = schedule->start();
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 #if DEBUG 1148 #if DEBUG
1153 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); 1149 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order);
1154 VerifySpecialRPO(num_loops, loops, final_order); 1150 VerifySpecialRPO(num_loops, loops, final_order);
1155 #endif 1151 #endif
1156 return final_order; 1152 return final_order;
1157 } 1153 }
1158 1154
1159 } // namespace compiler 1155 } // namespace compiler
1160 } // namespace internal 1156 } // namespace internal
1161 } // namespace v8 1157 } // 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