Home | History | Annotate | Download | only in compiler
      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 #include "src/compiler/schedule.h"
      6 
      7 #include "src/compiler/node.h"
      8 #include "src/compiler/node-properties.h"
      9 #include "src/ostreams.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace compiler {
     14 
     15 BasicBlock::BasicBlock(Zone* zone, Id id)
     16     : loop_number_(-1),
     17       rpo_number_(-1),
     18       deferred_(false),
     19       dominator_depth_(-1),
     20       dominator_(nullptr),
     21       rpo_next_(nullptr),
     22       loop_header_(nullptr),
     23       loop_end_(nullptr),
     24       loop_depth_(0),
     25       control_(kNone),
     26       control_input_(nullptr),
     27       nodes_(zone),
     28       successors_(zone),
     29       predecessors_(zone),
     30       id_(id) {}
     31 
     32 
     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_ == nullptr) return false;  // This is not a loop.
     38   return block->rpo_number_ >= rpo_number_ &&
     39          block->rpo_number_ < loop_end_->rpo_number_;
     40 }
     41 
     42 
     43 void BasicBlock::AddSuccessor(BasicBlock* successor) {
     44   successors_.push_back(successor);
     45 }
     46 
     47 
     48 void BasicBlock::AddPredecessor(BasicBlock* predecessor) {
     49   predecessors_.push_back(predecessor);
     50 }
     51 
     52 
     53 void BasicBlock::AddNode(Node* node) { nodes_.push_back(node); }
     54 
     55 
     56 void BasicBlock::set_control(Control control) {
     57   control_ = control;
     58 }
     59 
     60 
     61 void BasicBlock::set_control_input(Node* control_input) {
     62   control_input_ = control_input;
     63 }
     64 
     65 
     66 void BasicBlock::set_loop_depth(int32_t loop_depth) {
     67   loop_depth_ = loop_depth;
     68 }
     69 
     70 
     71 void BasicBlock::set_rpo_number(int32_t rpo_number) {
     72   rpo_number_ = rpo_number;
     73 }
     74 
     75 
     76 void BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; }
     77 
     78 
     79 void BasicBlock::set_loop_header(BasicBlock* loop_header) {
     80   loop_header_ = loop_header;
     81 }
     82 
     83 
     84 // static
     85 BasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
     86   while (b1 != b2) {
     87     if (b1->dominator_depth() < b2->dominator_depth()) {
     88       b2 = b2->dominator();
     89     } else {
     90       b1 = b1->dominator();
     91     }
     92   }
     93   return b1;
     94 }
     95 
     96 
     97 std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
     98   switch (c) {
     99     case BasicBlock::kNone:
    100       return os << "none";
    101     case BasicBlock::kGoto:
    102       return os << "goto";
    103     case BasicBlock::kCall:
    104       return os << "call";
    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::kTailCall:
    112       return os << "tailcall";
    113     case BasicBlock::kReturn:
    114       return os << "return";
    115     case BasicBlock::kThrow:
    116       return os << "throw";
    117   }
    118   UNREACHABLE();
    119   return os;
    120 }
    121 
    122 
    123 std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) {
    124   return os << id.ToSize();
    125 }
    126 
    127 
    128 Schedule::Schedule(Zone* zone, size_t node_count_hint)
    129     : zone_(zone),
    130       all_blocks_(zone),
    131       nodeid_to_block_(zone),
    132       rpo_order_(zone),
    133       start_(NewBasicBlock()),
    134       end_(NewBasicBlock()) {
    135   nodeid_to_block_.reserve(node_count_hint);
    136 }
    137 
    138 
    139 BasicBlock* Schedule::block(Node* node) const {
    140   if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) {
    141     return nodeid_to_block_[node->id()];
    142   }
    143   return nullptr;
    144 }
    145 
    146 
    147 bool Schedule::IsScheduled(Node* node) {
    148   if (node->id() >= nodeid_to_block_.size()) return false;
    149   return nodeid_to_block_[node->id()] != nullptr;
    150 }
    151 
    152 
    153 BasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) {
    154   DCHECK(block_id.ToSize() < all_blocks_.size());
    155   return all_blocks_[block_id.ToSize()];
    156 }
    157 
    158 
    159 bool Schedule::SameBasicBlock(Node* a, Node* b) const {
    160   BasicBlock* block = this->block(a);
    161   return block != nullptr && block == this->block(b);
    162 }
    163 
    164 
    165 BasicBlock* Schedule::NewBasicBlock() {
    166   BasicBlock* block = new (zone_)
    167       BasicBlock(zone_, BasicBlock::Id::FromSize(all_blocks_.size()));
    168   all_blocks_.push_back(block);
    169   return block;
    170 }
    171 
    172 
    173 void Schedule::PlanNode(BasicBlock* block, Node* node) {
    174   if (FLAG_trace_turbo_scheduler) {
    175     OFStream os(stdout);
    176     os << "Planning #" << node->id() << ":" << node->op()->mnemonic()
    177        << " for future add to B" << block->id() << "\n";
    178   }
    179   DCHECK(this->block(node) == nullptr);
    180   SetBlockForNode(block, node);
    181 }
    182 
    183 
    184 void Schedule::AddNode(BasicBlock* block, Node* node) {
    185   if (FLAG_trace_turbo_scheduler) {
    186     OFStream os(stdout);
    187     os << "Adding #" << node->id() << ":" << node->op()->mnemonic() << " to B"
    188        << block->id() << "\n";
    189   }
    190   DCHECK(this->block(node) == nullptr || this->block(node) == block);
    191   block->AddNode(node);
    192   SetBlockForNode(block, node);
    193 }
    194 
    195 
    196 void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
    197   DCHECK_EQ(BasicBlock::kNone, block->control());
    198   block->set_control(BasicBlock::kGoto);
    199   AddSuccessor(block, succ);
    200 }
    201 
    202 
    203 void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
    204                        BasicBlock* exception_block) {
    205   DCHECK_EQ(BasicBlock::kNone, block->control());
    206   DCHECK_EQ(IrOpcode::kCall, call->opcode());
    207   block->set_control(BasicBlock::kCall);
    208   AddSuccessor(block, success_block);
    209   AddSuccessor(block, exception_block);
    210   SetControlInput(block, call);
    211 }
    212 
    213 
    214 void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
    215                          BasicBlock* fblock) {
    216   DCHECK_EQ(BasicBlock::kNone, block->control());
    217   DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
    218   block->set_control(BasicBlock::kBranch);
    219   AddSuccessor(block, tblock);
    220   AddSuccessor(block, fblock);
    221   SetControlInput(block, branch);
    222 }
    223 
    224 
    225 void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
    226                          size_t succ_count) {
    227   DCHECK_EQ(BasicBlock::kNone, block->control());
    228   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
    229   block->set_control(BasicBlock::kSwitch);
    230   for (size_t index = 0; index < succ_count; ++index) {
    231     AddSuccessor(block, succ_blocks[index]);
    232   }
    233   SetControlInput(block, sw);
    234 }
    235 
    236 
    237 void Schedule::AddTailCall(BasicBlock* block, Node* input) {
    238   DCHECK_EQ(BasicBlock::kNone, block->control());
    239   block->set_control(BasicBlock::kTailCall);
    240   SetControlInput(block, input);
    241   if (block != end()) AddSuccessor(block, end());
    242 }
    243 
    244 
    245 void Schedule::AddReturn(BasicBlock* block, Node* input) {
    246   DCHECK_EQ(BasicBlock::kNone, block->control());
    247   block->set_control(BasicBlock::kReturn);
    248   SetControlInput(block, input);
    249   if (block != end()) AddSuccessor(block, end());
    250 }
    251 
    252 
    253 void Schedule::AddDeoptimize(BasicBlock* block, Node* input) {
    254   DCHECK_EQ(BasicBlock::kNone, block->control());
    255   block->set_control(BasicBlock::kDeoptimize);
    256   SetControlInput(block, input);
    257   if (block != end()) AddSuccessor(block, end());
    258 }
    259 
    260 
    261 void Schedule::AddThrow(BasicBlock* block, Node* input) {
    262   DCHECK_EQ(BasicBlock::kNone, block->control());
    263   block->set_control(BasicBlock::kThrow);
    264   SetControlInput(block, input);
    265   if (block != end()) AddSuccessor(block, end());
    266 }
    267 
    268 
    269 void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
    270                             BasicBlock* tblock, BasicBlock* fblock) {
    271   DCHECK_NE(BasicBlock::kNone, block->control());
    272   DCHECK_EQ(BasicBlock::kNone, end->control());
    273   end->set_control(block->control());
    274   block->set_control(BasicBlock::kBranch);
    275   MoveSuccessors(block, end);
    276   AddSuccessor(block, tblock);
    277   AddSuccessor(block, fblock);
    278   if (block->control_input() != nullptr) {
    279     SetControlInput(end, block->control_input());
    280   }
    281   SetControlInput(block, branch);
    282 }
    283 
    284 
    285 void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
    286                             BasicBlock** succ_blocks, size_t succ_count) {
    287   DCHECK_NE(BasicBlock::kNone, block->control());
    288   DCHECK_EQ(BasicBlock::kNone, end->control());
    289   end->set_control(block->control());
    290   block->set_control(BasicBlock::kSwitch);
    291   MoveSuccessors(block, end);
    292   for (size_t index = 0; index < succ_count; ++index) {
    293     AddSuccessor(block, succ_blocks[index]);
    294   }
    295   if (block->control_input() != nullptr) {
    296     SetControlInput(end, block->control_input());
    297   }
    298   SetControlInput(block, sw);
    299 }
    300 
    301 
    302 void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) {
    303   block->AddSuccessor(succ);
    304   succ->AddPredecessor(block);
    305 }
    306 
    307 
    308 void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
    309   for (BasicBlock* const successor : from->successors()) {
    310     to->AddSuccessor(successor);
    311     for (BasicBlock*& predecessor : successor->predecessors()) {
    312       if (predecessor == from) predecessor = to;
    313     }
    314   }
    315   from->ClearSuccessors();
    316 }
    317 
    318 
    319 void Schedule::SetControlInput(BasicBlock* block, Node* node) {
    320   block->set_control_input(node);
    321   SetBlockForNode(block, node);
    322 }
    323 
    324 
    325 void Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
    326   if (node->id() >= nodeid_to_block_.size()) {
    327     nodeid_to_block_.resize(node->id() + 1);
    328   }
    329   nodeid_to_block_[node->id()] = block;
    330 }
    331 
    332 
    333 std::ostream& operator<<(std::ostream& os, const Schedule& s) {
    334   for (BasicBlock* block : *s.rpo_order()) {
    335     os << "--- BLOCK B" << block->rpo_number();
    336     if (block->deferred()) os << " (deferred)";
    337     if (block->PredecessorCount() != 0) os << " <- ";
    338     bool comma = false;
    339     for (BasicBlock const* predecessor : block->predecessors()) {
    340       if (comma) os << ", ";
    341       comma = true;
    342       os << "B" << predecessor->rpo_number();
    343     }
    344     os << " ---\n";
    345     for (Node* node : *block) {
    346       os << "  " << *node;
    347       if (NodeProperties::IsTyped(node)) {
    348         Type* type = NodeProperties::GetType(node);
    349         os << " : ";
    350         type->PrintTo(os);
    351       }
    352       os << "\n";
    353     }
    354     BasicBlock::Control control = block->control();
    355     if (control != BasicBlock::kNone) {
    356       os << "  ";
    357       if (block->control_input() != nullptr) {
    358         os << *block->control_input();
    359       } else {
    360         os << "Goto";
    361       }
    362       os << " -> ";
    363       comma = false;
    364       for (BasicBlock const* successor : block->successors()) {
    365         if (comma) os << ", ";
    366         comma = true;
    367         os << "B" << successor->rpo_number();
    368       }
    369       os << "\n";
    370     }
    371   }
    372   return os;
    373 }
    374 
    375 }  // namespace compiler
    376 }  // namespace internal
    377 }  // namespace v8
    378