// 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/utils/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::RemovePredecessor(size_t index) {
  predecessors_.erase(predecessors_.begin() + index);
}

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) {
  if (!nodes_.empty() && control_input == nodes_.back()) {
    nodes_.pop_back();
  }
  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;
}

void BasicBlock::TrimNodes(iterator new_end) { nodes_.erase(new_end, end()); }

void BasicBlock::ResetRPOInfo() {
  loop_number_ = -1;
  rpo_number_ = -1;
  dominator_depth_ = -1;
  dominator_ = nullptr;
  rpo_next_ = nullptr;
  loop_header_ = nullptr;
  loop_end_ = nullptr;
  loop_depth_ = 0;
}

// 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() { StdoutStream{} << this; }

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()];
}

void Schedule::ClearBlockById(BasicBlock::Id block_id) {
  DCHECK(block_id.ToSize() < all_blocks_.size());
  all_blocks_[block_id.ToSize()] = nullptr;
}

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 = zone_->New<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) {
    StdoutStream{} << "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) {
    StdoutStream{} << "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) {
  CHECK_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:
      return true;
    default:
      return false;
  }
}

}  // namespace
#endif  // DEBUG

void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
                       BasicBlock* exception_block) {
  CHECK_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) {
  CHECK_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) {
  CHECK_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) {
  CHECK_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) {
  CHECK_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) {
  CHECK_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) {
  CHECK_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) {
  CHECK_NE(BasicBlock::kNone, block->control());
  CHECK_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) {
  CHECK_NE(BasicBlock::kNone, block->control());
  CHECK_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 (BasicBlock* block : all_blocks_copy) {
    if (block->PredecessorCount() > 1) {
      if (block != end_) {
        EnsureSplitEdgeForm(block);
      }
    }
  }

  EliminateRedundantPhiNodes();
}

void Schedule::EliminateRedundantPhiNodes() {
  // Ensure that useless phi nodes that only have a single input, identical
  // inputs, or are a self-referential loop phi,
  // -- which can happen with the automatically generated code in the CSA and
  // torque -- are pruned.
  // Since we have strucured control flow, this is enough to minimize the number
  // of phi nodes.
  bool reached_fixed_point = false;
  while (!reached_fixed_point) {
    reached_fixed_point = true;
    for (BasicBlock* block : all_blocks_) {
      int predecessor_count = static_cast<int>(block->PredecessorCount());
      for (size_t node_pos = 0; node_pos < block->NodeCount(); ++node_pos) {
        Node* node = block->NodeAt(node_pos);
        if (node->opcode() == IrOpcode::kPhi) {
          Node* first_input = node->InputAt(0);
          bool inputs_equal = true;
          for (int i = 1; i < predecessor_count; ++i) {
            Node* input = node->InputAt(i);
            if (input != first_input && input != node) {
              inputs_equal = false;
              break;
            }
          }
          if (!inputs_equal) continue;
          node->ReplaceUses(first_input);
          node->Kill();
          block->RemoveNode(block->begin() + node_pos);
          --node_pos;
          reached_fixed_point = false;
        }
      }
    }
  }
}

void Schedule::EnsureSplitEdgeForm(BasicBlock* block) {
#ifdef DEBUG
  DCHECK(block->PredecessorCount() > 1 && block != end_);
  for (auto current_pred = block->predecessors().begin();
       current_pred != block->predecessors().end(); ++current_pred) {
    BasicBlock* pred = *current_pred;
    DCHECK_LE(pred->SuccessorCount(), 1);
  }
#endif
}

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 == nullptr) continue;
    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)) {
        os << " : " << NodeProperties::GetType(node);
      }
      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
