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/node.h"
6 #include "src/compiler/node-properties.h"
7 #include "src/compiler/node-properties-inl.h"
8 #include "src/compiler/schedule.h"
9 #include "src/ostreams.h"
15 BasicBlock::BasicBlock(Zone* zone, Id id)
31 bool BasicBlock::LoopContains(BasicBlock* block) const {
32 // RPO numbers must be initialized.
33 DCHECK(rpo_number_ >= 0);
34 DCHECK(block->rpo_number_ >= 0);
35 if (loop_end_ < 0) return false; // This is not a loop.
36 return block->rpo_number_ >= rpo_number_ && block->rpo_number_ < loop_end_;
40 void BasicBlock::AddSuccessor(BasicBlock* successor) {
41 successors_.push_back(successor);
45 void BasicBlock::AddPredecessor(BasicBlock* predecessor) {
46 predecessors_.push_back(predecessor);
50 void BasicBlock::AddNode(Node* node) { nodes_.push_back(node); }
53 void BasicBlock::set_control(Control control) {
58 void BasicBlock::set_control_input(Node* control_input) {
59 control_input_ = control_input;
63 void BasicBlock::set_dominator(BasicBlock* dominator) {
64 dominator_ = dominator;
68 void BasicBlock::set_loop_depth(int32_t loop_depth) {
69 loop_depth_ = loop_depth;
73 void BasicBlock::set_rpo_number(int32_t rpo_number) {
74 rpo_number_ = rpo_number;
78 void BasicBlock::set_loop_end(int32_t loop_end) { loop_end_ = loop_end; }
81 void BasicBlock::set_loop_header(BasicBlock* loop_header) {
82 loop_header_ = loop_header;
86 std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
88 case BasicBlock::kNone:
90 case BasicBlock::kGoto:
92 case BasicBlock::kBranch:
93 return os << "branch";
94 case BasicBlock::kReturn:
95 return os << "return";
96 case BasicBlock::kThrow:
104 std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) {
105 return os << id.ToSize();
109 std::ostream& operator<<(std::ostream& os, const BasicBlock::RpoNumber& rpo) {
110 return os << rpo.ToSize();
114 Schedule::Schedule(Zone* zone, size_t node_count_hint)
117 nodeid_to_block_(zone),
119 start_(NewBasicBlock()),
120 end_(NewBasicBlock()) {
121 nodeid_to_block_.reserve(node_count_hint);
125 BasicBlock* Schedule::block(Node* node) const {
126 if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) {
127 return nodeid_to_block_[node->id()];
133 bool Schedule::IsScheduled(Node* node) {
134 int length = static_cast<int>(nodeid_to_block_.size());
135 if (node->id() >= length) return false;
136 return nodeid_to_block_[node->id()] != NULL;
140 BasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) {
141 DCHECK(block_id.ToSize() < all_blocks_.size());
142 return all_blocks_[block_id.ToSize()];
146 bool Schedule::SameBasicBlock(Node* a, Node* b) const {
147 BasicBlock* block = this->block(a);
148 return block != NULL && block == this->block(b);
152 BasicBlock* Schedule::NewBasicBlock() {
153 BasicBlock* block = new (zone_)
154 BasicBlock(zone_, BasicBlock::Id::FromSize(all_blocks_.size()));
155 all_blocks_.push_back(block);
160 void Schedule::PlanNode(BasicBlock* block, Node* node) {
161 if (FLAG_trace_turbo_scheduler) {
163 os << "Planning #" << node->id() << ":" << node->op()->mnemonic()
164 << " for future add to B" << block->id() << "\n";
166 DCHECK(this->block(node) == NULL);
167 SetBlockForNode(block, node);
171 void Schedule::AddNode(BasicBlock* block, Node* node) {
172 if (FLAG_trace_turbo_scheduler) {
174 os << "Adding #" << node->id() << ":" << node->op()->mnemonic() << " to B"
175 << block->id() << "\n";
177 DCHECK(this->block(node) == NULL || this->block(node) == block);
178 block->AddNode(node);
179 SetBlockForNode(block, node);
183 void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
184 DCHECK(block->control() == BasicBlock::kNone);
185 block->set_control(BasicBlock::kGoto);
186 AddSuccessor(block, succ);
190 void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
191 BasicBlock* fblock) {
192 DCHECK(block->control() == BasicBlock::kNone);
193 DCHECK(branch->opcode() == IrOpcode::kBranch);
194 block->set_control(BasicBlock::kBranch);
195 AddSuccessor(block, tblock);
196 AddSuccessor(block, fblock);
197 SetControlInput(block, branch);
201 void Schedule::AddReturn(BasicBlock* block, Node* input) {
202 DCHECK(block->control() == BasicBlock::kNone);
203 block->set_control(BasicBlock::kReturn);
204 SetControlInput(block, input);
205 if (block != end()) AddSuccessor(block, end());
209 void Schedule::AddThrow(BasicBlock* block, Node* input) {
210 DCHECK(block->control() == BasicBlock::kNone);
211 block->set_control(BasicBlock::kThrow);
212 SetControlInput(block, input);
213 if (block != end()) AddSuccessor(block, end());
217 void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
218 BasicBlock* tblock, BasicBlock* fblock) {
219 DCHECK(block->control() != BasicBlock::kNone);
220 DCHECK(end->control() == BasicBlock::kNone);
221 end->set_control(block->control());
222 block->set_control(BasicBlock::kBranch);
223 MoveSuccessors(block, end);
224 AddSuccessor(block, tblock);
225 AddSuccessor(block, fblock);
226 if (block->control_input() != NULL) {
227 SetControlInput(end, block->control_input());
229 SetControlInput(block, branch);
233 void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) {
234 block->AddSuccessor(succ);
235 succ->AddPredecessor(block);
239 void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
240 for (BasicBlock::Predecessors::iterator i = from->successors_begin();
241 i != from->successors_end(); ++i) {
242 BasicBlock* succ = *i;
243 to->AddSuccessor(succ);
244 for (BasicBlock::Predecessors::iterator j = succ->predecessors_begin();
245 j != succ->predecessors_end(); ++j) {
246 if (*j == from) *j = to;
249 from->ClearSuccessors();
253 void Schedule::SetControlInput(BasicBlock* block, Node* node) {
254 block->set_control_input(node);
255 SetBlockForNode(block, node);
259 void Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
260 int length = static_cast<int>(nodeid_to_block_.size());
261 if (node->id() >= length) {
262 nodeid_to_block_.resize(node->id() + 1);
264 nodeid_to_block_[node->id()] = block;
268 std::ostream& operator<<(std::ostream& os, const Schedule& s) {
269 // TODO(svenpanne) Const-correct the RPO stuff/iterators.
270 BasicBlockVector* rpo = const_cast<Schedule*>(&s)->rpo_order();
271 for (BasicBlockVectorIter i = rpo->begin(); i != rpo->end(); ++i) {
272 BasicBlock* block = *i;
273 os << "--- BLOCK B" << block->id();
274 if (block->deferred()) os << " (deferred)";
275 if (block->PredecessorCount() != 0) os << " <- ";
277 for (BasicBlock::Predecessors::iterator j = block->predecessors_begin();
278 j != block->predecessors_end(); ++j) {
279 if (comma) os << ", ";
281 os << "B" << (*j)->id();
284 for (BasicBlock::const_iterator j = block->begin(); j != block->end();
288 if (NodeProperties::IsTyped(node)) {
289 Bounds bounds = NodeProperties::GetBounds(node);
291 bounds.lower->PrintTo(os);
292 if (!bounds.upper->Is(bounds.lower)) {
294 bounds.upper->PrintTo(os);
299 BasicBlock::Control control = block->control();
300 if (control != BasicBlock::kNone) {
302 if (block->control_input() != NULL) {
303 os << *block->control_input();
309 for (BasicBlock::Successors::iterator j = block->successors_begin();
310 j != block->successors_end(); ++j) {
311 if (comma) os << ", ";
313 os << "B" << (*j)->id();
321 } // namespace compiler
322 } // namespace internal