11cb0ef41Sopenharmony_ci// Copyright 2013 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/compiler/schedule.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h"
81cb0ef41Sopenharmony_ci#include "src/compiler/node.h"
91cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h"
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_cinamespace v8 {
121cb0ef41Sopenharmony_cinamespace internal {
131cb0ef41Sopenharmony_cinamespace compiler {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciBasicBlock::BasicBlock(Zone* zone, Id id)
161cb0ef41Sopenharmony_ci    : loop_number_(-1),
171cb0ef41Sopenharmony_ci      rpo_number_(-1),
181cb0ef41Sopenharmony_ci      deferred_(false),
191cb0ef41Sopenharmony_ci      dominator_depth_(-1),
201cb0ef41Sopenharmony_ci      dominator_(nullptr),
211cb0ef41Sopenharmony_ci      rpo_next_(nullptr),
221cb0ef41Sopenharmony_ci      loop_header_(nullptr),
231cb0ef41Sopenharmony_ci      loop_end_(nullptr),
241cb0ef41Sopenharmony_ci      loop_depth_(0),
251cb0ef41Sopenharmony_ci      control_(kNone),
261cb0ef41Sopenharmony_ci      control_input_(nullptr),
271cb0ef41Sopenharmony_ci      nodes_(zone),
281cb0ef41Sopenharmony_ci      successors_(zone),
291cb0ef41Sopenharmony_ci      predecessors_(zone),
301cb0ef41Sopenharmony_ci#if DEBUG
311cb0ef41Sopenharmony_ci      debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)),
321cb0ef41Sopenharmony_ci#endif
331cb0ef41Sopenharmony_ci      id_(id) {
341cb0ef41Sopenharmony_ci}
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_cibool BasicBlock::LoopContains(BasicBlock* block) const {
371cb0ef41Sopenharmony_ci  // RPO numbers must be initialized.
381cb0ef41Sopenharmony_ci  DCHECK_LE(0, rpo_number_);
391cb0ef41Sopenharmony_ci  DCHECK_LE(0, block->rpo_number_);
401cb0ef41Sopenharmony_ci  if (loop_end_ == nullptr) return false;  // This is not a loop.
411cb0ef41Sopenharmony_ci  return block->rpo_number_ >= rpo_number_ &&
421cb0ef41Sopenharmony_ci         block->rpo_number_ < loop_end_->rpo_number_;
431cb0ef41Sopenharmony_ci}
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_civoid BasicBlock::AddSuccessor(BasicBlock* successor) {
461cb0ef41Sopenharmony_ci  successors_.push_back(successor);
471cb0ef41Sopenharmony_ci}
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_civoid BasicBlock::AddPredecessor(BasicBlock* predecessor) {
501cb0ef41Sopenharmony_ci  predecessors_.push_back(predecessor);
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_civoid BasicBlock::RemovePredecessor(size_t index) {
541cb0ef41Sopenharmony_ci  predecessors_.erase(predecessors_.begin() + index);
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_civoid BasicBlock::AddNode(Node* node) { nodes_.push_back(node); }
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_civoid BasicBlock::set_control(Control control) { control_ = control; }
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_civoid BasicBlock::set_control_input(Node* control_input) {
621cb0ef41Sopenharmony_ci  if (!nodes_.empty() && control_input == nodes_.back()) {
631cb0ef41Sopenharmony_ci    nodes_.pop_back();
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci  control_input_ = control_input;
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_civoid BasicBlock::set_loop_depth(int32_t loop_depth) {
691cb0ef41Sopenharmony_ci  loop_depth_ = loop_depth;
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_civoid BasicBlock::set_rpo_number(int32_t rpo_number) {
731cb0ef41Sopenharmony_ci  rpo_number_ = rpo_number;
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_civoid BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_civoid BasicBlock::set_loop_header(BasicBlock* loop_header) {
791cb0ef41Sopenharmony_ci  loop_header_ = loop_header;
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_civoid BasicBlock::TrimNodes(iterator new_end) { nodes_.erase(new_end, end()); }
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_civoid BasicBlock::ResetRPOInfo() {
851cb0ef41Sopenharmony_ci  loop_number_ = -1;
861cb0ef41Sopenharmony_ci  rpo_number_ = -1;
871cb0ef41Sopenharmony_ci  dominator_depth_ = -1;
881cb0ef41Sopenharmony_ci  dominator_ = nullptr;
891cb0ef41Sopenharmony_ci  rpo_next_ = nullptr;
901cb0ef41Sopenharmony_ci  loop_header_ = nullptr;
911cb0ef41Sopenharmony_ci  loop_end_ = nullptr;
921cb0ef41Sopenharmony_ci  loop_depth_ = 0;
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci// static
961cb0ef41Sopenharmony_ciBasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
971cb0ef41Sopenharmony_ci  while (b1 != b2) {
981cb0ef41Sopenharmony_ci    if (b1->dominator_depth() < b2->dominator_depth()) {
991cb0ef41Sopenharmony_ci      b2 = b2->dominator();
1001cb0ef41Sopenharmony_ci    } else {
1011cb0ef41Sopenharmony_ci      b1 = b1->dominator();
1021cb0ef41Sopenharmony_ci    }
1031cb0ef41Sopenharmony_ci  }
1041cb0ef41Sopenharmony_ci  return b1;
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_civoid BasicBlock::Print() { StdoutStream{} << *this << "\n"; }
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const BasicBlock& block) {
1101cb0ef41Sopenharmony_ci  os << "id:" << block.id();
1111cb0ef41Sopenharmony_ci#if DEBUG
1121cb0ef41Sopenharmony_ci  AssemblerDebugInfo info = block.debug_info();
1131cb0ef41Sopenharmony_ci  if (info.name) os << info;
1141cb0ef41Sopenharmony_ci  // Print predecessor blocks for better debugging.
1151cb0ef41Sopenharmony_ci  const int kMaxDisplayedBlocks = 4;
1161cb0ef41Sopenharmony_ci  int i = 0;
1171cb0ef41Sopenharmony_ci  const BasicBlock* current_block = &block;
1181cb0ef41Sopenharmony_ci  while (current_block->PredecessorCount() > 0 && i++ < kMaxDisplayedBlocks) {
1191cb0ef41Sopenharmony_ci    current_block = current_block->predecessors().front();
1201cb0ef41Sopenharmony_ci    os << " <= id:" << current_block->id();
1211cb0ef41Sopenharmony_ci    info = current_block->debug_info();
1221cb0ef41Sopenharmony_ci    if (info.name) os << info;
1231cb0ef41Sopenharmony_ci  }
1241cb0ef41Sopenharmony_ci#endif
1251cb0ef41Sopenharmony_ci  return os;
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
1291cb0ef41Sopenharmony_ci  switch (c) {
1301cb0ef41Sopenharmony_ci    case BasicBlock::kNone:
1311cb0ef41Sopenharmony_ci      return os << "none";
1321cb0ef41Sopenharmony_ci    case BasicBlock::kGoto:
1331cb0ef41Sopenharmony_ci      return os << "goto";
1341cb0ef41Sopenharmony_ci    case BasicBlock::kCall:
1351cb0ef41Sopenharmony_ci      return os << "call";
1361cb0ef41Sopenharmony_ci    case BasicBlock::kBranch:
1371cb0ef41Sopenharmony_ci      return os << "branch";
1381cb0ef41Sopenharmony_ci    case BasicBlock::kSwitch:
1391cb0ef41Sopenharmony_ci      return os << "switch";
1401cb0ef41Sopenharmony_ci    case BasicBlock::kDeoptimize:
1411cb0ef41Sopenharmony_ci      return os << "deoptimize";
1421cb0ef41Sopenharmony_ci    case BasicBlock::kTailCall:
1431cb0ef41Sopenharmony_ci      return os << "tailcall";
1441cb0ef41Sopenharmony_ci    case BasicBlock::kReturn:
1451cb0ef41Sopenharmony_ci      return os << "return";
1461cb0ef41Sopenharmony_ci    case BasicBlock::kThrow:
1471cb0ef41Sopenharmony_ci      return os << "throw";
1481cb0ef41Sopenharmony_ci  }
1491cb0ef41Sopenharmony_ci  UNREACHABLE();
1501cb0ef41Sopenharmony_ci}
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) {
1531cb0ef41Sopenharmony_ci  return os << id.ToSize();
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ciSchedule::Schedule(Zone* zone, size_t node_count_hint)
1571cb0ef41Sopenharmony_ci    : zone_(zone),
1581cb0ef41Sopenharmony_ci      all_blocks_(zone),
1591cb0ef41Sopenharmony_ci      nodeid_to_block_(zone),
1601cb0ef41Sopenharmony_ci      rpo_order_(zone),
1611cb0ef41Sopenharmony_ci      start_(NewBasicBlock()),
1621cb0ef41Sopenharmony_ci      end_(NewBasicBlock()) {
1631cb0ef41Sopenharmony_ci  nodeid_to_block_.reserve(node_count_hint);
1641cb0ef41Sopenharmony_ci}
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ciBasicBlock* Schedule::block(Node* node) const {
1671cb0ef41Sopenharmony_ci  if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) {
1681cb0ef41Sopenharmony_ci    return nodeid_to_block_[node->id()];
1691cb0ef41Sopenharmony_ci  }
1701cb0ef41Sopenharmony_ci  return nullptr;
1711cb0ef41Sopenharmony_ci}
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_cibool Schedule::IsScheduled(Node* node) {
1741cb0ef41Sopenharmony_ci  if (node->id() >= nodeid_to_block_.size()) return false;
1751cb0ef41Sopenharmony_ci  return nodeid_to_block_[node->id()] != nullptr;
1761cb0ef41Sopenharmony_ci}
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ciBasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) {
1791cb0ef41Sopenharmony_ci  DCHECK(block_id.ToSize() < all_blocks_.size());
1801cb0ef41Sopenharmony_ci  return all_blocks_[block_id.ToSize()];
1811cb0ef41Sopenharmony_ci}
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_civoid Schedule::ClearBlockById(BasicBlock::Id block_id) {
1841cb0ef41Sopenharmony_ci  DCHECK(block_id.ToSize() < all_blocks_.size());
1851cb0ef41Sopenharmony_ci  all_blocks_[block_id.ToSize()] = nullptr;
1861cb0ef41Sopenharmony_ci}
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_cibool Schedule::SameBasicBlock(Node* a, Node* b) const {
1891cb0ef41Sopenharmony_ci  BasicBlock* block = this->block(a);
1901cb0ef41Sopenharmony_ci  return block != nullptr && block == this->block(b);
1911cb0ef41Sopenharmony_ci}
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ciBasicBlock* Schedule::NewBasicBlock() {
1941cb0ef41Sopenharmony_ci  BasicBlock* block = zone_->New<BasicBlock>(
1951cb0ef41Sopenharmony_ci      zone_, BasicBlock::Id::FromSize(all_blocks_.size()));
1961cb0ef41Sopenharmony_ci  all_blocks_.push_back(block);
1971cb0ef41Sopenharmony_ci  return block;
1981cb0ef41Sopenharmony_ci}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_civoid Schedule::PlanNode(BasicBlock* block, Node* node) {
2011cb0ef41Sopenharmony_ci  if (FLAG_trace_turbo_scheduler) {
2021cb0ef41Sopenharmony_ci    StdoutStream{} << "Planning #" << node->id() << ":"
2031cb0ef41Sopenharmony_ci                   << node->op()->mnemonic()
2041cb0ef41Sopenharmony_ci                   << " for future add to id:" << block->id() << "\n";
2051cb0ef41Sopenharmony_ci  }
2061cb0ef41Sopenharmony_ci  DCHECK_NULL(this->block(node));
2071cb0ef41Sopenharmony_ci  SetBlockForNode(block, node);
2081cb0ef41Sopenharmony_ci}
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_civoid Schedule::AddNode(BasicBlock* block, Node* node) {
2111cb0ef41Sopenharmony_ci  if (FLAG_trace_turbo_scheduler) {
2121cb0ef41Sopenharmony_ci    StdoutStream{} << "Adding #" << node->id() << ":" << node->op()->mnemonic()
2131cb0ef41Sopenharmony_ci                   << " to id:" << block->id() << "\n";
2141cb0ef41Sopenharmony_ci  }
2151cb0ef41Sopenharmony_ci  DCHECK(this->block(node) == nullptr || this->block(node) == block);
2161cb0ef41Sopenharmony_ci  block->AddNode(node);
2171cb0ef41Sopenharmony_ci  SetBlockForNode(block, node);
2181cb0ef41Sopenharmony_ci}
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_civoid Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
2211cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, block->control());
2221cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kGoto);
2231cb0ef41Sopenharmony_ci  AddSuccessor(block, succ);
2241cb0ef41Sopenharmony_ci}
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci#if DEBUG
2271cb0ef41Sopenharmony_cinamespace {
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_cibool IsPotentiallyThrowingCall(IrOpcode::Value opcode) {
2301cb0ef41Sopenharmony_ci  switch (opcode) {
2311cb0ef41Sopenharmony_ci#define BUILD_BLOCK_JS_CASE(Name, ...) case IrOpcode::k##Name:
2321cb0ef41Sopenharmony_ci    JS_OP_LIST(BUILD_BLOCK_JS_CASE)
2331cb0ef41Sopenharmony_ci#undef BUILD_BLOCK_JS_CASE
2341cb0ef41Sopenharmony_ci    case IrOpcode::kCall:
2351cb0ef41Sopenharmony_ci      return true;
2361cb0ef41Sopenharmony_ci    default:
2371cb0ef41Sopenharmony_ci      return false;
2381cb0ef41Sopenharmony_ci  }
2391cb0ef41Sopenharmony_ci}
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci}  // namespace
2421cb0ef41Sopenharmony_ci#endif  // DEBUG
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_civoid Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
2451cb0ef41Sopenharmony_ci                       BasicBlock* exception_block) {
2461cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, block->control());
2471cb0ef41Sopenharmony_ci  DCHECK(IsPotentiallyThrowingCall(call->opcode()));
2481cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kCall);
2491cb0ef41Sopenharmony_ci  AddSuccessor(block, success_block);
2501cb0ef41Sopenharmony_ci  AddSuccessor(block, exception_block);
2511cb0ef41Sopenharmony_ci  SetControlInput(block, call);
2521cb0ef41Sopenharmony_ci}
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_civoid Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
2551cb0ef41Sopenharmony_ci                         BasicBlock* fblock) {
2561cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, block->control());
2571cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
2581cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kBranch);
2591cb0ef41Sopenharmony_ci  AddSuccessor(block, tblock);
2601cb0ef41Sopenharmony_ci  AddSuccessor(block, fblock);
2611cb0ef41Sopenharmony_ci  SetControlInput(block, branch);
2621cb0ef41Sopenharmony_ci}
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_civoid Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
2651cb0ef41Sopenharmony_ci                         size_t succ_count) {
2661cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, block->control());
2671cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
2681cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kSwitch);
2691cb0ef41Sopenharmony_ci  for (size_t index = 0; index < succ_count; ++index) {
2701cb0ef41Sopenharmony_ci    AddSuccessor(block, succ_blocks[index]);
2711cb0ef41Sopenharmony_ci  }
2721cb0ef41Sopenharmony_ci  SetControlInput(block, sw);
2731cb0ef41Sopenharmony_ci}
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_civoid Schedule::AddTailCall(BasicBlock* block, Node* input) {
2761cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, block->control());
2771cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kTailCall);
2781cb0ef41Sopenharmony_ci  SetControlInput(block, input);
2791cb0ef41Sopenharmony_ci  if (block != end()) AddSuccessor(block, end());
2801cb0ef41Sopenharmony_ci}
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_civoid Schedule::AddReturn(BasicBlock* block, Node* input) {
2831cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, block->control());
2841cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kReturn);
2851cb0ef41Sopenharmony_ci  SetControlInput(block, input);
2861cb0ef41Sopenharmony_ci  if (block != end()) AddSuccessor(block, end());
2871cb0ef41Sopenharmony_ci}
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_civoid Schedule::AddDeoptimize(BasicBlock* block, Node* input) {
2901cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, block->control());
2911cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kDeoptimize);
2921cb0ef41Sopenharmony_ci  SetControlInput(block, input);
2931cb0ef41Sopenharmony_ci  if (block != end()) AddSuccessor(block, end());
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_civoid Schedule::AddThrow(BasicBlock* block, Node* input) {
2971cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, block->control());
2981cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kThrow);
2991cb0ef41Sopenharmony_ci  SetControlInput(block, input);
3001cb0ef41Sopenharmony_ci  if (block != end()) AddSuccessor(block, end());
3011cb0ef41Sopenharmony_ci}
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_civoid Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
3041cb0ef41Sopenharmony_ci                            BasicBlock* tblock, BasicBlock* fblock) {
3051cb0ef41Sopenharmony_ci  CHECK_NE(BasicBlock::kNone, block->control());
3061cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, end->control());
3071cb0ef41Sopenharmony_ci  end->set_control(block->control());
3081cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kBranch);
3091cb0ef41Sopenharmony_ci  MoveSuccessors(block, end);
3101cb0ef41Sopenharmony_ci  AddSuccessor(block, tblock);
3111cb0ef41Sopenharmony_ci  AddSuccessor(block, fblock);
3121cb0ef41Sopenharmony_ci  if (block->control_input() != nullptr) {
3131cb0ef41Sopenharmony_ci    SetControlInput(end, block->control_input());
3141cb0ef41Sopenharmony_ci  }
3151cb0ef41Sopenharmony_ci  SetControlInput(block, branch);
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_civoid Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
3191cb0ef41Sopenharmony_ci                            BasicBlock** succ_blocks, size_t succ_count) {
3201cb0ef41Sopenharmony_ci  CHECK_NE(BasicBlock::kNone, block->control());
3211cb0ef41Sopenharmony_ci  CHECK_EQ(BasicBlock::kNone, end->control());
3221cb0ef41Sopenharmony_ci  end->set_control(block->control());
3231cb0ef41Sopenharmony_ci  block->set_control(BasicBlock::kSwitch);
3241cb0ef41Sopenharmony_ci  MoveSuccessors(block, end);
3251cb0ef41Sopenharmony_ci  for (size_t index = 0; index < succ_count; ++index) {
3261cb0ef41Sopenharmony_ci    AddSuccessor(block, succ_blocks[index]);
3271cb0ef41Sopenharmony_ci  }
3281cb0ef41Sopenharmony_ci  if (block->control_input() != nullptr) {
3291cb0ef41Sopenharmony_ci    SetControlInput(end, block->control_input());
3301cb0ef41Sopenharmony_ci  }
3311cb0ef41Sopenharmony_ci  SetControlInput(block, sw);
3321cb0ef41Sopenharmony_ci}
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_civoid Schedule::EnsureCFGWellFormedness() {
3351cb0ef41Sopenharmony_ci  // Make a copy of all the blocks for the iteration, since adding the split
3361cb0ef41Sopenharmony_ci  // edges will allocate new blocks.
3371cb0ef41Sopenharmony_ci  BasicBlockVector all_blocks_copy(all_blocks_);
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci  // Insert missing split edge blocks.
3401cb0ef41Sopenharmony_ci  for (BasicBlock* block : all_blocks_copy) {
3411cb0ef41Sopenharmony_ci    if (block->PredecessorCount() > 1) {
3421cb0ef41Sopenharmony_ci      if (block != end_) {
3431cb0ef41Sopenharmony_ci        EnsureSplitEdgeForm(block);
3441cb0ef41Sopenharmony_ci      }
3451cb0ef41Sopenharmony_ci    }
3461cb0ef41Sopenharmony_ci  }
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci  EliminateRedundantPhiNodes();
3491cb0ef41Sopenharmony_ci}
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_civoid Schedule::EliminateRedundantPhiNodes() {
3521cb0ef41Sopenharmony_ci  // Ensure that useless phi nodes that only have a single input, identical
3531cb0ef41Sopenharmony_ci  // inputs, or are a self-referential loop phi,
3541cb0ef41Sopenharmony_ci  // -- which can happen with the automatically generated code in the CSA and
3551cb0ef41Sopenharmony_ci  // torque -- are pruned.
3561cb0ef41Sopenharmony_ci  // Since we have strucured control flow, this is enough to minimize the number
3571cb0ef41Sopenharmony_ci  // of phi nodes.
3581cb0ef41Sopenharmony_ci  bool reached_fixed_point = false;
3591cb0ef41Sopenharmony_ci  while (!reached_fixed_point) {
3601cb0ef41Sopenharmony_ci    reached_fixed_point = true;
3611cb0ef41Sopenharmony_ci    for (BasicBlock* block : all_blocks_) {
3621cb0ef41Sopenharmony_ci      int predecessor_count = static_cast<int>(block->PredecessorCount());
3631cb0ef41Sopenharmony_ci      for (size_t node_pos = 0; node_pos < block->NodeCount(); ++node_pos) {
3641cb0ef41Sopenharmony_ci        Node* node = block->NodeAt(node_pos);
3651cb0ef41Sopenharmony_ci        if (node->opcode() == IrOpcode::kPhi) {
3661cb0ef41Sopenharmony_ci          Node* first_input = node->InputAt(0);
3671cb0ef41Sopenharmony_ci          bool inputs_equal = true;
3681cb0ef41Sopenharmony_ci          for (int i = 1; i < predecessor_count; ++i) {
3691cb0ef41Sopenharmony_ci            Node* input = node->InputAt(i);
3701cb0ef41Sopenharmony_ci            if (input != first_input && input != node) {
3711cb0ef41Sopenharmony_ci              inputs_equal = false;
3721cb0ef41Sopenharmony_ci              break;
3731cb0ef41Sopenharmony_ci            }
3741cb0ef41Sopenharmony_ci          }
3751cb0ef41Sopenharmony_ci          if (!inputs_equal) continue;
3761cb0ef41Sopenharmony_ci          node->ReplaceUses(first_input);
3771cb0ef41Sopenharmony_ci          node->Kill();
3781cb0ef41Sopenharmony_ci          block->RemoveNode(block->begin() + node_pos);
3791cb0ef41Sopenharmony_ci          --node_pos;
3801cb0ef41Sopenharmony_ci          reached_fixed_point = false;
3811cb0ef41Sopenharmony_ci        }
3821cb0ef41Sopenharmony_ci      }
3831cb0ef41Sopenharmony_ci    }
3841cb0ef41Sopenharmony_ci  }
3851cb0ef41Sopenharmony_ci}
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_civoid Schedule::EnsureSplitEdgeForm(BasicBlock* block) {
3881cb0ef41Sopenharmony_ci#ifdef DEBUG
3891cb0ef41Sopenharmony_ci  DCHECK(block->PredecessorCount() > 1 && block != end_);
3901cb0ef41Sopenharmony_ci  for (auto current_pred = block->predecessors().begin();
3911cb0ef41Sopenharmony_ci       current_pred != block->predecessors().end(); ++current_pred) {
3921cb0ef41Sopenharmony_ci    BasicBlock* pred = *current_pred;
3931cb0ef41Sopenharmony_ci    DCHECK_LE(pred->SuccessorCount(), 1);
3941cb0ef41Sopenharmony_ci  }
3951cb0ef41Sopenharmony_ci#endif
3961cb0ef41Sopenharmony_ci}
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_civoid Schedule::MovePhis(BasicBlock* from, BasicBlock* to) {
3991cb0ef41Sopenharmony_ci  for (size_t i = 0; i < from->NodeCount();) {
4001cb0ef41Sopenharmony_ci    Node* node = from->NodeAt(i);
4011cb0ef41Sopenharmony_ci    if (node->opcode() == IrOpcode::kPhi) {
4021cb0ef41Sopenharmony_ci      to->AddNode(node);
4031cb0ef41Sopenharmony_ci      from->RemoveNode(from->begin() + i);
4041cb0ef41Sopenharmony_ci      DCHECK_EQ(nodeid_to_block_[node->id()], from);
4051cb0ef41Sopenharmony_ci      nodeid_to_block_[node->id()] = to;
4061cb0ef41Sopenharmony_ci    } else {
4071cb0ef41Sopenharmony_ci      ++i;
4081cb0ef41Sopenharmony_ci    }
4091cb0ef41Sopenharmony_ci  }
4101cb0ef41Sopenharmony_ci}
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_civoid Schedule::PropagateDeferredMark() {
4131cb0ef41Sopenharmony_ci  // Push forward the deferred block marks through newly inserted blocks and
4141cb0ef41Sopenharmony_ci  // other improperly marked blocks until a fixed point is reached.
4151cb0ef41Sopenharmony_ci  // TODO(danno): optimize the propagation
4161cb0ef41Sopenharmony_ci  bool done = false;
4171cb0ef41Sopenharmony_ci  while (!done) {
4181cb0ef41Sopenharmony_ci    done = true;
4191cb0ef41Sopenharmony_ci    for (auto block : all_blocks_) {
4201cb0ef41Sopenharmony_ci      if (!block->deferred()) {
4211cb0ef41Sopenharmony_ci        bool deferred = block->PredecessorCount() > 0;
4221cb0ef41Sopenharmony_ci        for (auto pred : block->predecessors()) {
4231cb0ef41Sopenharmony_ci          if (!pred->deferred() && (pred->rpo_number() < block->rpo_number())) {
4241cb0ef41Sopenharmony_ci            deferred = false;
4251cb0ef41Sopenharmony_ci          }
4261cb0ef41Sopenharmony_ci        }
4271cb0ef41Sopenharmony_ci        if (deferred) {
4281cb0ef41Sopenharmony_ci          block->set_deferred(true);
4291cb0ef41Sopenharmony_ci          done = false;
4301cb0ef41Sopenharmony_ci        }
4311cb0ef41Sopenharmony_ci      }
4321cb0ef41Sopenharmony_ci    }
4331cb0ef41Sopenharmony_ci  }
4341cb0ef41Sopenharmony_ci}
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_civoid Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) {
4371cb0ef41Sopenharmony_ci  block->AddSuccessor(succ);
4381cb0ef41Sopenharmony_ci  succ->AddPredecessor(block);
4391cb0ef41Sopenharmony_ci}
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_civoid Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
4421cb0ef41Sopenharmony_ci  for (BasicBlock* const successor : from->successors()) {
4431cb0ef41Sopenharmony_ci    to->AddSuccessor(successor);
4441cb0ef41Sopenharmony_ci    for (BasicBlock*& predecessor : successor->predecessors()) {
4451cb0ef41Sopenharmony_ci      if (predecessor == from) predecessor = to;
4461cb0ef41Sopenharmony_ci    }
4471cb0ef41Sopenharmony_ci  }
4481cb0ef41Sopenharmony_ci  from->ClearSuccessors();
4491cb0ef41Sopenharmony_ci}
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_civoid Schedule::SetControlInput(BasicBlock* block, Node* node) {
4521cb0ef41Sopenharmony_ci  block->set_control_input(node);
4531cb0ef41Sopenharmony_ci  SetBlockForNode(block, node);
4541cb0ef41Sopenharmony_ci}
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_civoid Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
4571cb0ef41Sopenharmony_ci  if (node->id() >= nodeid_to_block_.size()) {
4581cb0ef41Sopenharmony_ci    nodeid_to_block_.resize(node->id() + 1);
4591cb0ef41Sopenharmony_ci  }
4601cb0ef41Sopenharmony_ci  nodeid_to_block_[node->id()] = block;
4611cb0ef41Sopenharmony_ci}
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const Schedule& s) {
4641cb0ef41Sopenharmony_ci  for (BasicBlock* block :
4651cb0ef41Sopenharmony_ci       ((s.RpoBlockCount() == 0) ? *s.all_blocks() : *s.rpo_order())) {
4661cb0ef41Sopenharmony_ci    if (block == nullptr) continue;
4671cb0ef41Sopenharmony_ci    if (block->rpo_number() == -1) {
4681cb0ef41Sopenharmony_ci      os << "--- BLOCK id:" << block->id();
4691cb0ef41Sopenharmony_ci    } else {
4701cb0ef41Sopenharmony_ci      os << "--- BLOCK B" << block->rpo_number();
4711cb0ef41Sopenharmony_ci    }
4721cb0ef41Sopenharmony_ci    if (block->deferred()) os << " (deferred)";
4731cb0ef41Sopenharmony_ci    if (block->PredecessorCount() != 0) os << " <- ";
4741cb0ef41Sopenharmony_ci    bool comma = false;
4751cb0ef41Sopenharmony_ci    for (BasicBlock const* predecessor : block->predecessors()) {
4761cb0ef41Sopenharmony_ci      if (comma) os << ", ";
4771cb0ef41Sopenharmony_ci      comma = true;
4781cb0ef41Sopenharmony_ci      if (predecessor->rpo_number() == -1) {
4791cb0ef41Sopenharmony_ci        os << "id:" << predecessor->id();
4801cb0ef41Sopenharmony_ci      } else {
4811cb0ef41Sopenharmony_ci        os << "B" << predecessor->rpo_number();
4821cb0ef41Sopenharmony_ci      }
4831cb0ef41Sopenharmony_ci    }
4841cb0ef41Sopenharmony_ci    os << " ---\n";
4851cb0ef41Sopenharmony_ci    for (Node* node : *block) {
4861cb0ef41Sopenharmony_ci      os << "  " << *node;
4871cb0ef41Sopenharmony_ci      if (NodeProperties::IsTyped(node)) {
4881cb0ef41Sopenharmony_ci        os << " : " << NodeProperties::GetType(node);
4891cb0ef41Sopenharmony_ci      }
4901cb0ef41Sopenharmony_ci      os << "\n";
4911cb0ef41Sopenharmony_ci    }
4921cb0ef41Sopenharmony_ci    BasicBlock::Control control = block->control();
4931cb0ef41Sopenharmony_ci    if (control != BasicBlock::kNone) {
4941cb0ef41Sopenharmony_ci      os << "  ";
4951cb0ef41Sopenharmony_ci      if (block->control_input() != nullptr) {
4961cb0ef41Sopenharmony_ci        os << *block->control_input();
4971cb0ef41Sopenharmony_ci      } else {
4981cb0ef41Sopenharmony_ci        os << "Goto";
4991cb0ef41Sopenharmony_ci      }
5001cb0ef41Sopenharmony_ci      os << " -> ";
5011cb0ef41Sopenharmony_ci      comma = false;
5021cb0ef41Sopenharmony_ci      for (BasicBlock const* successor : block->successors()) {
5031cb0ef41Sopenharmony_ci        if (comma) os << ", ";
5041cb0ef41Sopenharmony_ci        comma = true;
5051cb0ef41Sopenharmony_ci        if (successor->rpo_number() == -1) {
5061cb0ef41Sopenharmony_ci          os << "id:" << successor->id();
5071cb0ef41Sopenharmony_ci        } else {
5081cb0ef41Sopenharmony_ci          os << "B" << successor->rpo_number();
5091cb0ef41Sopenharmony_ci        }
5101cb0ef41Sopenharmony_ci      }
5111cb0ef41Sopenharmony_ci      os << "\n";
5121cb0ef41Sopenharmony_ci    }
5131cb0ef41Sopenharmony_ci  }
5141cb0ef41Sopenharmony_ci  return os;
5151cb0ef41Sopenharmony_ci}
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_ci}  // namespace compiler
5181cb0ef41Sopenharmony_ci}  // namespace internal
5191cb0ef41Sopenharmony_ci}  // namespace v8
520