Index: src/compiler/instruction-scheduler.h |
diff --git a/src/compiler/instruction-scheduler.h b/src/compiler/instruction-scheduler.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8b401107b1ca5f0b645cad7e762faeff610956c9 |
--- /dev/null |
+++ b/src/compiler/instruction-scheduler.h |
@@ -0,0 +1,117 @@ |
+// Copyright 2015 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef V8_COMPILER_INSTRUCTION_SCHEDULER_H_ |
+#define V8_COMPILER_INSTRUCTION_SCHEDULER_H_ |
+ |
+#include "src/compiler/instruction.h" |
+#include "src/zone-containers.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace compiler { |
+ |
+class InstructionScheduler final : public ZoneObject { |
+ public: |
+ InstructionScheduler(Zone* zone, InstructionSequence* sequence); |
+ |
+ void StartBlock(RpoNumber rpo); |
+ void EndBlock(RpoNumber rpo); |
+ |
+ void AddInstruction(Instruction* instr); |
+ |
+ private: |
+ // A scheduling graph node. |
+ // Represent an instruction and their dependencies. |
+ class ScheduleGraphNode: public ZoneObject { |
+ public: |
+ ScheduleGraphNode(Zone* zone, Instruction* instr); |
+ |
+ // Add an edge between two nodes in the scheduling graph. |
+ // Edges are directed and an edge from A -> B means that instruction A must |
+ // be scheduled before B. |
Jarin
2015/10/26 15:12:35
You might want to say that it means A is a depende
baptiste.afsa1
2015/10/27 16:00:24
Done.
Good idea. Using the term UnscheduledPredec
|
+ void AddSuccessor(ScheduleGraphNode* node); |
+ |
+ bool HasDependency() { return dependency_count_ != 0; } |
+ |
+ // Record that we have scheduled one of the dependencies of the current |
+ // node. |
+ void DropDependency() { |
+ DCHECK(dependency_count_ > 0); |
+ dependency_count_--; |
+ } |
+ |
+ Instruction* instruction() { return instr_; } |
+ ZoneVector<ScheduleGraphNode*> &successors() { return successors_; } |
+ int latency() const { return latency_; } |
+ |
+ int total_latency() const { return total_latency_; } |
+ void set_total_latency(int latency) { total_latency_ = latency; } |
+ |
+ int start_cycle() const { return start_cycle_; } |
+ void set_start_cycle(int start_cycle) { start_cycle_ = start_cycle; } |
+ |
+ private: |
+ Instruction* instr_; |
+ ZoneVector<ScheduleGraphNode*> successors_; |
Jarin
2015/10/26 15:12:35
I think it is better to use ZoneDeque here.
baptiste.afsa1
2015/10/27 16:00:24
Done.
|
+ int dependency_count_; // Number of dependencies for a given node. |
+ |
+ // Estimate of the instruction latency (the number of cycles it takes for |
+ // instruction to complete). |
+ int latency_; |
+ |
+ // The sum of all the latencies from a node to the root of the graph. |
Jarin
2015/10/26 15:12:35
What is the "root of the graph" here? From the cod
baptiste.afsa1
2015/10/27 16:00:24
Done.
|
+ int total_latency_; |
+ |
+ // The scheduler keeps a nominal cycle count to keep track of when the |
+ // result of an instruction is available. This field is updated by the |
+ // scheduler to indicate when the value of all the operands of this |
+ // instruction will be available. |
+ int start_cycle_; |
+ }; |
+ |
+ // Compare the two nodes and return true if node1 is a better candidate than |
+ // node2 (i.e. node1 should be scheduled before node2). |
+ bool CompareNodes(ScheduleGraphNode *node1, ScheduleGraphNode *node2) const; |
+ |
+ // Perform scheduling for the current block. |
+ void ScheduleBlock(); |
+ |
+ // Return true if instr2 uses any value defined by instr1. |
+ bool HasOperandDependency(const Instruction* instr1, |
+ const Instruction* instr2) const; |
+ |
+ // Return true if the instruction is a basic block terminator. |
+ bool IsBlockTerminator(const Instruction* instr) const; |
+ |
+ // Check whether the given instruction has side effects (e.g. function call, |
+ // memory store). |
+ bool HasSideEffect(const Instruction* instr) const { |
+ return instruction_flags_[instr->arch_opcode()] & kHasSideEffect; |
+ } |
+ |
+ // Return true if the instruction is a memory load. |
+ bool IsLoadOperation(const Instruction* instr) const { |
+ return instruction_flags_[instr->arch_opcode()] & kIsLoadOperation; |
+ } |
+ |
+ void ComputeTotalLatency(ScheduleGraphNode* node); |
+ |
+ static int GetInstructionLatency(const Instruction* instr); |
+ |
+ Zone* zone() { return zone_; } |
+ InstructionSequence* sequence() { return sequence_; } |
+ |
+ static const int instruction_flags_[]; |
+ |
+ Zone* zone_; |
+ InstructionSequence* sequence_; |
+ ZoneVector<ScheduleGraphNode*> graph_; |
+}; |
+ |
+} // namespace compiler |
+} // namespace internal |
+} // namespace v8 |
+ |
+#endif // V8_COMPILER_INSTRUCTION_SCHEDULER_H_ |