brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 43f8b62 Raw
178 lines · cpp
1//===--------------------- SchedulerStatistics.cpp --------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file implements the SchedulerStatistics interface.11///12//===----------------------------------------------------------------------===//13 14#include "Views/SchedulerStatistics.h"15#include "llvm/Support/Format.h"16#include "llvm/Support/FormattedStream.h"17 18namespace llvm {19namespace mca {20 21SchedulerStatistics::SchedulerStatistics(const llvm::MCSubtargetInfo &STI)22    : SM(STI.getSchedModel()), LQResourceID(0), SQResourceID(0), NumIssued(0),23      NumCycles(0), MostRecentLoadDispatched(~0U),24      MostRecentStoreDispatched(~0U),25      Usage(STI.getSchedModel().NumProcResourceKinds, {0, 0, 0}) {26  if (SM.hasExtraProcessorInfo()) {27    const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();28    LQResourceID = EPI.LoadQueueID;29    SQResourceID = EPI.StoreQueueID;30  }31}32 33// FIXME: This implementation works under the assumption that load/store queue34// entries are reserved at 'instruction dispatched' stage, and released at35// 'instruction executed' stage. This currently matches the behavior of LSUnit.36//37// The current design minimizes the number of events generated by the38// Dispatch/Execute stages, at the cost of doing extra bookkeeping in method39// `onEvent`. However, it introduces a subtle dependency between this view and40// how the LSUnit works.41//42// In future we should add a new "memory queue" event type, so that we stop43// making assumptions on how LSUnit internally works (See PR39828).44void SchedulerStatistics::onEvent(const HWInstructionEvent &Event) {45  if (Event.Type == HWInstructionEvent::Issued) {46    const Instruction &Inst = *Event.IR.getInstruction();47    NumIssued += Inst.getDesc().NumMicroOps;48  } else if (Event.Type == HWInstructionEvent::Dispatched) {49    const Instruction &Inst = *Event.IR.getInstruction();50    const unsigned Index = Event.IR.getSourceIndex();51    if (LQResourceID && Inst.getMayLoad() &&52        MostRecentLoadDispatched != Index) {53      Usage[LQResourceID].SlotsInUse++;54      MostRecentLoadDispatched = Index;55    }56    if (SQResourceID && Inst.getMayStore() &&57        MostRecentStoreDispatched != Index) {58      Usage[SQResourceID].SlotsInUse++;59      MostRecentStoreDispatched = Index;60    }61  } else if (Event.Type == HWInstructionEvent::Executed) {62    const Instruction &Inst = *Event.IR.getInstruction();63    if (LQResourceID && Inst.getMayLoad()) {64      assert(Usage[LQResourceID].SlotsInUse);65      Usage[LQResourceID].SlotsInUse--;66    }67    if (SQResourceID && Inst.getMayStore()) {68      assert(Usage[SQResourceID].SlotsInUse);69      Usage[SQResourceID].SlotsInUse--;70    }71  }72}73 74void SchedulerStatistics::onReservedBuffers(const InstRef & /* unused */,75                                            ArrayRef<unsigned> Buffers) {76  for (const unsigned Buffer : Buffers) {77    if (Buffer == LQResourceID || Buffer == SQResourceID)78      continue;79    Usage[Buffer].SlotsInUse++;80  }81}82 83void SchedulerStatistics::onReleasedBuffers(const InstRef & /* unused */,84                                            ArrayRef<unsigned> Buffers) {85  for (const unsigned Buffer : Buffers) {86    if (Buffer == LQResourceID || Buffer == SQResourceID)87      continue;88    Usage[Buffer].SlotsInUse--;89  }90}91 92void SchedulerStatistics::updateHistograms() {93  for (BufferUsage &BU : Usage) {94    BU.CumulativeNumUsedSlots += BU.SlotsInUse;95    BU.MaxUsedSlots = std::max(BU.MaxUsedSlots, BU.SlotsInUse);96  }97 98  IssueWidthPerCycle[NumIssued]++;99  NumIssued = 0;100}101 102void SchedulerStatistics::printSchedulerStats(raw_ostream &OS) const {103  OS << "\n\nSchedulers - "104     << "number of cycles where we saw N micro opcodes issued:\n";105  OS << "[# issued], [# cycles]\n";106 107  bool HasColors = OS.has_colors();108  const auto It = llvm::max_element(IssueWidthPerCycle);109  for (const std::pair<const unsigned, unsigned> &Entry : IssueWidthPerCycle) {110    unsigned NumIssued = Entry.first;111    if (NumIssued == It->first && HasColors)112      OS.changeColor(raw_ostream::SAVEDCOLOR, true, false);113 114    unsigned IPC = Entry.second;115    OS << " " << NumIssued << ",          " << IPC << "  ("116       << format("%.1f", ((double)IPC / NumCycles) * 100) << "%)\n";117    if (HasColors)118      OS.resetColor();119  }120}121 122void SchedulerStatistics::printSchedulerUsage(raw_ostream &OS) const {123  assert(NumCycles && "Unexpected number of cycles!");124 125  OS << "\nScheduler's queue usage:\n";126  if (all_of(Usage, [](const BufferUsage &BU) { return !BU.MaxUsedSlots; })) {127    OS << "No scheduler resources used.\n";128    return;129  }130 131  OS << "[1] Resource name.\n"132     << "[2] Average number of used buffer entries.\n"133     << "[3] Maximum number of used buffer entries.\n"134     << "[4] Total number of buffer entries.\n\n"135     << " [1]            [2]        [3]        [4]\n";136 137  formatted_raw_ostream FOS(OS);138  bool HasColors = FOS.has_colors();139  for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {140    const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);141    if (ProcResource.BufferSize <= 0)142      continue;143 144    const BufferUsage &BU = Usage[I];145    double AvgUsage = (double)BU.CumulativeNumUsedSlots / NumCycles;146    double AlmostFullThreshold = (double)(ProcResource.BufferSize * 4) / 5;147    unsigned NormalizedAvg = floor((AvgUsage * 10) + 0.5) / 10;148    unsigned NormalizedThreshold = floor((AlmostFullThreshold * 10) + 0.5) / 10;149 150    FOS << ProcResource.Name;151    FOS.PadToColumn(17);152    if (HasColors && NormalizedAvg >= NormalizedThreshold)153      FOS.changeColor(raw_ostream::YELLOW, true, false);154    FOS << NormalizedAvg;155    if (HasColors)156      FOS.resetColor();157    FOS.PadToColumn(28);158    if (HasColors &&159        BU.MaxUsedSlots == static_cast<unsigned>(ProcResource.BufferSize))160      FOS.changeColor(raw_ostream::RED, true, false);161    FOS << BU.MaxUsedSlots;162    if (HasColors)163      FOS.resetColor();164    FOS.PadToColumn(39);165    FOS << ProcResource.BufferSize << '\n';166  }167 168  FOS.flush();169}170 171void SchedulerStatistics::printView(raw_ostream &OS) const {172  printSchedulerStats(OS);173  printSchedulerUsage(OS);174}175 176} // namespace mca177} // namespace llvm178