| Index: src/compiler/instruction-scheduler.cc
|
| diff --git a/src/compiler/instruction-scheduler.cc b/src/compiler/instruction-scheduler.cc
|
| index 829e883f49a20f12d006df43d0678c1748a4030a..5369f6060e9ad2bce9249832f5075c82620adba6 100644
|
| --- a/src/compiler/instruction-scheduler.cc
|
| +++ b/src/compiler/instruction-scheduler.cc
|
| @@ -5,11 +5,57 @@
|
| #include "src/compiler/instruction-scheduler.h"
|
|
|
| #include "src/base/adapters.h"
|
| +#include "src/base/utils/random-number-generator.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| namespace compiler {
|
|
|
| +// Compare the two nodes and return true if node1 is a better candidate than
|
| +// node2 (i.e. node1 should be scheduled before node2).
|
| +bool InstructionScheduler::CriticalPathFirstQueue::CompareNodes(
|
| + ScheduleGraphNode *node1, ScheduleGraphNode *node2) const {
|
| + return node1->total_latency() > node2->total_latency();
|
| +}
|
| +
|
| +
|
| +InstructionScheduler::ScheduleGraphNode*
|
| +InstructionScheduler::CriticalPathFirstQueue::PopBestCandidate(int cycle) {
|
| + DCHECK(!IsEmpty());
|
| + auto candidate = nodes_.end();
|
| + for (auto iterator = nodes_.begin(); iterator != nodes_.end(); ++iterator) {
|
| + // We only consider instructions that have all their operands ready and
|
| + // we try to schedule the critical path first.
|
| + if (cycle >= (*iterator)->start_cycle()) {
|
| + if ((candidate == nodes_.end()) || CompareNodes(*iterator, *candidate)) {
|
| + candidate = iterator;
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (candidate != nodes_.end()) {
|
| + ScheduleGraphNode *result = *candidate;
|
| + nodes_.erase(candidate);
|
| + return result;
|
| + }
|
| +
|
| + return nullptr;
|
| +}
|
| +
|
| +
|
| +InstructionScheduler::ScheduleGraphNode*
|
| +InstructionScheduler::StressSchedulerQueue::PopBestCandidate(int cycle) {
|
| + DCHECK(!IsEmpty());
|
| + // Choose a random element from the ready list.
|
| + auto candidate = nodes_.begin();
|
| + std::advance(candidate, isolate()->random_number_generator()->NextInt(
|
| + static_cast<int>(nodes_.size())));
|
| + ScheduleGraphNode *result = *candidate;
|
| + nodes_.erase(candidate);
|
| + return result;
|
| +}
|
| +
|
| +
|
| InstructionScheduler::ScheduleGraphNode::ScheduleGraphNode(
|
| Zone* zone,
|
| Instruction* instr)
|
| @@ -50,7 +96,11 @@ void InstructionScheduler::StartBlock(RpoNumber rpo) {
|
|
|
|
|
| void InstructionScheduler::EndBlock(RpoNumber rpo) {
|
| - ScheduleBlock();
|
| + if (FLAG_turbo_stress_instruction_scheduling) {
|
| + ScheduleBlock<StressSchedulerQueue>();
|
| + } else {
|
| + ScheduleBlock<CriticalPathFirstQueue>();
|
| + }
|
| sequence()->EndBlock(rpo);
|
| graph_.clear();
|
| last_side_effect_instr_ = nullptr;
|
| @@ -110,14 +160,9 @@ void InstructionScheduler::AddInstruction(Instruction* instr) {
|
| }
|
|
|
|
|
| -bool InstructionScheduler::CompareNodes(ScheduleGraphNode *node1,
|
| - ScheduleGraphNode *node2) const {
|
| - return node1->total_latency() > node2->total_latency();
|
| -}
|
| -
|
| -
|
| +template <typename QueueType>
|
| void InstructionScheduler::ScheduleBlock() {
|
| - ZoneLinkedList<ScheduleGraphNode*> ready_list(zone());
|
| + QueueType ready_list(this);
|
|
|
| // Compute total latencies so that we can schedule the critical path first.
|
| ComputeTotalLatencies();
|
| @@ -125,43 +170,28 @@ void InstructionScheduler::ScheduleBlock() {
|
| // Add nodes which don't have dependencies to the ready list.
|
| for (auto node : graph_) {
|
| if (!node->HasUnscheduledPredecessor()) {
|
| - ready_list.push_back(node);
|
| + ready_list.AddNode(node);
|
| }
|
| }
|
|
|
| // Go through the ready list and schedule the instructions.
|
| int cycle = 0;
|
| - while (!ready_list.empty()) {
|
| - auto candidate = ready_list.end();
|
| - for (auto iterator = ready_list.begin(); iterator != ready_list.end();
|
| - ++iterator) {
|
| - // Look for the best candidate to schedule.
|
| - // We only consider instructions that have all their operands ready and
|
| - // we try to schedule the critical path first (we look for the instruction
|
| - // with the highest latency on the path to reach the end of the graph).
|
| - if (cycle >= (*iterator)->start_cycle()) {
|
| - if ((candidate == ready_list.end()) ||
|
| - CompareNodes(*iterator, *candidate)) {
|
| - candidate = iterator;
|
| - }
|
| - }
|
| - }
|
| + while (!ready_list.IsEmpty()) {
|
| + auto candidate = ready_list.PopBestCandidate(cycle);
|
|
|
| - if (candidate != ready_list.end()) {
|
| - sequence()->AddInstruction((*candidate)->instruction());
|
| + if (candidate != nullptr) {
|
| + sequence()->AddInstruction(candidate->instruction());
|
|
|
| - for (auto successor : (*candidate)->successors()) {
|
| + for (auto successor : candidate->successors()) {
|
| successor->DropUnscheduledPredecessor();
|
| successor->set_start_cycle(
|
| std::max(successor->start_cycle(),
|
| - cycle + (*candidate)->latency()));
|
| + cycle + candidate->latency()));
|
|
|
| if (!successor->HasUnscheduledPredecessor()) {
|
| - ready_list.push_back(successor);
|
| + ready_list.AddNode(successor);
|
| }
|
| }
|
| -
|
| - ready_list.erase(candidate);
|
| }
|
|
|
| cycle++;
|
|
|