//===- CodeLayout.cpp - Implementation of code layout algorithms ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// ExtTSP - layout of basic blocks with i-cache optimization.
//
// The algorithm tries to find a layout of nodes (basic blocks) of a given CFG
// optimizing jump locality and thus processor I-cache utilization. This is
// achieved via increasing the number of fall-through jumps and co-locating
// frequently executed nodes together. The name follows the underlying
// optimization problem, Extended-TSP, which is a generalization of classical
// (maximum) Traveling Salesmen Problem.
//
// The algorithm is a greedy heuristic that works with chains (ordered lists)
// of basic blocks. Initially all chains are isolated basic blocks. On every
// iteration, we pick a pair of chains whose merging yields the biggest increase
// in the ExtTSP score, which models how i-cache "friendly" a specific chain is.
// A pair of chains giving the maximum gain is merged into a new chain. The
// procedure stops when there is only one chain left, or when merging does not
// increase ExtTSP. In the latter case, the remaining chains are sorted by
// density in the decreasing order.
//
// An important aspect is the way two chains are merged. Unlike earlier
// algorithms (e.g., based on the approach of Pettis-Hansen), two
// chains, X and Y, are first split into three, X1, X2, and Y. Then we
// consider all possible ways of gluing the three chains (e.g., X1YX2, X1X2Y,
// X2X1Y, X2YX1, YX1X2, YX2X1) and choose the one producing the largest score.
// This improves the quality of the final result (the search space is larger)
// while keeping the implementation sufficiently fast.
//
// Reference:
//   * A. Newell and S. Pupyrev, Improved Basic Block Reordering,
//     IEEE Transactions on Computers, 2020
//     https://arxiv.org/abs/1809.04676
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/CodeLayout.h"
#include "llvm/Support/CommandLine.h"

#include <cmath>

using namespace llvm;
#define DEBUG_TYPE "code-layout"

namespace llvm {
cl::opt<bool> EnableExtTspBlockPlacement(
    "enable-ext-tsp-block-placement", cl::Hidden, cl::init(false),
    cl::desc("Enable machine block placement based on the ext-tsp model, "
             "optimizing I-cache utilization."));

cl::opt<bool> ApplyExtTspWithoutProfile(
    "ext-tsp-apply-without-profile",
    cl::desc("Whether to apply ext-tsp placement for instances w/o profile"),
    cl::init(true), cl::Hidden);
} // namespace llvm

// Algorithm-specific params. The values are tuned for the best performance
// of large-scale front-end bound binaries.
static cl::opt<double> ForwardWeightCond(
    "ext-tsp-forward-weight-cond", cl::ReallyHidden, cl::init(0.1),
    cl::desc("The weight of conditional forward jumps for ExtTSP value"));

static cl::opt<double> ForwardWeightUncond(
    "ext-tsp-forward-weight-uncond", cl::ReallyHidden, cl::init(0.1),
    cl::desc("The weight of unconditional forward jumps for ExtTSP value"));

static cl::opt<double> BackwardWeightCond(
    "ext-tsp-backward-weight-cond", cl::ReallyHidden, cl::init(0.1),
    cl::desc("The weight of conditonal backward jumps for ExtTSP value"));

static cl::opt<double> BackwardWeightUncond(
    "ext-tsp-backward-weight-uncond", cl::ReallyHidden, cl::init(0.1),
    cl::desc("The weight of unconditonal backward jumps for ExtTSP value"));

static cl::opt<double> FallthroughWeightCond(
    "ext-tsp-fallthrough-weight-cond", cl::ReallyHidden, cl::init(1.0),
    cl::desc("The weight of conditional fallthrough jumps for ExtTSP value"));

static cl::opt<double> FallthroughWeightUncond(
    "ext-tsp-fallthrough-weight-uncond", cl::ReallyHidden, cl::init(1.05),
    cl::desc("The weight of unconditional fallthrough jumps for ExtTSP value"));

static cl::opt<unsigned> ForwardDistance(
    "ext-tsp-forward-distance", cl::ReallyHidden, cl::init(1024),
    cl::desc("The maximum distance (in bytes) of a forward jump for ExtTSP"));

static cl::opt<unsigned> BackwardDistance(
    "ext-tsp-backward-distance", cl::ReallyHidden, cl::init(640),
    cl::desc("The maximum distance (in bytes) of a backward jump for ExtTSP"));

// The maximum size of a chain created by the algorithm. The size is bounded
// so that the algorithm can efficiently process extremely large instance.
static cl::opt<unsigned>
    MaxChainSize("ext-tsp-max-chain-size", cl::ReallyHidden, cl::init(4096),
                 cl::desc("The maximum size of a chain to create."));

// The maximum size of a chain for splitting. Larger values of the threshold
// may yield better quality at the cost of worsen run-time.
static cl::opt<unsigned> ChainSplitThreshold(
    "ext-tsp-chain-split-threshold", cl::ReallyHidden, cl::init(128),
    cl::desc("The maximum size of a chain to apply splitting"));

// The option enables splitting (large) chains along in-coming and out-going
// jumps. This typically results in a better quality.
static cl::opt<bool> EnableChainSplitAlongJumps(
    "ext-tsp-enable-chain-split-along-jumps", cl::ReallyHidden, cl::init(true),
    cl::desc("The maximum size of a chain to apply splitting"));

namespace {

// Epsilon for comparison of doubles.
constexpr double EPS = 1e-8;

// Compute the Ext-TSP score for a given jump.
double jumpExtTSPScore(uint64_t JumpDist, uint64_t JumpMaxDist, uint64_t Count,
                       double Weight) {
  if (JumpDist > JumpMaxDist)
    return 0;
  double Prob = 1.0 - static_cast<double>(JumpDist) / JumpMaxDist;
  return Weight * Prob * Count;
}

// Compute the Ext-TSP score for a jump between a given pair of blocks,
// using their sizes, (estimated) addresses and the jump execution count.
double extTSPScore(uint64_t SrcAddr, uint64_t SrcSize, uint64_t DstAddr,
                   uint64_t Count, bool IsConditional) {
  // Fallthrough
  if (SrcAddr + SrcSize == DstAddr) {
    return jumpExtTSPScore(0, 1, Count,
                           IsConditional ? FallthroughWeightCond
                                         : FallthroughWeightUncond);
  }
  // Forward
  if (SrcAddr + SrcSize < DstAddr) {
    const uint64_t Dist = DstAddr - (SrcAddr + SrcSize);
    return jumpExtTSPScore(Dist, ForwardDistance, Count,
                           IsConditional ? ForwardWeightCond
                                         : ForwardWeightUncond);
  }
  // Backward
  const uint64_t Dist = SrcAddr + SrcSize - DstAddr;
  return jumpExtTSPScore(Dist, BackwardDistance, Count,
                         IsConditional ? BackwardWeightCond
                                       : BackwardWeightUncond);
}

/// A type of merging two chains, X and Y. The former chain is split into
/// X1 and X2 and then concatenated with Y in the order specified by the type.
enum class MergeTypeTy : int { X_Y, X1_Y_X2, Y_X2_X1, X2_X1_Y };

/// The gain of merging two chains, that is, the Ext-TSP score of the merge
/// together with the corresponfiding merge 'type' and 'offset'.
class MergeGainTy {
public:
  explicit MergeGainTy() = default;
  explicit MergeGainTy(double Score, size_t MergeOffset, MergeTypeTy MergeType)
      : Score(Score), MergeOffset(MergeOffset), MergeType(MergeType) {}

  double score() const { return Score; }

  size_t mergeOffset() const { return MergeOffset; }

  MergeTypeTy mergeType() const { return MergeType; }

  // Returns 'true' iff Other is preferred over this.
  bool operator<(const MergeGainTy &Other) const {
    return (Other.Score > EPS && Other.Score > Score + EPS);
  }

  // Update the current gain if Other is preferred over this.
  void updateIfLessThan(const MergeGainTy &Other) {
    if (*this < Other)
      *this = Other;
  }

private:
  double Score{-1.0};
  size_t MergeOffset{0};
  MergeTypeTy MergeType{MergeTypeTy::X_Y};
};

class Jump;
class Chain;
class ChainEdge;

/// A node in the graph, typically corresponding to a basic block in CFG.
class Block {
public:
  Block(const Block &) = delete;
  Block(Block &&) = default;
  Block &operator=(const Block &) = delete;
  Block &operator=(Block &&) = default;

  // The original index of the block in CFG.
  size_t Index{0};
  // The index of the block in the current chain.
  size_t CurIndex{0};
  // Size of the block in the binary.
  uint64_t Size{0};
  // Execution count of the block in the profile data.
  uint64_t ExecutionCount{0};
  // Current chain of the node.
  Chain *CurChain{nullptr};
  // An offset of the block in the current chain.
  mutable uint64_t EstimatedAddr{0};
  // Forced successor of the block in CFG.
  Block *ForcedSucc{nullptr};
  // Forced predecessor of the block in CFG.
  Block *ForcedPred{nullptr};
  // Outgoing jumps from the block.
  std::vector<Jump *> OutJumps;
  // Incoming jumps to the block.
  std::vector<Jump *> InJumps;

public:
  explicit Block(size_t Index, uint64_t Size, uint64_t EC)
      : Index(Index), Size(Size), ExecutionCount(EC) {}
  bool isEntry() const { return Index == 0; }
};

/// An arc in the graph, typically corresponding to a jump between two blocks.
class Jump {
public:
  Jump(const Jump &) = delete;
  Jump(Jump &&) = default;
  Jump &operator=(const Jump &) = delete;
  Jump &operator=(Jump &&) = default;

  // Source block of the jump.
  Block *Source;
  // Target block of the jump.
  Block *Target;
  // Execution count of the arc in the profile data.
  uint64_t ExecutionCount{0};
  // Whether the jump corresponds to a conditional branch.
  bool IsConditional{false};

public:
  explicit Jump(Block *Source, Block *Target, uint64_t ExecutionCount)
      : Source(Source), Target(Target), ExecutionCount(ExecutionCount) {}
};

/// A chain (ordered sequence) of blocks.
class Chain {
public:
  Chain(const Chain &) = delete;
  Chain(Chain &&) = default;
  Chain &operator=(const Chain &) = delete;
  Chain &operator=(Chain &&) = default;

  explicit Chain(uint64_t Id, Block *Block)
      : Id(Id), Score(0), Blocks(1, Block) {}

  uint64_t id() const { return Id; }

  bool isEntry() const { return Blocks[0]->Index == 0; }

  bool isCold() const {
    for (auto *Block : Blocks) {
      if (Block->ExecutionCount > 0)
        return false;
    }
    return true;
  }

  double score() const { return Score; }

  void setScore(double NewScore) { Score = NewScore; }

  const std::vector<Block *> &blocks() const { return Blocks; }

  size_t numBlocks() const { return Blocks.size(); }

  const std::vector<std::pair<Chain *, ChainEdge *>> &edges() const {
    return Edges;
  }

  ChainEdge *getEdge(Chain *Other) const {
    for (auto It : Edges) {
      if (It.first == Other)
        return It.second;
    }
    return nullptr;
  }

  void removeEdge(Chain *Other) {
    auto It = Edges.begin();
    while (It != Edges.end()) {
      if (It->first == Other) {
        Edges.erase(It);
        return;
      }
      It++;
    }
  }

  void addEdge(Chain *Other, ChainEdge *Edge) {
    Edges.push_back(std::make_pair(Other, Edge));
  }

  void merge(Chain *Other, const std::vector<Block *> &MergedBlocks) {
    Blocks = MergedBlocks;
    // Update the block's chains
    for (size_t Idx = 0; Idx < Blocks.size(); Idx++) {
      Blocks[Idx]->CurChain = this;
      Blocks[Idx]->CurIndex = Idx;
    }
  }

  void mergeEdges(Chain *Other);

  void clear() {
    Blocks.clear();
    Blocks.shrink_to_fit();
    Edges.clear();
    Edges.shrink_to_fit();
  }

private:
  // Unique chain identifier.
  uint64_t Id;
  // Cached ext-tsp score for the chain.
  double Score;
  // Blocks of the chain.
  std::vector<Block *> Blocks;
  // Adjacent chains and corresponding edges (lists of jumps).
  std::vector<std::pair<Chain *, ChainEdge *>> Edges;
};

/// An edge in CFG representing jumps between two chains.
/// When blocks are merged into chains, the edges are combined too so that
/// there is always at most one edge between a pair of chains
class ChainEdge {
public:
  ChainEdge(const ChainEdge &) = delete;
  ChainEdge(ChainEdge &&) = default;
  ChainEdge &operator=(const ChainEdge &) = delete;
  ChainEdge &operator=(ChainEdge &&) = default;

  explicit ChainEdge(Jump *Jump)
      : SrcChain(Jump->Source->CurChain), DstChain(Jump->Target->CurChain),
        Jumps(1, Jump) {}

  const std::vector<Jump *> &jumps() const { return Jumps; }

  void changeEndpoint(Chain *From, Chain *To) {
    if (From == SrcChain)
      SrcChain = To;
    if (From == DstChain)
      DstChain = To;
  }

  void appendJump(Jump *Jump) { Jumps.push_back(Jump); }

  void moveJumps(ChainEdge *Other) {
    Jumps.insert(Jumps.end(), Other->Jumps.begin(), Other->Jumps.end());
    Other->Jumps.clear();
    Other->Jumps.shrink_to_fit();
  }

  bool hasCachedMergeGain(Chain *Src, Chain *Dst) const {
    return Src == SrcChain ? CacheValidForward : CacheValidBackward;
  }

  MergeGainTy getCachedMergeGain(Chain *Src, Chain *Dst) const {
    return Src == SrcChain ? CachedGainForward : CachedGainBackward;
  }

  void setCachedMergeGain(Chain *Src, Chain *Dst, MergeGainTy MergeGain) {
    if (Src == SrcChain) {
      CachedGainForward = MergeGain;
      CacheValidForward = true;
    } else {
      CachedGainBackward = MergeGain;
      CacheValidBackward = true;
    }
  }

  void invalidateCache() {
    CacheValidForward = false;
    CacheValidBackward = false;
  }

private:
  // Source chain.
  Chain *SrcChain{nullptr};
  // Destination chain.
  Chain *DstChain{nullptr};
  // Original jumps in the binary with correspinding execution counts.
  std::vector<Jump *> Jumps;
  // Cached ext-tsp value for merging the pair of chains.
  // Since the gain of merging (Src, Dst) and (Dst, Src) might be different,
  // we store both values here.
  MergeGainTy CachedGainForward;
  MergeGainTy CachedGainBackward;
  // Whether the cached value must be recomputed.
  bool CacheValidForward{false};
  bool CacheValidBackward{false};
};

void Chain::mergeEdges(Chain *Other) {
  assert(this != Other && "cannot merge a chain with itself");

  // Update edges adjacent to chain Other
  for (auto EdgeIt : Other->Edges) {
    Chain *DstChain = EdgeIt.first;
    ChainEdge *DstEdge = EdgeIt.second;
    Chain *TargetChain = DstChain == Other ? this : DstChain;
    ChainEdge *CurEdge = getEdge(TargetChain);
    if (CurEdge == nullptr) {
      DstEdge->changeEndpoint(Other, this);
      this->addEdge(TargetChain, DstEdge);
      if (DstChain != this && DstChain != Other) {
        DstChain->addEdge(this, DstEdge);
      }
    } else {
      CurEdge->moveJumps(DstEdge);
    }
    // Cleanup leftover edge
    if (DstChain != Other) {
      DstChain->removeEdge(Other);
    }
  }
}

using BlockIter = std::vector<Block *>::const_iterator;

/// A wrapper around three chains of blocks; it is used to avoid extra
/// instantiation of the vectors.
class MergedChain {
public:
  MergedChain(BlockIter Begin1, BlockIter End1, BlockIter Begin2 = BlockIter(),
              BlockIter End2 = BlockIter(), BlockIter Begin3 = BlockIter(),
              BlockIter End3 = BlockIter())
      : Begin1(Begin1), End1(End1), Begin2(Begin2), End2(End2), Begin3(Begin3),
        End3(End3) {}

  template <typename F> void forEach(const F &Func) const {
    for (auto It = Begin1; It != End1; It++)
      Func(*It);
    for (auto It = Begin2; It != End2; It++)
      Func(*It);
    for (auto It = Begin3; It != End3; It++)
      Func(*It);
  }

  std::vector<Block *> getBlocks() const {
    std::vector<Block *> Result;
    Result.reserve(std::distance(Begin1, End1) + std::distance(Begin2, End2) +
                   std::distance(Begin3, End3));
    Result.insert(Result.end(), Begin1, End1);
    Result.insert(Result.end(), Begin2, End2);
    Result.insert(Result.end(), Begin3, End3);
    return Result;
  }

  const Block *getFirstBlock() const { return *Begin1; }

private:
  BlockIter Begin1;
  BlockIter End1;
  BlockIter Begin2;
  BlockIter End2;
  BlockIter Begin3;
  BlockIter End3;
};

/// The implementation of the ExtTSP algorithm.
class ExtTSPImpl {
  using EdgeT = std::pair<uint64_t, uint64_t>;
  using EdgeCountMap = std::vector<std::pair<EdgeT, uint64_t>>;

public:
  ExtTSPImpl(size_t NumNodes, const std::vector<uint64_t> &NodeSizes,
             const std::vector<uint64_t> &NodeCounts,
             const EdgeCountMap &EdgeCounts)
      : NumNodes(NumNodes) {
    initialize(NodeSizes, NodeCounts, EdgeCounts);
  }

  /// Run the algorithm and return an optimized ordering of blocks.
  void run(std::vector<uint64_t> &Result) {
    // Pass 1: Merge blocks with their mutually forced successors
    mergeForcedPairs();

    // Pass 2: Merge pairs of chains while improving the ExtTSP objective
    mergeChainPairs();

    // Pass 3: Merge cold blocks to reduce code size
    mergeColdChains();

    // Collect blocks from all chains
    concatChains(Result);
  }

private:
  /// Initialize the algorithm's data structures.
  void initialize(const std::vector<uint64_t> &NodeSizes,
                  const std::vector<uint64_t> &NodeCounts,
                  const EdgeCountMap &EdgeCounts) {
    // Initialize blocks
    AllBlocks.reserve(NumNodes);
    for (uint64_t Node = 0; Node < NumNodes; Node++) {
      uint64_t Size = std::max<uint64_t>(NodeSizes[Node], 1ULL);
      uint64_t ExecutionCount = NodeCounts[Node];
      // The execution count of the entry block is set to at least 1
      if (Node == 0 && ExecutionCount == 0)
        ExecutionCount = 1;
      AllBlocks.emplace_back(Node, Size, ExecutionCount);
    }

    // Initialize jumps between blocks
    SuccNodes.resize(NumNodes);
    PredNodes.resize(NumNodes);
    std::vector<uint64_t> OutDegree(NumNodes, 0);
    AllJumps.reserve(EdgeCounts.size());
    for (auto It : EdgeCounts) {
      auto Pred = It.first.first;
      auto Succ = It.first.second;
      OutDegree[Pred]++;
      // Ignore self-edges
      if (Pred == Succ)
        continue;

      SuccNodes[Pred].push_back(Succ);
      PredNodes[Succ].push_back(Pred);
      auto ExecutionCount = It.second;
      if (ExecutionCount > 0) {
        auto &Block = AllBlocks[Pred];
        auto &SuccBlock = AllBlocks[Succ];
        AllJumps.emplace_back(&Block, &SuccBlock, ExecutionCount);
        SuccBlock.InJumps.push_back(&AllJumps.back());
        Block.OutJumps.push_back(&AllJumps.back());
      }
    }
    for (auto &Jump : AllJumps) {
      assert(OutDegree[Jump.Source->Index] > 0);
      Jump.IsConditional = OutDegree[Jump.Source->Index] > 1;
    }

    // Initialize chains
    AllChains.reserve(NumNodes);
    HotChains.reserve(NumNodes);
    for (Block &Block : AllBlocks) {
      AllChains.emplace_back(Block.Index, &Block);
      Block.CurChain = &AllChains.back();
      if (Block.ExecutionCount > 0) {
        HotChains.push_back(&AllChains.back());
      }
    }

    // Initialize chain edges
    AllEdges.reserve(AllJumps.size());
    for (Block &Block : AllBlocks) {
      for (auto &Jump : Block.OutJumps) {
        auto SuccBlock = Jump->Target;
        ChainEdge *CurEdge = Block.CurChain->getEdge(SuccBlock->CurChain);
        // this edge is already present in the graph
        if (CurEdge != nullptr) {
          assert(SuccBlock->CurChain->getEdge(Block.CurChain) != nullptr);
          CurEdge->appendJump(Jump);
          continue;
        }
        // this is a new edge
        AllEdges.emplace_back(Jump);
        Block.CurChain->addEdge(SuccBlock->CurChain, &AllEdges.back());
        SuccBlock->CurChain->addEdge(Block.CurChain, &AllEdges.back());
      }
    }
  }

  /// For a pair of blocks, A and B, block B is the forced successor of A,
  /// if (i) all jumps (based on profile) from A goes to B and (ii) all jumps
  /// to B are from A. Such blocks should be adjacent in the optimal ordering;
  /// the method finds and merges such pairs of blocks.
  void mergeForcedPairs() {
    // Find fallthroughs based on edge weights
    for (auto &Block : AllBlocks) {
      if (SuccNodes[Block.Index].size() == 1 &&
          PredNodes[SuccNodes[Block.Index][0]].size() == 1 &&
          SuccNodes[Block.Index][0] != 0) {
        size_t SuccIndex = SuccNodes[Block.Index][0];
        Block.ForcedSucc = &AllBlocks[SuccIndex];
        AllBlocks[SuccIndex].ForcedPred = &Block;
      }
    }

    // There might be 'cycles' in the forced dependencies, since profile
    // data isn't 100% accurate. Typically this is observed in loops, when the
    // loop edges are the hottest successors for the basic blocks of the loop.
    // Break the cycles by choosing the block with the smallest index as the
    // head. This helps to keep the original order of the loops, which likely
    // have already been rotated in the optimized manner.
    for (auto &Block : AllBlocks) {
      if (Block.ForcedSucc == nullptr || Block.ForcedPred == nullptr)
        continue;

      auto SuccBlock = Block.ForcedSucc;
      while (SuccBlock != nullptr && SuccBlock != &Block) {
        SuccBlock = SuccBlock->ForcedSucc;
      }
      if (SuccBlock == nullptr)
        continue;
      // Break the cycle
      AllBlocks[Block.ForcedPred->Index].ForcedSucc = nullptr;
      Block.ForcedPred = nullptr;
    }

    // Merge blocks with their fallthrough successors
    for (auto &Block : AllBlocks) {
      if (Block.ForcedPred == nullptr && Block.ForcedSucc != nullptr) {
        auto CurBlock = &Block;
        while (CurBlock->ForcedSucc != nullptr) {
          const auto NextBlock = CurBlock->ForcedSucc;
          mergeChains(Block.CurChain, NextBlock->CurChain, 0, MergeTypeTy::X_Y);
          CurBlock = NextBlock;
        }
      }
    }
  }

  /// Merge pairs of chains while improving the ExtTSP objective.
  void mergeChainPairs() {
    /// Deterministically compare pairs of chains
    auto compareChainPairs = [](const Chain *A1, const Chain *B1,
                                const Chain *A2, const Chain *B2) {
      if (A1 != A2)
        return A1->id() < A2->id();
      return B1->id() < B2->id();
    };

    while (HotChains.size() > 1) {
      Chain *BestChainPred = nullptr;
      Chain *BestChainSucc = nullptr;
      auto BestGain = MergeGainTy();
      // Iterate over all pairs of chains
      for (Chain *ChainPred : HotChains) {
        // Get candidates for merging with the current chain
        for (auto EdgeIter : ChainPred->edges()) {
          Chain *ChainSucc = EdgeIter.first;
          class ChainEdge *ChainEdge = EdgeIter.second;
          // Ignore loop edges
          if (ChainPred == ChainSucc)
            continue;

          // Stop early if the combined chain violates the maximum allowed size
          if (ChainPred->numBlocks() + ChainSucc->numBlocks() >= MaxChainSize)
            continue;

          // Compute the gain of merging the two chains
          MergeGainTy CurGain =
              getBestMergeGain(ChainPred, ChainSucc, ChainEdge);
          if (CurGain.score() <= EPS)
            continue;

          if (BestGain < CurGain ||
              (std::abs(CurGain.score() - BestGain.score()) < EPS &&
               compareChainPairs(ChainPred, ChainSucc, BestChainPred,
                                 BestChainSucc))) {
            BestGain = CurGain;
            BestChainPred = ChainPred;
            BestChainSucc = ChainSucc;
          }
        }
      }

      // Stop merging when there is no improvement
      if (BestGain.score() <= EPS)
        break;

      // Merge the best pair of chains
      mergeChains(BestChainPred, BestChainSucc, BestGain.mergeOffset(),
                  BestGain.mergeType());
    }
  }

  /// Merge remaining blocks into chains w/o taking jump counts into
  /// consideration. This allows to maintain the original block order in the
  /// absense of profile data
  void mergeColdChains() {
    for (size_t SrcBB = 0; SrcBB < NumNodes; SrcBB++) {
      // Iterating in reverse order to make sure original fallthrough jumps are
      // merged first; this might be beneficial for code size.
      size_t NumSuccs = SuccNodes[SrcBB].size();
      for (size_t Idx = 0; Idx < NumSuccs; Idx++) {
        auto DstBB = SuccNodes[SrcBB][NumSuccs - Idx - 1];
        auto SrcChain = AllBlocks[SrcBB].CurChain;
        auto DstChain = AllBlocks[DstBB].CurChain;
        if (SrcChain != DstChain && !DstChain->isEntry() &&
            SrcChain->blocks().back()->Index == SrcBB &&
            DstChain->blocks().front()->Index == DstBB &&
            SrcChain->isCold() == DstChain->isCold()) {
          mergeChains(SrcChain, DstChain, 0, MergeTypeTy::X_Y);
        }
      }
    }
  }

  /// Compute the Ext-TSP score for a given block order and a list of jumps.
  double extTSPScore(const MergedChain &MergedBlocks,
                     const std::vector<Jump *> &Jumps) const {
    if (Jumps.empty())
      return 0.0;
    uint64_t CurAddr = 0;
    MergedBlocks.forEach([&](const Block *BB) {
      BB->EstimatedAddr = CurAddr;
      CurAddr += BB->Size;
    });

    double Score = 0;
    for (auto &Jump : Jumps) {
      const Block *SrcBlock = Jump->Source;
      const Block *DstBlock = Jump->Target;
      Score += ::extTSPScore(SrcBlock->EstimatedAddr, SrcBlock->Size,
                             DstBlock->EstimatedAddr, Jump->ExecutionCount,
                             Jump->IsConditional);
    }
    return Score;
  }

  /// Compute the gain of merging two chains.
  ///
  /// The function considers all possible ways of merging two chains and
  /// computes the one having the largest increase in ExtTSP objective. The
  /// result is a pair with the first element being the gain and the second
  /// element being the corresponding merging type.
  MergeGainTy getBestMergeGain(Chain *ChainPred, Chain *ChainSucc,
                               ChainEdge *Edge) const {
    if (Edge->hasCachedMergeGain(ChainPred, ChainSucc)) {
      return Edge->getCachedMergeGain(ChainPred, ChainSucc);
    }

    // Precompute jumps between ChainPred and ChainSucc
    auto Jumps = Edge->jumps();
    ChainEdge *EdgePP = ChainPred->getEdge(ChainPred);
    if (EdgePP != nullptr) {
      Jumps.insert(Jumps.end(), EdgePP->jumps().begin(), EdgePP->jumps().end());
    }
    assert(!Jumps.empty() && "trying to merge chains w/o jumps");

    // The object holds the best currently chosen gain of merging the two chains
    MergeGainTy Gain = MergeGainTy();

    /// Given a merge offset and a list of merge types, try to merge two chains
    /// and update Gain with a better alternative
    auto tryChainMerging = [&](size_t Offset,
                               const std::vector<MergeTypeTy> &MergeTypes) {
      // Skip merging corresponding to concatenation w/o splitting
      if (Offset == 0 || Offset == ChainPred->blocks().size())
        return;
      // Skip merging if it breaks Forced successors
      auto BB = ChainPred->blocks()[Offset - 1];
      if (BB->ForcedSucc != nullptr)
        return;
      // Apply the merge, compute the corresponding gain, and update the best
      // value, if the merge is beneficial
      for (const auto &MergeType : MergeTypes) {
        Gain.updateIfLessThan(
            computeMergeGain(ChainPred, ChainSucc, Jumps, Offset, MergeType));
      }
    };

    // Try to concatenate two chains w/o splitting
    Gain.updateIfLessThan(
        computeMergeGain(ChainPred, ChainSucc, Jumps, 0, MergeTypeTy::X_Y));

    if (EnableChainSplitAlongJumps) {
      // Attach (a part of) ChainPred before the first block of ChainSucc
      for (auto &Jump : ChainSucc->blocks().front()->InJumps) {
        const auto SrcBlock = Jump->Source;
        if (SrcBlock->CurChain != ChainPred)
          continue;
        size_t Offset = SrcBlock->CurIndex + 1;
        tryChainMerging(Offset, {MergeTypeTy::X1_Y_X2, MergeTypeTy::X2_X1_Y});
      }

      // Attach (a part of) ChainPred after the last block of ChainSucc
      for (auto &Jump : ChainSucc->blocks().back()->OutJumps) {
        const auto DstBlock = Jump->Source;
        if (DstBlock->CurChain != ChainPred)
          continue;
        size_t Offset = DstBlock->CurIndex;
        tryChainMerging(Offset, {MergeTypeTy::X1_Y_X2, MergeTypeTy::Y_X2_X1});
      }
    }

    // Try to break ChainPred in various ways and concatenate with ChainSucc
    if (ChainPred->blocks().size() <= ChainSplitThreshold) {
      for (size_t Offset = 1; Offset < ChainPred->blocks().size(); Offset++) {
        // Try to split the chain in different ways. In practice, applying
        // X2_Y_X1 merging is almost never provides benefits; thus, we exclude
        // it from consideration to reduce the search space
        tryChainMerging(Offset, {MergeTypeTy::X1_Y_X2, MergeTypeTy::Y_X2_X1,
                                 MergeTypeTy::X2_X1_Y});
      }
    }
    Edge->setCachedMergeGain(ChainPred, ChainSucc, Gain);
    return Gain;
  }

  /// Compute the score gain of merging two chains, respecting a given
  /// merge 'type' and 'offset'.
  ///
  /// The two chains are not modified in the method.
  MergeGainTy computeMergeGain(const Chain *ChainPred, const Chain *ChainSucc,
                               const std::vector<Jump *> &Jumps,
                               size_t MergeOffset,
                               MergeTypeTy MergeType) const {
    auto MergedBlocks = mergeBlocks(ChainPred->blocks(), ChainSucc->blocks(),
                                    MergeOffset, MergeType);

    // Do not allow a merge that does not preserve the original entry block
    if ((ChainPred->isEntry() || ChainSucc->isEntry()) &&
        !MergedBlocks.getFirstBlock()->isEntry())
      return MergeGainTy();

    // The gain for the new chain
    auto NewGainScore = extTSPScore(MergedBlocks, Jumps) - ChainPred->score();
    return MergeGainTy(NewGainScore, MergeOffset, MergeType);
  }

  /// Merge two chains of blocks respecting a given merge 'type' and 'offset'.
  ///
  /// If MergeType == 0, then the result is a concatenation of two chains.
  /// Otherwise, the first chain is cut into two sub-chains at the offset,
  /// and merged using all possible ways of concatenating three chains.
  MergedChain mergeBlocks(const std::vector<Block *> &X,
                          const std::vector<Block *> &Y, size_t MergeOffset,
                          MergeTypeTy MergeType) const {
    // Split the first chain, X, into X1 and X2
    BlockIter BeginX1 = X.begin();
    BlockIter EndX1 = X.begin() + MergeOffset;
    BlockIter BeginX2 = X.begin() + MergeOffset;
    BlockIter EndX2 = X.end();
    BlockIter BeginY = Y.begin();
    BlockIter EndY = Y.end();

    // Construct a new chain from the three existing ones
    switch (MergeType) {
    case MergeTypeTy::X_Y:
      return MergedChain(BeginX1, EndX2, BeginY, EndY);
    case MergeTypeTy::X1_Y_X2:
      return MergedChain(BeginX1, EndX1, BeginY, EndY, BeginX2, EndX2);
    case MergeTypeTy::Y_X2_X1:
      return MergedChain(BeginY, EndY, BeginX2, EndX2, BeginX1, EndX1);
    case MergeTypeTy::X2_X1_Y:
      return MergedChain(BeginX2, EndX2, BeginX1, EndX1, BeginY, EndY);
    }
    llvm_unreachable("unexpected chain merge type");
  }

  /// Merge chain From into chain Into, update the list of active chains,
  /// adjacency information, and the corresponding cached values.
  void mergeChains(Chain *Into, Chain *From, size_t MergeOffset,
                   MergeTypeTy MergeType) {
    assert(Into != From && "a chain cannot be merged with itself");

    // Merge the blocks
    MergedChain MergedBlocks =
        mergeBlocks(Into->blocks(), From->blocks(), MergeOffset, MergeType);
    Into->merge(From, MergedBlocks.getBlocks());
    Into->mergeEdges(From);
    From->clear();

    // Update cached ext-tsp score for the new chain
    ChainEdge *SelfEdge = Into->getEdge(Into);
    if (SelfEdge != nullptr) {
      MergedBlocks = MergedChain(Into->blocks().begin(), Into->blocks().end());
      Into->setScore(extTSPScore(MergedBlocks, SelfEdge->jumps()));
    }

    // Remove chain From from the list of active chains
    llvm::erase_value(HotChains, From);

    // Invalidate caches
    for (auto EdgeIter : Into->edges()) {
      EdgeIter.second->invalidateCache();
    }
  }

  /// Concatenate all chains into a final order of blocks.
  void concatChains(std::vector<uint64_t> &Order) {
    // Collect chains and calculate some stats for their sorting
    std::vector<Chain *> SortedChains;
    DenseMap<const Chain *, double> ChainDensity;
    for (auto &Chain : AllChains) {
      if (!Chain.blocks().empty()) {
        SortedChains.push_back(&Chain);
        // Using doubles to avoid overflow of ExecutionCount
        double Size = 0;
        double ExecutionCount = 0;
        for (auto *Block : Chain.blocks()) {
          Size += static_cast<double>(Block->Size);
          ExecutionCount += static_cast<double>(Block->ExecutionCount);
        }
        assert(Size > 0 && "a chain of zero size");
        ChainDensity[&Chain] = ExecutionCount / Size;
      }
    }

    // Sorting chains by density in the decreasing order
    std::stable_sort(SortedChains.begin(), SortedChains.end(),
                     [&](const Chain *C1, const Chain *C2) {
                       // Make sure the original entry block is at the
                       // beginning of the order
                       if (C1->isEntry() != C2->isEntry()) {
                         return C1->isEntry();
                       }

                       const double D1 = ChainDensity[C1];
                       const double D2 = ChainDensity[C2];
                       // Compare by density and break ties by chain identifiers
                       return (D1 != D2) ? (D1 > D2) : (C1->id() < C2->id());
                     });

    // Collect the blocks in the order specified by their chains
    Order.reserve(NumNodes);
    for (Chain *Chain : SortedChains) {
      for (Block *Block : Chain->blocks()) {
        Order.push_back(Block->Index);
      }
    }
  }

private:
  /// The number of nodes in the graph.
  const size_t NumNodes;

  /// Successors of each node.
  std::vector<std::vector<uint64_t>> SuccNodes;

  /// Predecessors of each node.
  std::vector<std::vector<uint64_t>> PredNodes;

  /// All basic blocks.
  std::vector<Block> AllBlocks;

  /// All jumps between blocks.
  std::vector<Jump> AllJumps;

  /// All chains of basic blocks.
  std::vector<Chain> AllChains;

  /// All edges between chains.
  std::vector<ChainEdge> AllEdges;

  /// Active chains. The vector gets updated at runtime when chains are merged.
  std::vector<Chain *> HotChains;
};

} // end of anonymous namespace

std::vector<uint64_t> llvm::applyExtTspLayout(
    const std::vector<uint64_t> &NodeSizes,
    const std::vector<uint64_t> &NodeCounts,
    const std::vector<std::pair<EdgeT, uint64_t>> &EdgeCounts) {
  size_t NumNodes = NodeSizes.size();

  // Verify correctness of the input data.
  assert(NodeCounts.size() == NodeSizes.size() && "Incorrect input");
  assert(NumNodes > 2 && "Incorrect input");

  // Apply the reordering algorithm.
  auto Alg = ExtTSPImpl(NumNodes, NodeSizes, NodeCounts, EdgeCounts);
  std::vector<uint64_t> Result;
  Alg.run(Result);

  // Verify correctness of the output.
  assert(Result.front() == 0 && "Original entry point is not preserved");
  assert(Result.size() == NumNodes && "Incorrect size of reordered layout");
  return Result;
}

double llvm::calcExtTspScore(
    const std::vector<uint64_t> &Order, const std::vector<uint64_t> &NodeSizes,
    const std::vector<uint64_t> &NodeCounts,
    const std::vector<std::pair<EdgeT, uint64_t>> &EdgeCounts) {
  // Estimate addresses of the blocks in memory
  std::vector<uint64_t> Addr(NodeSizes.size(), 0);
  for (size_t Idx = 1; Idx < Order.size(); Idx++) {
    Addr[Order[Idx]] = Addr[Order[Idx - 1]] + NodeSizes[Order[Idx - 1]];
  }
  std::vector<uint64_t> OutDegree(NodeSizes.size(), 0);
  for (auto It : EdgeCounts) {
    auto Pred = It.first.first;
    OutDegree[Pred]++;
  }

  // Increase the score for each jump
  double Score = 0;
  for (auto It : EdgeCounts) {
    auto Pred = It.first.first;
    auto Succ = It.first.second;
    uint64_t Count = It.second;
    bool IsConditional = OutDegree[Pred] > 1;
    Score += ::extTSPScore(Addr[Pred], NodeSizes[Pred], Addr[Succ], Count,
                           IsConditional);
  }
  return Score;
}

double llvm::calcExtTspScore(
    const std::vector<uint64_t> &NodeSizes,
    const std::vector<uint64_t> &NodeCounts,
    const std::vector<std::pair<EdgeT, uint64_t>> &EdgeCounts) {
  std::vector<uint64_t> Order(NodeSizes.size());
  for (size_t Idx = 0; Idx < NodeSizes.size(); Idx++) {
    Order[Idx] = Idx;
  }
  return calcExtTspScore(Order, NodeSizes, NodeCounts, EdgeCounts);
}
