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.
5 #include "src/compiler/schedule.h"
7 #include "src/compiler/node.h"
8 #include "src/compiler/node-properties.h"
9 #include "src/ostreams.h"
15 BasicBlock::BasicBlock(Zone* zone, Id id)
22 loop_header_(nullptr),
26 control_input_(nullptr),
33 bool BasicBlock::LoopContains(BasicBlock* block) const {
34 // RPO numbers must be initialized.
35 DCHECK(rpo_number_ >= 0);
36 DCHECK(block->rpo_number_ >= 0);
37 if (loop_end_ == NULL) return false; // This is not a loop.
38 return block->rpo_number_ >= rpo_number_ &&
39 block->rpo_number_ < loop_end_->rpo_number_;
43 void BasicBlock::AddSuccessor(BasicBlock* successor) {
44 successors_.push_back(successor);
48 void BasicBlock::AddPredecessor(BasicBlock* predecessor) {
49 predecessors_.push_back(predecessor);
53 void BasicBlock::AddNode(Node* node) { nodes_.push_back(node); }
56 void BasicBlock::set_control(Control control) {
61 void BasicBlock::set_control_input(Node* control_input) {
62 control_input_ = control_input;
66 void BasicBlock::set_loop_depth(int32_t loop_depth) {
67 loop_depth_ = loop_depth;
71 void BasicBlock::set_rpo_number(int32_t rpo_number) {
72 rpo_number_ = rpo_number;
76 void BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; }
79 void BasicBlock::set_loop_header(BasicBlock* loop_header) {
80 loop_header_ = loop_header;
85 BasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
87 if (b1->dominator_depth() < b2->dominator_depth()) {
97 std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
99 case BasicBlock::kNone:
101 case BasicBlock::kGoto:
103 case BasicBlock::kCall:
105 case BasicBlock::kBranch:
106 return os << "branch";
107 case BasicBlock::kSwitch:
108 return os << "switch";
109 case BasicBlock::kDeoptimize:
110 return os << "deoptimize";
111 case BasicBlock::kReturn:
112 return os << "return";
113 case BasicBlock::kThrow:
114 return os << "throw";
121 std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) {
122 return os << id.ToSize();
126 Schedule::Schedule(Zone* zone, size_t node_count_hint)
129 nodeid_to_block_(zone),
131 start_(NewBasicBlock()),
132 end_(NewBasicBlock()) {
133 nodeid_to_block_.reserve(node_count_hint);
137 BasicBlock* Schedule::block(Node* node) const {
138 if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) {
139 return nodeid_to_block_[node->id()];
145 bool Schedule::IsScheduled(Node* node) {
146 int length = static_cast<int>(nodeid_to_block_.size());
147 if (node->id() >= length) return false;
148 return nodeid_to_block_[node->id()] != NULL;
152 BasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) {
153 DCHECK(block_id.ToSize() < all_blocks_.size());
154 return all_blocks_[block_id.ToSize()];
158 bool Schedule::SameBasicBlock(Node* a, Node* b) const {
159 BasicBlock* block = this->block(a);
160 return block != NULL && block == this->block(b);
164 BasicBlock* Schedule::NewBasicBlock() {
165 BasicBlock* block = new (zone_)
166 BasicBlock(zone_, BasicBlock::Id::FromSize(all_blocks_.size()));
167 all_blocks_.push_back(block);
172 void Schedule::PlanNode(BasicBlock* block, Node* node) {
173 if (FLAG_trace_turbo_scheduler) {
175 os << "Planning #" << node->id() << ":" << node->op()->mnemonic()
176 << " for future add to B" << block->id() << "\n";
178 DCHECK(this->block(node) == NULL);
179 SetBlockForNode(block, node);
183 void Schedule::AddNode(BasicBlock* block, Node* node) {
184 if (FLAG_trace_turbo_scheduler) {
186 os << "Adding #" << node->id() << ":" << node->op()->mnemonic() << " to B"
187 << block->id() << "\n";
189 DCHECK(this->block(node) == NULL || this->block(node) == block);
190 block->AddNode(node);
191 SetBlockForNode(block, node);
195 void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
196 DCHECK_EQ(BasicBlock::kNone, block->control());
197 block->set_control(BasicBlock::kGoto);
198 AddSuccessor(block, succ);
202 void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
203 BasicBlock* exception_block) {
204 DCHECK_EQ(BasicBlock::kNone, block->control());
205 DCHECK_EQ(IrOpcode::kCall, call->opcode());
206 block->set_control(BasicBlock::kCall);
207 AddSuccessor(block, success_block);
208 AddSuccessor(block, exception_block);
209 SetControlInput(block, call);
213 void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
214 BasicBlock* fblock) {
215 DCHECK_EQ(BasicBlock::kNone, block->control());
216 DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
217 block->set_control(BasicBlock::kBranch);
218 AddSuccessor(block, tblock);
219 AddSuccessor(block, fblock);
220 SetControlInput(block, branch);
224 void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
226 DCHECK_EQ(BasicBlock::kNone, block->control());
227 DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
228 block->set_control(BasicBlock::kSwitch);
229 for (size_t index = 0; index < succ_count; ++index) {
230 AddSuccessor(block, succ_blocks[index]);
232 SetControlInput(block, sw);
236 void Schedule::AddReturn(BasicBlock* block, Node* input) {
237 DCHECK_EQ(BasicBlock::kNone, block->control());
238 block->set_control(BasicBlock::kReturn);
239 SetControlInput(block, input);
240 if (block != end()) AddSuccessor(block, end());
244 void Schedule::AddDeoptimize(BasicBlock* block, Node* input) {
245 DCHECK_EQ(BasicBlock::kNone, block->control());
246 block->set_control(BasicBlock::kDeoptimize);
247 SetControlInput(block, input);
248 if (block != end()) AddSuccessor(block, end());
252 void Schedule::AddThrow(BasicBlock* block, Node* input) {
253 DCHECK_EQ(BasicBlock::kNone, block->control());
254 block->set_control(BasicBlock::kThrow);
255 SetControlInput(block, input);
256 if (block != end()) AddSuccessor(block, end());
260 void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
261 BasicBlock* tblock, BasicBlock* fblock) {
262 DCHECK_NE(BasicBlock::kNone, block->control());
263 DCHECK_EQ(BasicBlock::kNone, end->control());
264 end->set_control(block->control());
265 block->set_control(BasicBlock::kBranch);
266 MoveSuccessors(block, end);
267 AddSuccessor(block, tblock);
268 AddSuccessor(block, fblock);
269 if (block->control_input() != nullptr) {
270 SetControlInput(end, block->control_input());
272 SetControlInput(block, branch);
276 void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
277 BasicBlock** succ_blocks, size_t succ_count) {
278 DCHECK_NE(BasicBlock::kNone, block->control());
279 DCHECK_EQ(BasicBlock::kNone, end->control());
280 end->set_control(block->control());
281 block->set_control(BasicBlock::kSwitch);
282 MoveSuccessors(block, end);
283 for (size_t index = 0; index < succ_count; ++index) {
284 AddSuccessor(block, succ_blocks[index]);
286 if (block->control_input() != nullptr) {
287 SetControlInput(end, block->control_input());
289 SetControlInput(block, sw);
293 void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) {
294 block->AddSuccessor(succ);
295 succ->AddPredecessor(block);
299 void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
300 for (BasicBlock* const successor : from->successors()) {
301 to->AddSuccessor(successor);
302 for (BasicBlock*& predecessor : successor->predecessors()) {
303 if (predecessor == from) predecessor = to;
306 from->ClearSuccessors();
310 void Schedule::SetControlInput(BasicBlock* block, Node* node) {
311 block->set_control_input(node);
312 SetBlockForNode(block, node);
316 void Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
317 int length = static_cast<int>(nodeid_to_block_.size());
318 if (node->id() >= length) {
319 nodeid_to_block_.resize(node->id() + 1);
321 nodeid_to_block_[node->id()] = block;
325 std::ostream& operator<<(std::ostream& os, const Schedule& s) {
326 for (BasicBlock* block : *s.rpo_order()) {
327 os << "--- BLOCK B" << block->rpo_number();
328 if (block->deferred()) os << " (deferred)";
329 if (block->PredecessorCount() != 0) os << " <- ";
331 for (BasicBlock const* predecessor : block->predecessors()) {
332 if (comma) os << ", ";
334 os << "B" << predecessor->rpo_number();
337 for (Node* node : *block) {
339 if (NodeProperties::IsTyped(node)) {
340 Bounds bounds = NodeProperties::GetBounds(node);
342 bounds.lower->PrintTo(os);
343 if (!bounds.upper->Is(bounds.lower)) {
345 bounds.upper->PrintTo(os);
350 BasicBlock::Control control = block->control();
351 if (control != BasicBlock::kNone) {
353 if (block->control_input() != NULL) {
354 os << *block->control_input();
360 for (BasicBlock const* successor : block->successors()) {
361 if (comma) os << ", ";
363 os << "B" << successor->rpo_number();
371 } // namespace compiler
372 } // namespace internal