// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/compiler/backend/block_scheduler.h"

#include "vm/allocation.h"
#include "vm/code_patcher.h"
#include "vm/compiler/backend/flow_graph.h"
#include "vm/compiler/jit/compiler.h"

namespace dart {

static intptr_t GetEdgeCount(const Array& edge_counters, intptr_t edge_id) {
  if (!FLAG_reorder_basic_blocks) {
    // Assume everything was visited once.
    return 1;
  }
  return Smi::Value(Smi::RawCast(edge_counters.At(edge_id)));
}

// There is an edge from instruction->successor.  Set its weight (edge count
// per function entry).
static void SetEdgeWeight(BlockEntryInstr* block,
                          BlockEntryInstr* successor,
                          const Array& edge_counters,
                          intptr_t entry_count) {
  ASSERT(entry_count != 0);
  if (auto target = successor->AsTargetEntry()) {
    // If this block ends in a goto, the edge count of this edge is the same
    // as the count on the single outgoing edge. This is true as long as the
    // block does not throw an exception.
    intptr_t count = GetEdgeCount(edge_counters, target->preorder_number());
    if (count >= 0) {
      double weight =
          static_cast<double>(count) / static_cast<double>(entry_count);
      target->set_edge_weight(weight);
    }
  } else if (auto jump = block->last_instruction()->AsGoto()) {
    intptr_t count = GetEdgeCount(edge_counters, block->preorder_number());
    if (count >= 0) {
      double weight =
          static_cast<double>(count) / static_cast<double>(entry_count);
      jump->set_edge_weight(weight);
    }
  }
}

void BlockScheduler::AssignEdgeWeights(FlowGraph* flow_graph) {
  if (!FLAG_reorder_basic_blocks) {
    return;
  }
  if (CompilerState::Current().is_aot()) {
    return;
  }

  const Function& function = flow_graph->parsed_function().function();
  const Array& ic_data_array =
      Array::Handle(flow_graph->zone(), function.ic_data_array());
  if (ic_data_array.IsNull()) {
    DEBUG_ASSERT(IsolateGroup::Current()->HasAttemptedReload() ||
                 function.ForceOptimize());
    return;
  }
  Array& edge_counters = Array::Handle();
  edge_counters ^=
      ic_data_array.At(Function::ICDataArrayIndices::kEdgeCounters);
  if (edge_counters.IsNull()) {
    return;
  }

  auto graph_entry = flow_graph->graph_entry();
  BlockEntryInstr* entry = graph_entry->normal_entry();
  if (entry == nullptr) {
    entry = graph_entry->osr_entry();
    ASSERT(entry != nullptr);
  }
  const intptr_t entry_count =
      GetEdgeCount(edge_counters, entry->preorder_number());
  graph_entry->set_entry_count(entry_count);
  if (entry_count == 0) {
    return;  // Nothing to do.
  }

  for (BlockIterator it = flow_graph->reverse_postorder_iterator(); !it.Done();
       it.Advance()) {
    BlockEntryInstr* block = it.Current();
    Instruction* last = block->last_instruction();
    for (intptr_t i = 0; i < last->SuccessorCount(); ++i) {
      BlockEntryInstr* succ = last->SuccessorAt(i);
      SetEdgeWeight(block, succ, edge_counters, entry_count);
    }
  }
}

// A weighted control-flow graph edge.
struct Edge {
  Edge(BlockEntryInstr* source, BlockEntryInstr* target, double weight)
      : source(source), target(target), weight(weight) {}

  static int LowestWeightFirst(const Edge* a, const Edge* b);

  BlockEntryInstr* source;
  BlockEntryInstr* target;
  double weight;
};

// A linked list node in a chain of blocks.
struct Link : public ZoneAllocated {
  Link(BlockEntryInstr* block, Link* next) : block(block), next(next) {}

  BlockEntryInstr* block;
  Link* next;
};

// A chain of blocks with first and last pointers for fast concatenation and
// a length to support adding a shorter chain's links to a longer chain.
struct Chain : public ZoneAllocated {
  explicit Chain(BlockEntryInstr* block)
      : first(new Link(block, nullptr)), last(first), length(1) {}

  Link* first;
  Link* last;
  intptr_t length;
};

int Edge::LowestWeightFirst(const Edge* a, const Edge* b) {
  if (a->weight < b->weight) {
    return -1;
  }
  return (a->weight > b->weight) ? 1 : 0;
}

// Combine two chains by adding the shorter chain's links to the longer
// chain.
static void Union(GrowableArray<Chain*>* chains,
                  Chain* source_chain,
                  Chain* target_chain) {
  if (source_chain->length < target_chain->length) {
    for (Link* link = source_chain->first; link != nullptr; link = link->next) {
      (*chains)[link->block->postorder_number()] = target_chain;
    }
    // Link the chains.
    source_chain->last->next = target_chain->first;
    // Update the state of the longer chain.
    target_chain->first = source_chain->first;
    target_chain->length += source_chain->length;
  } else {
    for (Link* link = target_chain->first; link != nullptr; link = link->next) {
      (*chains)[link->block->postorder_number()] = source_chain;
    }
    source_chain->last->next = target_chain->first;
    source_chain->last = target_chain->last;
    source_chain->length += target_chain->length;
  }
}

void BlockScheduler::ReorderBlocks(FlowGraph* flow_graph) {
  if (!flow_graph->should_reorder_blocks()) {
    return;
  }

  if (CompilerState::Current().is_aot()) {
    ReorderBlocksAOT(flow_graph);
  } else {
    ReorderBlocksJIT(flow_graph);
  }
}

void BlockScheduler::ReorderBlocksJIT(FlowGraph* flow_graph) {
  // Add every block to a chain of length 1 and compute a list of edges
  // sorted by weight.
  intptr_t block_count = flow_graph->preorder().length();
  GrowableArray<Edge> edges(2 * block_count);

  // A map from a block's postorder number to the chain it is in.  Used to
  // implement a simple (ordered) union-find data structure.  Chains are
  // stored by pointer so that they are aliased (mutating one mutates all
  // shared ones).  Find(n) is simply chains[n].
  GrowableArray<Chain*> chains(block_count);

  for (BlockIterator it = flow_graph->postorder_iterator(); !it.Done();
       it.Advance()) {
    BlockEntryInstr* block = it.Current();
    chains.Add(new Chain(block));

    Instruction* last = block->last_instruction();
    for (intptr_t i = 0; i < last->SuccessorCount(); ++i) {
      BlockEntryInstr* succ = last->SuccessorAt(i);
      double weight = 0.0;
      if (succ->IsTargetEntry()) {
        weight = succ->AsTargetEntry()->edge_weight();
      } else if (last->IsGoto()) {
        weight = last->AsGoto()->edge_weight();
      }
      edges.Add(Edge(block, succ, weight));
    }
  }

  // Handle each edge in turn.  The edges are sorted by increasing weight.
  edges.Sort(Edge::LowestWeightFirst);
  while (!edges.is_empty()) {
    Edge edge = edges.RemoveLast();
    Chain* source_chain = chains[edge.source->postorder_number()];
    Chain* target_chain = chains[edge.target->postorder_number()];

    // If the source and target are already in the same chain or if the
    // edge's source or target is not exposed at the appropriate end of a
    // chain skip this edge.
    if ((source_chain == target_chain) ||
        (edge.source != source_chain->last->block) ||
        (edge.target != target_chain->first->block)) {
      continue;
    }

    Union(&chains, source_chain, target_chain);
  }

  // Ensure the checked entry remains first to avoid needing another offset on
  // Instructions, compare Code::EntryPointOf.
  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
  flow_graph->CodegenBlockOrder()->Add(graph_entry);
  FunctionEntryInstr* checked_entry = graph_entry->normal_entry();
  if (checked_entry != nullptr) {
    flow_graph->CodegenBlockOrder()->Add(checked_entry);
  }
  // Build a new block order.  Emit each chain when its first block occurs
  // in the original reverse postorder ordering.
  // Note: the resulting order is not topologically sorted and can't be
  // used a replacement for reverse_postorder in algorithms that expect
  // topological sort.
  for (intptr_t i = block_count - 1; i >= 0; --i) {
    if (chains[i]->first->block == flow_graph->postorder()[i]) {
      for (Link* link = chains[i]->first; link != nullptr; link = link->next) {
        if ((link->block != checked_entry) && (link->block != graph_entry)) {
          flow_graph->CodegenBlockOrder()->Add(link->block);
        }
      }
    }
  }
}

// AOT block order is based on reverse post order but with two changes:
//
// - Blocks which always throw and their direct predecessors are considered
// *cold* and moved to the end of the order.
// - Blocks which belong to the same loop are kept together (where possible)
// and not interspersed with other blocks.
//
namespace {
class AOTBlockScheduler {
 public:
  explicit AOTBlockScheduler(FlowGraph* flow_graph)
      : flow_graph_(flow_graph),
        block_count_(flow_graph->reverse_postorder().length()),
        marks_(block_count_),
        postorder_(block_count_),
        cold_postorder_(10) {
    marks_.FillWith(0, 0, block_count_);
  }

  void ComputeOrder() {
    ComputeOrderImpl();

    const auto codegen_order = flow_graph_->CodegenBlockOrder();
    for (intptr_t i = postorder_.length() - 1; i >= 0; --i) {
      codegen_order->Add(postorder_[i]);
    }
    for (intptr_t i = cold_postorder_.length() - 1; i >= 0; --i) {
      codegen_order->Add(cold_postorder_[i]);
    }
  }

 private:
  // The algorithm below is almost identical to |FlowGraph::DiscoverBlocks|, but
  // with few tweaks which guarantee improved scheduling for cold code and
  // loops.
  void ComputeOrderImpl() {
    PushBlock(flow_graph_->graph_entry());
    while (!block_stack_.is_empty()) {
      BlockEntryInstr* block = block_stack_.Last();
      auto& marks = MarksOf(block);
      auto last = block->last_instruction();
      const auto successor_count = last->SuccessorCount();

      if ((marks & kVisitedMark) == 0) {
        marks |= kVisitedMark;

        if (last->IsThrow() || last->IsReThrow() || last->IsStop()) {
          marks |= kColdMark;
        } else {
          // When visiting a block inside a loop with two successors
          // push the successor with lesser nesting *last*, so that it is
          // visited first. This helps to keep blocks which belong to the
          // same loop together.
          //
          // This is the main difference from |DiscoverBlocks| which always
          // visits successors in reverse order.
          if (successor_count == 2 && block->loop_info() != nullptr) {
            auto succ0 = last->SuccessorAt(0);
            auto succ1 = last->SuccessorAt(1);

            if (succ0->NestingDepth() < succ1->NestingDepth()) {
              PushBlock(succ1);
              PushBlock(succ0);
            } else {
              PushBlock(succ0);
              PushBlock(succ1);
            }
          } else {
            for (intptr_t i = 0; i < successor_count; i++) {
              PushBlock(last->SuccessorAt(i));
            }
          }

          // We have pushed some successors to the stack. Process them first.
          if (block_stack_.Last() != block) {
            continue;
          }

          // No successors added, fall through.
        }
      }

      // All successors of this block were visited, which means we are
      // done with this block.
      block_stack_.RemoveLast();

      // Propagate cold mark from the successors: if all successors are
      // cold then this block is cold as well.
      if (successor_count > 0) {
        uint8_t cold_mark = kColdMark;
        for (intptr_t i = 0; i < successor_count; i++) {
          cold_mark &= MarksOf(last->SuccessorAt(i));
        }
        marks |= cold_mark;
      }

      if ((marks & (kColdMark | kPinnedMark)) == kColdMark) {
        // This block is cold and not pinned: move it to cold section at
        // the end.
        cold_postorder_.Add(block);
      } else {
        postorder_.Add(block);
      }
    }
  }

  // The block was added to the stack.
  static constexpr uint8_t kSeenMark = 1 << 0;
  // The block was visited and all of its successors were added to the stack.
  static constexpr uint8_t kVisitedMark = 1 << 1;
  // The block terminates with unconditional throw or rethrow.
  static constexpr uint8_t kColdMark = 1 << 2;
  // The block should not move to cold section.
  static constexpr uint8_t kPinnedMark = 1 << 3;

  uint8_t& MarksOf(BlockEntryInstr* block) {
    return marks_[block->preorder_number()];
  }

  void PushBlock(BlockEntryInstr* block) {
    auto& marks = MarksOf(block);
    if ((marks & kSeenMark) == 0) {
      marks |= kSeenMark;
      block_stack_.Add(block);

      if (block->IsFunctionEntry() || block->IsGraphEntry()) {
        marks |= kPinnedMark;
      }
    }
  }

  FlowGraph* const flow_graph_;
  const intptr_t block_count_;

  // Block marks for each block indexed by block preorder number.
  GrowableArray<uint8_t> marks_;

  // Stack of blocks to process.
  GrowableArray<BlockEntryInstr*> block_stack_;

  GrowableArray<BlockEntryInstr*> postorder_;
  GrowableArray<BlockEntryInstr*> cold_postorder_;
};
}  // namespace

void BlockScheduler::ReorderBlocksAOT(FlowGraph* flow_graph) {
  AOTBlockScheduler(flow_graph).ComputeOrder();
}

}  // namespace dart
