blob: 0bba689785728fe9409bdc7fd8edca499cfda020 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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_SCHEDULE_H_
6#define V8_COMPILER_SCHEDULE_H_
7
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008#include <iosfwd>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include <vector>
10
11#include "src/v8.h"
12
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/node.h"
14#include "src/compiler/opcodes.h"
15#include "src/zone.h"
16
17namespace v8 {
18namespace internal {
19namespace compiler {
20
21class BasicBlock;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022class BasicBlockInstrumentor;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023class Graph;
24class ConstructScheduleData;
25class CodeGenerator; // Because of a namespace bug in clang.
26
Emily Bernierd0a1eb72015-03-24 16:35:39 -040027// A basic block contains an ordered list of nodes and ends with a control
28// node. Note that if a basic block has phis, then all phis must appear as the
29// first nodes in the block.
30class BasicBlock FINAL : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 public:
32 // Possible control nodes that can end a block.
33 enum Control {
34 kNone, // Control not initialized yet.
35 kGoto, // Goto a single successor block.
36 kBranch, // Branch if true to first successor, otherwise second.
37 kReturn, // Return a value from this method.
38 kThrow // Throw an exception.
39 };
40
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041 class Id {
42 public:
43 int ToInt() const { return static_cast<int>(index_); }
44 size_t ToSize() const { return index_; }
45 static Id FromSize(size_t index) { return Id(index); }
46 static Id FromInt(int index) { return Id(static_cast<size_t>(index)); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047
Emily Bernierd0a1eb72015-03-24 16:35:39 -040048 private:
49 explicit Id(size_t index) : index_(index) {}
50 size_t index_;
51 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +000052
Emily Bernierd0a1eb72015-03-24 16:35:39 -040053 static const int kInvalidRpoNumber = -1;
54 class RpoNumber FINAL {
55 public:
56 int ToInt() const {
57 DCHECK(IsValid());
58 return index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040060 size_t ToSize() const {
61 DCHECK(IsValid());
62 return static_cast<size_t>(index_);
63 }
64 bool IsValid() const { return index_ >= 0; }
65 static RpoNumber FromInt(int index) { return RpoNumber(index); }
66 static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067
Emily Bernierd0a1eb72015-03-24 16:35:39 -040068 bool IsNext(const RpoNumber other) const {
69 DCHECK(IsValid());
70 return other.index_ == this->index_ + 1;
71 }
72
73 bool operator==(RpoNumber other) const {
74 return this->index_ == other.index_;
75 }
76
77 private:
78 explicit RpoNumber(int32_t index) : index_(index) {}
79 int32_t index_;
80 };
81
82 BasicBlock(Zone* zone, Id id);
83
84 Id id() const { return id_; }
85
86 // Predecessors and successors.
87 typedef ZoneVector<BasicBlock*> Predecessors;
88 Predecessors::iterator predecessors_begin() { return predecessors_.begin(); }
89 Predecessors::iterator predecessors_end() { return predecessors_.end(); }
90 Predecessors::const_iterator predecessors_begin() const {
91 return predecessors_.begin();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040093 Predecessors::const_iterator predecessors_end() const {
94 return predecessors_.end();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096 size_t PredecessorCount() const { return predecessors_.size(); }
97 BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
98 void ClearPredecessors() { predecessors_.clear(); }
99 void AddPredecessor(BasicBlock* predecessor);
100
101 typedef ZoneVector<BasicBlock*> Successors;
102 Successors::iterator successors_begin() { return successors_.begin(); }
103 Successors::iterator successors_end() { return successors_.end(); }
104 Successors::const_iterator successors_begin() const {
105 return successors_.begin();
106 }
107 Successors::const_iterator successors_end() const {
108 return successors_.end();
109 }
110 size_t SuccessorCount() const { return successors_.size(); }
111 BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
112 void ClearSuccessors() { successors_.clear(); }
113 void AddSuccessor(BasicBlock* successor);
114
115 // Nodes in the basic block.
116 Node* NodeAt(size_t index) { return nodes_[index]; }
117 size_t NodeCount() const { return nodes_.size(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118
119 typedef NodeVector::iterator iterator;
120 iterator begin() { return nodes_.begin(); }
121 iterator end() { return nodes_.end(); }
122
123 typedef NodeVector::const_iterator const_iterator;
124 const_iterator begin() const { return nodes_.begin(); }
125 const_iterator end() const { return nodes_.end(); }
126
127 typedef NodeVector::reverse_iterator reverse_iterator;
128 reverse_iterator rbegin() { return nodes_.rbegin(); }
129 reverse_iterator rend() { return nodes_.rend(); }
130
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400131 void AddNode(Node* node);
132 template <class InputIterator>
133 void InsertNodes(iterator insertion_point, InputIterator insertion_start,
134 InputIterator insertion_end) {
135 nodes_.insert(insertion_point, insertion_start, insertion_end);
136 }
137
138 // Accessors.
139 Control control() const { return control_; }
140 void set_control(Control control);
141
142 Node* control_input() const { return control_input_; }
143 void set_control_input(Node* control_input);
144
145 bool deferred() const { return deferred_; }
146 void set_deferred(bool deferred) { deferred_ = deferred; }
147
148 int32_t dominator_depth() const { return dominator_depth_; }
149 void set_dominator_depth(int32_t depth) { dominator_depth_ = depth; }
150
151 BasicBlock* dominator() const { return dominator_; }
152 void set_dominator(BasicBlock* dominator) { dominator_ = dominator; }
153
154 BasicBlock* rpo_next() const { return rpo_next_; }
155 void set_rpo_next(BasicBlock* rpo_next) { rpo_next_ = rpo_next; }
156
157 BasicBlock* loop_header() const { return loop_header_; }
158 void set_loop_header(BasicBlock* loop_header);
159
160 BasicBlock* loop_end() const { return loop_end_; }
161 void set_loop_end(BasicBlock* loop_end);
162
163 int32_t loop_depth() const { return loop_depth_; }
164 void set_loop_depth(int32_t loop_depth);
165
166 int32_t loop_number() const { return loop_number_; }
167 void set_loop_number(int32_t loop_number) { loop_number_ = loop_number; }
168
169 RpoNumber GetRpoNumber() const { return RpoNumber::FromInt(rpo_number_); }
170 int32_t rpo_number() const { return rpo_number_; }
171 void set_rpo_number(int32_t rpo_number);
172
173 // Loop membership helpers.
174 inline bool IsLoopHeader() const { return loop_end_ != NULL; }
175 bool LoopContains(BasicBlock* block) const;
176
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400178 int32_t loop_number_; // loop number of the block.
179 int32_t rpo_number_; // special RPO number of the block.
180 bool deferred_; // true if the block contains deferred code.
181 int32_t dominator_depth_; // Depth within the dominator tree.
182 BasicBlock* dominator_; // Immediate dominator of the block.
183 BasicBlock* rpo_next_; // Link to next block in special RPO order.
184 BasicBlock* loop_header_; // Pointer to dominating loop header basic block,
185 // NULL if none. For loop headers, this points to
186 // enclosing loop header.
187 BasicBlock* loop_end_; // end of the loop, if this block is a loop header.
188 int32_t loop_depth_; // loop nesting, 0 is top-level
189
190 Control control_; // Control at the end of the block.
191 Node* control_input_; // Input value for control.
192 NodeVector nodes_; // nodes of this block in forward order.
193
194 Successors successors_;
195 Predecessors predecessors_;
196 Id id_;
197
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 DISALLOW_COPY_AND_ASSIGN(BasicBlock);
199};
200
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400201std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c);
202std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id);
203std::ostream& operator<<(std::ostream& os, const BasicBlock::RpoNumber& rpo);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204
205typedef ZoneVector<BasicBlock*> BasicBlockVector;
206typedef BasicBlockVector::iterator BasicBlockVectorIter;
207typedef BasicBlockVector::reverse_iterator BasicBlockVectorRIter;
208
209// A schedule represents the result of assigning nodes to basic blocks
210// and ordering them within basic blocks. Prior to computing a schedule,
211// a graph has no notion of control flow ordering other than that induced
212// by the graph's dependencies. A schedule is required to generate code.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213class Schedule FINAL : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400215 explicit Schedule(Zone* zone, size_t node_count_hint = 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216
217 // Return the block which contains {node}, if any.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400218 BasicBlock* block(Node* node) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220 bool IsScheduled(Node* node);
221 BasicBlock* GetBlockById(BasicBlock::Id block_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400223 size_t BasicBlockCount() const { return all_blocks_.size(); }
224 size_t RpoBlockCount() const { return rpo_order_.size(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225
226 // Check if nodes {a} and {b} are in the same block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400227 bool SameBasicBlock(Node* a, Node* b) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228
229 // BasicBlock building: create a new block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400230 BasicBlock* NewBasicBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231
232 // BasicBlock building: records that a node will later be added to a block but
233 // doesn't actually add the node to the block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234 void PlanNode(BasicBlock* block, Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235
236 // BasicBlock building: add a node to the end of the block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400237 void AddNode(BasicBlock* block, Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238
239 // BasicBlock building: add a goto to the end of {block}.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400240 void AddGoto(BasicBlock* block, BasicBlock* succ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241
242 // BasicBlock building: add a branch at the end of {block}.
243 void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400244 BasicBlock* fblock);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245
246 // BasicBlock building: add a return at the end of {block}.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400247 void AddReturn(BasicBlock* block, Node* input);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248
249 // BasicBlock building: add a throw at the end of {block}.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400250 void AddThrow(BasicBlock* block, Node* input);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400252 // BasicBlock mutation: insert a branch into the end of {block}.
253 void InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
254 BasicBlock* tblock, BasicBlock* fblock);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400256 // Exposed publicly for testing only.
257 void AddSuccessorForTesting(BasicBlock* block, BasicBlock* succ) {
258 return AddSuccessor(block, succ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259 }
260
261 BasicBlockVector* rpo_order() { return &rpo_order_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400262 const BasicBlockVector* rpo_order() const { return &rpo_order_; }
263
264 BasicBlock* start() { return start_; }
265 BasicBlock* end() { return end_; }
266
267 Zone* zone() const { return zone_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268
269 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400270 friend class Scheduler;
271 friend class BasicBlockInstrumentor;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400273 void AddSuccessor(BasicBlock* block, BasicBlock* succ);
274 void MoveSuccessors(BasicBlock* from, BasicBlock* to);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400276 void SetControlInput(BasicBlock* block, Node* node);
277 void SetBlockForNode(BasicBlock* block, Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278
279 Zone* zone_;
280 BasicBlockVector all_blocks_; // All basic blocks in the schedule.
281 BasicBlockVector nodeid_to_block_; // Map from node to containing block.
282 BasicBlockVector rpo_order_; // Reverse-post-order block list.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400283 BasicBlock* start_;
284 BasicBlock* end_;
285
286 DISALLOW_COPY_AND_ASSIGN(Schedule);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287};
288
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400289std::ostream& operator<<(std::ostream& os, const Schedule& s);
290
291} // namespace compiler
292} // namespace internal
293} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294
295#endif // V8_COMPILER_SCHEDULE_H_