//===- bolt/Passes/ReorderAlgorithm.cpp - Basic block reordering ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements classes used by several basic block reordering
// algorithms.
//
//===----------------------------------------------------------------------===//

#include "bolt/Passes/ReorderAlgorithm.h"
#include "bolt/Core/BinaryBasicBlock.h"
#include "bolt/Core/BinaryFunction.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Utils/CodeLayout.h"
#include <queue>
#include <random>
#include <stack>

#undef DEBUG_TYPE
#define DEBUG_TYPE "bolt"

using namespace llvm;
using namespace bolt;

namespace opts {

extern cl::OptionCategory BoltOptCategory;
extern cl::opt<bool> NoThreads;

static cl::opt<unsigned> ColdThreshold(
    "cold-threshold",
    cl::desc("tenths of percents of main entry frequency to use as a "
             "threshold when evaluating whether a basic block is cold "
             "(0 means it is only considered cold if the block has zero "
             "samples). Default: 0 "),
    cl::init(0), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory));

static cl::opt<bool> PrintClusters("print-clusters", cl::desc("print clusters"),
                                   cl::Hidden, cl::cat(BoltOptCategory));

cl::opt<uint32_t> RandomSeed("bolt-seed", cl::desc("seed for randomization"),
                             cl::init(42), cl::Hidden,
                             cl::cat(BoltOptCategory));

} // namespace opts

namespace {

template <class T> inline void hashCombine(size_t &Seed, const T &Val) {
  std::hash<T> Hasher;
  Seed ^= Hasher(Val) + 0x9e3779b9 + (Seed << 6) + (Seed >> 2);
}

template <typename A, typename B> struct HashPair {
  size_t operator()(const std::pair<A, B> &Val) const {
    std::hash<A> Hasher;
    size_t Seed = Hasher(Val.first);
    hashCombine(Seed, Val.second);
    return Seed;
  }
};

} // namespace

void ClusterAlgorithm::computeClusterAverageFrequency(const BinaryContext &BC) {
  // Create a separate MCCodeEmitter to allow lock-free execution
  BinaryContext::IndependentCodeEmitter Emitter;
  if (!opts::NoThreads)
    Emitter = BC.createIndependentMCCodeEmitter();

  AvgFreq.resize(Clusters.size(), 0.0);
  for (uint32_t I = 0, E = Clusters.size(); I < E; ++I) {
    double Freq = 0.0;
    uint64_t ClusterSize = 0;
    for (const BinaryBasicBlock *BB : Clusters[I]) {
      if (BB->getNumNonPseudos() > 0) {
        Freq += BB->getExecutionCount();
        // Estimate the size of a block in bytes at run time
        // NOTE: This might be inaccurate
        ClusterSize += BB->estimateSize(Emitter.MCE.get());
      }
    }
    AvgFreq[I] = ClusterSize == 0 ? 0 : Freq / ClusterSize;
  }
}

void ClusterAlgorithm::printClusters() const {
  for (uint32_t I = 0, E = Clusters.size(); I < E; ++I) {
    errs() << "Cluster number " << I;
    if (AvgFreq.size() == Clusters.size())
      errs() << " (frequency: " << AvgFreq[I] << ")";
    errs() << " : ";
    const char *Sep = "";
    for (const BinaryBasicBlock *BB : Clusters[I]) {
      errs() << Sep << BB->getName();
      Sep = ", ";
    }
    errs() << "\n";
  }
}

void ClusterAlgorithm::reset() {
  Clusters.clear();
  ClusterEdges.clear();
  AvgFreq.clear();
}

void GreedyClusterAlgorithm::EdgeTy::print(raw_ostream &OS) const {
  OS << Src->getName() << " -> " << Dst->getName() << ", count: " << Count;
}

size_t GreedyClusterAlgorithm::EdgeHash::operator()(const EdgeTy &E) const {
  HashPair<const BinaryBasicBlock *, const BinaryBasicBlock *> Hasher;
  return Hasher(std::make_pair(E.Src, E.Dst));
}

bool GreedyClusterAlgorithm::EdgeEqual::operator()(const EdgeTy &A,
                                                   const EdgeTy &B) const {
  return A.Src == B.Src && A.Dst == B.Dst;
}

void GreedyClusterAlgorithm::clusterBasicBlocks(BinaryFunction &BF,
                                                bool ComputeEdges) {
  reset();

  // Greedy heuristic implementation for the TSP, applied to BB layout. Try to
  // maximize weight during a path traversing all BBs. In this way, we will
  // convert the hottest branches into fall-throughs.

  // This is the queue of edges from which we will pop edges and use them to
  // cluster basic blocks in a greedy fashion.
  std::vector<EdgeTy> Queue;

  // Initialize inter-cluster weights.
  if (ComputeEdges)
    ClusterEdges.resize(BF.getLayout().block_size());

  // Initialize clusters and edge queue.
  for (BinaryBasicBlock *BB : BF.getLayout().blocks()) {
    // Create a cluster for this BB.
    uint32_t I = Clusters.size();
    Clusters.emplace_back();
    std::vector<BinaryBasicBlock *> &Cluster = Clusters.back();
    Cluster.push_back(BB);
    BBToClusterMap[BB] = I;
    // Populate priority queue with edges.
    auto BI = BB->branch_info_begin();
    for (const BinaryBasicBlock *I : BB->successors()) {
      assert(BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
             "attempted reordering blocks of function with no profile data");
      Queue.emplace_back(EdgeTy(BB, I, BI->Count));
      ++BI;
    }
  }
  // Sort and adjust the edge queue.
  initQueue(Queue, BF);

  // Grow clusters in a greedy fashion.
  while (!Queue.empty()) {
    EdgeTy E = Queue.back();
    Queue.pop_back();

    const BinaryBasicBlock *SrcBB = E.Src;
    const BinaryBasicBlock *DstBB = E.Dst;

    LLVM_DEBUG(dbgs() << "Popped edge "; E.print(dbgs()); dbgs() << "\n");

    // Case 1: BBSrc and BBDst are the same. Ignore this edge
    if (SrcBB == DstBB || DstBB == *BF.getLayout().block_begin()) {
      LLVM_DEBUG(dbgs() << "\tIgnored (same src, dst)\n");
      continue;
    }

    int I = BBToClusterMap[SrcBB];
    int J = BBToClusterMap[DstBB];

    // Case 2: If they are already allocated at the same cluster, just increase
    // the weight of this cluster
    if (I == J) {
      if (ComputeEdges)
        ClusterEdges[I][I] += E.Count;
      LLVM_DEBUG(dbgs() << "\tIgnored (src, dst belong to the same cluster)\n");
      continue;
    }

    std::vector<BinaryBasicBlock *> &ClusterA = Clusters[I];
    std::vector<BinaryBasicBlock *> &ClusterB = Clusters[J];
    if (areClustersCompatible(ClusterA, ClusterB, E)) {
      // Case 3: SrcBB is at the end of a cluster and DstBB is at the start,
      // allowing us to merge two clusters.
      for (const BinaryBasicBlock *BB : ClusterB)
        BBToClusterMap[BB] = I;
      ClusterA.insert(ClusterA.end(), ClusterB.begin(), ClusterB.end());
      ClusterB.clear();
      if (ComputeEdges) {
        // Increase the intra-cluster edge count of cluster A with the count of
        // this edge as well as with the total count of previously visited edges
        // from cluster B cluster A.
        ClusterEdges[I][I] += E.Count;
        ClusterEdges[I][I] += ClusterEdges[J][I];
        // Iterate through all inter-cluster edges and transfer edges targeting
        // cluster B to cluster A.
        for (uint32_t K = 0, E = ClusterEdges.size(); K != E; ++K)
          ClusterEdges[K][I] += ClusterEdges[K][J];
      }
      // Adjust the weights of the remaining edges and re-sort the queue.
      adjustQueue(Queue, BF);
      LLVM_DEBUG(dbgs() << "\tMerged clusters of src, dst\n");
    } else {
      // Case 4: Both SrcBB and DstBB are allocated in positions we cannot
      // merge them. Add the count of this edge to the inter-cluster edge count
      // between clusters A and B to help us decide ordering between these
      // clusters.
      if (ComputeEdges)
        ClusterEdges[I][J] += E.Count;
      LLVM_DEBUG(
          dbgs() << "\tIgnored (src, dst belong to incompatible clusters)\n");
    }
  }
}

void GreedyClusterAlgorithm::reset() {
  ClusterAlgorithm::reset();
  BBToClusterMap.clear();
}

void PHGreedyClusterAlgorithm::initQueue(std::vector<EdgeTy> &Queue,
                                         const BinaryFunction &BF) {
  // Define a comparison function to establish SWO between edges.
  auto Comp = [&BF](const EdgeTy &A, const EdgeTy &B) {
    // With equal weights, prioritize branches with lower index
    // source/destination. This helps to keep original block order for blocks
    // when optimal order cannot be deducted from a profile.
    if (A.Count == B.Count) {
      const signed SrcOrder = BF.getOriginalLayoutRelativeOrder(A.Src, B.Src);
      return (SrcOrder != 0)
                 ? SrcOrder > 0
                 : BF.getOriginalLayoutRelativeOrder(A.Dst, B.Dst) > 0;
    }
    return A.Count < B.Count;
  };

  // Sort edges in increasing profile count order.
  llvm::sort(Queue, Comp);
}

void PHGreedyClusterAlgorithm::adjustQueue(std::vector<EdgeTy> &Queue,
                                           const BinaryFunction &BF) {
  // Nothing to do.
}

bool PHGreedyClusterAlgorithm::areClustersCompatible(const ClusterTy &Front,
                                                     const ClusterTy &Back,
                                                     const EdgeTy &E) const {
  return Front.back() == E.Src && Back.front() == E.Dst;
}

int64_t MinBranchGreedyClusterAlgorithm::calculateWeight(
    const EdgeTy &E, const BinaryFunction &BF) const {
  const BinaryBasicBlock *SrcBB = E.Src;
  const BinaryBasicBlock *DstBB = E.Dst;

  // Initial weight value.
  int64_t W = (int64_t)E.Count;

  // Adjust the weight by taking into account other edges with the same source.
  auto BI = SrcBB->branch_info_begin();
  for (const BinaryBasicBlock *SuccBB : SrcBB->successors()) {
    assert(BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
           "attempted reordering blocks of function with no profile data");
    assert(BI->Count <= std::numeric_limits<int64_t>::max() &&
           "overflow detected");
    // Ignore edges with same source and destination, edges that target the
    // entry block as well as the edge E itself.
    if (SuccBB != SrcBB && SuccBB != *BF.getLayout().block_begin() &&
        SuccBB != DstBB)
      W -= (int64_t)BI->Count;
    ++BI;
  }

  // Adjust the weight by taking into account other edges with the same
  // destination.
  for (const BinaryBasicBlock *PredBB : DstBB->predecessors()) {
    // Ignore edges with same source and destination as well as the edge E
    // itself.
    if (PredBB == DstBB || PredBB == SrcBB)
      continue;
    auto BI = PredBB->branch_info_begin();
    for (const BinaryBasicBlock *SuccBB : PredBB->successors()) {
      if (SuccBB == DstBB)
        break;
      ++BI;
    }
    assert(BI != PredBB->branch_info_end() && "invalid control flow graph");
    assert(BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
           "attempted reordering blocks of function with no profile data");
    assert(BI->Count <= std::numeric_limits<int64_t>::max() &&
           "overflow detected");
    W -= (int64_t)BI->Count;
  }

  return W;
}

void MinBranchGreedyClusterAlgorithm::initQueue(std::vector<EdgeTy> &Queue,
                                                const BinaryFunction &BF) {
  // Initialize edge weights.
  for (const EdgeTy &E : Queue)
    Weight.emplace(std::make_pair(E, calculateWeight(E, BF)));

  // Sort edges in increasing weight order.
  adjustQueue(Queue, BF);
}

void MinBranchGreedyClusterAlgorithm::adjustQueue(std::vector<EdgeTy> &Queue,
                                                  const BinaryFunction &BF) {
  // Define a comparison function to establish SWO between edges.
  auto Comp = [&](const EdgeTy &A, const EdgeTy &B) {
    // With equal weights, prioritize branches with lower index
    // source/destination. This helps to keep original block order for blocks
    // when optimal order cannot be deduced from a profile.
    if (Weight[A] == Weight[B]) {
      const signed SrcOrder = BF.getOriginalLayoutRelativeOrder(A.Src, B.Src);
      return (SrcOrder != 0)
                 ? SrcOrder > 0
                 : BF.getOriginalLayoutRelativeOrder(A.Dst, B.Dst) > 0;
    }
    return Weight[A] < Weight[B];
  };

  // Iterate through all remaining edges to find edges that have their
  // source and destination in the same cluster.
  std::vector<EdgeTy> NewQueue;
  for (const EdgeTy &E : Queue) {
    const BinaryBasicBlock *SrcBB = E.Src;
    const BinaryBasicBlock *DstBB = E.Dst;

    // Case 1: SrcBB and DstBB are the same or DstBB is the entry block. Ignore
    // this edge.
    if (SrcBB == DstBB || DstBB == *BF.getLayout().block_begin()) {
      LLVM_DEBUG(dbgs() << "\tAdjustment: Ignored edge "; E.print(dbgs());
                 dbgs() << " (same src, dst)\n");
      continue;
    }

    int I = BBToClusterMap[SrcBB];
    int J = BBToClusterMap[DstBB];
    std::vector<BinaryBasicBlock *> &ClusterA = Clusters[I];
    std::vector<BinaryBasicBlock *> &ClusterB = Clusters[J];

    // Case 2: They are already allocated at the same cluster or incompatible
    // clusters. Adjust the weights of edges with the same source or
    // destination, so that this edge has no effect on them any more, and ignore
    // this edge. Also increase the intra- (or inter-) cluster edge count.
    if (I == J || !areClustersCompatible(ClusterA, ClusterB, E)) {
      if (!ClusterEdges.empty())
        ClusterEdges[I][J] += E.Count;
      LLVM_DEBUG(dbgs() << "\tAdjustment: Ignored edge "; E.print(dbgs());
                 dbgs() << " (src, dst belong to same cluster or incompatible "
                           "clusters)\n");
      for (const BinaryBasicBlock *SuccBB : SrcBB->successors()) {
        if (SuccBB == DstBB)
          continue;
        auto WI = Weight.find(EdgeTy(SrcBB, SuccBB, 0));
        assert(WI != Weight.end() && "CFG edge not found in Weight map");
        WI->second += (int64_t)E.Count;
      }
      for (const BinaryBasicBlock *PredBB : DstBB->predecessors()) {
        if (PredBB == SrcBB)
          continue;
        auto WI = Weight.find(EdgeTy(PredBB, DstBB, 0));
        assert(WI != Weight.end() && "CFG edge not found in Weight map");
        WI->second += (int64_t)E.Count;
      }
      continue;
    }

    // Case 3: None of the previous cases is true, so just keep this edge in
    // the queue.
    NewQueue.emplace_back(E);
  }

  // Sort remaining edges in increasing weight order.
  Queue.swap(NewQueue);
  llvm::sort(Queue, Comp);
}

bool MinBranchGreedyClusterAlgorithm::areClustersCompatible(
    const ClusterTy &Front, const ClusterTy &Back, const EdgeTy &E) const {
  return Front.back() == E.Src && Back.front() == E.Dst;
}

void MinBranchGreedyClusterAlgorithm::reset() {
  GreedyClusterAlgorithm::reset();
  Weight.clear();
}

void TSPReorderAlgorithm::reorderBasicBlocks(BinaryFunction &BF,
                                             BasicBlockOrder &Order) const {
  std::vector<std::vector<uint64_t>> Weight;
  std::vector<BinaryBasicBlock *> IndexToBB;

  const size_t N = BF.getLayout().block_size();
  assert(N <= std::numeric_limits<uint64_t>::digits &&
         "cannot use TSP solution for sizes larger than bits in uint64_t");

  // Populating weight map and index map
  for (BinaryBasicBlock *BB : BF.getLayout().blocks()) {
    BB->setLayoutIndex(IndexToBB.size());
    IndexToBB.push_back(BB);
  }
  Weight.resize(N);
  for (const BinaryBasicBlock *BB : BF.getLayout().blocks()) {
    auto BI = BB->branch_info_begin();
    Weight[BB->getLayoutIndex()].resize(N);
    for (BinaryBasicBlock *SuccBB : BB->successors()) {
      if (BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE)
        Weight[BB->getLayoutIndex()][SuccBB->getLayoutIndex()] = BI->Count;
      ++BI;
    }
  }

  std::vector<std::vector<int64_t>> DP;
  DP.resize(static_cast<size_t>(1) << N);
  for (std::vector<int64_t> &Elmt : DP)
    Elmt.resize(N, -1);

  // Start with the entry basic block being allocated with cost zero
  DP[1][0] = 0;
  // Walk through TSP solutions using a bitmask to represent state (current set
  // of BBs in the layout)
  uint64_t BestSet = 1;
  uint64_t BestLast = 0;
  int64_t BestWeight = 0;
  for (uint64_t Set = 1; Set < (1ULL << N); ++Set) {
    // Traverse each possibility of Last BB visited in this layout
    for (uint64_t Last = 0; Last < N; ++Last) {
      // Case 1: There is no possible layout with this BB as Last
      if (DP[Set][Last] == -1)
        continue;

      // Case 2: There is a layout with this Set and this Last, and we try
      // to expand this set with New
      for (uint64_t New = 1; New < N; ++New) {
        // Case 2a: BB "New" is already in this Set
        if ((Set & (1ULL << New)) != 0)
          continue;

        // Case 2b: BB "New" is not in this set and we add it to this Set and
        // record total weight of this layout with "New" as the last BB.
        uint64_t NewSet = (Set | (1ULL << New));
        if (DP[NewSet][New] == -1)
          DP[NewSet][New] = DP[Set][Last] + (int64_t)Weight[Last][New];
        DP[NewSet][New] = std::max(DP[NewSet][New],
                                   DP[Set][Last] + (int64_t)Weight[Last][New]);

        if (DP[NewSet][New] > BestWeight) {
          BestWeight = DP[NewSet][New];
          BestSet = NewSet;
          BestLast = New;
        }
      }
    }
  }

  // Define final function layout based on layout that maximizes weight
  uint64_t Last = BestLast;
  uint64_t Set = BestSet;
  BitVector Visited;
  Visited.resize(N);
  Visited[Last] = true;
  Order.push_back(IndexToBB[Last]);
  Set = Set & ~(1ULL << Last);
  while (Set != 0) {
    int64_t Best = -1;
    uint64_t NewLast;
    for (uint64_t I = 0; I < N; ++I) {
      if (DP[Set][I] == -1)
        continue;
      int64_t AdjWeight = Weight[I][Last] > 0 ? Weight[I][Last] : 0;
      if (DP[Set][I] + AdjWeight > Best) {
        NewLast = I;
        Best = DP[Set][I] + AdjWeight;
      }
    }
    Last = NewLast;
    Visited[Last] = true;
    Order.push_back(IndexToBB[Last]);
    Set = Set & ~(1ULL << Last);
  }
  std::reverse(Order.begin(), Order.end());

  // Finalize layout with BBs that weren't assigned to the layout using the
  // input layout.
  for (BinaryBasicBlock *BB : BF.getLayout().blocks())
    if (Visited[BB->getLayoutIndex()] == false)
      Order.push_back(BB);
}

void ExtTSPReorderAlgorithm::reorderBasicBlocks(BinaryFunction &BF,
                                                BasicBlockOrder &Order) const {
  if (BF.getLayout().block_empty())
    return;

  // Do not change layout of functions w/o profile information
  if (!BF.hasValidProfile() || BF.getLayout().block_size() <= 2) {
    for (BinaryBasicBlock *BB : BF.getLayout().blocks())
      Order.push_back(BB);
    return;
  }

  // Create a separate MCCodeEmitter to allow lock-free execution
  BinaryContext::IndependentCodeEmitter Emitter;
  if (!opts::NoThreads)
    Emitter = BF.getBinaryContext().createIndependentMCCodeEmitter();

  // Initialize CFG nodes and their data
  std::vector<uint64_t> BlockSizes;
  std::vector<uint64_t> BlockCounts;
  BasicBlockOrder OrigOrder;
  BF.getLayout().updateLayoutIndices();
  for (BinaryBasicBlock *BB : BF.getLayout().blocks()) {
    uint64_t Size = std::max<uint64_t>(BB->estimateSize(Emitter.MCE.get()), 1);
    BlockSizes.push_back(Size);
    BlockCounts.push_back(BB->getKnownExecutionCount());
    OrigOrder.push_back(BB);
  }

  // Initialize CFG edges
  std::vector<codelayout::EdgeCount> JumpCounts;
  for (BinaryBasicBlock *BB : BF.getLayout().blocks()) {
    auto BI = BB->branch_info_begin();
    for (BinaryBasicBlock *SuccBB : BB->successors()) {
      assert(BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
             "missing profile for a jump");
      JumpCounts.push_back(
          {BB->getLayoutIndex(), SuccBB->getLayoutIndex(), BI->Count});
      ++BI;
    }
  }

  // Run the layout algorithm
  auto Result =
      codelayout::computeExtTspLayout(BlockSizes, BlockCounts, JumpCounts);
  Order.reserve(BF.getLayout().block_size());
  for (uint64_t R : Result)
    Order.push_back(OrigOrder[R]);
}

void OptimizeReorderAlgorithm::reorderBasicBlocks(
    BinaryFunction &BF, BasicBlockOrder &Order) const {
  if (BF.getLayout().block_empty())
    return;

  // Cluster basic blocks.
  CAlgo->clusterBasicBlocks(BF);

  if (opts::PrintClusters)
    CAlgo->printClusters();

  // Arrange basic blocks according to clusters.
  for (ClusterAlgorithm::ClusterTy &Cluster : CAlgo->Clusters)
    Order.insert(Order.end(), Cluster.begin(), Cluster.end());
}

void OptimizeBranchReorderAlgorithm::reorderBasicBlocks(
    BinaryFunction &BF, BasicBlockOrder &Order) const {
  if (BF.getLayout().block_empty())
    return;

  // Cluster basic blocks.
  CAlgo->clusterBasicBlocks(BF, /* ComputeEdges = */ true);
  std::vector<ClusterAlgorithm::ClusterTy> &Clusters = CAlgo->Clusters;
  std::vector<std::unordered_map<uint32_t, uint64_t>> &ClusterEdges =
      CAlgo->ClusterEdges;

  // Compute clusters' average frequencies.
  CAlgo->computeClusterAverageFrequency(BF.getBinaryContext());
  std::vector<double> &AvgFreq = CAlgo->AvgFreq;

  if (opts::PrintClusters)
    CAlgo->printClusters();

  // Cluster layout order
  std::vector<uint32_t> ClusterOrder;

  // Do a topological sort for clusters, prioritizing frequently-executed BBs
  // during the traversal.
  std::stack<uint32_t> Stack;
  std::vector<uint32_t> Status;
  std::vector<uint32_t> Parent;
  Status.resize(Clusters.size(), 0);
  Parent.resize(Clusters.size(), 0);
  constexpr uint32_t STACKED = 1;
  constexpr uint32_t VISITED = 2;
  Status[0] = STACKED;
  Stack.push(0);
  while (!Stack.empty()) {
    uint32_t I = Stack.top();
    if (!(Status[I] & VISITED)) {
      Status[I] |= VISITED;
      // Order successors by weight
      auto ClusterComp = [&ClusterEdges, I](uint32_t A, uint32_t B) {
        return ClusterEdges[I][A] > ClusterEdges[I][B];
      };
      std::priority_queue<uint32_t, std::vector<uint32_t>,
                          decltype(ClusterComp)>
          SuccQueue(ClusterComp);
      for (std::pair<const uint32_t, uint64_t> &Target : ClusterEdges[I]) {
        if (Target.second > 0 && !(Status[Target.first] & STACKED) &&
            !Clusters[Target.first].empty()) {
          Parent[Target.first] = I;
          Status[Target.first] = STACKED;
          SuccQueue.push(Target.first);
        }
      }
      while (!SuccQueue.empty()) {
        Stack.push(SuccQueue.top());
        SuccQueue.pop();
      }
      continue;
    }
    // Already visited this node
    Stack.pop();
    ClusterOrder.push_back(I);
  }
  std::reverse(ClusterOrder.begin(), ClusterOrder.end());
  // Put unreachable clusters at the end
  for (uint32_t I = 0, E = Clusters.size(); I < E; ++I)
    if (!(Status[I] & VISITED) && !Clusters[I].empty())
      ClusterOrder.push_back(I);

  // Sort nodes with equal precedence
  auto Beg = ClusterOrder.begin();
  // Don't reorder the first cluster, which contains the function entry point
  ++Beg;
  std::stable_sort(Beg, ClusterOrder.end(),
                   [&AvgFreq, &Parent](uint32_t A, uint32_t B) {
                     uint32_t P = Parent[A];
                     while (Parent[P] != 0) {
                       if (Parent[P] == B)
                         return false;
                       P = Parent[P];
                     }
                     P = Parent[B];
                     while (Parent[P] != 0) {
                       if (Parent[P] == A)
                         return true;
                       P = Parent[P];
                     }
                     return AvgFreq[A] > AvgFreq[B];
                   });

  if (opts::PrintClusters) {
    errs() << "New cluster order: ";
    const char *Sep = "";
    for (uint32_t O : ClusterOrder) {
      errs() << Sep << O;
      Sep = ", ";
    }
    errs() << '\n';
  }

  // Arrange basic blocks according to cluster order.
  for (uint32_t ClusterIndex : ClusterOrder) {
    ClusterAlgorithm::ClusterTy &Cluster = Clusters[ClusterIndex];
    Order.insert(Order.end(), Cluster.begin(), Cluster.end());
  }
}

void OptimizeCacheReorderAlgorithm::reorderBasicBlocks(
    BinaryFunction &BF, BasicBlockOrder &Order) const {
  if (BF.getLayout().block_empty())
    return;

  const uint64_t ColdThreshold =
      opts::ColdThreshold *
      (*BF.getLayout().block_begin())->getExecutionCount() / 1000;

  // Cluster basic blocks.
  CAlgo->clusterBasicBlocks(BF);
  std::vector<ClusterAlgorithm::ClusterTy> &Clusters = CAlgo->Clusters;

  // Compute clusters' average frequencies.
  CAlgo->computeClusterAverageFrequency(BF.getBinaryContext());
  std::vector<double> &AvgFreq = CAlgo->AvgFreq;

  if (opts::PrintClusters)
    CAlgo->printClusters();

  // Cluster layout order
  std::vector<uint32_t> ClusterOrder;

  // Order clusters based on average instruction execution frequency
  for (uint32_t I = 0, E = Clusters.size(); I < E; ++I)
    if (!Clusters[I].empty())
      ClusterOrder.push_back(I);
  // Don't reorder the first cluster, which contains the function entry point
  std::stable_sort(
      std::next(ClusterOrder.begin()), ClusterOrder.end(),
      [&AvgFreq](uint32_t A, uint32_t B) { return AvgFreq[A] > AvgFreq[B]; });

  if (opts::PrintClusters) {
    errs() << "New cluster order: ";
    const char *Sep = "";
    for (uint32_t O : ClusterOrder) {
      errs() << Sep << O;
      Sep = ", ";
    }
    errs() << '\n';
  }

  // Arrange basic blocks according to cluster order.
  for (uint32_t ClusterIndex : ClusterOrder) {
    ClusterAlgorithm::ClusterTy &Cluster = Clusters[ClusterIndex];
    Order.insert(Order.end(), Cluster.begin(), Cluster.end());
    // Force zero execution count on clusters that do not meet the cut off
    // specified by --cold-threshold.
    if (AvgFreq[ClusterIndex] < static_cast<double>(ColdThreshold))
      for (BinaryBasicBlock *BBPtr : Cluster)
        BBPtr->setExecutionCount(0);
  }
}

void ReverseReorderAlgorithm::reorderBasicBlocks(BinaryFunction &BF,
                                                 BasicBlockOrder &Order) const {
  if (BF.getLayout().block_empty())
    return;

  BinaryBasicBlock *FirstBB = *BF.getLayout().block_begin();
  Order.push_back(FirstBB);
  for (auto RLI = BF.getLayout().block_rbegin(); *RLI != FirstBB; ++RLI)
    Order.push_back(*RLI);
}

void RandomClusterReorderAlgorithm::reorderBasicBlocks(
    BinaryFunction &BF, BasicBlockOrder &Order) const {
  if (BF.getLayout().block_empty())
    return;

  // Cluster basic blocks.
  CAlgo->clusterBasicBlocks(BF);
  std::vector<ClusterAlgorithm::ClusterTy> &Clusters = CAlgo->Clusters;

  if (opts::PrintClusters)
    CAlgo->printClusters();

  // Cluster layout order
  std::vector<uint32_t> ClusterOrder;

  // Order clusters based on average instruction execution frequency
  for (uint32_t I = 0, E = Clusters.size(); I < E; ++I)
    if (!Clusters[I].empty())
      ClusterOrder.push_back(I);

  std::shuffle(std::next(ClusterOrder.begin()), ClusterOrder.end(),
               std::default_random_engine(opts::RandomSeed.getValue()));

  if (opts::PrintClusters) {
    errs() << "New cluster order: ";
    const char *Sep = "";
    for (uint32_t O : ClusterOrder) {
      errs() << Sep << O;
      Sep = ", ";
    }
    errs() << '\n';
  }

  // Arrange basic blocks according to cluster order.
  for (uint32_t ClusterIndex : ClusterOrder) {
    ClusterAlgorithm::ClusterTy &Cluster = Clusters[ClusterIndex];
    Order.insert(Order.end(), Cluster.begin(), Cluster.end());
  }
}
