//===--------------------- BottleneckAnalysis.cpp ---------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements the functionalities used by the BottleneckAnalysis
/// to report bottleneck info.
///
//===----------------------------------------------------------------------===//

#include "Views/BottleneckAnalysis.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MCA/Support.h"
#include "llvm/Support/Format.h"

namespace llvm {
namespace mca {

#define DEBUG_TYPE "llvm-mca"

PressureTracker::PressureTracker(const MCSchedModel &Model)
    : SM(Model),
      ResourcePressureDistribution(Model.getNumProcResourceKinds(), 0),
      ProcResID2Mask(Model.getNumProcResourceKinds(), 0),
      ResIdx2ProcResID(Model.getNumProcResourceKinds(), 0),
      ProcResID2ResourceUsersIndex(Model.getNumProcResourceKinds(), 0) {
  computeProcResourceMasks(SM, ProcResID2Mask);

  // Ignore the invalid resource at index zero.
  unsigned NextResourceUsersIdx = 0;
  for (unsigned I = 1, E = Model.getNumProcResourceKinds(); I < E; ++I) {
    const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
    ProcResID2ResourceUsersIndex[I] = NextResourceUsersIdx;
    NextResourceUsersIdx += ProcResource.NumUnits;
    uint64_t ResourceMask = ProcResID2Mask[I];
    ResIdx2ProcResID[getResourceStateIndex(ResourceMask)] = I;
  }

  ResourceUsers.resize(NextResourceUsersIdx);
  std::fill(ResourceUsers.begin(), ResourceUsers.end(),
            std::make_pair<unsigned, unsigned>(~0U, 0U));
}

void PressureTracker::getResourceUsers(uint64_t ResourceMask,
                                       SmallVectorImpl<User> &Users) const {
  unsigned Index = getResourceStateIndex(ResourceMask);
  unsigned ProcResID = ResIdx2ProcResID[Index];
  const MCProcResourceDesc &PRDesc = *SM.getProcResource(ProcResID);
  for (unsigned I = 0, E = PRDesc.NumUnits; I < E; ++I) {
    const User U = getResourceUser(ProcResID, I);
    if (U.second && IPI.contains(U.first))
      Users.emplace_back(U);
  }
}

void PressureTracker::onInstructionDispatched(unsigned IID) {
  IPI.try_emplace(IID);
}

void PressureTracker::onInstructionExecuted(unsigned IID) { IPI.erase(IID); }

void PressureTracker::handleInstructionIssuedEvent(
    const HWInstructionIssuedEvent &Event) {
  unsigned IID = Event.IR.getSourceIndex();
  for (const ResourceUse &Use : Event.UsedResources) {
    const ResourceRef &RR = Use.first;
    unsigned Index = ProcResID2ResourceUsersIndex[RR.first];
    Index += llvm::countr_zero(RR.second);
    ResourceUsers[Index] = std::make_pair(IID, Use.second.getNumerator());
  }
}

void PressureTracker::updateResourcePressureDistribution(
    uint64_t CumulativeMask) {
  while (CumulativeMask) {
    uint64_t Current = CumulativeMask & (-CumulativeMask);
    unsigned ResIdx = getResourceStateIndex(Current);
    unsigned ProcResID = ResIdx2ProcResID[ResIdx];
    uint64_t Mask = ProcResID2Mask[ProcResID];

    if (Mask == Current) {
      ResourcePressureDistribution[ProcResID]++;
      CumulativeMask ^= Current;
      continue;
    }

    Mask ^= Current;
    while (Mask) {
      uint64_t SubUnit = Mask & (-Mask);
      ResIdx = getResourceStateIndex(SubUnit);
      ProcResID = ResIdx2ProcResID[ResIdx];
      ResourcePressureDistribution[ProcResID]++;
      Mask ^= SubUnit;
    }

    CumulativeMask ^= Current;
  }
}

void PressureTracker::handlePressureEvent(const HWPressureEvent &Event) {
  assert(Event.Reason != HWPressureEvent::INVALID &&
         "Unexpected invalid event!");

  switch (Event.Reason) {
  default:
    break;

  case HWPressureEvent::RESOURCES: {
    const uint64_t ResourceMask = Event.ResourceMask;
    updateResourcePressureDistribution(Event.ResourceMask);

    for (const InstRef &IR : Event.AffectedInstructions) {
      const Instruction &IS = *IR.getInstruction();
      unsigned BusyResources = IS.getCriticalResourceMask() & ResourceMask;
      if (!BusyResources)
        continue;

      unsigned IID = IR.getSourceIndex();
      IPI[IID].ResourcePressureCycles++;
    }
    break;
  }

  case HWPressureEvent::REGISTER_DEPS:
    for (const InstRef &IR : Event.AffectedInstructions) {
      unsigned IID = IR.getSourceIndex();
      IPI[IID].RegisterPressureCycles++;
    }
    break;

  case HWPressureEvent::MEMORY_DEPS:
    for (const InstRef &IR : Event.AffectedInstructions) {
      unsigned IID = IR.getSourceIndex();
      IPI[IID].MemoryPressureCycles++;
    }
  }
}

#ifndef NDEBUG
void DependencyGraph::dumpDependencyEdge(raw_ostream &OS,
                                         const DependencyEdge &DepEdge,
                                         MCInstPrinter &MCIP) const {
  unsigned FromIID = DepEdge.FromIID;
  unsigned ToIID = DepEdge.ToIID;
  assert(FromIID < ToIID && "Graph should be acyclic!");

  const DependencyEdge::Dependency &DE = DepEdge.Dep;
  assert(DE.Type != DependencyEdge::DT_INVALID && "Unexpected invalid edge!");

  OS << " FROM: " << FromIID << " TO: " << ToIID << "             ";
  if (DE.Type == DependencyEdge::DT_REGISTER) {
    OS << " - REGISTER: ";
    MCIP.printRegName(OS, DE.ResourceOrRegID);
  } else if (DE.Type == DependencyEdge::DT_MEMORY) {
    OS << " - MEMORY";
  } else {
    assert(DE.Type == DependencyEdge::DT_RESOURCE &&
           "Unsupported dependency type!");
    OS << " - RESOURCE MASK: " << DE.ResourceOrRegID;
  }
  OS << " - COST: " << DE.Cost << '\n';
}
#endif // NDEBUG

void DependencyGraph::pruneEdges(unsigned Iterations) {
  for (DGNode &N : Nodes) {
    unsigned NumPruned = 0;
    const unsigned Size = N.OutgoingEdges.size();
    // Use a cut-off threshold to prune edges with a low frequency.
    for (unsigned I = 0, E = Size; I < E; ++I) {
      DependencyEdge &Edge = N.OutgoingEdges[I];
      if (Edge.Frequency == Iterations)
        continue;
      double Factor = (double)Edge.Frequency / Iterations;
      if (0.10 < Factor)
        continue;
      Nodes[Edge.ToIID].NumPredecessors--;
      std::swap(Edge, N.OutgoingEdges[E - 1]);
      --E;
      ++NumPruned;
    }

    if (NumPruned)
      N.OutgoingEdges.resize(Size - NumPruned);
  }
}

void DependencyGraph::initializeRootSet(
    SmallVectorImpl<unsigned> &RootSet) const {
  for (unsigned I = 0, E = Nodes.size(); I < E; ++I) {
    const DGNode &N = Nodes[I];
    if (N.NumPredecessors == 0 && !N.OutgoingEdges.empty())
      RootSet.emplace_back(I);
  }
}

void DependencyGraph::propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet,
                                            unsigned Iterations) {
  SmallVector<unsigned, 8> ToVisit;

  // A critical sequence is computed as the longest path from a node of the
  // RootSet to a leaf node (i.e. a node with no successors).  The RootSet is
  // composed of nodes with at least one successor, and no predecessors.
  //
  // Each node of the graph starts with an initial default cost of zero.  The
  // cost of a node is a measure of criticality: the higher the cost, the bigger
  // is the performance impact.
  // For register and memory dependencies, the cost is a function of the write
  // latency as well as the actual delay (in cycles) caused to users.
  // For processor resource dependencies, the cost is a function of the resource
  // pressure. Resource interferences with low frequency values are ignored.
  //
  // This algorithm is very similar to a (reverse) Dijkstra.  Every iteration of
  // the inner loop selects (i.e. visits) a node N from a set of `unvisited
  // nodes`, and then propagates the cost of N to all its neighbors.
  //
  // The `unvisited nodes` set initially contains all the nodes from the
  // RootSet.  A node N is added to the `unvisited nodes` if all its
  // predecessors have been visited already.
  //
  // For simplicity, every node tracks the number of unvisited incoming edges in
  // field `NumVisitedPredecessors`.  When the value of that field drops to
  // zero, then the corresponding node is added to a `ToVisit` set.
  //
  // At the end of every iteration of the outer loop, set `ToVisit` becomes our
  // new `unvisited nodes` set.
  //
  // The algorithm terminates when the set of unvisited nodes (i.e. our RootSet)
  // is empty. This algorithm works under the assumption that the graph is
  // acyclic.
  do {
    for (unsigned IID : RootSet) {
      const DGNode &N = Nodes[IID];
      for (const DependencyEdge &DepEdge : N.OutgoingEdges) {
        unsigned ToIID = DepEdge.ToIID;
        DGNode &To = Nodes[ToIID];
        uint64_t Cost = N.Cost + DepEdge.Dep.Cost;
        // Check if this is the most expensive incoming edge seen so far.  In
        // case, update the total cost of the destination node (ToIID), as well
        // its field `CriticalPredecessor`.
        if (Cost > To.Cost) {
          To.CriticalPredecessor = DepEdge;
          To.Cost = Cost;
          To.Depth = N.Depth + 1;
        }
        To.NumVisitedPredecessors++;
        if (To.NumVisitedPredecessors == To.NumPredecessors)
          ToVisit.emplace_back(ToIID);
      }
    }

    std::swap(RootSet, ToVisit);
    ToVisit.clear();
  } while (!RootSet.empty());
}

void DependencyGraph::getCriticalSequence(
    SmallVectorImpl<const DependencyEdge *> &Seq) const {
  // At this stage, nodes of the graph have been already visited, and costs have
  // been propagated through the edges (see method `propagateThroughEdges()`).

  // Identify the node N with the highest cost in the graph. By construction,
  // that node is the last instruction of our critical sequence.
  // Field N.Depth would tell us the total length of the sequence.
  //
  // To obtain the sequence of critical edges, we simply follow the chain of
  // critical predecessors starting from node N (field
  // DGNode::CriticalPredecessor).
  const auto It =
      llvm::max_element(Nodes, [](const DGNode &Lhs, const DGNode &Rhs) {
        return Lhs.Cost < Rhs.Cost;
      });
  unsigned IID = std::distance(Nodes.begin(), It);
  Seq.resize(Nodes[IID].Depth);
  for (const DependencyEdge *&DE : llvm::reverse(Seq)) {
    const DGNode &N = Nodes[IID];
    DE = &N.CriticalPredecessor;
    IID = N.CriticalPredecessor.FromIID;
  }
}

void BottleneckAnalysis::printInstruction(formatted_raw_ostream &FOS,
                                          const MCInst &MCI,
                                          bool UseDifferentColor) const {
  FOS.PadToColumn(14);
  if (UseDifferentColor)
    FOS.changeColor(raw_ostream::CYAN, true, false);
  FOS << printInstructionString(MCI);
  if (UseDifferentColor)
    FOS.resetColor();
}

void BottleneckAnalysis::printCriticalSequence(raw_ostream &OS) const {
  // Early exit if no bottlenecks were found during the simulation.
  if (!SeenStallCycles || !BPI.PressureIncreaseCycles)
    return;

  SmallVector<const DependencyEdge *, 16> Seq;
  DG.getCriticalSequence(Seq);
  if (Seq.empty())
    return;

  OS << "\nCritical sequence based on the simulation:\n\n";

  const DependencyEdge &FirstEdge = *Seq[0];
  ArrayRef<llvm::MCInst> Source = getSource();
  unsigned FromIID = FirstEdge.FromIID % Source.size();
  unsigned ToIID = FirstEdge.ToIID % Source.size();
  bool IsLoopCarried = FromIID >= ToIID;

  formatted_raw_ostream FOS(OS);
  FOS.PadToColumn(14);
  FOS << "Instruction";
  FOS.PadToColumn(58);
  FOS << "Dependency Information";

  bool HasColors = FOS.has_colors();

  unsigned CurrentIID = 0;
  if (IsLoopCarried) {
    FOS << "\n +----< " << FromIID << ".";
    printInstruction(FOS, Source[FromIID], HasColors);
    FOS << "\n |\n |    < loop carried > \n |";
  } else {
    while (CurrentIID < FromIID) {
      FOS << "\n        " << CurrentIID << ".";
      printInstruction(FOS, Source[CurrentIID]);
      CurrentIID++;
    }

    FOS << "\n +----< " << CurrentIID << ".";
    printInstruction(FOS, Source[CurrentIID], HasColors);
    CurrentIID++;
  }

  for (const DependencyEdge *&DE : Seq) {
    ToIID = DE->ToIID % Source.size();
    unsigned LastIID = CurrentIID > ToIID ? Source.size() : ToIID;

    while (CurrentIID < LastIID) {
      FOS << "\n |      " << CurrentIID << ".";
      printInstruction(FOS, Source[CurrentIID]);
      CurrentIID++;
    }

    if (CurrentIID == ToIID) {
      FOS << "\n +----> " << ToIID << ".";
      printInstruction(FOS, Source[CurrentIID], HasColors);
    } else {
      FOS << "\n |\n |    < loop carried > \n |"
          << "\n +----> " << ToIID << ".";
      printInstruction(FOS, Source[ToIID], HasColors);
    }
    FOS.PadToColumn(58);

    const DependencyEdge::Dependency &Dep = DE->Dep;
    if (HasColors)
      FOS.changeColor(raw_ostream::SAVEDCOLOR, true, false);

    if (Dep.Type == DependencyEdge::DT_REGISTER) {
      FOS << "## REGISTER dependency:  ";
      if (HasColors)
        FOS.changeColor(raw_ostream::MAGENTA, true, false);
      getInstPrinter().printRegName(FOS, Dep.ResourceOrRegID);
    } else if (Dep.Type == DependencyEdge::DT_MEMORY) {
      FOS << "## MEMORY dependency.";
    } else {
      assert(Dep.Type == DependencyEdge::DT_RESOURCE &&
             "Unsupported dependency type!");
      FOS << "## RESOURCE interference:  ";
      if (HasColors)
        FOS.changeColor(raw_ostream::MAGENTA, true, false);
      FOS << Tracker.resolveResourceName(Dep.ResourceOrRegID);
      if (HasColors) {
        FOS.resetColor();
        FOS.changeColor(raw_ostream::SAVEDCOLOR, true, false);
      }
      FOS << " [ probability: " << ((DE->Frequency * 100) / Iterations)
          << "% ]";
    }
    if (HasColors)
      FOS.resetColor();
    ++CurrentIID;
  }

  while (CurrentIID < Source.size()) {
    FOS << "\n        " << CurrentIID << ".";
    printInstruction(FOS, Source[CurrentIID]);
    CurrentIID++;
  }

  FOS << '\n';
  FOS.flush();
}

#ifndef NDEBUG
void DependencyGraph::dump(raw_ostream &OS, MCInstPrinter &MCIP) const {
  OS << "\nREG DEPS\n";
  for (const DGNode &Node : Nodes)
    for (const DependencyEdge &DE : Node.OutgoingEdges)
      if (DE.Dep.Type == DependencyEdge::DT_REGISTER)
        dumpDependencyEdge(OS, DE, MCIP);

  OS << "\nMEM DEPS\n";
  for (const DGNode &Node : Nodes)
    for (const DependencyEdge &DE : Node.OutgoingEdges)
      if (DE.Dep.Type == DependencyEdge::DT_MEMORY)
        dumpDependencyEdge(OS, DE, MCIP);

  OS << "\nRESOURCE DEPS\n";
  for (const DGNode &Node : Nodes)
    for (const DependencyEdge &DE : Node.OutgoingEdges)
      if (DE.Dep.Type == DependencyEdge::DT_RESOURCE)
        dumpDependencyEdge(OS, DE, MCIP);
}
#endif // NDEBUG

void DependencyGraph::addDependency(unsigned From, unsigned To,
                                    DependencyEdge::Dependency &&Dep) {
  DGNode &NodeFrom = Nodes[From];
  DGNode &NodeTo = Nodes[To];
  SmallVectorImpl<DependencyEdge> &Vec = NodeFrom.OutgoingEdges;

  auto It = find_if(Vec, [To, Dep](DependencyEdge &DE) {
    return DE.ToIID == To && DE.Dep.ResourceOrRegID == Dep.ResourceOrRegID;
  });

  if (It != Vec.end()) {
    It->Dep.Cost += Dep.Cost;
    It->Frequency++;
    return;
  }

  DependencyEdge DE = {Dep, From, To, 1};
  Vec.emplace_back(DE);
  NodeTo.NumPredecessors++;
}

BottleneckAnalysis::BottleneckAnalysis(const MCSubtargetInfo &sti,
                                       MCInstPrinter &Printer,
                                       ArrayRef<MCInst> S, unsigned NumIter)
    : InstructionView(sti, Printer, S), Tracker(sti.getSchedModel()),
      DG(S.size() * 3), Iterations(NumIter), TotalCycles(0),
      PressureIncreasedBecauseOfResources(false),
      PressureIncreasedBecauseOfRegisterDependencies(false),
      PressureIncreasedBecauseOfMemoryDependencies(false),
      SeenStallCycles(false), BPI() {}

void BottleneckAnalysis::addRegisterDep(unsigned From, unsigned To,
                                        unsigned RegID, unsigned Cost) {
  bool IsLoopCarried = From >= To;
  unsigned SourceSize = getSource().size();
  if (IsLoopCarried) {
    DG.addRegisterDep(From, To + SourceSize, RegID, Cost);
    DG.addRegisterDep(From + SourceSize, To + (SourceSize * 2), RegID, Cost);
    return;
  }
  DG.addRegisterDep(From + SourceSize, To + SourceSize, RegID, Cost);
}

void BottleneckAnalysis::addMemoryDep(unsigned From, unsigned To,
                                      unsigned Cost) {
  bool IsLoopCarried = From >= To;
  unsigned SourceSize = getSource().size();
  if (IsLoopCarried) {
    DG.addMemoryDep(From, To + SourceSize, Cost);
    DG.addMemoryDep(From + SourceSize, To + (SourceSize * 2), Cost);
    return;
  }
  DG.addMemoryDep(From + SourceSize, To + SourceSize, Cost);
}

void BottleneckAnalysis::addResourceDep(unsigned From, unsigned To,
                                        uint64_t Mask, unsigned Cost) {
  bool IsLoopCarried = From >= To;
  unsigned SourceSize = getSource().size();
  if (IsLoopCarried) {
    DG.addResourceDep(From, To + SourceSize, Mask, Cost);
    DG.addResourceDep(From + SourceSize, To + (SourceSize * 2), Mask, Cost);
    return;
  }
  DG.addResourceDep(From + SourceSize, To + SourceSize, Mask, Cost);
}

void BottleneckAnalysis::onEvent(const HWInstructionEvent &Event) {
  const unsigned IID = Event.IR.getSourceIndex();
  if (Event.Type == HWInstructionEvent::Dispatched) {
    Tracker.onInstructionDispatched(IID);
    return;
  }
  if (Event.Type == HWInstructionEvent::Executed) {
    Tracker.onInstructionExecuted(IID);
    return;
  }

  if (Event.Type != HWInstructionEvent::Issued)
    return;

  ArrayRef<llvm::MCInst> Source = getSource();
  const Instruction &IS = *Event.IR.getInstruction();
  unsigned To = IID % Source.size();

  unsigned Cycles = 2 * Tracker.getResourcePressureCycles(IID);
  uint64_t ResourceMask = IS.getCriticalResourceMask();
  SmallVector<std::pair<unsigned, unsigned>, 4> Users;
  while (ResourceMask) {
    uint64_t Current = ResourceMask & (-ResourceMask);
    Tracker.getResourceUsers(Current, Users);
    for (const std::pair<unsigned, unsigned> &U : Users)
      addResourceDep(U.first % Source.size(), To, Current, U.second + Cycles);
    Users.clear();
    ResourceMask ^= Current;
  }

  const CriticalDependency &RegDep = IS.getCriticalRegDep();
  if (RegDep.Cycles) {
    Cycles = RegDep.Cycles + 2 * Tracker.getRegisterPressureCycles(IID);
    unsigned From = RegDep.IID % Source.size();
    addRegisterDep(From, To, RegDep.RegID, Cycles);
  }

  const CriticalDependency &MemDep = IS.getCriticalMemDep();
  if (MemDep.Cycles) {
    Cycles = MemDep.Cycles + 2 * Tracker.getMemoryPressureCycles(IID);
    unsigned From = MemDep.IID % Source.size();
    addMemoryDep(From, To, Cycles);
  }

  Tracker.handleInstructionIssuedEvent(
      static_cast<const HWInstructionIssuedEvent &>(Event));

  // Check if this is the last simulated instruction.
  if (IID == ((Iterations * Source.size()) - 1))
    DG.finalizeGraph(Iterations);
}

void BottleneckAnalysis::onEvent(const HWPressureEvent &Event) {
  assert(Event.Reason != HWPressureEvent::INVALID &&
         "Unexpected invalid event!");

  Tracker.handlePressureEvent(Event);

  switch (Event.Reason) {
  default:
    break;

  case HWPressureEvent::RESOURCES:
    PressureIncreasedBecauseOfResources = true;
    break;
  case HWPressureEvent::REGISTER_DEPS:
    PressureIncreasedBecauseOfRegisterDependencies = true;
    break;
  case HWPressureEvent::MEMORY_DEPS:
    PressureIncreasedBecauseOfMemoryDependencies = true;
    break;
  }
}

void BottleneckAnalysis::onCycleEnd() {
  ++TotalCycles;

  bool PressureIncreasedBecauseOfDataDependencies =
      PressureIncreasedBecauseOfRegisterDependencies ||
      PressureIncreasedBecauseOfMemoryDependencies;
  if (!PressureIncreasedBecauseOfResources &&
      !PressureIncreasedBecauseOfDataDependencies)
    return;

  ++BPI.PressureIncreaseCycles;
  if (PressureIncreasedBecauseOfRegisterDependencies)
    ++BPI.RegisterDependencyCycles;
  if (PressureIncreasedBecauseOfMemoryDependencies)
    ++BPI.MemoryDependencyCycles;
  if (PressureIncreasedBecauseOfDataDependencies)
    ++BPI.DataDependencyCycles;
  if (PressureIncreasedBecauseOfResources)
    ++BPI.ResourcePressureCycles;
  PressureIncreasedBecauseOfResources = false;
  PressureIncreasedBecauseOfRegisterDependencies = false;
  PressureIncreasedBecauseOfMemoryDependencies = false;
}

void BottleneckAnalysis::printBottleneckHints(raw_ostream &OS) const {
  if (!SeenStallCycles || !BPI.PressureIncreaseCycles) {
    OS << "\n\nNo resource or data dependency bottlenecks discovered.\n";
    return;
  }

  double PressurePerCycle =
      (double)BPI.PressureIncreaseCycles * 100 / TotalCycles;
  double ResourcePressurePerCycle =
      (double)BPI.ResourcePressureCycles * 100 / TotalCycles;
  double DDPerCycle = (double)BPI.DataDependencyCycles * 100 / TotalCycles;
  double RegDepPressurePerCycle =
      (double)BPI.RegisterDependencyCycles * 100 / TotalCycles;
  double MemDepPressurePerCycle =
      (double)BPI.MemoryDependencyCycles * 100 / TotalCycles;

  OS << "\n\nCycles with backend pressure increase [ "
     << format("%.2f", floor((PressurePerCycle * 100) + 0.5) / 100) << "% ]";

  OS << "\nThroughput Bottlenecks: "
     << "\n  Resource Pressure       [ "
     << format("%.2f", floor((ResourcePressurePerCycle * 100) + 0.5) / 100)
     << "% ]";

  if (BPI.PressureIncreaseCycles) {
    ArrayRef<unsigned> Distribution = Tracker.getResourcePressureDistribution();
    const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
    for (unsigned I = 0, E = Distribution.size(); I < E; ++I) {
      unsigned ReleaseAtCycles = Distribution[I];
      if (ReleaseAtCycles) {
        double Frequency = (double)ReleaseAtCycles * 100 / TotalCycles;
        const MCProcResourceDesc &PRDesc = *SM.getProcResource(I);
        OS << "\n  - " << PRDesc.Name << "  [ "
           << format("%.2f", floor((Frequency * 100) + 0.5) / 100) << "% ]";
      }
    }
  }

  OS << "\n  Data Dependencies:      [ "
     << format("%.2f", floor((DDPerCycle * 100) + 0.5) / 100) << "% ]";
  OS << "\n  - Register Dependencies [ "
     << format("%.2f", floor((RegDepPressurePerCycle * 100) + 0.5) / 100)
     << "% ]";
  OS << "\n  - Memory Dependencies   [ "
     << format("%.2f", floor((MemDepPressurePerCycle * 100) + 0.5) / 100)
     << "% ]\n";
}

void BottleneckAnalysis::printView(raw_ostream &OS) const {
  std::string Buffer;
  raw_string_ostream TempStream(Buffer);
  printBottleneckHints(TempStream);
  TempStream.flush();
  OS << Buffer;
  printCriticalSequence(OS);
}

json::Value BottleneckAnalysis::toJSON() const {
  if (!SeenStallCycles || !BPI.PressureIncreaseCycles) {
    json::Object JO({{"PressureIncreaseCycles", 0}});
    return JO;
  }

  json::Array CriticalSequence;
  // get critical sequence
  SmallVector<const DependencyEdge *, 16> Seq;
  DG.getCriticalSequence(Seq);
  if (!Seq.empty()) {
    for (const DependencyEdge *&DE : Seq) {
      json::Object DEJO({{"FromID", DE->FromIID},
                         {"ToID", DE->ToIID},
                         {"Type", static_cast<unsigned>(DE->Dep.Type)},
                         {"ResourceOrRegID", DE->Dep.ResourceOrRegID}});
      CriticalSequence.push_back(std::move(DEJO));
    }
  }

  json::Array ResourcePressure;
  if (BPI.PressureIncreaseCycles) {
    ArrayRef<unsigned> Distribution = Tracker.getResourcePressureDistribution();
    const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
    for (unsigned I = 0, E = Distribution.size(); I < E; ++I) {
      unsigned ReleaseAtCycles = Distribution[I];
      if (ReleaseAtCycles) {
        const MCProcResourceDesc &PRDesc = *SM.getProcResource(I);
        json::Object RPJO({{PRDesc.Name, ReleaseAtCycles}});
        ResourcePressure.push_back(std::move(RPJO));
      }
    }
  }

  json::Object JO({{"PressureIncreaseCycles", BPI.PressureIncreaseCycles},
                   {"ResourcePressureCycles", BPI.ResourcePressureCycles},
                   {"DataDependencyCycles", BPI.DataDependencyCycles},
                   {"RegisterDependencyCycles", BPI.RegisterDependencyCycles},
                   {"MemoryDependencyCycles", BPI.MemoryDependencyCycles},
                   {"TotalCycles", TotalCycles},
                   {"DependencyEdge", std::move(CriticalSequence)},
                   {"ResourcePressure", std::move(ResourcePressure)}});

  return JO;
}

} // namespace mca.
} // namespace llvm
