// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/schedule.h"

#include "src/compiler/node-properties.h"
#include "src/compiler/node.h"
#include "src/ostreams.h"

namespace v8 {
namespace internal {
namespace compiler {

BasicBlock::BasicBlock(Zone* zone, Id id)
    : loop_number_(-1),
      rpo_number_(-1),
      deferred_(false),
      dominator_depth_(-1),
      dominator_(nullptr),
      rpo_next_(nullptr),
      loop_header_(nullptr),
      loop_end_(nullptr),
      loop_depth_(0),
      control_(kNone),
      control_input_(nullptr),
      nodes_(zone),
      successors_(zone),
      predecessors_(zone),
#if DEBUG
      debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)),
#endif
      id_(id) {
}

bool BasicBlock::LoopContains(BasicBlock* block) const {
  // RPO numbers must be initialized.
  DCHECK_LE(0, rpo_number_);
  DCHECK_LE(0, block->rpo_number_);
  if (loop_end_ == nullptr) return false;  // This is not a loop.
  return block->rpo_number_ >= rpo_number_ &&
         block->rpo_number_ < loop_end_->rpo_number_;
}


void BasicBlock::AddSuccessor(BasicBlock* successor) {
  successors_.push_back(successor);
}


void BasicBlock::AddPredecessor(BasicBlock* predecessor) {
  predecessors_.push_back(predecessor);
}


void BasicBlock::AddNode(Node* node) { nodes_.push_back(node); }


void BasicBlock::set_control(Control control) {
  control_ = control;
}


void BasicBlock::set_control_input(Node* control_input) {
  control_input_ = control_input;
}


void BasicBlock::set_loop_depth(int32_t loop_depth) {
  loop_depth_ = loop_depth;
}


void BasicBlock::set_rpo_number(int32_t rpo_number) {
  rpo_number_ = rpo_number;
}


void BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; }


void BasicBlock::set_loop_header(BasicBlock* loop_header) {
  loop_header_ = loop_header;
}


// static
BasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
  while (b1 != b2) {
    if (b1->dominator_depth() < b2->dominator_depth()) {
      b2 = b2->dominator();
    } else {
      b1 = b1->dominator();
    }
  }
  return b1;
}

void BasicBlock::Print() {
#ifndef V8_OS_STARBOARD
  OFStream(stdout) << this;
#endif
}

std::ostream& operator<<(std::ostream& os, const BasicBlock& block) {
  os << "B" << block.id();
#if DEBUG
  AssemblerDebugInfo info = block.debug_info();
  if (info.name) os << info;
  // Print predecessor blocks for better debugging.
  const int kMaxDisplayedBlocks = 4;
  int i = 0;
  const BasicBlock* current_block = &block;
  while (current_block->PredecessorCount() > 0 && i++ < kMaxDisplayedBlocks) {
    current_block = current_block->predecessors().front();
    os << " <= B" << current_block->id();
    info = current_block->debug_info();
    if (info.name) os << info;
  }
#endif
  return os;
}

std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
  switch (c) {
    case BasicBlock::kNone:
      return os << "none";
    case BasicBlock::kGoto:
      return os << "goto";
    case BasicBlock::kCall:
      return os << "call";
    case BasicBlock::kBranch:
      return os << "branch";
    case BasicBlock::kSwitch:
      return os << "switch";
    case BasicBlock::kDeoptimize:
      return os << "deoptimize";
    case BasicBlock::kTailCall:
      return os << "tailcall";
    case BasicBlock::kReturn:
      return os << "return";
    case BasicBlock::kThrow:
      return os << "throw";
  }
  UNREACHABLE();
}


std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) {
  return os << id.ToSize();
}


Schedule::Schedule(Zone* zone, size_t node_count_hint)
    : zone_(zone),
      all_blocks_(zone),
      nodeid_to_block_(zone),
      rpo_order_(zone),
      start_(NewBasicBlock()),
      end_(NewBasicBlock()) {
  nodeid_to_block_.reserve(node_count_hint);
}


BasicBlock* Schedule::block(Node* node) const {
  if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) {
    return nodeid_to_block_[node->id()];
  }
  return nullptr;
}


bool Schedule::IsScheduled(Node* node) {
  if (node->id() >= nodeid_to_block_.size()) return false;
  return nodeid_to_block_[node->id()] != nullptr;
}


BasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) {
  DCHECK(block_id.ToSize() < all_blocks_.size());
  return all_blocks_[block_id.ToSize()];
}


bool Schedule::SameBasicBlock(Node* a, Node* b) const {
  BasicBlock* block = this->block(a);
  return block != nullptr && block == this->block(b);
}


BasicBlock* Schedule::NewBasicBlock() {
  BasicBlock* block = new (zone_)
      BasicBlock(zone_, BasicBlock::Id::FromSize(all_blocks_.size()));
  all_blocks_.push_back(block);
  return block;
}


void Schedule::PlanNode(BasicBlock* block, Node* node) {
#ifndef V8_OS_STARBOARD
  if (FLAG_trace_turbo_scheduler) {
    OFStream os(stdout);
    os << "Planning #" << node->id() << ":" << node->op()->mnemonic()
       << " for future add to B" << block->id() << "\n";
  }
#endif
  DCHECK_NULL(this->block(node));
  SetBlockForNode(block, node);
}


void Schedule::AddNode(BasicBlock* block, Node* node) {
#ifndef V8_OS_STARBOARD
  if (FLAG_trace_turbo_scheduler) {
    OFStream os(stdout);
    os << "Adding #" << node->id() << ":" << node->op()->mnemonic() << " to B"
       << block->id() << "\n";
  }
#endif
  DCHECK(this->block(node) == nullptr || this->block(node) == block);
  block->AddNode(node);
  SetBlockForNode(block, node);
}


void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
  DCHECK_EQ(BasicBlock::kNone, block->control());
  block->set_control(BasicBlock::kGoto);
  AddSuccessor(block, succ);
}

#if DEBUG
namespace {

bool IsPotentiallyThrowingCall(IrOpcode::Value opcode) {
  switch (opcode) {
#define BUILD_BLOCK_JS_CASE(Name) case IrOpcode::k##Name:
    JS_OP_LIST(BUILD_BLOCK_JS_CASE)
#undef BUILD_BLOCK_JS_CASE
    case IrOpcode::kCall:
    case IrOpcode::kCallWithCallerSavedRegisters:
      return true;
    default:
      return false;
  }
}

}  // namespace
#endif  // DEBUG

void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
                       BasicBlock* exception_block) {
  DCHECK_EQ(BasicBlock::kNone, block->control());
  DCHECK(IsPotentiallyThrowingCall(call->opcode()));
  block->set_control(BasicBlock::kCall);
  AddSuccessor(block, success_block);
  AddSuccessor(block, exception_block);
  SetControlInput(block, call);
}


void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
                         BasicBlock* fblock) {
  DCHECK_EQ(BasicBlock::kNone, block->control());
  DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
  block->set_control(BasicBlock::kBranch);
  AddSuccessor(block, tblock);
  AddSuccessor(block, fblock);
  SetControlInput(block, branch);
}


void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
                         size_t succ_count) {
  DCHECK_EQ(BasicBlock::kNone, block->control());
  DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
  block->set_control(BasicBlock::kSwitch);
  for (size_t index = 0; index < succ_count; ++index) {
    AddSuccessor(block, succ_blocks[index]);
  }
  SetControlInput(block, sw);
}


void Schedule::AddTailCall(BasicBlock* block, Node* input) {
  DCHECK_EQ(BasicBlock::kNone, block->control());
  block->set_control(BasicBlock::kTailCall);
  SetControlInput(block, input);
  if (block != end()) AddSuccessor(block, end());
}


void Schedule::AddReturn(BasicBlock* block, Node* input) {
  DCHECK_EQ(BasicBlock::kNone, block->control());
  block->set_control(BasicBlock::kReturn);
  SetControlInput(block, input);
  if (block != end()) AddSuccessor(block, end());
}


void Schedule::AddDeoptimize(BasicBlock* block, Node* input) {
  DCHECK_EQ(BasicBlock::kNone, block->control());
  block->set_control(BasicBlock::kDeoptimize);
  SetControlInput(block, input);
  if (block != end()) AddSuccessor(block, end());
}


void Schedule::AddThrow(BasicBlock* block, Node* input) {
  DCHECK_EQ(BasicBlock::kNone, block->control());
  block->set_control(BasicBlock::kThrow);
  SetControlInput(block, input);
  if (block != end()) AddSuccessor(block, end());
}


void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
                            BasicBlock* tblock, BasicBlock* fblock) {
  DCHECK_NE(BasicBlock::kNone, block->control());
  DCHECK_EQ(BasicBlock::kNone, end->control());
  end->set_control(block->control());
  block->set_control(BasicBlock::kBranch);
  MoveSuccessors(block, end);
  AddSuccessor(block, tblock);
  AddSuccessor(block, fblock);
  if (block->control_input() != nullptr) {
    SetControlInput(end, block->control_input());
  }
  SetControlInput(block, branch);
}


void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
                            BasicBlock** succ_blocks, size_t succ_count) {
  DCHECK_NE(BasicBlock::kNone, block->control());
  DCHECK_EQ(BasicBlock::kNone, end->control());
  end->set_control(block->control());
  block->set_control(BasicBlock::kSwitch);
  MoveSuccessors(block, end);
  for (size_t index = 0; index < succ_count; ++index) {
    AddSuccessor(block, succ_blocks[index]);
  }
  if (block->control_input() != nullptr) {
    SetControlInput(end, block->control_input());
  }
  SetControlInput(block, sw);
}

void Schedule::EnsureCFGWellFormedness() {
  // Make a copy of all the blocks for the iteration, since adding the split
  // edges will allocate new blocks.
  BasicBlockVector all_blocks_copy(all_blocks_);

  // Insert missing split edge blocks.
  for (auto block : all_blocks_copy) {
    if (block->PredecessorCount() > 1) {
      if (block != end_) {
        EnsureSplitEdgeForm(block);
      }
      if (block->deferred()) {
        EnsureDeferredCodeSingleEntryPoint(block);
      }
    }
  }
}

void Schedule::EnsureSplitEdgeForm(BasicBlock* block) {
  DCHECK(block->PredecessorCount() > 1 && block != end_);
  for (auto current_pred = block->predecessors().begin();
       current_pred != block->predecessors().end(); ++current_pred) {
    BasicBlock* pred = *current_pred;
    if (pred->SuccessorCount() > 1) {
      // Found a predecessor block with multiple successors.
      BasicBlock* split_edge_block = NewBasicBlock();
      split_edge_block->set_control(BasicBlock::kGoto);
      split_edge_block->successors().push_back(block);
      split_edge_block->predecessors().push_back(pred);
      split_edge_block->set_deferred(block->deferred());
      *current_pred = split_edge_block;
      // Find a corresponding successor in the previous block, replace it
      // with the split edge block... but only do it once, since we only
      // replace the previous blocks in the current block one at a time.
      for (auto successor = pred->successors().begin();
           successor != pred->successors().end(); ++successor) {
        if (*successor == block) {
          *successor = split_edge_block;
          break;
        }
      }
    }
  }
}

void Schedule::EnsureDeferredCodeSingleEntryPoint(BasicBlock* block) {
  // If a deferred block has multiple predecessors, they have to
  // all be deferred. Otherwise, we can run into a situation where a range
  // that spills only in deferred blocks inserts its spill in the block, but
  // other ranges need moves inserted by ResolveControlFlow in the predecessors,
  // which may clobber the register of this range.
  // To ensure that, when a deferred block has multiple predecessors, and some
  // are not deferred, we add a non-deferred block to collect all such edges.

  DCHECK(block->deferred() && block->PredecessorCount() > 1);
  bool all_deferred = true;
  for (auto current_pred = block->predecessors().begin();
       current_pred != block->predecessors().end(); ++current_pred) {
    BasicBlock* pred = *current_pred;
    if (!pred->deferred()) {
      all_deferred = false;
      break;
    }
  }

  if (all_deferred) return;
  BasicBlock* merger = NewBasicBlock();
  merger->set_control(BasicBlock::kGoto);
  merger->successors().push_back(block);
  for (auto current_pred = block->predecessors().begin();
       current_pred != block->predecessors().end(); ++current_pred) {
    BasicBlock* pred = *current_pred;
    merger->predecessors().push_back(pred);
    pred->successors().clear();
    pred->successors().push_back(merger);
  }
  merger->set_deferred(false);
  block->predecessors().clear();
  block->predecessors().push_back(merger);
  MovePhis(block, merger);
}

void Schedule::MovePhis(BasicBlock* from, BasicBlock* to) {
  for (size_t i = 0; i < from->NodeCount();) {
    Node* node = from->NodeAt(i);
    if (node->opcode() == IrOpcode::kPhi) {
      to->AddNode(node);
      from->RemoveNode(from->begin() + i);
      DCHECK_EQ(nodeid_to_block_[node->id()], from);
      nodeid_to_block_[node->id()] = to;
    } else {
      ++i;
    }
  }
}

void Schedule::PropagateDeferredMark() {
  // Push forward the deferred block marks through newly inserted blocks and
  // other improperly marked blocks until a fixed point is reached.
  // TODO(danno): optimize the propagation
  bool done = false;
  while (!done) {
    done = true;
    for (auto block : all_blocks_) {
      if (!block->deferred()) {
        bool deferred = block->PredecessorCount() > 0;
        for (auto pred : block->predecessors()) {
          if (!pred->deferred() && (pred->rpo_number() < block->rpo_number())) {
            deferred = false;
          }
        }
        if (deferred) {
          block->set_deferred(true);
          done = false;
        }
      }
    }
  }
}

void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) {
  block->AddSuccessor(succ);
  succ->AddPredecessor(block);
}


void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
  for (BasicBlock* const successor : from->successors()) {
    to->AddSuccessor(successor);
    for (BasicBlock*& predecessor : successor->predecessors()) {
      if (predecessor == from) predecessor = to;
    }
  }
  from->ClearSuccessors();
}


void Schedule::SetControlInput(BasicBlock* block, Node* node) {
  block->set_control_input(node);
  SetBlockForNode(block, node);
}


void Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
  if (node->id() >= nodeid_to_block_.size()) {
    nodeid_to_block_.resize(node->id() + 1);
  }
  nodeid_to_block_[node->id()] = block;
}


std::ostream& operator<<(std::ostream& os, const Schedule& s) {
  for (BasicBlock* block :
       ((s.RpoBlockCount() == 0) ? *s.all_blocks() : *s.rpo_order())) {
    if (block->rpo_number() == -1) {
      os << "--- BLOCK id:" << block->id().ToInt();
    } else {
      os << "--- BLOCK B" << block->rpo_number();
    }
    if (block->deferred()) os << " (deferred)";
    if (block->PredecessorCount() != 0) os << " <- ";
    bool comma = false;
    for (BasicBlock const* predecessor : block->predecessors()) {
      if (comma) os << ", ";
      comma = true;
      if (predecessor->rpo_number() == -1) {
        os << "id:" << predecessor->id().ToInt();
      } else {
        os << "B" << predecessor->rpo_number();
      }
    }
    os << " ---\n";
    for (Node* node : *block) {
      os << "  " << *node;
      if (NodeProperties::IsTyped(node)) {
        Type* type = NodeProperties::GetType(node);
        os << " : ";
        type->PrintTo(os);
      }
      os << "\n";
    }
    BasicBlock::Control control = block->control();
    if (control != BasicBlock::kNone) {
      os << "  ";
      if (block->control_input() != nullptr) {
        os << *block->control_input();
      } else {
        os << "Goto";
      }
      os << " -> ";
      comma = false;
      for (BasicBlock const* successor : block->successors()) {
        if (comma) os << ", ";
        comma = true;
        if (successor->rpo_number() == -1) {
          os << "id:" << successor->id().ToInt();
        } else {
          os << "B" << successor->rpo_number();
        }
      }
      os << "\n";
    }
  }
  return os;
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
