v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
scheduler.h
Go to the documentation of this file.
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
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_SCHEDULER_H_
6#define V8_COMPILER_SCHEDULER_H_
7
8#include <optional>
9
10#include "src/base/flags.h"
11#include "src/compiler/node.h"
14
15namespace v8 {
16namespace internal {
17
18class ProfileDataFromFile;
19class TickCounter;
20
21namespace compiler {
22
23// Forward declarations.
24class CFGBuilder;
25class ControlEquivalence;
26class TFGraph;
27class SpecialRPONumberer;
28
29// Computes a schedule from a graph, placing nodes into basic blocks and
30// ordering the basic blocks in the special RPO order.
32 public:
33 // Flags that control the mode of operation.
34 enum Flag { kNoFlags = 0u, kSplitNodes = 1u << 1, kTempSchedule = 1u << 2 };
36
37 // The complete scheduling algorithm. Creates a new schedule and places all
38 // nodes from the graph into it.
39 static Schedule* ComputeSchedule(Zone* temp_zone, TFGraph* graph, Flags flags,
40 TickCounter* tick_counter,
41 const ProfileDataFromFile* profile_data);
42
43 // Compute the RPO of blocks in an existing schedule.
44 static BasicBlockVector* ComputeSpecialRPO(Zone* zone, Schedule* schedule);
45
46 // Computes the dominator tree on an existing schedule that has RPO computed.
47 static void GenerateDominatorTree(Schedule* schedule);
48
49 const ProfileDataFromFile* profile_data() const { return profile_data_; }
50
51 private:
52 // Placement of a node changes during scheduling. The placement state
53 // transitions over time while the scheduler is choosing a position:
54 //
55 // +---------------------+-----+----> kFixed
56 // / / /
57 // kUnknown ----+------> kCoupled ----+ /
58 // \ /
59 // +----> kSchedulable ----+--------> kScheduled
60 //
61 // 1) InitializePlacement(): kUnknown -> kCoupled|kSchedulable|kFixed
62 // 2) UpdatePlacement(): kCoupled|kSchedulable -> kFixed|kScheduled
63 //
64 // We maintain the invariant that all nodes that are not reachable
65 // from the end have kUnknown placement. After the PrepareUses phase runs,
66 // also the opposite is true - all nodes with kUnknown placement are not
67 // reachable from the end.
68 enum Placement { kUnknown, kSchedulable, kFixed, kCoupled, kScheduled };
69
70 // Implements a two-dimensional map: (int, int) -> BasicBlock*.
72
73 // Per-node data tracked during scheduling.
75 BasicBlock* minimum_block_; // Minimum legal RPO placement.
76 int unscheduled_count_; // Number of unscheduled uses of this node.
77 Placement placement_; // Whether the node is fixed, schedulable,
78 // coupled to another node, or not yet known.
79 };
80
86 scheduled_nodes_; // Per-block list of nodes in reverse.
87 NodeVector schedule_root_nodes_; // Fixed root nodes seed the worklist.
88 ZoneQueue<Node*> schedule_queue_; // Worklist of schedulable nodes.
89 ZoneVector<SchedulerData> node_data_; // Per-node data for all nodes.
90 CFGBuilder* control_flow_builder_; // Builds basic blocks for controls.
91 SpecialRPONumberer* special_rpo_; // Special RPO numbering of blocks.
92 ControlEquivalence* equivalence_; // Control dependence equivalence.
96
97 Scheduler(Zone* zone, TFGraph* graph, Schedule* schedule, Flags flags,
98 size_t node_count_hint_, TickCounter* tick_counter,
99 const ProfileDataFromFile* profile_data);
100
101 inline SchedulerData DefaultSchedulerData();
102 inline SchedulerData* GetData(Node* node);
103
104 Placement GetPlacement(Node* node);
105 Placement InitializePlacement(Node* node);
106 void UpdatePlacement(Node* node, Placement placement);
107 bool IsLive(Node* node);
108
109 // If the node is coupled, returns the coupled control edge index.
110 inline std::optional<int> GetCoupledControlEdge(Node* node);
111 void IncrementUnscheduledUseCount(Node* node, Node* from);
112 void DecrementUnscheduledUseCount(Node* node, Node* from);
113
114 static void PropagateImmediateDominators(BasicBlock* block);
115
116 // Uses {common_dominator_cache_} to speed up repeated calls.
117 BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2);
118 // Returns the common dominator of {b1} and {b2} if it can be found in
119 // {common_dominator_cache_}, or nullptr otherwise.
120 // Not meant to be called directly, only from {GetCommonDominator}.
121 BasicBlock* GetCommonDominatorIfCached(BasicBlock* b1, BasicBlock* b2);
122
123 // Phase 1: Build control-flow graph.
124 friend class CFGBuilder;
125 void BuildCFG();
126
127 // Phase 2: Compute special RPO and dominator tree.
128 friend class SpecialRPONumberer;
129 void ComputeSpecialRPONumbering();
130 void GenerateDominatorTree();
131
132 // Phase 3: Prepare use counts for nodes.
133 friend class PrepareUsesVisitor;
134 void PrepareUses();
135
136 // Phase 4: Schedule nodes early.
138 void ScheduleEarly();
139
140 // Phase 5: Schedule nodes late.
142 void ScheduleLate();
143
144 // Phase 6: Seal the final schedule.
145 void SealFinalSchedule();
146
147 void FuseFloatingControl(BasicBlock* block, Node* node);
148 void MovePlannedNodes(BasicBlock* from, BasicBlock* to);
149};
150
151
153
154} // namespace compiler
155} // namespace internal
156} // namespace v8
157
158#endif // V8_COMPILER_SCHEDULER_H_
Schedule * schedule
#define DEFINE_OPERATORS_FOR_FLAGS(Type)
Definition flags.h:100
SpecialRPONumberer * special_rpo_
Definition scheduler.h:91
const ProfileDataFromFile * profile_data() const
Definition scheduler.h:49
ControlEquivalence * equivalence_
Definition scheduler.h:92
const ProfileDataFromFile * profile_data_
Definition scheduler.h:94
CommonDominatorCache common_dominator_cache_
Definition scheduler.h:95
ZoneQueue< Node * > schedule_queue_
Definition scheduler.h:88
ZoneVector< NodeVector * > scheduled_nodes_
Definition scheduler.h:86
ZoneVector< SchedulerData > node_data_
Definition scheduler.h:89
TickCounter *const tick_counter_
Definition scheduler.h:93
#define V8_EXPORT_PRIVATE
Definition macros.h:460